Android Multimedia框架总结(二十二)MediaCodec中C++中创建到start过程及状态变换

时间:2019-05-13 19:14:23下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《Android Multimedia框架总结(二十二)MediaCodec中C++中创建到start过程及状态变换》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《Android Multimedia框架总结(二十二)MediaCodec中C++中创建到start过程及状态变换》。

第一篇:Android Multimedia框架总结(二十二)MediaCodec中C++中创建到start过程及状态变换

Android Multimedia框架总结(二十二)MediaCodec中C++中创建到start过程

及状态变换

从今天开始,将深入源码中看看其c++过程,看下Agenda如下:

mediacodec.h CreateByType initMediaCodec中BufferInfo内部类: configure过程 start BufferInfo在MediaCodec.h中对应是一个结构体

//create by 逆流的鱼yuiop on 2016/12/11 //blog地址:http://blog.csdn.net/hejjunlin struct BufferInfo {

uint32_t mBufferID;

sp mData;

sp mEncryptedData;

sp mSharedEncryptedBuffer;

sp mNotify;

sp mFormat;

bool mOwnedByClient;};mediacodec.h的方法的声明,位于frameworksavincludemediastagefright下

//create by 逆流的鱼yuiop on 2016/12/11 //blog地址:http://blog.csdn.net/hejjunlin namespace android { struct ABuffer;struct AMessage;struct AReplyToken;struct AString;struct CodecBase;struct IBatteryStats;struct ICrypto;class IMemory;struct MemoryDealer;class IResourceManagerClient;class IResourceManagerService;struct PersistentSurface;struct SoftwareRenderer;struct Surface;struct MediaCodec : public AHandler {

enum ConfigureFlags {

CONFIGURE_FLAG_ENCODE

= 1,};

enum BufferFlags {

BUFFER_FLAG_SYNCFRAME

= 1,BUFFER_FLAG_CODECCONFIG = 2,BUFFER_FLAG_EOS

= 4,};

enum {

CB_INPUT_AVAILABLE = 1,CB_OUTPUT_AVAILABLE = 2,CB_ERROR = 3,CB_OUTPUT_FORMAT_CHANGED = 4,CB_RESOURCE_RECLAIMED = 5,};

static const pid_t kNoPid =-1;

static sp CreateByType(const sp &looper, const char *mime, bool encoder, status_t *err = NULL,pid_t pid = kNoPid);

static sp CreateByComponentName(const sp &looper, const char *name, status_t *err = NULL,pid_t pid = kNoPid);

static sp

CreatePersistentInputSurface();

status_t configure(const sp &format,const sp &nativeWindow,const sp &crypto,uint32_t flags);

status_t setCallback(const sp &callback);

status_t setOnFrameRenderedNotification(const sp ¬ify);

status_t createInputSurface(sp* bufferProducer);

status_t setInputSurface(const sp

&surface);

status_t start();

// Returns to a state in which the component remains allocated but

// unconfigured.status_t stop();

// Resets the codec to the INITIALIZED state.Can be called after an error

// has occured to make the codec usable.status_t reset();

// Client MUST call release before releasing final reference to this

// object.status_t release();

status_t flush();

status_t queueInputBuffer(size_t index,size_t offset,size_t size,int64_t presentationTimeUs,uint32_t flags,AString *errorDetailMsg = NULL);

status_t queueSecureInputBuffer(size_t index,size_t offset,const CryptoPlugin::SubSample *subSamples,size_t numSubSamples,const uint8_t key[16],const uint8_t iv[16],CryptoPlugin::Mode mode,int64_t presentationTimeUs,uint32_t flags,AString *errorDetailMsg = NULL);

status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs = 0ll);

status_t dequeueOutputBuffer(size_t *index,size_t *offset,size_t *size,int64_t *presentationTimeUs,uint32_t *flags,int64_t timeoutUs = 0ll);

status_t renderOutputBufferAndRelease(size_t index, int64_t timestampNs);

status_t renderOutputBufferAndRelease(size_t index);

status_t releaseOutputBuffer(size_t index);

status_t signalEndOfInputStream();

status_t getOutputFormat(sp *format)const;

status_t getInputFormat(sp *format)const;

status_t getWidevineLegacyBuffers(Vector > *buffers)const;

