Android多媒体之录制 v&&Android系统Camera录像过程分析

http://blog.csdn.net/tankai19880619/article/details/9270837

一、运行相关

frameworks/base/media/java/android/media/MediaRecorder.java

frameworks/base/media/jni/android_media_MediaRecorder.cpp

frameworks/av/media/libmedia/Mediarecoder.cpp

二、参数设置相关

frameworks/base/media/java/android/media/CamcorderProfile.java

frameworks/base/media/jni/android_media_MediaProfiles.cpp

frameworks/av/media/libmedia/MediaProfiles.cpp

/system/etc/media_profiles.xml


Android系统Camera录像过程分析

http://blog.csdn.net/tankai19880619/article/details/16848135

最近调试系统Camera,遇到如下问题:在录像过程中,拔掉Camera;会出现应用程序卡死现象。

  先说说之前的设计架构:

  当用户拔掉Camera时,会给应用程序发送广播;当应用程序收到广播后调用Activity类的finish方法(系统会自动调用onPause方法),而我们的onPause方法做了停止录制和关闭Camera的动作。

  问题出在:

  当调用系统MediaRecorder的stop方法停止录制时,应用程序因为阻塞而卡死。

下面就着重分析下系统Camera和MediaRecorder(libstagefright中MPEG4Writer以及CameraSource的关系)。

  首先,通过图示、看看Android系统Camera录像时的调用时序:

1.录像命令时序


2.录像数据回调时序


一、应用部分

1.主Activity启动

packages/apps/Camera/src/com/android/camera/CameraActivity.java

[java] view plain copy
  1. public void onCreate(Bundle state)   
  2. {  
  3.   mCurrentModule.init(this, mFrame, true);  
  4. }  

2.录像Activity初始化

packages/apps/Camera/src/com/android/camera/VideoModule.java

