4

我正在尝试录制mpeg2-ts视频,以便server / socket使用此处Android MediaRecorder描述的类将其流式传输到...

代码如下:

public class MediaRecorderDemo extends Activity
{
private final static String TAG = "MediaRecorderDemo";
Camera camera;
CameraPreview cameraPreview;
MediaRecorder mediaRecorder;
File outputFile = new File(Environment.getExternalStorageDirectory().getPath() + "/out1.ts");

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.media_recorder_demo_layout);

    camera = getCameraInstance();
    cameraPreview = new CameraPreview(this);
    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
    preview.addView(cameraPreview);
}

private Camera getCameraInstance()
{
    final String FUNCTION = "getCameraInstance";

    Camera c = null;
    try
    {
        c = Camera.open();
    }
    catch(Exception e)
    {
        Log.e(TAG, FUNCTION + " : " + e.getMessage());
    }

    return c;
}

void initMediaRecorder()
{
    final String FUNCTION = "initMediaRecorder";
    FileDescriptor outputFileFD = null;
    try
    {
        outputFile.createNewFile();
        outputFileFD = new FileOutputStream(outputFile).getFD();
    }
    catch(Exception e)
    {
        Log.e(TAG, FUNCTION + " : " + e.getMessage());
    }

    mediaRecorder = new MediaRecorder();
    mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
        final static String TAG = "MediaRecorder.onErrorListener";

        @Override
        public void onError(MediaRecorder mr, int what, int extra) {
            Log.e(TAG, "Error : " + what + " " + extra);
        }
    });

    camera.unlock();
    mediaRecorder.setPreviewDisplay(cameraPreview.getHolder().getSurface());
    mediaRecorder.setCamera(camera);
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    //mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
    mediaRecorder.setOutputFormat(8);
    Log.d(TAG, "File Exists : " + outputFile.exists());
    mediaRecorder.setOutputFile(outputFileFD);
    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    //mediaRecorder.setVideoSize(640, 480);
    mediaRecorder.setMaxDuration(-1);
    //mediaRecorder.setVideoFrameRate(16);
    mediaRecorder.setVideoEncodingBitRate(1024 * 1024);

    try
    {
        mediaRecorder.prepare();
        Log.d(TAG, "MediaRecorder Prepared.");
        mediaRecorder.start();

    }
    catch(Exception e)
    {
        Log.e(TAG, FUNCTION + " : " + e.getMessage());
        //releaseMediaRecorder();
    }
}

void releaseMediaRecorder()
{
    final String FUNCTION = "releaseMediaRecorder";

    try
    {
        if(mediaRecorder != null)
        {
            mediaRecorder.stop();
            mediaRecorder.reset();
            mediaRecorder.release();
            mediaRecorder = null;
            camera.lock();
        }
    }

    catch(Exception e)
    {
        Log.e(TAG, FUNCTION + " : " + e.getMessage());
    }
}

void releaseCamera()
{
    final String FUNCTION = "releaseCamera";
    try
    {
        if(camera != null)
        {
            camera.stopPreview();
            camera.release();
        }
        camera = null;
    }
    catch(Exception e)
    {
        Log.e(TAG, FUNCTION + " : " + e.getMessage());
    }
}

@Override
public void onStart()
{
    super.onStart();
}

@Override
public void onPause()
{
    super.onPause();
}

@Override
public void onResume()
{
    super.onResume();
}

@Override
public void onStop()
{
    super.onStop();
}

@Override
public void onDestroy()
{
    super.onDestroy();
}

public class CameraPreview extends SurfaceView
{
    private final static String TAG = "CameraPreview"; 
    SurfaceHolder holder;
    boolean isPreviewDisplaySet;

    public CameraPreview(Context context)
    {
        this(context, (AttributeSet)null);

        this.holder = getHolder();
        this.holder.addCallback(new SurfaceHolderCallback());
    }

    public CameraPreview(Context context, AttributeSet attrSet)
    {
        this(context, attrSet, 0);
    }

    public CameraPreview(Context context, AttributeSet attrSet, int defStyle)
    {
        super(context, attrSet, defStyle);
    }

    private void releaseCamera()
    {
        if(camera != null)
        {
            camera.release();
            camera = null;
        }
    }

    private class SurfaceHolderCallback implements SurfaceHolder.Callback
    {
        @Override
        public void surfaceCreated(SurfaceHolder holder)
        {
            final String FUNCTION = "surfaceCreated";
            Log.d(TAG, "Surface Created.");

            try
            {
                camera.setPreviewDisplay(holder);
                camera.startPreview();

                initMediaRecorder();
                //mediaRecorder.start();
            }
            catch(Exception e)
            {
                Log.e(TAG, FUNCTION + " : " + e.getMessage());
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder)
        {
            final String FUNCTION = "surfaceDestroyed";
            Log.d(TAG, "Surface Destroyed.");

            try
            {
                releaseMediaRecorder();
                releaseCamera();
            }
            catch(Exception e)
            {
                Log.e(TAG, FUNCTION + " : " + e.getMessage());
            } 
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
        {
            final String FUNCTION = "surfaceChanged";
            Log.d(TAG, "Surface Changed.");

            if(holder.getSurface() == null)
                return;

            try
            {
                camera.stopPreview();
            }
            catch(Exception e)
            {
                Log.e(TAG, FUNCTION + " : " + e.getMessage());
            }

            try
            {
                camera.setPreviewDisplay(holder);
                camera.startPreview();
            }
            catch(Exception e)
            {
                Log.e(TAG, FUNCTION + " : " + e.getMessage());
            }
        }
    }
}
}

mediaRecorder.prepare()调用and没有任何错误并显示mediaRecorder.start()相机预览...但是过了一会儿预览被切断然后屏幕冻结并在输出路径创建一个空文件...这个问题也正在报告Android 问题列表,但尚未纠正...

我曾尝试在具有 Stock Android ICS ROM 的 Galaxy Note N7000 以及三星 Galaxy Tab 2 P3100 但具有自定义 Android 4.2 ROM 上运行相同的应用程序......所以它似乎与 ROM 或特定的硬件配置...

如果有什么遗漏或做错了,知道这一点会很高兴,当然也会松一口气……?

谢谢...

4

2 回答 2

2

解决方案是在M2ts Writer. 构建libstagefright.so并推送到设备。在应用程序中也设置如下

recorder.setAudioSamplingRate(48000); 
recorder.setAudioEncodingBitRate(128000);

否则它不会完整地记录剪辑。不过,我没有深入研究设置上述参数的原因。

补丁:M2tsWriter_libstagefright

diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp

index c9ed5bb..a42371f 100644

--- a/media/libstagefright/MPEG2TSWriter.cpp

+++ b/media/libstagefright/MPEG2TSWriter.cpp

@@ -411,6 +411,7 @@ void MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) { 
                            (const uint8_t *)buffer->data() 
                             + buffer->range_offset(), 
                            buffer->range_length()); 
+                    readMore(); 
                 } else if (buffer->range_length() > 0) {
                     if (mStreamType == 0x0f) { 
                         if (!appendAACFrames(buffer)) { 
于 2014-09-26T21:07:06.217 回答
-1

我遇到了与您类似的问题,尽管不在同一设备上。根据我的初步调查,在录制 mpeg ts 时,HAL 中摄像机的录制堆(缓冲区)没有正确释放。但我仍然不太确定 yuv 数据是否已经到达 OMX。高级原因应由每个硬件供应商检查。希望能帮助到你。:)

于 2013-03-26T03:21:40.500 回答