status_t getInputBuffers(Vector > *buffers)const;

status_t getOutputBuffers(Vector > *buffers)const;

status_t getOutputBuffer(size_t index, sp *buffer);

status_t getOutputFormat(size_t index, sp *format);

status_t getInputBuffer(size_t index, sp *buffer);

status_t setSurface(const sp &nativeWindow);

status_t requestIDRFrame();

// Notification will be posted once there “is something to do”, i.e.// an input/output buffer has become available, a format change is

// pending, an error is pending.void requestActivityNotification(const sp ¬ify);

status_t getName(AString *componentName)const;

status_t setParameters(const sp ¶ms);

// Create a MediaCodec notification message from a list of rendered or dropped render infos

// by adding rendered frame information to a base notification message.Returns the number

// of frames that were rendered.static size_t CreateFramesRenderedMessage(std::list done, sp &msg);protected:

virtual ~MediaCodec();

virtual void onMessageReceived(const sp &msg);private:

// used by ResourceManagerClient

status_t reclaim(bool force = false);

friend struct ResourceManagerClient;private:

enum State {

UNINITIALIZED,INITIALIZING,INITIALIZED,CONFIGURING,CONFIGURED,STARTING,STARTED,FLUSHING,FLUSHED,STOPPING,RELEASING,};

enum {

kPortIndexInput

= 0,kPortIndexOutput

= 1,};

enum {

kWhatInit

= 'init',kWhatConfigure

= 'conf',kWhatSetSurface

= 'sSur',kWhatCreateInputSurface

= 'cisf',kWhatSetInputSurface

= 'sisf',kWhatStart

= 'strt',kWhatStop

= 'stop',kWhatRelease

= 'rele',kWhatDequeueInputBuffer

= 'deqI',kWhatQueueInputBuffer

= 'queI',kWhatDequeueOutputBuffer

= 'deqO',kWhatReleaseOutputBuffer

= 'relO',kWhatSignalEndOfInputStream

= 'eois',kWhatGetBuffers

= 'getB',kWhatFlush

= 'flus',kWhatGetOutputFormat

= 'getO',kWhatGetInputFormat

= 'getI',kWhatDequeueInputTimedOut

= 'dITO',kWhatDequeueOutputTimedOut

= 'dOTO',kWhatCodecNotify

= 'codc',kWhatRequestIDRFrame

= 'ridr',kWhatRequestActivityNotification

= 'racN',kWhatGetName

= 'getN',kWhatSetParameters

= 'setP',kWhatSetCallback

= 'setC',kWhatSetNotification

= 'setN',};

enum {

kFlagUsesSoftwareRenderer

= 1,kFlagOutputFormatChanged

= 2,kFlagOutputBuffersChanged

= 4,kFlagStickyError

= 8,kFlagDequeueInputPending

= 16,kFlagDequeueOutputPending

= 32,kFlagIsSecure

= 64,kFlagSawMediaServerDie

= 128,kFlagIsEncoder

= 256,kFlagGatherCodecSpecificData

= 512,kFlagIsAsync

= 1024,kFlagIsComponentAllocated

= 2048,kFlagPushBlankBuffersOnShutdown = 4096,};

struct BufferInfo {

uint32_t mBufferID;

sp mData;

sp mEncryptedData;

sp mSharedEncryptedBuffer;

sp mNotify;

sp mFormat;

bool mOwnedByClient;

};

struct ResourceManagerServiceProxy : public IBinder::DeathRecipient {

ResourceManagerServiceProxy(pid_t pid);

~ResourceManagerServiceProxy();

void init();

// implements DeathRecipient

virtual void binderDied(const wp& /*who*/);

void addResource(int64_t clientId,const sp client,const Vector &resources);

void removeResource(int64_t clientId);

bool reclaimResource(const Vector &resources);

private:

Mutex mLock;

sp mService;

pid_t mPid;

};

State mState;

bool mReleasedByResourceManager;

sp mLooper;

sp mCodecLooper;

sp mCodec;

AString mComponentName;

sp mReplyID;

uint32_t mFlags;

status_t mStickyError;

sp mSurface;

SoftwareRenderer *mSoftRenderer;

sp mOutputFormat;

sp mInputFormat;

sp mCallback;

