android Recorder流程

环境:我们的项目T082所使用的平台是samsung C110, android系统为4.0.3版本。
在android系统Framework层,有Mediarecorder.h文件,其中有定义:
enum video_source {
    VIDEO_SOURCE_DEFAULT = 0,
    VIDEO_SOURCE_CAMERA = 1,
    VIDEO_SOURCE_GRALLOC_BUFFER = 2,

    VIDEO_SOURCE_LIST_END  // must be last - used to validate audio source type
};

//Please update media/java/android/media/MediaRecorder.java if the following is updated.
enum output_format {
    OUTPUT_FORMAT_DEFAULT = 0,
    OUTPUT_FORMAT_THREE_GPP = 1,
    OUTPUT_FORMAT_MPEG_4 = 2,


    OUTPUT_FORMAT_AUDIO_ONLY_START = 3, // Used in validating the output format.  Should be the
                                        //  at the start of the audio only output formats.

    /* These are audio only file formats */
    OUTPUT_FORMAT_RAW_AMR = 3, //to be backward compatible
    OUTPUT_FORMAT_AMR_NB = 3,
    OUTPUT_FORMAT_AMR_WB = 4,
    OUTPUT_FORMAT_AAC_ADIF = 5,
    OUTPUT_FORMAT_AAC_ADTS = 6,

    /* Stream over a socket, limited to a single stream */
    OUTPUT_FORMAT_RTP_AVP = 7,

    /* H.264/AAC data encapsulated in MPEG2/TS */
    OUTPUT_FORMAT_MPEG2TS = 8,

    OUTPUT_FORMAT_LIST_END // must be last - used to validate format type
};

enum audio_encoder {
    AUDIO_ENCODER_DEFAULT = 0,
    AUDIO_ENCODER_AMR_NB = 1,
    AUDIO_ENCODER_AMR_WB = 2,
    AUDIO_ENCODER_AAC = 3,
    AUDIO_ENCODER_AAC_PLUS = 4,
    AUDIO_ENCODER_EAAC_PLUS = 5,

    AUDIO_ENCODER_LIST_END // must be the last - used to validate the audio encoder type
};

enum video_encoder {
    VIDEO_ENCODER_DEFAULT = 0,
    VIDEO_ENCODER_H263 = 1,
    VIDEO_ENCODER_H264 = 2,
    VIDEO_ENCODER_MPEG_4_SP = 3,

    VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type
};
上面分别定义了支持的视频源、输出格式和编码格式,其中视频源主要分三种模式:第一种是默认源,在本项目中,设定为camara源作为默认源
另外一种就是VIDEO_SOURCE_CAMERA支持camara录制视频,还有一种就是VIDEO_SOURCE_GRALLOC_BUFFER,这一种是用户自己分配空间,然后填充自己的数据进行编码输出,也是我这次学习的重点。

class MediaRecorder : public BnMediaRecorderClient{}这是一个recorder应用实体对应的类对象,它从BnMediaRecorderClient派生过来,跟踪代码可发现,继承这个类主要是为了给远程提供notify机制,以便在录制过程中接收其它端的消息。

类中有 sp<IMediaRecorder>          mMediaRecorder;    sp<MediaRecorderListener>   mListener;    
// Reference toISurfaceTexture
    // for encoding GL Frames. That is useful only when the
    // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER
    sp<ISurfaceTexture>         mSurfaceMediaSource;
几个成员变量,其中mMediaRecorder是为了通过IMediaRecorder与MediaPlayerService进行控制操作;mListener是为了在接收到其它进程通知时作出相应的处理;mSurfaceMediaSource只有在VIDEO_SOURCE_GRALLOC_BUFFER模式下才分配,是为了实际填充待编码数据的。


一,初始化
一个简单的recorder客户端的初始化过程如下:
LOGE("Starting setupMediasource...");
     sp<MediaRecorder> mr = new MediaRecorder();  //创建一个实例化对象
     mr->setVideoSource(VIDEO_SOURCE_GRALLOC_BUFFER);  //设定录制机的模式
     mr->setOutputFormat(OUTPUT_FORMAT_MPEG_4);    //   设置输出的文件格式为MPEG4
 //       mr->setOutputFormat(OUTPUT_FORMAT_MPEG2TS);   //         设置输出的文件格式为MPEG2TS
     mr->setVideoEncoder(VIDEO_ENCODER_H264);           // 设置输出的文件的编码格式为H264
     mr->setOutputFile(fd, 0, 0);                                      //   设置输出的文件所要写的fd
     mr->setVideoSize(mYuvTexWidth, mYuvTexHeight);       //   设置输出视频的尺寸
     mr->setVideoFrameRate(fps);                                       // 设置输出视频的帧率
     mr->prepare();                                        //             开始准备
     mr->start();                                              //               正式开始录制
     LOGE("Starting MediaRecorder..."); 


 sp<MediaRecorder> mr = new MediaRecorder();--->IMediaPlayerService.createMediaRecorder(getpid())(通过binder通知MediaPlayerService创建一个实例对象)--->MediaPlayerService::createMediaRecorder()---->new MediaRecorderClient(this, pid);--->mRecorder = new StagefrightRecorder;到这里也就是创建一个StagefrightRecorder对象,供mr操控,同时进行了一系列的初始化;

