【六】Android MediaPlayer整体架构源码分析 -【start请求播放处理流程】【Part 5】【01】

承接上一章节分析:【六】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(&params);
            params.bEnable = OMX_TRUE;

            err = mOMXNode->setParameter(index, &params, 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 (!

你可能感兴趣的:(MediaPlayer,configureCodec,ACodec,setPortMode,MediaCodec)