首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用MediaRecorder录制MPEG

使用MediaRecorder录制MPEG
EN

Stack Overflow用户
提问于 2013-03-21 05:43:15
回答 2查看 3.2K关注 0票数 4

我正在尝试录制mpeg2-ts视频,以便使用Android MediaRecorder类将其流式传输到server / socket,如here所述……

代码如下:

代码语言:javascript
复制
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()mediaRecorder.start()时不会出现任何错误,并显示相机预览...但过了一段时间,预览被切断,然后屏幕冻结,在输出路径上创建了一个空文件……这个问题在Android Issue List上也有报道,但尚未得到纠正...

我曾尝试在Galaxy Note N7000和三星Galaxy Tab2 P3100上运行相同的应用程序,但在自定义安卓4.2 ROM...So上,它似乎与只读存储器或特定的硬件配置无关。

如果我错过了什么或做错了什么,我会很高兴,当然也会松一口气……?

谢谢..。

EN

回答 2

Stack Overflow用户

发布于 2014-09-27 05:07:06

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

代码语言:javascript
复制
recorder.setAudioSamplingRate(48000); 
recorder.setAudioEncodingBitRate(128000);

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

libstagefrightM2tsWriter的修补程序

代码语言:javascript
复制
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)) { 
票数 2
EN

Stack Overflow用户

发布于 2013-03-26 11:21:41

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

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15535335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档