4

Я пытаюсь записать mpeg2-ts видео для того, чтобы поток его в server/socket используя Android MediaRecorder класс, как описано here ...Запись 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, но еще не исправляется ...

Я попытался запустить такое же приложение на галактике Note N7000 с Android ICS ROM, а также на Samsung Galaxy Tab 2 P3100, но с Пользовательский Android 4.2 ROM ... Так что это не похоже на то, что связано с ПЗУ или конкретной аппаратной конфигурацией ...

Если есть что-то, чего не хватает или что-то не так, было бы приятно и, конечно же, облегчено знаете, что ...?

Благодаря ...

+0

Вы получаете какие-либо ошибки на вашем 'logcat'? Можете ли вы поделиться, если у вас есть журналы? Кроме того, вы наблюдаете это поведение только с помощью «MPEG-2 TS» или видите ли вы, например, запись MPEG-4? – Ganesh

+0

В настоящее время API-интерфейс hide OUTPUT_FORMAT_MPEG2TS работает только для видео, если кодировать как видео, так и аудио, вывод ts неверен. Решение заключается в том, что два MediaRecorder запускают видео и аудио отдельно, а затем мультиплексируют видео и аудио рамку самостоятельно. – yorkw

ответ

-1

я получил подобную проблему с вашими, хотя и не на том же устройстве. Согласно моему первоначальному исследованию, запись кучи (буфера) камеры в HAL не была правильно выбрана при записи mpeg ts. Но я все еще не очень уверен, достигли ли данные yuv OMX. Продвинутая причина должна быть проверена каждым поставщиком оборудования. Надеюсь, это поможет. :)

+0

Вы найдете решение проблемы или решение этой проблемы ...? – Stryker33

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

Похоже, что некоторые из вашего кода отсутствуют ... – nrussell

+0

Я не вижу никакого кода. 1 изменение кода линии в медиа/libstagefright/MPEG2TSWriter.cpp и вызов 2-го выше установленного apis для настройки aac-кодировщика. – sdh

Смежные вопросы