MediaCodec对接到OMX的简单分析

article/2025/10/6 17:49:30

一、引言:

nuplayer播放器是使用MediaCodec来进行编解码的,而OMX组件则是MediaCodec的解码核心,但是因为涉及的面太过底层,往往是芯片公司才会涉及到这一块,所以就做一个简单分析,对通路有个大致了解就行。

二、流程跟踪:

从MediaCodec的api来分析下流程:

1.构造函数:

MediaCodec::CreateByType()和MediaCodec::CreateByComponentName()只是对外初始化MediaCodec的不同接口,前者是以接收mimetype来进行初始化,后者则是通过确定的codec名字来实例化,在构造了MediaCodec之后最终都会调入到MediaCodec::init中;

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

2.MediaCodec::init分析:

status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {.../* 1.实例化ACodec */mCodec = new ACodec;.../* 2.注册hanlder用于消息处理 */mLooper->registerHandler(this);mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));/* 3.处理kWhatInit消息 */sp<AMessage> msg = new AMessage(kWhatInit, id());msg->setString("name", name);msg->setInt32("nameIsType", nameIsType);if (nameIsType) {msg->setInt32("encoder", encoder);}sp<AMessage> response;return PostAndAwaitResponse(msg, &response);
}

先来看下ACodec的实例化,ACodec可以理解为Android对于解码器的封装层,对下衔接OMX解码组件,对上回调必要信息到MediaCodec:

ACodec::ACodec(): mQuirks(0),mNode(0),mSentFormat(false),mIsEncoder(false),mUseMetadataOnEncoderOutput(false),mFatalError(false),mShutdownInProgress(false),mExplicitShutdown(false),mEncoderDelay(0),mEncoderPadding(0),mRotationDegrees(0),mChannelMaskPresent(false),mChannelMask(0),mDequeueCounter(0),mStoreMetaDataInOutputBuffers(false),mMetaDataBuffersToSubmit(0),mRepeatFrameDelayUs(-1ll),mMaxPtsGapUs(-1ll),mTimePerFrameUs(-1ll),mTimePerCaptureUs(-1ll),mCreateInputBuffersSuspended(false),mTunneled(false) {mFastOutput = false;mHisiVdp = false;mIsVideo = false;mSaveES = false;mVideoFile = NULL;mAudioFile = NULL;mStats = false;sEnableLogcatV = false;char value[PROPERTY_VALUE_MAX];if (property_get("service.media.codec.logcat", value, "false")&& (!strcasecmp("true", value))) {sEnableLogcatV = true;}if (property_get("service.media.codec.savees", value, "false")&& (!strcasecmp("true", value))) {ALOGI("Will save ES streams");mSaveES = true;}if (property_get("service.media.codec.stats", value, "false")&& (!strcasecmp("true", value))) {mStats = true;}mUninitializedState = new UninitializedState(this);mLoadedState = new LoadedState(this);mLoadedToIdleState = new LoadedToIdleState(this);mIdleToExecutingState = new IdleToExecutingState(this);mExecutingState = new ExecutingState(this);mOutputPortSettingsChangedState =new OutputPortSettingsChangedState(this);mExecutingToIdleState = new ExecutingToIdleState(this);mIdleToLoadedState = new IdleToLoadedState(this);mFlushingState = new FlushingState(this);mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;mInputEOSResult = OK;changeState(mUninitializedState);
}

ACodec构造最主要的操作是实例化了各种状态值,通过消息机制来对OMX进行操作。最后再来看下kWhatInit消息的处理:

        case kWhatInit:{uint32_t replyID;CHECK(msg->senderAwaitsResponse(&replyID));if (mState != UNINITIALIZED) {PostReplyWithError(replyID, INVALID_OPERATION);break;}mReplyID = replyID;setState(INITIALIZING);AString name;CHECK(msg->findString("name", &name));int32_t nameIsType;int32_t encoder = false;CHECK(msg->findInt32("nameIsType", &nameIsType));if (nameIsType) {CHECK(msg->findInt32("encoder", &encoder));}sp<AMessage> format = new AMessage;if (nameIsType) {format->setString("mime", name.c_str());format->setInt32("encoder", encoder);} else {format->setString("componentName", name.c_str());}/* 调用组件初始化 */mCodec->initiateAllocateComponent(format);break;}