sp mOnFrameRenderedNotification;

sp mDealer;

sp mResourceManagerClient;

sp mResourceManagerService;

bool mBatteryStatNotified;

bool mIsVideo;

int32_t mVideoWidth;

int32_t mVideoHeight;

int32_t mRotationDegrees;

// initial create parameters

AString mInitName;

bool mInitNameIsType;

bool mInitIsEncoder;

// configure parameter

sp mConfigureMsg;

// Used only to synchronize asynchronous getBufferAndFormat

// across all the other(synchronous)buffer state change

// operations, such as de/queueIn/OutputBuffer, start and

// stop/flush/reset/release.Mutex mBufferLock;

List mAvailPortBuffers[2];

Vector mPortBuffers[2];

int32_t mDequeueInputTimeoutGeneration;

sp mDequeueInputReplyID;

int32_t mDequeueOutputTimeoutGeneration;

sp mDequeueOutputReplyID;

sp mCrypto;

List > mCSD;

sp mActivityNotify;

bool mHaveInputSurface;

bool mHavePendingInputBuffers;

MediaCodec(const sp &looper, pid_t pid);

static status_t PostAndAwaitResponse(const sp &msg, sp *response);

void PostReplyWithError(const sp &replyID, int32_t err);

status_t init(const AString &name, bool nameIsType, bool encoder);

void setState(State newState);

void returnBuffersToCodec();

void returnBuffersToCodecOnPort(int32_t portIndex);

size_t updateBuffers(int32_t portIndex, const sp &msg);

status_t onQueueInputBuffer(const sp &msg);

status_t onReleaseOutputBuffer(const sp &msg);

ssize_t dequeuePortBuffer(int32_t portIndex);

status_t getBufferAndFormat(size_t portIndex, size_t index,sp *buffer, sp *format);

bool handleDequeueInputBuffer(const sp &replyID, bool newRequest = false);

bool handleDequeueOutputBuffer(const sp &replyID, bool newRequest = false);

void cancelPendingDequeueOperations();

void extractCSD(const sp &format);

status_t queueCSDInputBuffer(size_t bufferIndex);

status_t handleSetSurface(const sp &surface);

status_t connectToSurface(const sp &surface);

status_t disconnectFromSurface();

void postActivityNotificationIfPossible();

void onInputBufferAvailable();

void onOutputBufferAvailable();

void onError(status_t err, int32_t actionCode, const char *detail = NULL);

void onOutputFormatChanged();

status_t onSetParameters(const sp ¶ms);

status_t amendOutputFormatWithCodecSpecificData(const sp &buffer);

void updateBatteryStat();

bool isExecuting()const;

uint64_t getGraphicBufferSize();

void addResource(const String8 &type, const String8 &subtype, uint64_t value);

bool hasPendingBuffer(int portIndex);

bool hasPendingBuffer();

/* called to get the last codec error when the sticky flag is set.* if no such codec error is found, returns UNKNOWN_ERROR.*/

inline status_t getStickyError()const {

return mStickyError!= 0 ? mStickyError : UNKNOWN_ERROR;

}

inline void setStickyError(status_t err){

mFlags |= kFlagStickyError;

mStickyError = err;

}

DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);};} // namespace android CreateByType

//create by 逆流的鱼yuiop on 2016/12/11 //blog地址:http://blog.csdn.net/hejjunlin // static sp MediaCodec::CreateByType(const sp &looper, const char *mime, bool encoder, status_t *err, pid_t pid){

sp codec = new MediaCodec(looper, pid);//这果实际上new出MediaCodec对象

const status_t ret = codec->init(mime, true /* nameIsType */, encoder);

if(err!= NULL){

*err = ret;

}

return ret == OK ? codec : NULL;// NULL deallocates codec.} 接着到init过程

//create by 逆流的鱼yuiop on 2016/12/11 //blog地址:http://blog.csdn.net/hejjunlin status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder){

mResourceManagerService->init();

// 保存 初始参数,到时用于reset

mInitName = name;

mInitNameIsType = nameIsType;

mInitIsEncoder = encoder;

// 目前视频解码器不能马上从OMX_FillThisBuffer返回,违反OpenMAX规格,直到提醒我们需要入驻另一个第三方的looper释放在事件队列中。

