4.1 看下 drainInputBuffers();实现
- void OMXCodec::drainInputBuffers() {
- for (size_t i = 0; i < buffers->size(); ++i) {
- BufferInfo *info = &buffers->editItemAt(i);
- if (info->mStatus != OWNED_BY_US) {
- continue;
- }
- if (!drainInputBuffer(info)) {
- break;
- }
- if (mFlags & kOnlySubmitOneInputBufferAtOneTime) {
- break;
- }
- }
- }
void OMXCodec::drainInputBuffers() { for (size_t i = 0; i < buffers->size(); ++i) { BufferInfo *info = &buffers->editItemAt(i); if (info->mStatus != OWNED_BY_US) { continue; } if (!drainInputBuffer(info)) { break; } if (mFlags & kOnlySubmitOneInputBufferAtOneTime) { break; } } }这里解释下,我们可能申请了多个输入缓冲区,因此是一个循环,先检查我们有没有权限使用即OWNED_BY_US,这一缓冲区获取完数据后会检测
kOnlySubmitOneInputBufferAtOneTime即每次只允许读一个包,否则循环都读满。
下面继续跟进drainInputBuffer(info),忽略无关代码:
- bool OMXCodec::drainInputBuffer(BufferInfo *info) {
- **********
- status_t err;
- bool signalEOS = false;
- int64_t timestampUs = 0;
- size_t offset = 0;
- int32_t n = 0;
- for (;;) {
- MediaBuffer *srcBuffer;
- err = mSource->read(&srcBuffer);
- size_t remainingBytes = info->mSize - offset;
- 下面是判断从extractor读取到的数据是不是超过了总大小
- if (srcBuffer->range_length() > remainingBytes) {
- if (offset == 0) {
- srcBuffer->release();
- srcBuffer = NULL;
- setState(ERROR);
- return false;
- }
- mLeftOverBuffer = srcBuffer;
- break;
- } memcpy((uint8_t *)info->mData + offset,
- (const uint8_t *)srcBuffer->data()
- + srcBuffer->range_offset(),
- srcBuffer->range_length());
- offset += srcBuffer->range_length();
- if (releaseBuffer) {
- srcBuffer->release();
- srcBuffer = NULL;
- }
- 数据读取完毕后将srcBufferrelease掉
- }
- err = mOMX->emptyBuffer(
- mNode, info->mBuffer, 0, offset,
- flags, timestampUs);
- info->mStatus = OWNED_BY_COMPONENT;
- }
这里读取完毕后将缓冲区的状态设置成OWNED_BY_COMPONENT 解码器就可以解码了
这里可以看出来读取数据时实现了一次拷贝~~,而不是用的同一块缓冲区,注意下
读取数据可以参考前面介绍的extractor的内容,比较简单不说了。
下面看读取数据完毕后调用mOMX->emptyBuffer都干了些啥
通过前面我们很容易的理解实际调用的是
omx::emptybufferèOMXNodeInstance::emptyBuffer,
从代码可以看到最终调用的是
((OMX_COMPONENTTYPE*)hComponent)->EmptyThisBuffer()
实际代码在SimpleSoftOMXComponent.cpp中,具体如下
- OMX_ERRORTYPE SimpleSoftOMXComponent::emptyThisBuffer(
- OMX_BUFFERHEADERTYPE *buffer) {
- sp<AMessage> msg = new AMessage(kWhatEmptyThisBuffer, mHandler->id());
- msg->setPointer("header", buffer);
- msg->post();
- return OMX_ErrorNone;
- }
OMX_ERRORTYPE SimpleSoftOMXComponent::emptyThisBuffer( OMX_BUFFERHEADERTYPE *buffer) { sp<AMessage> msg = new AMessage(kWhatEmptyThisBuffer, mHandler->id()); msg->setPointer("header", buffer); msg->post(); return OMX_ErrorNone; }可以看到就是发了一条命令kWhatEmptyThisBuffer
通过handler->id确定了自己发的还得自己收,处理函数如下:
- void SimpleSoftOMXComponent::onMessageReceived(const sp<AMessage> &msg) {
- Mutex::Autolock autoLock(mLock);
- uint32_t msgType = msg->what();
- ALOGV("msgType = %d", msgType);
- switch (msgType) {
- ********
- case kWhatEmptyThisBuffer:
- case kWhatFillThisBuffer:
- {
- OMX_BUFFERHEADERTYPE *header;
- CHECK(msg->findPointer("header", (void **)&header));
- CHECK(mState == OMX_StateExecuting && mTargetState == mState);
- bool found = false;
- size_t portIndex = (kWhatEmptyThisBuffer == msgType)? header->nInputPortIndex: header->nOutputPortIndex;
- PortInfo *port = &mPorts.editItemAt(portIndex);
- for (size_t j = 0; j < port->mBuffers.size(); ++j) {
- BufferInfo *buffer = &port->mBuffers.editItemAt(j);
- if (buffer->mHeader == header) {
- CHECK(!buffer->mOwnedByUs);
- buffer->mOwnedByUs = true;
- CHECK((msgType == kWhatEmptyThisBuffer
- && port->mDef.eDir == OMX_DirInput)|| (port->mDef.eDir == OMX_DirOutput));
- port->mQueue.push_back(buffer);
- onQueueFilled(portIndex);
- found = true;
- break;
- }
- }
- CHECK(found);
- break;
- }
- default:
- TRESPASS();
- break;
- }
- }
void SimpleSoftOMXComponent::onMessageReceived(const sp<AMessage> &msg) { Mutex::Autolock autoLock(mLock); uint32_t msgType = msg->what(); ALOGV("msgType = %d", msgType); switch (msgType) { ******** case kWhatEmptyThisBuffer: case kWhatFillThisBuffer: { OMX_BUFFERHEADERTYPE *header; CHECK(msg->findPointer("header", (void **)&header)); CHECK(mState == OMX_StateExecuting && mTargetState == mState); bool found = false; size_t portIndex = (kWhatEmptyThisBuffer == msgType)? header->nInputPortIndex: header->nOutputPortIndex; PortInfo *port = &mPorts.editItemAt(portIndex); for (size_t j = 0; j < port->mBuffers.size(); ++j) { BufferInfo *buffer = &port->mBuffers.editItemAt(j); if (buffer->mHeader == header) { CHECK(!buffer->mOwnedByUs); buffer->mOwnedByUs = true; CHECK((msgType == kWhatEmptyThisBuffer && port->mDef.eDir == OMX_DirInput)|| (port->mDef.eDir == OMX_DirOutput)); port->mQueue.push_back(buffer); onQueueFilled(portIndex); found = true; break; } } CHECK(found); break; } default: TRESPASS(); break; } }
从代码这里来看这两个case都走同一套代码,而且都是通过onQueueFilled来处理,这样我们就引出了实际的处理函数,也就是onQueueFilled,以mp3为例这里具体实现在SoftMP3中。
具体解释看代码中注释
- void SoftMP3::onQueueFilled(OMX_U32 portIndex) {
- if (mSignalledError || mOutputPortSettingsChange != NONE) {
- return;
- }
- 获取输入输出链表
- List<BufferInfo *> &inQueue = getPortQueue(0);
- List<BufferInfo *> &outQueue = getPortQueue(1);
- while (!inQueue.empty() && !outQueue.empty()) {
- 各自取输入输出缓冲区中的第一个缓冲区
- BufferInfo *inInfo = *inQueue.begin();
- OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
- BufferInfo *outInfo = *outQueue.begin();
- OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
- 判断缓冲区是不是没有数据,若果第一个都没有那就是没有
- if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
- inQueue.erase(inQueue.begin());
- inInfo->mOwnedByUs = false;
- notifyEmptyBufferDone(inHeader);
- if (!mIsFirst) {
- // pad the end of the stream with 529 samples, since that many samples
- // were trimmed off the beginning when decoding started
- outHeader->nFilledLen =
- kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
- memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
- } else {
- // Since we never discarded frames from the start, we won't have
- // to add any padding at the end either.
- outHeader->nFilledLen = 0;
- }
- outHeader->nFlags = OMX_BUFFERFLAG_EOS;
- outQueue.erase(outQueue.begin());
- outInfo->mOwnedByUs = false;
- notifyFillBufferDone(outHeader);
- return;
- }
- 如果offset==0说明是第一包的开头,需要读取pts,请结合extractor理解
- if (inHeader->nOffset == 0) {
- mAnchorTimeUs = inHeader->nTimeStamp;
- mNumFramesOutput = 0;
- }
- mConfig->pInputBuffer =
- inHeader->pBuffer + inHeader->nOffset;
- mConfig->inputBufferCurrentLength = inHeader->nFilledLen;
- mConfig->inputBufferMaxLength = 0;
- mConfig->inputBufferUsedLength = 0;
- mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
- mConfig->pOutputBuffer =
- reinterpret_cast<int16_t *>(outHeader->pBuffer);
- ERROR_CODE decoderErr;
- 上面是配置参数 下面调用自己的解码器进行解码
- if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
- != NO_DECODING_ERROR) {
- ***出错处理*
- 这里注意如果解码失败,则填充0数据,也就是静音帧
- // play silence instead.
- memset(outHeader->pBuffer,
- 0,
- mConfig->outputFrameSize * sizeof(int16_t));
- mConfig->inputBufferUsedLength = inHeader->nFilledLen;
- } else if (mConfig->samplingRate != mSamplingRate
- || mConfig->num_channels != mNumChannels) {
- 这里说明参数发生了改变,即采样率等改变了,需要重新设置输出
- mSamplingRate = mConfig->samplingRate;
- mNumChannels = mConfig->num_channels;
- notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
- mOutputPortSettingsChange = AWAITING_DISABLED;
- return;
- }
- if (mIsFirst) {
- mIsFirst = false;
- // The decoder delay is 529 samples, so trim that many samples off
- // the start of the first output buffer. This essentially makes this
- // decoder have zero delay, which the rest of the pipeline assumes.
- outHeader->nOffset =
- kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
- outHeader->nFilledLen =
- mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset;
- } else {
- outHeader->nOffset = 0;
- outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t);
- }
- outHeader->nTimeStamp =
- mAnchorTimeUs
- + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate;
- outHeader->nFlags = 0;
- CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);
- inHeader->nOffset += mConfig->inputBufferUsedLength;
- inHeader->nFilledLen -= mConfig->inputBufferUsedLength;
- mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
- 如果输入缓冲区数据都解码完了,则调用notifyEmptyBufferDone
- if (inHeader->nFilledLen == 0) {
- inInfo->mOwnedByUs = false;
- inQueue.erase(inQueue.begin());
- inInfo = NULL;
- notifyEmptyBufferDone(inHeader);
- inHeader = NULL;
- }
- outInfo->mOwnedByUs = false;
- outQueue.erase(outQueue.begin());
- outInfo = NULL;
- 这是将解码出来的数据告诉外部,通过调用notifyFillBufferDone
- notifyFillBufferDone(outHeader);
- outHeader = NULL;
- }
- }
void SoftMP3::onQueueFilled(OMX_U32 portIndex) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } 获取输入输出链表 List<BufferInfo *> &inQueue = getPortQueue(0); List<BufferInfo *> &outQueue = getPortQueue(1); while (!inQueue.empty() && !outQueue.empty()) { 各自取输入输出缓冲区中的第一个缓冲区 BufferInfo *inInfo = *inQueue.begin(); OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; BufferInfo *outInfo = *outQueue.begin(); OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 判断缓冲区是不是没有数据,若果第一个都没有那就是没有 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { inQueue.erase(inQueue.begin()); inInfo->mOwnedByUs = false; notifyEmptyBufferDone(inHeader); if (!mIsFirst) { // pad the end of the stream with 529 samples, since that many samples // were trimmed off the beginning when decoding started outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); memset(outHeader->pBuffer, 0, outHeader->nFilledLen); } else { // Since we never discarded frames from the start, we won't have // to add any padding at the end either. outHeader->nFilledLen = 0; } outHeader->nFlags = OMX_BUFFERFLAG_EOS; outQueue.erase(outQueue.begin()); outInfo->mOwnedByUs = false; notifyFillBufferDone(outHeader); return; } 如果offset==0说明是第一包的开头,需要读取pts,请结合extractor理解 if (inHeader->nOffset == 0) { mAnchorTimeUs = inHeader->nTimeStamp; mNumFramesOutput = 0; } mConfig->pInputBuffer = inHeader->pBuffer + inHeader->nOffset; mConfig->inputBufferCurrentLength = inHeader->nFilledLen; mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); mConfig->pOutputBuffer = reinterpret_cast<int16_t *>(outHeader->pBuffer); ERROR_CODE decoderErr; 上面是配置参数 下面调用自己的解码器进行解码 if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf)) != NO_DECODING_ERROR) { ***出错处理* 这里注意如果解码失败,则填充0数据,也就是静音帧 // play silence instead. memset(outHeader->pBuffer, 0, mConfig->outputFrameSize * sizeof(int16_t)); mConfig->inputBufferUsedLength = inHeader->nFilledLen; } else if (mConfig->samplingRate != mSamplingRate || mConfig->num_channels != mNumChannels) { 这里说明参数发生了改变,即采样率等改变了,需要重新设置输出 mSamplingRate = mConfig->samplingRate; mNumChannels = mConfig->num_channels; notify(OMX_EventPortSettingsChanged, 1, 0, NULL); mOutputPortSettingsChange = AWAITING_DISABLED; return; } if (mIsFirst) { mIsFirst = false; // The decoder delay is 529 samples, so trim that many samples off // the start of the first output buffer. This essentially makes this // decoder have zero delay, which the rest of the pipeline assumes. outHeader->nOffset = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset; } else { outHeader->nOffset = 0; outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t); } outHeader->nTimeStamp = mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate; outHeader->nFlags = 0; CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength); inHeader->nOffset += mConfig->inputBufferUsedLength; inHeader->nFilledLen -= mConfig->inputBufferUsedLength; mNumFramesOutput += mConfig->outputFrameSize / mNumChannels; 如果输入缓冲区数据都解码完了,则调用notifyEmptyBufferDone if (inHeader->nFilledLen == 0) { inInfo->mOwnedByUs = false; inQueue.erase(inQueue.begin()); inInfo = NULL; notifyEmptyBufferDone(inHeader); inHeader = NULL; } outInfo->mOwnedByUs = false; outQueue.erase(outQueue.begin()); outInfo = NULL; 这是将解码出来的数据告诉外部,通过调用notifyFillBufferDone notifyFillBufferDone(outHeader); outHeader = NULL; } }下面分析下,如何将输入缓冲区释放和将输出缓冲区中的数据传递出去
A、输入部分的清空
- void SoftOMXComponent::notifyEmptyBufferDone(OMX_BUFFERHEADERTYPE *header) {
- (*mCallbacks->EmptyBufferDone)(
- mComponent, mComponent->pApplicationPrivate, header);
- }
void SoftOMXComponent::notifyEmptyBufferDone(OMX_BUFFERHEADERTYPE *header) { (*mCallbacks->EmptyBufferDone)( mComponent, mComponent->pApplicationPrivate, header); }通知外面我们emptythisbuffer完工了,具体调用的是OMXNodeInstance中的方法,具体怎么传进去的,大家可以自己分析下:
- OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
- OMX_IN OMX_HANDLETYPE hComponent,
- OMX_IN OMX_PTR pAppData,
- OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
- OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
- if (instance->mDying) {
- return OMX_ErrorNone;
- }
- return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
- }
OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_PTR pAppData, OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); if (instance->mDying) { return OMX_ErrorNone; } return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); }OMXNodeInstance的ownner是OMX,因此代码为
- OMX_ERRORTYPE OMX::OnEmptyBufferDone(
- node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
- ALOGV("OnEmptyBufferDone buffer=%p", pBuffer);
- omx_message msg;
- msg.type = omx_message::EMPTY_BUFFER_DONE;
- msg.node = node;
- msg.u.buffer_data.buffer = pBuffer;
- findDispatcher(node)->post(msg);
- return OMX_ErrorNone;
- }
OMX_ERRORTYPE OMX::OnEmptyBufferDone( node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { ALOGV("OnEmptyBufferDone buffer=%p", pBuffer); omx_message msg; msg.type = omx_message::EMPTY_BUFFER_DONE; msg.node = node; msg.u.buffer_data.buffer = pBuffer; findDispatcher(node)->post(msg); return OMX_ErrorNone; }其中findDispatcher定义如下
- sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) {
- Mutex::Autolock autoLock(mLock);
- ssize_t index = mDispatchers.indexOfKey(node);
- return index < 0 ? NULL : mDispatchers.valueAt(index);
- }
sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) { Mutex::Autolock autoLock(mLock); ssize_t index = mDispatchers.indexOfKey(node); return index < 0 ? NULL : mDispatchers.valueAt(index); }这里mDispatcher在之前allocateNode中通过mDispatchers.add(*node, new CallbackDispatcher(instance)); 创建的
看下实际的实现可知道,CallbackDispatcher的post方法最终会调用dispatch
- void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
- if (mOwner == NULL) {
- ALOGV("Would have dispatched a message to a node that's already gone.");
- return;
- }
- mOwner->onMessage(msg);
- }
void OMX::CallbackDispatcher::dispatch(const omx_message &msg) { if (mOwner == NULL) { ALOGV("Would have dispatched a message to a node that's already gone."); return; } mOwner->onMessage(msg); }而owner是OMXNodeInstance,因此消息饶了一圈还是到了OMXNodeInstance的OnMessage方法接收了
- void OMXNodeInstance::onMessage(const omx_message &msg) {
- if (msg.type == omx_message::FILL_BUFFER_DONE) {
- OMX_BUFFERHEADERTYPE *buffer =
- static_cast<OMX_BUFFERHEADERTYPE *>(
- msg.u.extended_buffer_data.buffer);
- BufferMeta *buffer_meta =
- static_cast<BufferMeta *>(buffer->pAppPrivate);
- buffer_meta->CopyFromOMX(buffer);
- }
- mObserver->onMessage(msg);
- }
void OMXNodeInstance::onMessage(const omx_message &msg) { if (msg.type == omx_message::FILL_BUFFER_DONE) { OMX_BUFFERHEADERTYPE *buffer = static_cast<OMX_BUFFERHEADERTYPE *>( msg.u.extended_buffer_data.buffer); BufferMeta *buffer_meta = static_cast<BufferMeta *>(buffer->pAppPrivate); buffer_meta->CopyFromOMX(buffer); } mObserver->onMessage(msg); }而onMessage又将消息传递到 mObserver中,也就是在OMXCodec::Create中构造的OMXCodecObserver对象,其OnMessage实现如下
- virtual void onMessage(const omx_message &msg) {
- sp<OMXCodec> codec = mTarget.promote();
- if (codec.get() != NULL) {
- Mutex::Autolock autoLock(codec->mLock);
- codec->on_message(msg);
- codec.clear();
- }
- }
virtual void onMessage(const omx_message &msg) { sp<OMXCodec> codec = mTarget.promote(); if (codec.get() != NULL) { Mutex::Autolock autoLock(codec->mLock); codec->on_message(msg); codec.clear(); } }最终还是传递给了OMXCodec里,具体看下:
- void OMXCodec::on_message(const omx_message &msg) {
- switch (msg.type) {
- ************
- case omx_message::EMPTY_BUFFER_DONE:
- {
- IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
- Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
- size_t i = 0;
- while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
- ++i;
- }
- BufferInfo* info = &buffers->editItemAt(i);
- info->mStatus = OWNED_BY_US;
- // Buffer could not be released until empty buffer done is called.
- if (info->mMediaBuffer != NULL) {
- info->mMediaBuffer->release();
- info->mMediaBuffer = NULL;
- }
- drainInputBuffer(&buffers->editItemAt(i));
- break;
- }
- ****************
- }
void OMXCodec::on_message(const omx_message &msg) { switch (msg.type) { ************ case omx_message::EMPTY_BUFFER_DONE: { IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer; Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput]; size_t i = 0; while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) { ++i; } BufferInfo* info = &buffers->editItemAt(i); info->mStatus = OWNED_BY_US; // Buffer could not be released until empty buffer done is called. if (info->mMediaBuffer != NULL) { info->mMediaBuffer->release(); info->mMediaBuffer = NULL; } drainInputBuffer(&buffers->editItemAt(i)); break; } **************** }
这部分很绕,但搞清楚就好了,请大家仔细阅读,此处虽然调用了info->mMediaBuffer->release();但是由于其引用始终大于0,因此不会真正的release二是当release完毕后,会调用drainInputBuffer(&buffers->editItemAt(i));来填充数据
也就是说当我们启动一次解码播放后,会在此处循环读取数和据解码数据。而输出数据在后面的filloutbuffer中。
B、输出数据的清空notifyFillBufferDone(outHeader);
- void SoftOMXComponent::notifyFillBufferDone(OMX_BUFFERHEADERTYPE *header) {
- (*mCallbacks->FillBufferDone)(
- mComponent, mComponent->pApplicationPrivate, header);
- }
void SoftOMXComponent::notifyFillBufferDone(OMX_BUFFERHEADERTYPE *header) { (*mCallbacks->FillBufferDone)( mComponent, mComponent->pApplicationPrivate, header); }
- OMX_ERRORTYPE OMX::OnFillBufferDone(
- node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
- ALOGV("OnFillBufferDone buffer=%p", pBuffer);
- omx_message msg;
- msg.type = omx_message::FILL_BUFFER_DONE;
- msg.node = node;
- msg.u.extended_buffer_data.buffer = pBuffer;
- msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
- msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
- msg.u.extended_buffer_data.flags = pBuffer->nFlags;
- msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
- msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
- msg.u.extended_buffer_data.data_ptr = pBuffer->pBuffer;
- findDispatcher(node)->post(msg);
- return OMX_ErrorNone;
- }
OMX_ERRORTYPE OMX::OnFillBufferDone( node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { ALOGV("OnFillBufferDone buffer=%p", pBuffer); omx_message msg; msg.type = omx_message::FILL_BUFFER_DONE; msg.node = node; msg.u.extended_buffer_data.buffer = pBuffer; msg.u.extended_buffer_data.range_offset = pBuffer->nOffset; msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen; msg.u.extended_buffer_data.flags = pBuffer->nFlags; msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp; msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate; msg.u.extended_buffer_data.data_ptr = pBuffer->pBuffer; findDispatcher(node)->post(msg); return OMX_ErrorNone; }最终处理在OMXCodec.cpp中
- void OMXCodec::on_message(const omx_message &msg) {
- {
- case omx_message::FILL_BUFFER_DONE:
- info->mStatus = OWNED_BY_US;
- mFilledBuffers.push_back(i);
- mBufferFilled.signal();
- break;
- }
- }
void OMXCodec::on_message(const omx_message &msg) { { case omx_message::FILL_BUFFER_DONE: info->mStatus = OWNED_BY_US; mFilledBuffers.push_back(i); mBufferFilled.signal(); break; } }
主体就这么几句,先将mStatus设置成OWNED_BY_US,这样component便不能操作了,后面将这个buffer push到mFilledBuffers中。4.2 fillOutputBuffers
- void OMXCodec::fillOutputBuffers() {
- CHECK_EQ((int)mState, (int)EXECUTING);
- Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
- for (size_t i = 0; i < buffers->size(); ++i) {
- BufferInfo *info = &buffers->editItemAt(i);
- if (info->mStatus == OWNED_BY_US) {
- fillOutputBuffer(&buffers->editItemAt(i));
- }
- }
- }
void OMXCodec::fillOutputBuffers() { CHECK_EQ((int)mState, (int)EXECUTING); Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput]; for (size_t i = 0; i < buffers->size(); ++i) { BufferInfo *info = &buffers->editItemAt(i); if (info->mStatus == OWNED_BY_US) { fillOutputBuffer(&buffers->editItemAt(i)); } } }找到一个输出缓冲区bufferinfo,启动输出
- void OMXCodec::fillOutputBuffer(BufferInfo *info) {
- **************
- status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
- info->mStatus = OWNED_BY_COMPONENT;
- }
void OMXCodec::fillOutputBuffer(BufferInfo *info) { ************** status_t err = mOMX->fillBuffer(mNode, info->mBuffer); info->mStatus = OWNED_BY_COMPONENT; }下面和解码流程类似,我们依次来看:
- status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
- Mutex::Autolock autoLock(mLock);
- OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
- header->nFilledLen = 0;
- header->nOffset = 0;
- header->nFlags = 0;
- OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
- return StatusFromOMXError(err);
- }
status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { Mutex::Autolock autoLock(mLock); OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; header->nFilledLen = 0; header->nOffset = 0; header->nFlags = 0; OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); return StatusFromOMXError(err); }进行一些初始化后,调用进入了softMP3中,也就是
- OMX_ERRORTYPE SimpleSoftOMXComponent::fillThisBuffer(
- OMX_BUFFERHEADERTYPE *buffer) {
- sp<AMessage> msg = new AMessage(kWhatFillThisBuffer, mHandler->id());
- msg->setPointer("header", buffer);
- msg->post();
- return OMX_ErrorNone;
- }
OMX_ERRORTYPE SimpleSoftOMXComponent::fillThisBuffer( OMX_BUFFERHEADERTYPE *buffer) { sp<AMessage> msg = new AMessage(kWhatFillThisBuffer, mHandler->id()); msg->setPointer("header", buffer); msg->post(); return OMX_ErrorNone; }同理,接收程序也在本文件中:
- void SimpleSoftOMXComponent::onMessageReceived(const sp<AMessage> &msg) {
- Mutex::Autolock autoLock(mLock);
- uint32_t msgType = msg->what();
- ALOGV("msgType = %d", msgType);
- switch (msgType) {
- case kWhatEmptyThisBuffer:
- case kWhatFillThisBuffer:
- {
- OMX_BUFFERHEADERTYPE *header;
- CHECK(msg->findPointer("header", (void **)&header));
- CHECK(mState == OMX_StateExecuting && mTargetState == mState);
- bool found = false;
- size_t portIndex = (kWhatEmptyThisBuffer == msgType)?
- header->nInputPortIndex: header->nOutputPortIndex;
- PortInfo *port = &mPorts.editItemAt(portIndex);
- for (size_t j = 0; j < port->mBuffers.size(); ++j) {
- BufferInfo *buffer = &port->mBuffers.editItemAt(j);
- if (buffer->mHeader == header) {
- CHECK(!buffer->mOwnedByUs);
- buffer->mOwnedByUs = true;
- CHECK((msgType == kWhatEmptyThisBuffer
- && port->mDef.eDir == OMX_DirInput)
- || (port->mDef.eDir == OMX_DirOutput));
- port->mQueue.push_back(buffer);
- onQueueFilled(portIndex);
- found = true;
- break;
- }
- }
- CHECK(found);
- break;
- }
- default:
- TRESPASS();
- break;
- }
- }
void SimpleSoftOMXComponent::onMessageReceived(const sp<AMessage> &msg) { Mutex::Autolock autoLock(mLock); uint32_t msgType = msg->what(); ALOGV("msgType = %d", msgType); switch (msgType) { case kWhatEmptyThisBuffer: case kWhatFillThisBuffer: { OMX_BUFFERHEADERTYPE *header; CHECK(msg->findPointer("header", (void **)&header)); CHECK(mState == OMX_StateExecuting && mTargetState == mState); bool found = false; size_t portIndex = (kWhatEmptyThisBuffer == msgType)? header->nInputPortIndex: header->nOutputPortIndex; PortInfo *port = &mPorts.editItemAt(portIndex); for (size_t j = 0; j < port->mBuffers.size(); ++j) { BufferInfo *buffer = &port->mBuffers.editItemAt(j); if (buffer->mHeader == header) { CHECK(!buffer->mOwnedByUs); buffer->mOwnedByUs = true; CHECK((msgType == kWhatEmptyThisBuffer && port->mDef.eDir == OMX_DirInput) || (port->mDef.eDir == OMX_DirOutput)); port->mQueue.push_back(buffer); onQueueFilled(portIndex); found = true; break; } } CHECK(found); break; } default: TRESPASS(); break; } }
也会调用void SoftMP3::onQueueFilled执行一次解码操作,然后再通过notifyEmptyBufferDone(inHeader);
notifyFillBufferDone(outHeader);
两个函数来推进播放进度。
【结束】
欢迎转载,请注明出处!
上一篇:【stagefrightplayer】3 MediaExtractor介绍 下一篇:【stagefrightplayer】5 音频输出AudioPlayer介绍 -