这里的mCodec即ACodec,看一下OMX组件初始化:

void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {msg->setWhat(kWhatAllocateComponent);msg->setTarget(id());msg->post();
}

跟进消息:

case ACodec::kWhatAllocateComponent:
{onAllocateComponent(msg);handled = true;break;
}
bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {ALOGV("onAllocateComponent");CHECK(mCodec->mNode == NULL);/* 1.获取OMX的binder对象 */OMXClient client;CHECK_EQ(client.connect(), (status_t)OK);sp<IOMX> omx = client.interface();	.../* 2.找到底层支持的解码器 */OMXCodec::findMatchingCodecs(mime.c_str(),encoder, // createEncoderNULL,  // matchComponentName0,     // flags&matchingCodecs);.../* 3.申请omx组件 */status_t err = omx->allocateNode(componentName.c_str(), observer, &node);	.../* 4.回调通知MediaCodec */{sp<AMessage> notify = mCodec->mNotify->dup();notify->setInt32("what", CodecBase::kWhatComponentAllocated);notify->setString("componentName", mCodec->mComponentName.c_str());notify->post();}/* 切换ACodec的状态 */mCodec->changeState(mCodec->mLoadedState);	         
}

这里需要注意下,OMX的Bn端在OMX.CPP中,看一下allocateNode实现:

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

status_t OMX::allocateNode(const char *name, const sp<IOMXObserver> &observer, node_id *node) {Mutex::Autolock autoLock(mLock);*node = 0;/* 实例化instance */OMXNodeInstance *instance = new OMXNodeInstance(this, observer, name);OMX_COMPONENTTYPE *handle;/* 获取组件 */OMX_ERRORTYPE err = mMaster->makeComponentInstance(name, &OMXNodeInstance::kCallbacks,instance, &handle);if (err != OMX_ErrorNone) {ALOGE("FAILED to allocate omx component '%s'", name);instance->onGetHandleFailed();return UNKNOWN_ERROR;}*node = makeNodeID(instance);mDispatchers.add(*node, new CallbackDispatcher(instance));instance->setHandle(*node, handle);mLiveNodes.add(observer->asBinder(), instance);observer->asBinder()->linkToDeath(this);return OK;
}

这里有一个特别需要注意的点是,omx组件是可以由芯片厂商自行扩展的,所以,在OMXMaster中会决定是加载Android原生的软解码还是芯片厂商的硬解码,我所调试的环境为海思平台,故加载的为海思插件。

3.configure分析:

status_t MediaCodec::configure(const sp<AMessage> &format,const sp<Surface> &nativeWindow,const sp<ICrypto> &crypto,uint32_t flags) {sp<AMessage> msg = new AMessage(kWhatConfigure, id());msg->setMessage("format", format);msg->setInt32("flags", flags);...sp<AMessage> response;status_t err = PostAndAwaitResponse(msg, &response);...
}

看下kWhatConfigure消息处理:

        case kWhatConfigure:{...mCodec->initiateConfigureComponent(format);break;}

再看下MediaCodec中initiateConfigureComponent函数的消息:

void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {msg->setWhat(kWhatConfigureComponent);msg->setTarget(id());msg->post();
}
case ACodec::kWhatConfigureComponent:
{onConfigureComponent(msg);handled = true;break;
}

onConfigureComponent函数非常长,主要是为了给omx组件设置参数,这里就不去具体分析了。

4.start函数分析:

status_t MediaCodec::start() {sp<AMessage> msg = new AMessage(kWhatStart, id());sp<AMessage> response;return PostAndAwaitResponse(msg, &response);
}
        case kWhatStart:{uint32_t replyID;CHECK(msg->senderAwaitsResponse(&replyID));if (mState == FLUSHED) {setState(STARTED);mCodec->signalResume();PostReplyWithError(replyID, OK);break;} else if (mState != CONFIGURED) {PostReplyWithError(replyID, INVALID_OPERATION);break;}mReplyID = replyID;setState(STARTING);mCodec->initiateStart();break;}

和之前的逻辑一样,MediaCodec对start的逻辑也是先更新自己维护的状态,然后再调用到ACodec中:

void ACodec::initiateStart() {(new AMessage(kWhatStart, id()))->post();
}
        case ACodec::kWhatStart:{onStart();handled = true;break;}
void ACodec::LoadedState::onStart() {ALOGV("onStart");CHECK_EQ(mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),(status_t)OK);mCodec->changeState(mCodec->mLoadedToIdleState);
}

