Record MPEG TS using MediaRecorder

I am trying to record mpeg2-ts video in order to transfer it to server / socket using the Android MediaRecorder class as described here ...

The code is as follows:

 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() is called without any errors and the camera preview is displayed ... But after a while, the preview is turned off and then the screen freezes and an empty file is created on the output path ... This problem also reported in Android Issue List but not yet fixed ...

I tried to run the same application on the Galaxy Note N7000 with Android ICS ROM, as well as on the Samsung Galaxy Tab 2 P3100, but with a custom Android 4.2 ROM ... So this doesn’t look like something related to ROM or a specific hardware configuration ...

If there is something that is missing or something is wrong, it would be nice and, of course, easier to know that ...?

Thanks...

+4
source share
2 answers

The solution uses the patch in M2ts Writer . Build libstagefright.so and click on the device. Also below in the app

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

otherwise it will not fully record the clip. I did not explain the reason for setting the above parameters.

Patch for M2tsWriter in 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)) { 
+2
source

I had a similar problem with yours, although not on the same device. According to my initial research, the recording of the heap (buffer) of the camera in the HAL was not correctly selected when recording mpeg ts. But I'm still not very sure if yuv OMX data has reached. A leading cause should be verified by each equipment supplier. Hope it helps. :)

-1
source

All Articles