if(nameIsType ||!strncasecmp(name.c_str(), “omx.”, 4)){//omx.匹配

mCodec = new ACodec;//实例化ACodec

} else if(!nameIsType

&&!strncasecmp(name.c_str(), “android.filter.”, 15)){

mCodec = new MediaFilter;// 实例化MediaFilter

} else {

return NAME_NOT_FOUND;

}

bool secureCodec = false;

if(nameIsType &&!strncasecmp(name.c_str(), “video/”, 6)){

mIsVideo = true;

} else {

AString tmp = name;

if(tmp.endsWith(“.secure”)){

secureCodec = true;

tmp.erase(tmp.size()-7, 7);

}

const sp mcl = MediaCodecList::getInstance();

if(mcl == NULL){

mCodec = NULL;// remove the codec.return NO_INIT;// if called from Java should raise IOException

}

ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());

if(codecIdx >= 0){

const sp info = mcl->getCodecInfo(codecIdx);

Vector mimes;

info->getSupportedMimes(&mimes);

for(size_t i = 0;i < mimes.size();i++){

if(mimes[i].startsWith(“video/”)){

mIsVideo = true;

break;

}

}

}

}

if(mIsVideo){

// video codec needs dedicated looper

if(mCodecLooper == NULL){

mCodecLooper = new ALooper;

mCodecLooper->setName(“CodecLooper”);//设置名字为CodecLooper

mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);

}

mCodecLooper->registerHandler(mCodec);

} else {

mLooper->registerHandler(mCodec);

}

mLooper->registerHandler(this);

mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, this));

sp msg = new AMessage(kWhatInit, this);

msg->setString(“name”, name);

msg->setInt32(“nameIsType”, nameIsType);

if(nameIsType){

msg->setInt32(“encoder”, encoder);

}

status_t err;

Vector resources;

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 resource for the first time.if(!mResourceManagerService->reclaimResource(resources)){

break;

}

}

sp response;

err = PostAndAwaitResponse(msg, &response);

if(!isResourceError(err)){

break;

}

}

return err;} configure过程

//create by 逆流的鱼yuiop on 2016/12/11 //blog地址:http://blog.csdn.net/hejjunlin status_t MediaCodec::configure(const sp &format,const sp &surface,const sp &crypto,uint32_t flags){

sp msg = new AMessage(kWhatConfigure, this);

if(mIsVideo){

format->findInt32(“width”, &mVideoWidth);

format->findInt32(“height”, &mVideoHeight);

if(!format->findInt32(“rotation-degrees”, &mRotationDegrees)){

mRotationDegrees = 0;

}

}

msg->setMessage(“format”, format);

msg->setInt32(“flags”, flags);

msg->setObject(“surface”, surface);

if(crypto!= NULL){

msg->setPointer(“crypto”, crypto.get());

}

// save msg for reset

mConfigureMsg = msg;

status_t err;

Vector resources;

const char *type =(mFlags & kFlagIsSecure)?

kResourceSecureCodec : kResourceNonSecureCodec;

const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;

resources.push_back(MediaResource(String8(type), String8(subtype), 1));

// Don't know the buffer size at this point, but it's fine to use 1 because

// the reclaimResource call doesn't consider the requester's buffer size for now.resources.push_back(MediaResource(String8(kResourceGraphicMemory), 1));

for(int i = 0;i <= kMaxRetry;++i){

if(i > 0){

// Don't try to reclaim resource for the first time.if(!mResourceManagerService->reclaimResource(resources)){

break;

}

}

sp response;

err = PostAndAwaitResponse(msg, &response);

if(err!= OK && err!= INVALID_OPERATION){

// MediaCodec now set state to UNINITIALIZED upon any fatal error.// To maintain backward-compatibility, do a reset()to put codec

// back into INITIALIZED state.// But don't reset if the err is INVALID_OPERATION, which means

// the configure failure is due to wrong state.ALOGE(“configure failed with err 0x%08x, resetting...”, err);

reset();

}

if(!isResourceError(err)){

break;

}

}

return err;} start过程

//create by 逆流的鱼yuiop on 2016/12/11 //blog地址:http://blog.csdn.net/hejjunlin status_t MediaCodec::start(){

sp msg = new AMessage(kWhatStart, this);