这里就会调用到下层OMX组件中,由组件来执行响应的操作了。MediaCodec对到OMX组件的流程比较绕,Android在这里弄的比较复杂,对于不是芯片厂商的开发人员而言会比较难理解一些,在这里对这些流程也只是一个简单跟踪,里面还有很多内容没有详细扩展,需要根据工作中的具体情况去做分析了。

 如果你对音视频开发感兴趣,觉得文章对您有帮助,别忘了点赞、收藏哦!或者对本文的一些阐述有自己的看法,有任何问题,欢迎在下方评论区讨论!

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓


http://chatgpt.dhexx.cn/article/F3gCCXDb.shtml

相关文章

MediaCodec(native)状态机分析

一、引入&#xff1a; MediaCodec这条通路的调用逻辑是MediaCode->ACodec->OMX&#xff0c;因为OMX有自己的状态机&#xff0c;所以MediaCodec和ACodec也分别基于OMX组件的调用维护了其状态机&#xff0c;这篇博客就先分析MediaCodec的状态机是如何运转的。 二、MediaCo…

视频-MediaCodec

1.解析视频可以使用android 提供的api MediaPlayer,实现简单的播放暂停&#xff0c;提取视频中的一帧或者编辑视频&#xff0c;需要另一个api MediaCodec&#xff08;硬解&#xff0c;控制DSP芯片&#xff09;或者 ffmpeg(软解&#xff0c;耗时)&#xff0c;选择的优先级一定要…

MediaCodec解析MP4视频

MediaCodec讲解 MediaCodec是Android提供的用于对音视频进行编解码的类&#xff0c;它通过访问底层的codec来实现编解码的功能。是Android media基础框架的一部分&#xff0c;通常和 MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface和AudioTra…

Android视频编解码之MediaCodec简单入门

本篇只是简单入门&#xff0c;后面会继续写文章详细讲解&#xff1a; 由于MediaCodec涉及内容众多&#xff0c;原本想一篇文章把所有内容概括&#xff0c;但是后来发现不太可能&#xff0c;限于自己能力&#xff0c;想要考虑全面太难&#xff0c;我也是刚开始学习需要借助网上…

Android:MediaCodec基本原理

最近需要使用MediaCodec做一些工作&#xff0c;因此对MediaCodec做了些研究和代码编写&#xff0c;在此先对MediaCodec的一些基础原理、工作流程、常用API等做个初步总结&#xff0c;方便后续开发过程中查阅。 1.MediaCodec简介 1.1 MediaCodec来历 Android从最初的API 1.0版…

MediaCodec原理及使用

使用MediaCodec目的 MediaCodec是Android底层多媒体框架的一部分&#xff0c;通常与MediaExtractor、MediaMuxer、AudioTrack结合使用&#xff0c;可以编码H264、H265、AAC、3gp等常见的音视频格式 MediaCodec工作原理是处理输入数据以产生输出数据 MediaCodec工作流程 Medi…

Android MediaCodec

Android中可以使用MediaCodec来访问底层的媒体编解码器&#xff0c;可以对媒体进行编/解码。 MediaCodec可以处理的数据有以下三种类型&#xff1a;压缩数据、原始音频数据、原始视频数据。这三种类型的数据均可以利用ByteBuffers进行处理&#xff0c;但是对于原始视频数据应提…

android P MediaCodec编解码流程分析

1.MediaCodec初始化流程分析 通过上面流程分析可知&#xff0c;MediaCodecList初始化是通过调用它的getLocalInstance函数&#xff0c;然后在里面new的MediaCodecList对象。在MediaCodec的CreateByType函数中new了MediaCodec对象。 allocateNode调用流程是在ACodec.cpp中的onA…

MediaCodec_Analyze-3-start

MediaCodec Analyse – start Refrence: https://source.android.google.cn/devices/media 一 APK调用的核心API Android APK使用 MediaCodec API 播放音视频的简易流程&#xff1a; MediaCodec codec MediaCodec.createDecoderByType("video/avc"); MediaFormat …

