【问题标题】:Get frame from SurfaceTexture (Android)从 SurfaceTexture (Android) 获取帧
【发布时间】:2016-02-04 09:13:32
【问题描述】:

我正在使用SurfaceTexture 在后台运行设备的摄像头并从中获取帧。我看到onFrameAvailable 回调没有带来框架,而是SurfaceTexture。我想得到它的框架或图像表示,但我不知道该怎么做。当我搜索时,我发现我需要使用GraphicBuffer,但它似乎太复杂了,我不清楚如何使用它。

我也在这里查看了解决方案:

Texture Image processing on the GPU?

Android SDK: Get raw preview camera image without displaying it

但不清楚如何在代码中做到这一点。这是我的代码:

public class BackgroundService extends Service  {

    private Camera camera = null;
    private int  NOTIFICATION_ID= 1;
    private static final String TAG = "OCVSample::Activity";
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();
    private WindowManager windowManager;
    private SurfaceTexture mSurfaceTexture= new SurfaceTexture (10);
    Intent intializerIntent;





    public class LocalBinder extends Binder {
        BackgroundService getService() {
            // Return this instance of this service so clients can call public methods
            return BackgroundService.this;
        }
    }//end inner class that returns an instance of the service.

    @Override
    public IBinder onBind(Intent intent) {
        intializerIntent = intent;
        return mBinder;
    }//end onBind.


    @Override
    public void onCreate() {

        Log.i(TAG, "onCreate is called");
        // Start foreground service to avoid unexpected kill

        startForeground(NOTIFICATION_ID, buildNotification());

        Thread thread = new Thread() {
            public void run() {

                camera = Camera.open(1);

                mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
                    @Override
                    public void onFrameAvailable(SurfaceTexture surfaceTexture) {
                        Log.i(TAG, "frame captured from texture");


                        if (camera!=null) {
                            //camera.setPreviewCallbackWithBuffer(null);
                            //camera.setPreviewCallback(null);
                            //camera.setOneShotPreviewCallback(null);

                            //if the following two lines are not called, many frames will be droped. 
                            camera.stopPreview();
                            camera.startPreview();
                        }


                    }
                });
                //now try to set the preview texture of the camera which is actually the  surfaceTexture that has just been created.

                try {
                    camera.setPreviewTexture(mSurfaceTexture);
                } catch (IOException e) {
                    Log.e(TAG, "Error in setting the camera surface texture");
                }



                camera.startPreview();
            }


        };
        thread.start();

    }

    private Notification buildNotification () {

        NotificationCompat.Builder notificationBuilder=new NotificationCompat.Builder(this);

        notificationBuilder.setOngoing(true); //this notification should be ongoing

        notificationBuilder.setContentTitle(getString(R.string.notification_title))
                .setContentText(getString (R.string.notification_text_and_ticker))
                .setSmallIcon(R.drawable.vecsat_logo)
                .setTicker(getString(R.string.notification_text_and_ticker));
        return(notificationBuilder.build());

    }


    @Override
    public void onDestroy() {

        Log.i(TAG, "surfaceDestroyed method");

        camera.stopPreview();
        //camera.lock();

        camera.release();
        mSurfaceTexture.detachFromGLContext();
        mSurfaceTexture.release();
        stopService(intializerIntent) ;
        //windowManager.removeView(surfaceView);

    }
}

如何获取帧并在 GPU 或 CPU 上处理它们?如果有办法在 GPU 上做到这一点,然后从那里得到结果,那就太好了,因为它看起来更有效率。

谢谢。

【问题讨论】:

    标签: android android-camera android-service


    【解决方案1】:

    SurfaceTexture 获取发送到 Surface 的任何内容并将其转换为 OpenGL ES“外部”纹理。如果您想从软件访问这些像素,您需要将纹理渲染到帧缓冲区,然后使用glReadPixels() 读取像素。这方面的一个例子是 bigflake ExtractMpegFramesTest,它将解码的视频帧转换为 PNG。

    通过在 GPU 上进行所有处理可以获得更好的性能(参见例如this demo),但这并不总是可行的。

    【讨论】:

    • 谢谢。我认为这段代码记录了视频,在我的情况下我没有记录它。我需要更仔细地阅读它。请给我一些时间,如果我有问题,我会尽力理解并回复你。谢谢。
    • 该代码似乎先保存视频,然后尝试使用 MediaCodec,但我无法理解它的必要性。你能帮我么?在我的情况下,我如何在服务中使用这种技术?或者,我可以在 GPU 上做哪些其他替代方案?谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 2016-01-04
    • 2013-03-21
    相关资源
    最近更新 更多