MediaCodec是Android Video Framework中一个很重要的类,可以被NuPlayer直接使用
也可以被MediaCodec.java通过JNI的方式直接调用,可以赋予app很高的自由性,
是多媒体开发中的一个很重要的类
1、创建MediaCodec
创建MediaCodec有两种方式,一种是 CreateByType, 根据应用或NuPlayer传递下来的MIME来创建;
另一种是 CreateByComponentName,根据传递下来的ComponentName来创建。
具体方法如下:
CreateByType:
sp<MediaCodec> MediaCodec::CreateByType(
const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid,
uid_t uid) {
VTRACE_CALL();
sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
if (err != NULL) {
*err = ret;
}
return ret == OK ? codec : NULL; // NULL deallocates codec.
}
CreateByComponentName:
// static
sp<MediaCodec> MediaCodec::CreateByComponentName(
const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid, uid_t uid) {
VTRACE_CALL();
sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
if (err != NULL) {
*err = ret;
}
return ret == OK ? codec : NULL; // NULL deallocates codec.
}
这两个方法较简单,
1、 调用 MediaCodec 构造函数
2、调用 init 函数
构造函数很简单,没有什么逻辑,我们分析一下 init 函数
MediaCodec::init 函数中逻辑较多
主要分为以下几步:
1、 创建ACodec
2、 与 ACodec, ACodecBufferChannel等类建立消息关联机制
3、发送 kWhatInit 消息,并等待返回
1.1 创建ACodec
status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
VTRACE_METHOD();
mResourceManagerService->init();
// save init parameters for reset
mInitName = name;
mInitNameIsType = nameIsType;
mInitIsEncoder = encoder;
// Current video decoders do not return from OMX_FillThisBuffer
// quickly, violating the OpenMAX specs, until that is remedied
// we need to invest in an extra looper to free the main event
// queue.
mCodec = GetCodecBase(name, nameIsType); //创建ACodec
if (mCodec == NULL) {
return NAME_NOT_FOUND;
}
……
详解查看 GetCodecBase 函数:
sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, bool nameIsType) {
// at this time only ACodec specifies a mime type.
if (nameIsType || name.startsWithIgnoreCase("omx.")) {
return new ACodec;
} else if (name.startsWithIgnoreCase("android.filter.")) {
return new MediaFilter;
} else {
return NULL;
}
}
我们使用MediaCodec主要是创建编解码的Codec,
目前很少用到滤波器 filter,故我们着重分析MediaCodec -> ACodec及ACodec向下的流程,不分析 MediaFilter的流程。
查看ACodec 构造函数
ACodec::ACodec()
: mSampleRate(0),
mNodeGeneration(0),
mUsingNativeWindow(false),
mNativeWindowUsageBits(0),
mLastNativeWindowDataSpace(HAL_DATASPACE_UNKNOWN),
mIsVideo(false),
mIsEncoder(false),
mFatalError(false),
mShutdownInProgress(false),
mExplicitShutdown(false),