mediacodec api

mediacodec api 官网&#xff1a; https://developer.android.com/reference/android/media/MediaCodec 中文&#xff1a; https://www.apiref.com/android-zh/android/media/MediaCodec.html 学习mediacodec api的使用说明&#xff0c;在android源码查看&#xff1a; andro…

MediaCodec硬解流程

一 MediaCodec概述 MediaCodec 是Android 4.1(api 16)版本引入的低层编解码接口&#xff0c;同时支持音视频的编码和解码。通常与MediaExtractor、MediaMuxer、AudioTrack结合使用&#xff0c;能够编解码诸如H.264、H.265、AAC、3gp等常见的音视频格式。MediaCodec在编解码的过…

MediaCodec_Analyze-1-create

MediaCodec Analyse – create Refrence: https://source.android.google.cn/devices/media 一 APK调用的核心API Android APK使用 MediaCodec API 播放音视频的简易流程&#xff1a; MediaCodec codec MediaCodec.createDecoderByType("video/avc"); MediaFormat…

mediacodec

MedaiCodec简介 MediaCodec是Android中提供的音视频编/解码工具。它主要是完成上层接口的封装&#xff0c;供给开发者使用&#xff0c;编解码功能实际是在native底层服务中完成的 MediaCodec工作流程 包括两个缓冲区队列 一个输入缓冲区队列&#xff0c;包含一组输入缓冲区(格…

Android MediaCodec 完全解析

MediaCodec是什么&#xff1f; MediaCodec类为开发者提供了能访问到Android底层媒体Codec&#xff08;Encoder/Decoder&#xff09;的能力&#xff0c;它是Android底层多媒体基础架构的一部分&#xff08;通常和MediaExtractor、MediaSync、MediaMuxer、MediaCrypto、MediaDrm…

Android MediaCodec解析

Android MediaCodec解析 1 引言 MediaCodec是Android平台提供的一个底层的音视频编解码框架&#xff0c;它是安卓底层多媒体基础框架的重要组成部分。它经常和 MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface, AudioTrack一起使用。解码的作…

Android原生编解码接口MediaCodec详解

作者&#xff1a;躬行之 了解了音视频的相关知识&#xff0c;可以先阅读同系列文章&#xff1a; 音视频开发基础知识音频帧、视频帧及其同步Camera2、MediaCodec录制mp4 MediaCodec 是 Android 中的编解码器组件&#xff0c;用来访问底层提供的编解码器&#xff0c;通常与 Me…

MediaCodec视频解码流程详解及参考demo

一、MediaCodec简介 MediaCodec是Android自带的底层多媒体支持架构的一部分&#xff08;通常与 MediaExtractor&#xff0c;MediaSync&#xff0c;MediaMuxer&#xff0c;MediaCrypto&#xff0c;MediaDrm&#xff0c;Image&#xff0c;Surface 和 AudioTrack 一起使用&#xf…

Android MediaCodec简单总结

#.MedaiCodec简介 MediaCodec是Android中提供的音视频编码、解码工具。它主要是完成上层接口的封装&#xff0c;提供给开发者使用&#xff0c;编解码功能实际是在native底层服务中完成的。 #.MediaCodec工作的宏观流程&#xff1a; ##.包换两个缓冲区队列 一个输入缓冲区队列&a…

软件测试面试指导之自我介绍

面试自我介绍虽然人人都准备&#xff0c;但是做到让人印象深刻可不容易啊。 本篇就具体来聊聊人人都要经历的面试&#xff0c;怎么做自我介绍&#xff0c;才能让你在面试官的眼睛里像金子一样闪闪发光&#xff1f; 面试是什么&#xff1f; 它是个机会&#xff0c;让面试官更…

软件测试面试要注意的细节以及处理(自我介绍篇)

面试问题第一问&#xff0c;95%都会是&#xff1a; 请简单的做个自我介绍吧~ 分以下几点说明。 一、个人的基本信息&#xff0c;扬长避短 1、年纪太大与太小&#xff0c;都不需要主动去说明。 比如我年纪只有21岁 例子&#xff1a;面试官您好&#xff0c;我叫***&#xff…