status_t err;

Vector resources;

const char *type =(mFlags & kFlagIsSecure)?

kResourceSecureCodec : kResourceNonSecureCodec;

const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;

resources.push_back(MediaResource(String8(type), String8(subtype), 1));

// Don't know the buwww.xiexiebang.comffer size at this point, but it's fine to use 1 because

// the reclaimResource call doesn't consider the requester's buffer size for now.resources.push_back(MediaResource(String8(kResourceGraphicMemory), 1));

for(int i = 0;i <= kMaxRetry;++i){

if(i > 0){

// Don't try to reclaim resource for the first time.if(!mResourceManagerService->reclaimResource(resources)){

break;

}

// Recover codec from previous error before retry start.err = reset();

if(err!= OK){

ALOGE(“retrying start: failed to reset codec”);

break;

}

sp response;

err = PostAndAwaitResponse(mConfigureMsg, &response);

if(err!= OK){

ALOGE(“retrying start: failed to configure codec”);

break;

}

}

sp response;

err = PostAndAwaitResponse(msg, &response);

if(!isResourceError(err)){

break;

}

}

return err;} stop过程

//create by 逆流的鱼yuiop on 2016/12/11 //blog地址:http://blog.csdn.net/hejjunlin status_t MediaCodec::stop(){

sp msg = new AMessage(kWhatStop, this);

sp response;

return PostAndAwaitResponse(msg, &response);} 找到对应的AMessage.cpp,对应同样有一套AHandler.cpp,及ALooper.cpp,这此组成了在c++中一套机制,接口 方法的名字和Java层保持一致。

所有message都在onMessageReceived方法中处理,MediaCodec的各个状态的相关切换。

void MediaCodec::onMessageReceived(const sp &msg){

switch(mState){

case INITIALIZING://初始化中

{

setState(UNINITIALIZED);

break;

}

case CONFIGURING://配置中

{

setState(actionCode == ACTION_CODE_FATAL ?

UNINITIALIZED : INITIALIZED);

break;

}

case STARTING://start中

{

setState(actionCode == ACTION_CODE_FATAL ?

UNINITIALIZED : CONFIGURED);

break;

}

case STOPPING://停止中

case RELEASING://释放中

{

// Ignore the error, assuming we'll still get

// the shnc630.comutdown complete notification.sendErrorResponse = false;

if(mFlags & kFlagSawMediaServerDie){

// MediaServer died, there definitely won't

// be a shutdown complete notification after

// all.// note that we're directly going from

// STOPPING->UNINITIALIZED, instead of the

// usual STOPPING->INITIALIZED state.setState(UNINITIALIZED);

if(mState == RELEASING){

mComponentName.clear();

}

STARTED);

(new AMessage)->postReply(mReplyID);

}

break;}

case FLUSHING://刷新中 {

if(actionCode == ACTION_CODE_FATAL){

setState(UNINITIALIZED);

} else {

setState((mFlags & kFlagIsAsync)? FLUSHED :

}

break;}

case FLUSHED: case STARTED: {

sendErrorResponse = false;

setStickyError(err);

postActivityNotificationIfPossible();

cancelPendingDequeueOperations();

if(mFlags & kFlagIsAsync){

onError(err, actionCode);

}

switch(actionCode){

case ACTION_CODE_TRANSIENT:

break;

case ACTION_CODE_RECOVERABLE:

setState(INITIALIZED);

break;

default:

setState(UNINITIALIZED);

break;

}

break;

}

default:

{

sendErrorResponse = false;

setStickyError(err);

postActivityNotificationIfPossible();

// actionCode in an uninitialized state is always fatal.if(mState == UNINITIALIZED){

}

actionCode = ACTION_CODE_FATAL;

}

if(mFlags & kFlagIsAsync){

onError(err, actionCode);

}

switch(actionCode){

case ACTION_CODE_TRANSIENT:

break;

case ACTION_CODE_RECOVERABLE:

setState(INITIALIZED);

break;

default:

setState(UNINITIALIZED);

break;

}

break;}

下载Android Multimedia框架总结(二十二)MediaCodec中C++中创建到start过程及状态变换word格式文档
下载Android Multimedia框架总结(二十二)MediaCodec中C++中创建到start过程及状态变换.doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