十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
本例中media source为camera。(学习的平台是android sdk6.0)
网站建设哪家好,找创新互联公司!专注于网页设计、网站建设、微信开发、小程序制作、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了清水河免费建站欢迎大家使用!
调用关系图:
startRecording:
recorder = New MediaRecorder(String16());
classMediaRecorder : public BnMediaRecorderClient,
public virtualIMediaDeathNotifier
在创建mediaRecorder的时侯,我们先获取IMediaPlayerService指针,然后再创建IMediaRecorder
(关于的声明sp
mMediaRecorder =service->createMediaRecorder(opPackageName);
在service->createMediaRecorder中会先把对象IMediaPlayerService序列话(利用data打包),然后把请求CREATE_MEDIA_RECORDER发送给remote(就是bpbinder)处理
remote()->transact(CREATE_MEDIA_RECORDER, data,&reply);
最后根据远端的reply来创建本地对应的对象
interface_cast
后续的方法都通过BpMediaRecorder(remote)来发送到BnMediaRecorder操作。
a) BnMediaRecorder继承了BnInterface
classBnMediaRecorder: publicBnInterface
{
public:
virtual status_t onTransact( uint32_t code,
constParcel& data,
Parcel*reply,
uint32_tflags = 0);
};
在这个方法里,每个操作都有对应的处理分支
c) BnMediaRecorder是个虚函数,具体工作由MediaRecorderClient来完成:MediaRecorderClient : public BnMediaRecorder
class BpMediaRecorder: public BpInterface
在对应的方法中最后都通过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这个类,每一项任务都要它来完成
在MediaRecorderClient的构造函数中可以看到
mRecorder = AVMediaServiceFactory::get()->createStagefrightRecorder(opPackageName);
因此,具体的工作由StagefrightRecorder来完成
在AVMediaServiceFactory.cpp中
StagefrightRecorder*AVMediaServiceFactory::createStagefrightRecorder(
const String16 &opPackageName) {
return newStagefrightRecorder(opPackageName);
}
StagefrightRecorder recorder->start()
在prepare中或者start中调用StagefrightRecorder::prepareInternal()
在这里根据输出编码设定,选择对应的编码器进行初始化。
我们以OUTPUT_FORMAT_MPEG_4为例进行分析
根据输出格式进入setupMPEG4orWEBMRecording()
setupMPEG4orWEBMRecording()
在这里创建了MPEG4Writer
writer = mp4writer =AVFactory::get()->CreateMPEG4Writer(mOutputFd);
setupMediaSource将camera指定为encoder的input source
sp
err = setupVideoEncoder(mediaSource, &encoder);创建encoder
setupVideoEncoder(mediaSource,&encoder);
首先将camera中的各项参数设定读出来设入到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参数设置函数,android中默认没有实现,是空函数
接着创建encoder。
sp
mLooper, format, cameraSource,mPersistentSurface, flags);
sp
=MediaCodecSource::Create(
mLooper,
format,
cameraSource,
mPersistentSurface,
;
在create函数中先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;
}
}
}