本例中media source為camera。(學習的平臺是android sdk6.0)
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、小程序制作、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了清水河免費建站歡迎大家使用!
調(diào)用關(guān)系圖:
startRecording:
recorder = New MediaRecorder(String16());
classMediaRecorder : public BnMediaRecorderClient,
public virtualIMediaDeathNotifier
在創(chuàng)建mediaRecorder的時侯,我們先獲取IMediaPlayerService指針,然后再創(chuàng)建IMediaRecorder
(關(guān)于的聲明sp
mMediaRecorder =service->createMediaRecorder(opPackageName);
在service->createMediaRecorder中會先把對象IMediaPlayerService序列話(利用data打包),然后把請求CREATE_MEDIA_RECORDER發(fā)送給remote(就是bpbinder)處理
remote()->transact(CREATE_MEDIA_RECORDER, data,&reply);
最后根據(jù)遠端的reply來創(chuàng)建本地對應(yīng)的對象
interface_cast
后續(xù)的方法都通過BpMediaRecorder(remote)來發(fā)送到BnMediaRecorder操作。
a) BnMediaRecorder繼承了BnInterface
classBnMediaRecorder: publicBnInterface
{
public:
virtual status_t onTransact( uint32_t code,
constParcel& data,
Parcel*reply,
uint32_tflags = 0);
};
在這個方法里,每個操作都有對應(yīng)的處理分支
c) BnMediaRecorder是個虛函數(shù),具體工作由MediaRecorderClient來完成:MediaRecorderClient : public BnMediaRecorder
class BpMediaRecorder: public BpInterface
在對應(yīng)的方法中最后都通過remote送給Bn處理,如:
Parceldata, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeString8(params);
remote()->transact(SET_PARAMETERS,data, &reply);
recorder->setParameters(…….)
recorder->prepare()
recorder->start()
3. 在MediaRecorderClient中封裝了MediaRecorderBase這個類,每一項任務(wù)都要它來完成
在MediaRecorderClient的構(gòu)造函數(shù)中可以看到
mRecorder = AVMediaServiceFactory::get()->createStagefrightRecorder(opPackageName);
因此,具體的工作由StagefrightRecorder來完成
在AVMediaServiceFactory.cpp中
StagefrightRecorder*AVMediaServiceFactory::createStagefrightRecorder(
const String16 &opPackageName) {
return newStagefrightRecorder(opPackageName);
}
StagefrightRecorder recorder->start()
在prepare中或者start中調(diào)用StagefrightRecorder::prepareInternal()
在這里根據(jù)輸出編碼設(shè)定,選擇對應(yīng)的編碼器進行初始化。
我們以O(shè)UTPUT_FORMAT_MPEG_4為例進行分析
根據(jù)輸出格式進入setupMPEG4orWEBMRecording()
setupMPEG4orWEBMRecording()
在這里創(chuàng)建了MPEG4Writer
writer = mp4writer =AVFactory::get()->CreateMPEG4Writer(mOutputFd);
setupMediaSource將camera指定為encoder的input source
sp
err = setupVideoEncoder(mediaSource, &encoder);創(chuàng)建encoder
setupVideoEncoder(mediaSource,&encoder);
首先將camera中的各項參數(shù)設(shè)定讀出來設(shè)入到encoder中(camera為null則使用default值)
sp
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參數(shù)設(shè)置函數(shù),android中默認沒有實現(xiàn),是空函數(shù)
接著創(chuàng)建encoder。
sp
mLooper, format, cameraSource,mPersistentSurface, flags);
sp
=MediaCodecSource::Create(
mLooper,
format,
cameraSource,
mPersistentSurface,
;
在create函數(shù)中先new一個對象,
sp
new MediaCodecSource(looper, format, source, consumer, flags);
if (mediaSource->init() == OK) {
return mediaSource;
}
MediaCodecSource::init()
status_t err = initEncoder();
initEncoder(){
mReflector = new AHandlerReflector
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();
}
MediaCodec::CreateByType(
mCodecLooper, outputMIME.c_str(), true /* encoder */) {
sp
const status_tret = codec->init(mime, true /* nameIsType */, encoder);
}
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
msg->setString("name", name);
msg->setInt32("nameIsType",nameIsType);
if (nameIsType) {
msg->setInt32("encoder",encoder);
}
status_t err;
Vector
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
err = PostAndAwaitResponse(msg,&response);
if (!isResourceError(err)) {
break;
}
}
}