承接上一章节分析:【六】Android MediaPlayer整体架构源码分析 -【start请求播放处理流程】【Part 4】
本系列文章分析的安卓源码版本:【Android 10.0 版本】
【此章节小节编号将重新排序】
mCodec->configureCodec(mime.c_str(), msg)实现分析:
ACodec配置编解码器。【备注:该章节分析的该配置处理流程非常长】
// [frameworks/av/media/libstagefright/ACodec.cpp]
status_t ACodec::configureCodec(
const char *mime, const sp<AMessage> &msg) {
// 获取是否为编码器,默认为false即0
int32_t encoder;
if (!msg->findInt32("encoder", &encoder)) {
encoder = false;
}
// 创建出入输出格式信息
sp<AMessage> inputFormat = new AMessage;
sp<AMessage> outputFormat = new AMessage;
// 缓存传入参数信息即输入格式配置信息
mConfigFormat = msg;
mIsEncoder = encoder;
// 是否为视频编解码器
mIsVideo = !strncasecmp(mime, "video/", 6);
// 是否为图片编解码器
mIsImage = !strncasecmp(mime, "image/", 6);
// 预设输入输出buffer端口模式为字节buffer
// 备注:此前已初始化相同模式几次了
mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
// 设置组件角色信息
// 见第1小节分析
status_t err = setComponentRole(encoder /* isEncoder */, mime);
// 编解码器角色信息必须不能出错
if (err != OK) {
return err;
}
// 码率控制类型(模式)枚举:如可变码率、恒定码率、恒定质量码率等码率模式
OMX_VIDEO_CONTROLRATETYPE bitrateMode;
int32_t bitrate = 0, quality;
// 注释:FLAC和video编码器在恒定质量码率模式下不需要一个码率,其他编码器则需要
// FLAC encoder or video encoder in constant quality mode doesn't need a
// bitrate, other encoders do.
if (encoder) {
// 编码器时
if (mIsVideo || mIsImage) {
// 视频或图片编码器时,查找视频码率控制信息,默认为可变码率模式
// 见第2小节分析
if (!findVideoBitrateControlInfo(msg, &bitrateMode, &bitrate, &quality)) {
return INVALID_OPERATION;
}
} else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
&& !msg->findInt32("bitrate", &bitrate)) {
// 若是flac音频则取码率,失败则进入此处
return INVALID_OPERATION;
}
}
// 根据注释可知:获取原输入格式码率信息,设置给输出格式对象(使其可以数据合成即复用处理流程),并且还有ISO国际标准的阐述
// propagate bitrate to the output so that the muxer has it
if (encoder && msg->findInt32("bitrate", &bitrate)) {
// Technically ISO spec says that 'bitrate' should be 0 for VBR even though it is the
// average bitrate. We've been setting both bitrate and max-bitrate to this same value.
outputFormat->setInt32("bitrate", bitrate);
outputFormat->setInt32("max-bitrate", bitrate);
}
// 存储元
int32_t storeMeta;
if (encoder) {
// 编码器时
IOMX::PortMode mode = IOMX::kPortModePresetByteBuffer;
// 获取输入媒体元数据buffer类型(枚举)
// 备注:其实该枚举类型数据的作用简单的说就是用来定义,在编码时使用的媒体元buffer数据类型(比如ANativeWindowBuffer),
// 将会被传递给编码器进行编码使用,并且也是定义当前媒体元数据的数据源的生产者,比如来自Camera组件。
// 【其实也就是说编码器在这些类型时处理完buffer后不能直接释放它的内存,应该返回给每个生产者提供方(组件),提供方才能释放它】
if (msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
&& storeMeta != kMetadataBufferTypeInvalid) {
// 有效时进入
if (storeMeta == kMetadataBufferTypeNativeHandleSource) {
mode = IOMX::kPortModeDynamicNativeHandle;
} else if (storeMeta == kMetadataBufferTypeANWBuffer ||
storeMeta == kMetadataBufferTypeGrallocSource) {
mode = IOMX::kPortModeDynamicANWBuffer;
} else {
return BAD_VALUE;
}
}
// 设置输入缓冲区buffer端口模式,也就是数据源buffer类型
// TODO:目前暂不单独分析编码器的处理,后续有时间再考虑。此处将会调用具体so编码器组件实现内部
err = setPortMode(kPortIndexInput, mode);
if (err != OK) {
return err;
}
if (mode != IOMX::kPortModePresetByteBuffer) {
uint32_t usageBits;
if (mOMXNode->getParameter(
(OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
&usageBits, sizeof(usageBits)) == OK) {
inputFormat->setInt32(
"using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
}
}
}
// TODO:下面涉及到编码器部分时目前都暂不单独分析编码器的处理,后续有时间再考虑。
// 预置SPS、PPS给IDR帧(即I帧)
int32_t prependSPSPPS = 0;
if (encoder && mIsVideo
&& msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
&& prependSPSPPS != 0) {
OMX_INDEXTYPE index;
err = mOMXNode->getExtensionIndex(
"OMX.google.android.index.prependSPSPPSToIDRFrames", &index);
if (err == OK) {
PrependSPSPPSToIDRFramesParams params;
InitOMXParams(¶ms);
params.bEnable = OMX_TRUE;
err = mOMXNode->setParameter(index, ¶ms, sizeof(params));
}
if (err != OK) {
ALOGE("Encoder could not be configured to emit SPS/PPS before "
"IDR frames. (err %d)", err);
return err;
}
}
// Only enable metadata mode on encoder output if encoder can prepend
// sps/pps to idr frames, since in metadata mode the bitstream is in an
// opaque handle, to which we don't have access.
if (encoder && mIsVideo) {
OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
&& msg->findInt32("android._store-metadata-in-buffers-output", &storeMeta)
&& storeMeta != 0);
if (mFlags & kFlagIsSecure) {
enable = OMX_TRUE;
}
err = setPortMode(kPortIndexOutput, enable ?
IOMX::kPortModePresetSecureBuffer : IOMX::kPortModePresetByteBuffer);
if (err != OK) {
return err;
}
if (!msg->findInt64(
KEY_REPEAT_PREVIOUS_FRAME_AFTER, &mRepeatFrameDelayUs)) {
mRepeatFrameDelayUs = -1LL;
}
if (!msg->findDouble("time-lapse-fps", &mCaptureFps)) {
float captureRate;
if (msg->findAsFloat(KEY_CAPTURE_RATE, &captureRate)) {
mCaptureFps = captureRate;
} else {
mCaptureFps = -1.0;
}
}
if (!msg->findInt32(
KEY_CREATE_INPUT_SURFACE_SUSPENDED,
(int32_t*)&mCreateInputBuffersSuspended)) {
mCreateInputBuffersSuspended = false;
}
}
if (encoder && (mIsVideo || mIsImage)) {
// only allow 32-bit value, since we pass it as U32 to OMX.
if (!msg->findInt64(KEY_MAX_PTS_GAP_TO_ENCODER, &mMaxPtsGapUs)) {
mMaxPtsGapUs = 0LL;
} else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < INT32_MIN) {
ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
mMaxPtsGapUs = 0LL;
}
if (!