[java] view plain copy
  1. public void init(CameraActivity activity, View root, boolean reuseScreenNail) {  
  2. {  
  3.   CameraOpenThread cameraOpenThread = new CameraOpenThread();  
  4.   /* 
  5.   protected class CameraOpenThread extends Thread { 
  6.     @Override 
  7.     public void run() { 
  8.       openCamera(); 
  9.     } 
  10.   } 
  11.   */  
  12. }  

3.开始录制和停止录制

[java] view plain copy
  1. //当用户点击录像后调用  
  2. public void onShutterButtonClick()   
  3. {  
  4.   startVideoRecording();  
  5. }  
  6. private void startVideoRecording()   
  7. {  
  8.   initializeRecorder();  
  9.   /* 
  10.   private void initializeRecorder()    
  11.   { 
  12.     mMediaRecorder = new MediaRecorder(); 
  13.     //调用至frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp 
  14.     /* 
  15.     status_t StagefrightRecorder::setCamera(const sp &camera, 
  16.                                         const sp &proxy) { 
  17.       mCamera = camera; 
  18.     } 
  19.     */  
  20.     mMediaRecorder.setCamera(mActivity.mCameraDevice.getCamera());   
  21.     mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);  
  22.     mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);  
  23.     mMediaRecorder.setProfile(mProfile);  
  24.     mMediaRecorder.setMaxDuration(mMaxVideoDurationInMs);  
  25.     mMediaRecorder.setOutputFile(mVideoFilename);  
  26.   }  
  27.   */  
  28.   mMediaRecorder.start();  
  29. }  
  30. //当用户点击停止录制后调用  
  31. public void onShutterButtonClick() {  
  32.   public void onShutterButtonClick() {  
  33. }  
  34. private void onStopVideoRecording() {  
  35.   stopVideoRecording();  
  36. }  
  37. private boolean stopVideoRecording() {  
  38.   mMediaRecorder.setOnErrorListener(null);  
  39.   mMediaRecorder.setOnInfoListener(null);  
  40.   mMediaRecorder.stop();  
  41.   closeCamera(closeEffects);  
  42. }  

二、框架部分

1.MediaRecorder的API部分

frameworks/base/media/java/android/media/MediaRecorder.java

[java] view plain copy
  1. public native void start() throws IllegalStateException;  
  2. public native void stop() throws IllegalStateException;  

2.Native部分

frameworks/base/media/jni/android_media_MediaRecorder.cpp

[cpp] view plain copy
  1. static JNINativeMethod gMethods[] = {  
  2.   {"start",  "()V",   (void *)android_media_MediaRecorder_start},  
  3.   {"stop",  "()V",   (void *)android_media_MediaRecorder_stop},  
  4. }  
  5. static void  
  6. android_media_MediaRecorder_start(JNIEnv *env, jobject thiz)  
  7. {  
  8.   ALOGV("start");  
  9.   sp mr = getMediaRecorder(env, thiz);  
  10.   process_media_recorder_call(env, mr->start(), "java/lang/RuntimeException""start failed.");  
  11. }  
  12. static void  
  13. android_media_MediaRecorder_stop(JNIEnv *env, jobject thiz)  
  14. {  
  15.   ALOGV("stop");  
  16.   sp mr = getMediaRecorder(env, thiz);  
  17.   process_media_recorder_call(env, mr->stop(), "java/lang/RuntimeException""stop failed.");  
  18. }  

3.C++部分

frameworks/av/media/libmedia/MediaRecorder.cpp

[cpp] view plain copy
  1. status_t MediaRecorder::start()  
  2. {  
  3.   status_t ret = mMediaRecorder->start();  
  4.   /* 
  5.   MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL) 
  6.   { 
  7.     const sp& service(getMediaPlayerService()); 
  8.     mMediaRecorder = service->createMediaRecorder(getpid()); 
  9.     //frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp 
  10.     //sp MediaPlayerService::createMediaRecorder(pid_t pid) 
  11.     //{ 
  12.     //  sp recorder = new MediaRecorderClient(this, pid); 
  13.     //  return recorder; 
  14.     //} 
  15.   } 
  16.   */  
  17. }  

4.服务端(Android的Binder)

frameworks/av/media/libmediaplayerservice/MediaRecorderClient.cpp

[cpp] view plain copy
  1. MediaRecorderClient::MediaRecorderClient(const sp& service, pid_t pid)  
  2. {  
  3.   ALOGV("Client constructor");  
  4.   mPid = pid;  
  5.   mRecorder = new StagefrightRecorder;  
  6.   mMediaPlayerService = service;  
  7. }  
  8. status_t MediaRecorderClient::start()  
  9. {  
  10.   return mRecorder->start();  
  11. }  

Android4.2多媒体使用Stagefright架构

frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp

[cpp] view plain copy
  1. status_t StagefrightRecorder::start() {  
  2.   switch (mOutputFormat) {  
  3.     case OUTPUT_FORMAT_MPEG_4:  
  4.       status = startMPEG4Recording();  
  5.       break;  
  6.     case OUTPUT_FORMAT_AMR_WB:  
  7.       status = startAMRRecording();  
  8.       break;  
  9.     case OUTPUT_FORMAT_AAC_ADTS:  
  10.       status = startAACRecording();      
  11.       break;  
  12.     case OUTPUT_FORMAT_RTP_AVP:    
  13.       status = startRTPRecording();  
  14.       break;  
  15.     case OUTPUT_FORMAT_MPEG2TS:  
  16.       status = startMPEG2TSRecording();  
  17.       break;  
  18.   }  
  19. }  
  20. status_t StagefrightRecorder::startMPEG4Recording() {  
  21.   status_t err = setupMPEG4Recording(  
  22.             mOutputFd, mVideoWidth, mVideoHeight,  
  23.             mVideoBitRate, &totalBitRate, &mWriter);  
  24.   /* 
  25.   status_t StagefrightRecorder::setupMPEG4Recording( 
  26.         int outputFd, 
  27.         int32_t videoWidth, int32_t videoHeight, 
  28.         int32_t videoBitRate, 
  29.         int32_t *totalBitRate, 
  30.         sp *mediaWriter) { 
  31.     sp writer = new MPEG4Writer(outputFd); 
  32.     if (mVideoSource < VIDEO_SOURCE_LIST_END) { 
  33.       sp mediaSource; 
  34.       //创建CameraSource: 
  35.       //这步使用mCamera,mMediaRecorder.setCamera(mActivity.mCameraDevice.getCamera())应用设置过来的 
  36.       err = setupMediaSource(&mediaSource);  
  37.       sp encoder; 
  38.       //重要!!!!!设置输入类型,如:YUV420SP等 
  39.       err = setupVideoEncoder(mediaSource, videoBitRate, &encoder);  
  40.       //sp meta = cameraSource->getFormat(); 
  41.       //CameraSource.cpp 
  42.       ////mColorFormat = getColorFormat(params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT)); 
  43.       //CameraHal.cpp: 
  44.       ////p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP); 
  45.       //setVideoInputFormat(mMIME, meta); 
  46.       //setVideoPortFormatType 
  47.       writer->addSource(encoder); 
  48.     } 
  49.     if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_CNT)) { 
  50.       //创建AudioSource;这步使用new AudioRecord 
  51.       err = setupAudioEncoder(writer);  
  52.       if (err != OK) return err; 
  53.       *totalBitRate += mAudioBitRate; 
  54.     } 
  55.   } 
  56.   */    
  57.   err = mWriter->start(meta.get());  
  58. }  
MPEG4编码器部分

frameworks/av/media/libstagefright/MPEG4Writer.cpp

[cpp] view plain copy
  1. status_t MPEG4Writer::Track::start(MetaData *params) {  
  2.   pthread_create(&mThread, &attr, ThreadWrapper, this);  
  3.   /* 
  4.   void *MPEG4Writer::Track::ThreadWrapper(void *me) { 
  5.     Track *track = static_cast(me); 
  6.     status_t err = track->threadEntry(); 
  7.     return (void *) err; 
  8.   } 
  9.   status_t MPEG4Writer::Track::threadEntry() { 
  10.     while (!mDone && (err = mSource->read(&buffer)) == OK) { 
  11.       //如上read即是frameworks/av/media/libstagefright/CameraSource.cpp的read 
  12.     } 
  13.   } 
  14.   */    
  15. }  
  16. status_t MPEG4Writer::Track::stop() {  
  17.   mDone = true;  
  18.   void *dummy;  
  19.   pthread_join(mThread, &dummy); //等待刚才的主线程退出  
  20. }  

当有数据来时CameraSource的dataCallbackTimestamp函数会被调用,如此、完成视频录制。

三、分析问题

  我们的问题就出在直接拔掉Camera时;应用程序调用mMediaRecorder.stop()超时卡死;经分析是上述框架部分“Camera拔出时录制的主线程不能退出、导致接口阻塞”。后调试发现:mDone变量并不能在两个线程间传参数;后打入之前一个patcher(see bug 4724339),修改了主线程中的mSource->read、并在相应的while循环中做判断,问题解决。

frameworks/av/media/libstagefright/CameraSource.cpp

[cpp] view plain copy
  1. status_t CameraSource::read(  
  2.         MediaBuffer **buffer, const ReadOptions *options) {  
  3.   ALOGW("Timed out waiting for incoming camera video frames: %lld us",  
  4.                     mLastFrameTimestampUs);  
  5.   //add by tankai  
  6.   // For funtion OMXCodec::read timeout return in writer, then Writer (e.g. VECaptureWriter) thread can exit  when  
  7.   // media recorder stop  
  8.   // reason: when media recorder start with no frame send to OMXCodec(with camera source),  
  9.   // media recorder can not stop always (because writer can't exit)  
  10.   // this change impact cameras: vecapture fake camera and Webcam  
  11.   return ERROR_END_OF_STREAM;  
  12.   //end tankai  
  13. }  

四、补充,分析MPEG4中Audio流程;接分析二中的实现

1.Audio录音

frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp

[cpp] view plain copy
  1. status_t StagefrightRecorder::setupAudioEncoder(const sp& writer) {() {  
  2.   sp audioEncoder = createAudioSource();  
  3.   writer->addSource(audioEncoder);  
  4. }  
  5. sp StagefrightRecorder::createAudioSource() {  
  6.   sp audioSource =  
  7.         new AudioSource(  
  8.                 mAudioSource,  
  9.                 mSampleRate,  
  10.                 mAudioChannels);  
  11. }  
frameworks/av/media/libstagefright/AudioSource.cpp
[cpp] view plain copy
  1. AudioSource::AudioSource(  
  2.         audio_source_t inputSource, uint32_t sampleRate, uint32_t channelCount)  
  3.     : mRecord(NULL),  
  4.       mStarted(false),  
  5.       mSampleRate(sampleRate),  
  6.       mPrevSampleTimeUs(0),  
  7.       mNumFramesReceived(0),  
  8.       mNumClientOwnedBuffers(0) {  
  9.   mRecord = new AudioRecord(  
  10.                     inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,  
  11.                     audio_channel_in_mask_from_count(channelCount),  
  12.                     bufCount * frameCount,  
  13.                     AudioRecordCallbackFunction,  
  14.                     this,  
  15.                     frameCount);  
  16. }  

至此,MediaRecorder与AudioFlinger建立联系。

2.Audio放音

MediaPlayer播放音频服务端(后边有时间在具体分析应用程序/客户端流程):

frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

[cpp] view plain copy
  1. status_t MediaPlayerService::AudioOutput::open(  
  2.         uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,  
  3.         audio_format_t format, int bufferCount,  
  4.         AudioCallback cb, void *cookie,  
  5.         audio_output_flags_t flags)  
  6. {  
  7.   AudioTrack *t;  
  8.   //最终放声音使用AudioTrack  
  9.   t = new AudioTrack(  
  10.                 mStreamType,  
  11.                 sampleRate,  
  12.                 format,  
  13.                 channelMask,  
  14.                 frameCount,  
  15.                 flags,  
  16.                 CallbackWrapper,  
  17.                 newcbd,  
  18.                 0,  // notification frames  
  19.                 mSessionId);  


你可能感兴趣的:(Q_CAMERA)