4

我试图记录mpeg2-ts视频,以便使用Android MediaRecorder类描述here到它传输到server/socket ...记录MPEG TS使用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()mediaRecorder.start()被调用时没有任何错误,并显示相机预览... 但过了一段时间,预览被切断,然后屏幕冻结,并在输出路径上创建一个空文件... 此问题也正在报告Android Issue List,但还没有被纠正...

我试图在Galaxy Note N7000上使用Stock Android ICS ROM和三星Galaxy Tab 2 P3100上运行相同的应用程序,但与一个自定义安卓4.2 ROM ...所以它似乎并没有涉及到一个ROM或特定的硬件配置...

如果有什么是错过了或做错了,会很高兴,当然松了一口气我知道...?

谢谢...

+0

你得到你的'logcat'任何错误?如果你有任何日志,你可以分享吗?另外,您是否仅通过“MPEG-2 TS”观察了这种行为,或者您是否还观察过说'MPEG-4'录制? – Ganesh 2013-03-23 02:39:56

+0

目前隐藏API OUTPUT_FORMAT_MPEG2TS仅适用于视频,如果对视频和音频进行编码,则ts输出格式不正确。解决方法是先启动两台MediaRecorder分别处理视频和音频,然后再自行处理多路视频和音频帧。 – yorkw 2015-06-10 10:39:23

回答

-1

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

+0

您是否发现上述问题的任何解决方法或解决方案...? – Stryker33 2013-03-26 10:15:03

2

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

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

否则它将不会完全记录剪辑。我没有深入探讨设置上述参数的原因。在libstagefright

修补程序M2tsWriter

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)) { 
+0

它看起来像你的一些代码是缺少的... – nrussell 2014-09-26 21:14:01

+0

我看不到任何代码缺失。 在media/libstagefright/MPEG2TSWriter.cpp中更改1行代码,并调用上述2个设置apis进行aac编码器设置。 – sdh 2014-09-28 02:21:11