mr中间的一系列操作只是设置一些标志位,mr->start(); ---->MediaRecorder::start()---->IMediaRecorder. start()--->MediaRecorderClient::start()----->StagefrightRecorder::start()---->startMPEG4Recording()(前面设置的输出格式是OUTPUT_FORMAT_MPEG_4)------>setupMPEG4Recording()--->
     1,setupMPEG4Recording()--->writer = new MPEG4Writer(outputFd)+setupMediaSource()---->setupSurfaceMediaSource()(当前面选择VIDEO_SOURCE_CAMERA时,setupCameraSource())---->new SurfaceMediaSource()--->mGraphicBufferAlloc = composer->createGraphicBufferAlloc()(创建一个alloc对象,用于后面申请memory空间)
     2,mWriter->start()---->MPEG4Writer::start()---->startWriterThread();

二,填充数据

sp<SurfaceTextureClient> mSTC;
sp<ANativeWindow> mANW;
sp<ISurfaceTexture> iST = mr->querySurfaceMediaSourceFromMediaServer();
mSTC = new SurfaceTextureClient(iST);
mANW = mSTC;

ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), HAL_PIXEL_FORMAT_YV12));

     int32_t nFramesCount = 0;
     while (nFramesCount <= 30)
     {
          ANativeWindowBuffer* anb;
         
          ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
          ASSERT_TRUE(anb != NULL)

          sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
         ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));

          // Fill the buffer with the a checkerboard pattern
          uint8_t* img = NULL;
          buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
          if (img)
               fillYV12Buffer(img, mYuvTexWidth, mYuvTexHeight, buf->getStride());
          else
               LOGE("buf->lock FAILED...");
        
          buf->unlock();

          //ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
         
          usleep(33*1000);
          nFramesCount++;

     }

    ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU));
     LOGE("Stopping MediaRecorder...");
     if (mr->stop()!=OK)
     {
          LOGE("mr->stop()...");
          return;
     }


native_window_api_connect() 和native_window_api_disconnect()是一对,现版本的代码是不做任何处理;
native_window_set_buffers_format()是对将要申请的buffer的数据类型标志进行设定,这里设定为HAL_PIXEL_FORMAT_YV12,还可以设置RGBA_8888等类型;

mANW->dequeueBuffer()--->ANativeWindow::dequeueBuffer()--->SurfaceTextureClient::hook_dequeueBuffer()--->SurfaceTextureClient::dequeueBuffer()---->mSurfaceTexture.dequeueBuffer()----->ISurfaceTexture::dequeueBuffer()----->SurfaceTexture::dequeueBuffer()---->(当已存在申请的buffer,返回buffer序号)mGraphicBufferAlloc->createGraphicBuffer()(在初始化SurfaceTexture对象时,mGraphicBufferAlloc=ISurfaceComposer::createGraphicBufferAlloc())---->IGraphicBufferAlloc::createGraphicBuffer()---->(Bn对象是在surfaceFlinger::createGraphicBufferAlloc()创建的)GraphicBufferAlloc::createGraphicBuffer()---->new GraphicBuffer()--->initSize()---->(surfaceFlinger中的都用同一个GraphicBufferAllocator实例)GraphicBufferAllocator::alloc()--->mAllocDev::alloc()(这里用到HAL层的gralloc.so库了)

中间的几个过程就是锁定buffer,提取出实际的 buffer指针,然后往地址中填数据;
mANW->queueBuffer()----> ANativeWindow::()--->SurfaceTextureClient::hook_queueBuffer()--->SurfaceTextureClient::queueBuffer()---->mSurfaceTexture.queueBuffer()----->ISurfaceTexture::queueBuffer()----->SurfaceTexture::queueBuffer()将相应的slot状态修改,并通过listener通知相应的处理模块;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值