利用 android mediaRecorder c++类进行视频编码

青春须早为,岂能长少年。这篇文章主要讲述利用 android mediaRecorder c++类进行视频编码相关的知识,希望能为你提供帮助。
本例中media source为camera。(学习的平台是android sdk6.0)
调用关系图:


startRecording:

  1. recorder = New MediaRecorder(String16());
classMediaRecorder : public BnMediaRecorderClient,
                                          public virtualIMediaDeathNotifier
  1. 在创建mediaRecorder的时侯,我们先获取IMediaPlayerService指针,然后再创建IMediaRecorder
(关于的声明sp< IMediaRecorder>                   mMediaRecorder; )
              mMediaRecorder =service-> createMediaRecorder(opPackageName);
 
  1. 在service-> createMediaRecorder中会先把对象IMediaPlayerService序列话(利用data打包),然后把请求CREATE_MEDIA_RECORDER发送给remote(就是bpbinder)处理
remote()-> transact(CREATE_MEDIA_RECORDER, data,& reply);
  1. 最后根据远端的reply来创建本地对应的对象
interface_cast< IMediaRecorder> (reply.readStrongBinder());
  1. 后续的方法都通过BpMediaRecorder(remote)来发送到BnMediaRecorder操作。
  2. a)            BnMediaRecorder继承了BnInterface< IMediaRecorder> ,并实现了ontransact
classBnMediaRecorder: publicBnInterface< IMediaRecorder>
{
public:
      virtual status_t      onTransact( uint32_t code,
                                                                      constParcel& data,
                                                                      Parcel*reply,
                                                                      uint32_tflags = 0);
};
  1. 在这个方法里,每个操作都有对应的处理分支
  2. c)              BnMediaRecorder是个虚函数,具体工作由MediaRecorderClient 来完成:MediaRecorderClient : public BnMediaRecorder
  3. class BpMediaRecorder: public BpInterface< IMediaRecorder>
在对应的方法中最后都通过remote送给Bn处理,如:
Parceldata, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeString8(params);
      remote()-> transact(SET_PARAMETERS,data, & reply);
  1. recorder-> setParameters(…….)
  2. recorder-> prepare()
  3. recorder-> start()
  4. 3.          在MediaRecorderClient中封装了MediaRecorderBase这个类,每一项任务都要它来完成
在MediaRecorderClient的构造函数中可以看到
      mRecorder = AVMediaServiceFactory::get()-> createStagefrightRecorder(opPackageName);
  1. 因此,具体的工作由StagefrightRecorder来完成
  2. 在AVMediaServiceFactory.cpp中
StagefrightRecorder*AVMediaServiceFactory::createStagefrightRecorder(
              const String16 & opPackageName) {
      return newStagefrightRecorder(opPackageName);
}
  1. StagefrightRecorder   recorder-> start()
在prepare中或者start中调用StagefrightRecorder::prepareInternal()
在这里根据输出编码设定,选择对应的编码器进行初始化。
我们以OUTPUT_FORMAT_MPEG_4为例进行分析
根据输出格式进入setupMPEG4orWEBMRecording()
  1. setupMPEG4orWEBMRecording()
在这里创建了MPEG4Writer
  1. writer = mp4writer =AVFactory::get()-> CreateMPEG4Writer(mOutputFd);
  2. setupMediaSource将camera指定为encoder的input source
  3. sp< MediaSource> encoder;
err = setupVideoEncoder(mediaSource, & encoder); 创建encoder
  1. setupVideoEncoder(mediaSource,& encoder);
