本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
Android系统Camera录像过程分析
追忆似水年华 · 779浏览 · 发布于2019-07-08 +关注

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

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

1.录像命令时序

11.png

2.录像数据回调时序

22.png


一、应用部分

1.主Activity启动

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

  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

  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.开始录制和停止录制

  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<ICamera> &camera, 

  16.                                         const sp<ICameraRecordingProxy> &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

  1. public native void start() throws IllegalStateException;  

  2. public native void stop() throws IllegalStateException;  


2.Native部分

frameworks/base/media/jni/android_media_MediaRecorder.cpp

  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<MediaRecorder> 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<MediaRecorder> 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

  1. status_t MediaRecorder::start()  

  2. {  

  3.   status_t ret = mMediaRecorder->start();  

  4.   /* 

  5.   MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL) 

  6.   { 

  7.     const sp<IMediaPlayerService>& service(getMediaPlayerService()); 

  8.     mMediaRecorder = service->createMediaRecorder(getpid()); 

  9.     //frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp 

  10.     //sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid) 

  11.     //{ 

  12.     //  sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid); 

  13.     //  return recorder; 

  14.     //} 

  15.   } 

  16.   */  

  17. }  

 

4.服务端(Android的Binder)

frameworks/av/media/libmediaplayerservice/MediaRecorderClient.cpp

  1. MediaRecorderClient::MediaRecorderClient(const sp<MediaPlayerService>& 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

  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> *mediaWriter) { 

  31.     sp<MediaWriter> writer = new MPEG4Writer(outputFd); 

  32.     if (mVideoSource < VIDEO_SOURCE_LIST_END) { 

  33.       sp<MediaSource> mediaSource; 

  34.       //创建CameraSource: 

  35.       //这步使用mCamera,mMediaRecorder.setCamera(mActivity.mCameraDevice.getCamera())应用设置过来的 

  36.       err = setupMediaSource(&mediaSource);  

  37.       sp<MediaSource> encoder; 

  38.       //重要!!!!!设置输入类型,如:YUV420SP等 

  39.       err = setupVideoEncoder(mediaSource, videoBitRate, &encoder);  

  40.       //sp<MetaData> 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

  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<Track *>(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

  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

  1. status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {() {  

  2.   sp<MediaSource> audioEncoder = createAudioSource();  

  3.   writer->addSource(audioEncoder);  

  4. }  

  5. sp<MediaSource> StagefrightRecorder::createAudioSource() {  

  6.   sp<AudioSource> audioSource =  

  7.         new AudioSource(  

  8.                 mAudioSource,  

  9.                 mSampleRate,  

  10.                 mAudioChannels);  

  11. }  

frameworks/av/media/libstagefright/AudioSource.cpp

  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

  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);  


相关推荐

android下vulkan与opengles纹理互通

talkchan · 1173浏览 · 2020-11-23 10:37:39
Android 使用RecyclerView实现轮播图

奔跑的男人 · 2171浏览 · 2019-05-09 17:11:13
微软发布新命令行工具 Windows Terminal

吴振华 · 866浏览 · 2019-05-09 17:15:04
Facebook 停止屏蔽部分区块链广告

· 752浏览 · 2019-05-09 17:20:08
加载中

0评论

评论
分类专栏
小鸟云服务器
扫码进入手机网页