首先将camera中的各项参数设定读出来设入到encoder中(camera为null则使用default值)
sp< MetaData> meta = cameraSource-> getFormat();
 
              int32_t width, height, stride,sliceHeight, colorFormat;
              CHECK(meta-> findInt32(kKeyWidth,& width));
              CHECK(meta-> findInt32(kKeyHeight,& height));
              CHECK(meta-> findInt32(kKeyStride,& stride));
              CHECK(meta-> findInt32(kKeySliceHeight, & sliceHeight));
              CHECK(meta-> findInt32(kKeyColorFormat, & colorFormat));
 
              format-> setInt32("width",width);
              format-> setInt32("height",height);
              format-> setInt32("stride",stride);
              format-> setInt32("slice-height", sliceHeight);
              format-> setInt32("color-format", colorFormat);
这里预留了custom参数设置函数,android中默认没有实现,是空函数
接着创建encoder。
      sp< MediaCodecSource> encoder =MediaCodecSource::Create(
                      mLooper, format, cameraSource,mPersistentSurface, flags);
  1.         sp< MediaCodecSource> encoder
=MediaCodecSource::Create(                        
mLooper,
  format,
cameraSource,
  mPersistentSurface,
  1. ;
在create函数中先new一个对象,
      sp< MediaCodecSource> mediaSource =
                      new MediaCodecSource(looper, format, source, consumer, flags);
 
      if (mediaSource-> init() == OK) {
              return mediaSource;
      }
  1. MediaCodecSource::init()
status_t err = initEncoder();
  1. initEncoder(){
mReflector = new AHandlerReflector< MediaCodecSource> (this);
mLooper-> registerHandler(mReflector);
 
      mCodecLooper = new ALooper;
      mCodecLooper-> setName("codec_looper");
mCodecLooper-> start();
……………..
              mEncoder =MediaCodec::CreateByType(
                      mCodecLooper,outputMIME.c_str(), true /* encoder */);
….
      mEncoderActivityNotify =new AMessage(kWhatEncoderActivity, mReflector);
      mEncoder-> setCallback(mEncoderActivityNotify);
 
      status_t err =mEncoder-> configure(
                              mOutputFormat,
                              NULL /*nativeWindow */,
                              NULL /* crypto*/,
                              MediaCodec::CONFIGURE_FLAG_ENCODE);
…………………………
 
      err = mEncoder-> start();

  1.     MediaCodec::CreateByType(
mCodecLooper, outputMIME.c_str(), true /* encoder */) {
                      sp< MediaCodec> codec = new MediaCodec(looper, pid);
 
      const status_tret = codec-> init(mime, true /* nameIsType */, encoder);
}
 
  1. MediaCodec::init (const AString& name, bool nameIsType, bool encoder) {
………..
/// name 包含video, nameIsType is true
因此
              mCodec =AVFactory::get()-> createACodec();
…………..
              mIsVideo =true;
…………..
              mCodecLooper-> registerHandler(mCodec);
      mCodec-> setNotificationMessage(newAMessage(kWhatCodecNotify, this));
 
      sp< AMessage> msg = newAMessage(kWhatInit, this);
      msg-> setString("name", name);
      msg-> setInt32("nameIsType",nameIsType);
 
      if (nameIsType) {
              msg-> setInt32("encoder",encoder);
      }
 
      status_t err;
Vector< MediaResource> resources;
      const char *type = secureCodec ?kResourceSecureCodec : kResourceNonSecureCodec;
      const char *subtype = mIsVideo ?kResourceVideoCodec : kResourceAudioCodec;
      resources.push_back(MediaResource(String8(type), String8(subtype), 1));
      for (int i = 0; i < = kMaxRetry; ++i) {
              if (i > 0) {
                      // Don‘t try to reclaim resourcefor the first time.
                      if(!mResourceManagerService-> reclaimResource(resources)) {
                              break;
                      }
              }
 
              sp< AMessage> response;
              err = PostAndAwaitResponse(msg,& response);
              if (!isResourceError(err)) {
                      break;
              }
      }
}


【利用 android mediaRecorder c++类进行视频编码】本文出自 “龙骑舞” 博客,请务必保留此出处http://westfisher.blog.51cto.com/3396434/1945121

    推荐阅读