MediaCodec与ACodec通知分析

ACodec与MediaCodec的通知。OMX的组件解码之后,当ACodec的onOMXFillBufferDone会被回调,去取得解码后的数据。
ACodec在onOMXFillBufferDone调用后会调用notify通知MediaCodec(notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);//发给MediaCodec的消息。
MediaCodec收到ACodec发的消息之后会更新updateBuffers(kPortIndexOutput, msg),同时onOutputBufferAvailable()中通知Decoder。


1.ACodec的onOMXFillBufferDone;

[cpp]  view plain  copy
  1. bool ACodec::BaseState::onOMXFillBufferDone(  
  2.         IOMX::buffer_id bufferID,  
  3.         size_t rangeOffset, size_t rangeLength,  
  4.         OMX_U32 flags,  
  5.         int64_t timeUs,  
  6.         int fenceFd) {  
  7.     ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",  
  8.          mCodec->mComponentName.c_str(), bufferID, timeUs, flags);  
  9.   
  10.     ssize_t index;  
  11.     status_t err= OK;  
  12.   
  13. #if TRACK_BUFFER_TIMING  
  14.     index = mCodec->mBufferStats.indexOfKey(timeUs);  
  15.     if (index >= 0) {  
  16.         ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);  
  17.         stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();  
  18.   
  19.         ALOGI("frame PTS %lld: %lld",  
  20.                 timeUs,  
  21.                 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);  
  22.   
  23.         mCodec->mBufferStats.removeItemsAt(index);  
  24.         stats = NULL;  
  25.     }  
  26. #endif  
  27.   
  28.     BufferInfo *info =  
  29.         mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);//根据bufferID找到ACodec的BufferInfo  
  30.     BufferInfo::Status status = BufferInfo::getSafeStatus(info);  
  31.     if (status != BufferInfo::OWNED_BY_COMPONENT) {  
  32.         ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);  
  33.         mCodec->dumpBuffers(kPortIndexOutput);  
  34.         mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);  
  35.         if (fenceFd >= 0) {  
  36.             ::close(fenceFd);  
  37.         }  
  38.         return true;  
  39.     }  
  40.   
  41.     info->mDequeuedAt = ++mCodec->mDequeueCounter;  
  42.     info->mStatus = BufferInfo::OWNED_BY_US;  
  43.   
  44.     if (info->mRenderInfo != NULL) {  
  45.         // The fence for an emptied buffer must have signaled, but there still could be queued  
  46.         // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these,  
  47.         // as we will soon requeue this buffer to the surface. While in theory we could still keep  
  48.         // track of buffers that are requeued to the surface, it is better to add support to the  
  49.         // buffer-queue to notify us of released buffers and their fences (in the future).  
  50.         mCodec->notifyOfRenderedFrames(true /* dropIncomplete */);  
  51.     }  
  52.   
  53.     // byte buffers cannot take fences, so wait for any fence now  
  54.     if (mCodec->mNativeWindow == NULL) {  
  55.         (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone");  
  56.         fenceFd = -1;  
  57.     }  
  58.     info->setReadFence(fenceFd, "onOMXFillBufferDone");  
  59.   
  60.     PortMode mode = getPortMode(kPortIndexOutput);  
  61.   
  62.     switch (mode) {  
  63.         case KEEP_BUFFERS:  
  64.             break;  
  65.   
  66.         case RESUBMIT_BUFFERS:  
  67.         {  
  68.             if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)  
  69.                     || mCodec->mPortEOS[kPortIndexOutput])) {  
  70.                 ALOGV("[%s] calling fillBuffer %u",  
  71.                      mCodec->mComponentName.c_str(), info->mBufferID);  
  72.   
  73.   
  74.                 err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);//继续填充outputbuffer  
  75.                 info->mFenceFd = -1;  
  76.                 if (err != OK) {  
  77.                     mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));  
  78.                     return true;  
  79.                 }  
  80.   
  81.                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;  
  82.                 break;  
  83.             }  
  84.   
  85.   
  86.             sp reply =  
  87.                 new AMessage(kWhatOutputBufferDrained, mCodec);//ACodec生成reply消息,最终会传给MediaCodec  
  88.   
  89.   
  90.             if (!mCodec->mSentFormat && rangeLength > 0) {  
  91.                 mCodec->sendFormatChange(reply);  
  92.             }  
  93.             if (mCodec->usingMetadataOnEncoderOutput()) {  
  94.                 native_handle_t *handle = NULL;  
  95.                 VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data();  
  96.                 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data();  
  97.                 if (info->mData->size() >= sizeof(grallocMeta)  
  98.                         && grallocMeta.eType == kMetadataBufferTypeGrallocSource) {  
  99.                     handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle;  
  100.                 } else if (info->mData->size() >= sizeof(nativeMeta)  
  101.                         && nativeMeta.eType == kMetadataBufferTypeANWBuffer) {  
  102. #ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS  
  103.                     // ANativeWindowBuffer is only valid on 32-bit/mediaserver process  
  104.                     handle = NULL;  
  105. #else  
  106.                     handle = (native_handle_t *)nativeMeta.pBuffer->handle;  
  107. #endif  
  108.                 }  
  109.                 info->mData->meta()->setPointer("handle", handle);  
  110.                 info->mData->meta()->setInt32("rangeOffset", rangeOffset);  
  111.                 info->mData->meta()->setInt32("rangeLength", rangeLength);  
  112.             } else {  
  113.                 info->mData->setRange(rangeOffset, rangeLength);  
  114.             }  
  115. #if 0  
  116.             if (mCodec->mNativeWindow == NULL) {  
  117.                 if (IsIDR(info->mData)) {  
  118.                     ALOGI("IDR frame");  
  119.                 }  
  120.             }  
  121. #endif  
  122.   
  123.   
  124.             if (mCodec->mSkipCutBuffer != NULL) {  
  125.                 mCodec->mSkipCutBuffer->submit(info->mData);  
  126.             }  
  127.             info->mData->meta()->setInt64("timeUs", timeUs);  
  128.             info->mData->meta()->setObject("graphic-buffer", info->mGraphicBuffer);//在info的mDate(sp)的mMeta(sp)中设置graphic-buffer  
  129.   
  130.   
  131.             sp notify = mCodec->mNotify->dup();  
  132.             notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);//发给MediaCodec的消息  
  133.             notify->setInt32("buffer-id", info->mBufferID);  
  134.             notify->setBuffer("buffer", info->mData);  
  135.             notify->setInt32("flags", flags);  
  136.   
  137.   
  138.             reply->setInt32("buffer-id", info->mBufferID);//reply在发给(传给)MediaCodec的BufferInfo的mNotify的时候,已经设置的buffer-id  
  139.   
  140.   
  141.             (void)mCodec->setDSModeHint(reply, flags, timeUs);  
  142.   
  143.   
  144.             notify->setMessage("reply", reply);//把reply设进去,用于MediaCodec向ACodec发消息  
  145.   
  146.             notify->post();//notify发出去之后MediaCodec会处理  
  147.   
  148.   
  149.             info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;  
  150.   
  151.   
  152.             if (flags & OMX_BUFFERFLAG_EOS) {  
  153.                 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());  
  154.   
  155.                 sp notify = mCodec->mNotify->dup();  
  156.                 notify->setInt32("what", CodecBase::kWhatEOS);  
  157.                 notify->setInt32("err", mCodec->mInputEOSResult);  
  158.                 notify->post();  
  159.   
  160.                 mCodec->mPortEOS[kPortIndexOutput] = true;  
  161.             }  
  162.             break;  
  163.         }  
  164.   
  165.         case FREE_BUFFERS:  
  166.             err = mCodec->freeBuffer(kPortIndexOutput, index);  
  167.             if (err != OK) {  
  168.                 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));  
  169.                 return true;  
  170.             }  
  171.             break;  
  172.   
  173.         default:  
  174.             ALOGE("Invalid port mode: %d", mode);  
  175.             return false;  
  176.     }  
  177.   
  178.   
  179.     return true;  
  180. }  




2.MediaCodec收到ACodec发的消息之后会更新updateBuffers(kPortIndexOutput, msg);同时onOutputBufferAvailable()中通知Decoder

[cpp]  view plain  copy
  1. case CodecBase::kWhatDrainThisBuffer:  
  2.     {  
  3.         /* size_t index = */updateBuffers(kPortIndexOutput, msg);//updateBuffers  
  4.   
  5.   
  6.         if (mState == FLUSHING  
  7.                 || mState == STOPPING  
  8.                 || mState == RELEASING) {  
  9.             returnBuffersToCodecOnPort(kPortIndexOutput);  
  10.             break;  
  11.         }  
  12.   
  13.   
  14.         sp buffer;  
  15.         CHECK(msg->findBuffer("buffer", &buffer));  
  16.   
  17.   
  18.         int32_t omxFlags;  
  19.         CHECK(msg->findInt32("flags", &omxFlags));  
  20.   
  21.   
  22.         buffer->meta()->setInt32("omxFlags", omxFlags);  
  23.   
  24.   
  25.         if (mFlags & kFlagGatherCodecSpecificData) {  
  26.             // This is the very first output buffer after a  
  27.             // format change was signalled, it'll either contain  
  28.             // the one piece of codec specific data we can expect  
  29.             // or there won't be codec specific data.  
  30.             if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {  
  31.                 status_t err =  
  32.                     amendOutputFormatWithCodecSpecificData(buffer);  
  33.   
  34.   
  35.                 if (err != OK) {  
  36.                     ALOGE("Codec spit out malformed codec "  
  37.                           "specific data!");  
  38.                 }  
  39.             }  
  40.   
  41.   
  42.             mFlags &= ~kFlagGatherCodecSpecificData;  
  43.             if (mFlags & kFlagIsAsync) {  
  44.                 onOutputFormatChanged();  
  45.             } else {  
  46.                 mFlags |= kFlagOutputFormatChanged;  
  47.             }  
  48.         }  
  49.   
  50.   
  51.         if (mFlags & kFlagIsAsync) {  
  52.             onOutputBufferAvailable();//通知Decoder  
  53.         } else if (mFlags & kFlagDequeueOutputPending) {  
  54.             CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));  
  55.   
  56.   
  57.             ++mDequeueOutputTimeoutGeneration;  
  58.             mFlags &= ~kFlagDequeueOutputPending;  
  59.             mDequeueOutputReplyID = 0;  
  60.         } else {  
  61.             postActivityNotificationIfPossible();  
  62.         }  
  63.   
  64.   
  65.         break;  
  66.     }  




3.1 MediaCodec的updateBuffers,找到随消息过来的reply,并存放在MediaCodec的BufferInfo的mNotify中。
[cpp]  view plain  copy
  1. size_t MediaCodec::updateBuffers(  
  2.         int32_t portIndex, const sp &msg) {  
  3.     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);  
  4.   
  5.     uint32_t bufferID;  
  6.     CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));  
  7.     Mutex::Autolock al(mBufferLock);  
  8.   
  9.     Vector *buffers = &mPortBuffers[portIndex];  
  10.   
  11.     for (size_t i = 0; i < buffers->size(); ++i) {  
  12.         BufferInfo *info = &buffers->editItemAt(i);  
  13.   
  14.         if (info->mBufferID == bufferID) {  
  15.             CHECK(info->mNotify == NULL);  
  16.             CHECK(msg->findMessage("reply", &info->mNotify));//找到随消息过来的reply,并存放在MediaCodec的BufferInfo的mNotify中  
  17.   
  18.             info->mFormat =  
  19.                 (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat;  
  20.             mAvailPortBuffers[portIndex].push_back(i);  
  21.   
  22.             return i;  
  23.         }  
  24.     }  
  25.   
  26.     TRESPASS();  
  27.   
  28.     return 0;  
  29. }  




3.2 MediaCodec的onOutputBufferAvailable,通知Decoder有可用的output buffer.


[cpp]  view plain  copy
  1. void MediaCodec::onOutputBufferAvailable() {  
  2.     int32_t index;  
  3.     while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {  
  4.         const sp &buffer =  
  5.             mPortBuffers[kPortIndexOutput].itemAt(index).mData;  
  6.         sp msg = mCallback->dup();//发送给Decoder的消息,kWhatCodecNotify  
  7.         msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);//设置callbackID,CB_OUTPUT_AVAILABLE,通知有可用的outputbuffer  
  8.         msg->setInt32("index", index);  
  9.         msg->setSize("offset", buffer->offset());  
  10.         msg->setSize("size", buffer->size());  
  11.   
  12.         int64_t timeUs;  
  13.         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));  
  14.   
  15.         msg->setInt64("timeUs", timeUs);  
  16.   
  17.         int32_t omxFlags;  
  18.         CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));  
  19.   
  20.         uint32_t flags = 0;  
  21.         if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {  
  22.             flags |= BUFFER_FLAG_SYNCFRAME;  
  23.         }  
  24.         if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {  
  25.             flags |= BUFFER_FLAG_CODECCONFIG;  
  26.         }  
  27.         if (omxFlags & OMX_BUFFERFLAG_EOS) {  
  28.             flags |= BUFFER_FLAG_EOS;  
  29.         }  
  30.   
  31.         msg->setInt32("flags", flags);  
  32.   
  33.         msg->post();  
  34.     }  
  35. }  



3.Decoder收到从MediaCodec::onOutputBufferAvailable发回的回调消息kWhatCodecNotify之后,知道有可用的buffer,就handleAnOutputBuffer.

[cpp]  view plain  copy
  1. void NuPlayer::Decoder::onMessageReceived(const sp &msg) {  
  2.     ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());  
  3.   
  4.     switch (msg->what()) {  
  5.         case kWhatCodecNotify://MediaCodec发回的回调消息  
  6.         {  
  7.             int32_t cbID;  
  8.             CHECK(msg->findInt32("callbackID", &cbID));  
  9.   
  10.             ALOGV("[%s] kWhatCodecNotify: cbID = %d, paused = %d",  
  11.                     mIsAudio ? "audio" : "video", cbID, mPaused);  
  12.   
  13.             if (mPaused) {  
  14.                 break;  
  15.             }  
  16.   
  17.             switch (cbID) {  
  18.                 case MediaCodec::CB_INPUT_AVAILABLE:  
  19.                 {  
  20.                     int32_t index;  
  21.                     CHECK(msg->findInt32("index", &index));  
  22.   
  23.                     handleAnInputBuffer(index);  
  24.                     break;  
  25.                 }  
  26.   
  27.                 case MediaCodec::CB_OUTPUT_AVAILABLE: // CB_OUTPUT_AVAILABLE,有可用的output buffer  
  28.                 {  
  29.                     int32_t index;  
  30.                     size_t offset;  
  31.                     size_t size;  
  32.                     int64_t timeUs;  
  33.                     int32_t flags;  
  34.   
  35.                     CHECK(msg->findInt32("index", &index));  
  36.                     CHECK(msg->findSize("offset", &offset));  
  37.                     CHECK(msg->findSize("size", &size));  
  38.                     CHECK(msg->findInt64("timeUs", &timeUs));  
  39.                     CHECK(msg->findInt32("flags", &flags));  
  40.   
  41.                     handleAnOutputBuffer(index, offset, size, timeUs, flags);//开始handleAnOutputBuffer  
  42.                     break;  
  43.                 }  
  44.   
  45.                 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:  
  46.                 {  
  47.                     sp format;  
  48.                     CHECK(msg->findMessage("format", &format));  
  49.   
  50.                     handleOutputFormatChange(format);  
  51.                     break;  
  52.                 }  
  53.   
  54.                 case MediaCodec::CB_ERROR:  
  55.                 {  
  56.                     status_t err;  
  57.                     CHECK(msg->findInt32("err", &err));  
  58.                     ALOGE("Decoder (%s) reported error : 0x%x",  
  59.                             mIsAudio ? "audio" : "video", err);  
  60.   
  61.                     handleError(err);  
  62.                     break;  
  63.                 }  
  64.   
  65.                 default:  
  66.                 {  
  67.                     TRESPASS();  
  68.                     break;  
  69.                 }  
  70.             }  
  71.   
  72.             break;  
  73.         }  
  74.   
  75.         case kWhatRenderBuffer:  
  76.         {  
  77.             if (!isStaleReply(msg)) {  
  78.                 onRenderBuffer(msg);  
  79.             }  
  80.             break;  
  81.         }  
  82.   
  83.         case kWhatSetVideoSurface:  
  84.         {  
  85.             sp replyID;  
  86.             CHECK(msg->senderAwaitsResponse(&replyID));  
  87.   
  88.             sp obj;  
  89.             CHECK(msg->findObject("surface", &obj));  
  90.             sp surface = static_cast(obj.get()); // non-null  
  91.             int32_t err = INVALID_OPERATION;  
  92.             // NOTE: in practice mSurface is always non-null, but checking here for completeness  
  93.             if (mCodec != NULL && mSurface != NULL) {  
  94.                 // TODO: once AwesomePlayer is removed, remove this automatic connecting  
  95.                 // to the surface by MediaPlayerService.  
  96.                 //  
  97.                 // at this point MediaPlayerService::client has already connected to the  
  98.                 // surface, which MediaCodec does not expect  
  99.                 err = native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);  
  100.                 if (err == OK) {  
  101.                     err = mCodec->setSurface(surface);  
  102.                     ALOGI_IF(err, "codec setSurface returned: %d", err);  
  103.                     if (err == OK) {  
  104.                         // reconnect to the old surface as MPS::Client will expect to  
  105.                         // be able to disconnect from it.  
  106.                         (void)native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);  
  107.                         mSurface = surface;  
  108.                     }  
  109.                 }  
  110.                 if (err != OK) {  
  111.                     // reconnect to the new surface on error as MPS::Client will expect to  
  112.                     // be able to disconnect from it.  
  113.                     (void)native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);  
  114.                 }  
  115.             }  
  116.   
  117.             sp response = new AMessage;  
  118.             response->setInt32("err", err);  
  119.             response->postReply(replyID);  
  120.             break;  
  121.         }  
  122.   
  123.         default:  
  124.             DecoderBase::onMessageReceived(msg);  
  125.             break;  
  126.     }  
  127. }  



4.Decoder::handleAnOutputBuffer, 之后Decoder要与Render交互确定是否渲染。参看《NuPlayerDecoder与NuPlayerRender分析》

[cpp]  view plain  copy
  1. bool NuPlayer::Decoder::handleAnOutputBuffer(  
  2.         size_t index,  
  3.         size_t offset,  
  4.         size_t size,  
  5.         int64_t timeUs,  
  6.         int32_t flags) {  
  7. //    CHECK_LT(bufferIx, mOutputBuffers.size());  
  8.     sp buffer;  
  9.     mCodec->getOutputBuffer(index, &buffer);//用index找到对应的ABuffer  
  10.   
  11.     if (index >= mOutputBuffers.size()) {  
  12.         for (size_t i = mOutputBuffers.size(); i <= index; ++i) {  
  13.             mOutputBuffers.add();  
  14.         }  
  15.     }  
  16.   
  17.     mOutputBuffers.editItemAt(index) = buffer;  
  18.   
  19.     buffer->setRange(offset, size);  
  20.     buffer->meta()->clear();  
  21.     buffer->meta()->setInt64("timeUs", timeUs);  
  22.     setPcmFormat(buffer->meta());  
  23.   
  24.     bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;  
  25.     // we do not expect CODECCONFIG or SYNCFRAME for decoder  
  26.   
  27.     sp reply = new AMessage(kWhatRenderBuffer, this);//Decoder发给Renderer的用于回调的消息  
  28.     reply->setSize("buffer-ix", index);  
  29.     reply->setInt32("generation", mBufferGeneration);  
  30.   
  31.     if (eos) {  
  32.         ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video");  
  33.   
  34.         buffer->meta()->setInt32("eos"true);  
  35.         reply->setInt32("eos"true);  
  36.     } else if (mSkipRenderingUntilMediaTimeUs >= 0) {  
  37.         if (timeUs < mSkipRenderingUntilMediaTimeUs) {  
  38.             ALOGV("[%s] dropping buffer at time %lld as requested.",  
  39.                      mComponentName.c_str(), (long long)timeUs);  
  40.   
  41.             reply->post();  
  42.             return true;  
  43.         }  
  44.   
  45.         mSkipRenderingUntilMediaTimeUs = -1;  
  46.     }  
  47.   
  48.     mNumFramesTotal += !mIsAudio;  
  49.   
  50.     // wait until 1st frame comes out to signal resume complete  
  51.     notifyResumeCompleteIfNecessary();  
  52.   
  53.     if (mRenderer != NULL) {  
  54.         // send the buffer to renderer.  
  55.         mRenderer->queueBuffer(mIsAudio, buffer, reply);//Renderer的相关处理,注意设进去的reply  
  56.         if (eos && !isDiscontinuityPending()) {  
  57.             mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);  
  58.         }  
  59.     }  
  60.   
  61.     return true;  
  62. }  




5. Decoder 接受 renderer对(mVideoQueue的QueueEntry)buffer发回的消费消息,并在Decoder的onRenderBuffer中调用MediaCodec的mCodec>renderOutputBufferAndRelease(bufferIx, timestampNs)或者mCodec->releaseOutputBuffer(bufferIx)。

5.1. Decoder 接受 renderer对(mVideoQueue的QueueEntry)buffer发回的消息进行消费

[cpp]  view plain  copy
  1. case kWhatRenderBuffer:  
  2. {  
  3.     if (!isStaleReply(msg)) {  
  4.         onRenderBuffer(msg);  
  5.     }  
  6.     break;  
  7. }  

5.2 Decoder的onRenderBuffer

[cpp]  view plain  copy
  1. void NuPlayer::Decoder::onRenderBuffer(const sp &msg) {  
  2.     status_t err;  
  3.     int32_t render;  
  4.     size_t bufferIx;  
  5.     int32_t eos;  
  6.     CHECK(msg->findSize("buffer-ix", &bufferIx));//找到buffer-ix  
  7.   
  8.     if (!mIsAudio) {  
  9.         int64_t timeUs;  
  10.         sp buffer = mOutputBuffers[bufferIx];  
  11.         buffer->meta()->findInt64("timeUs", &timeUs);  
  12.   
  13.         if (mCCDecoder != NULL && mCCDecoder->isSelected()) {  
  14.             mCCDecoder->display(timeUs);  
  15.         }  
  16.     }  
  17.   
  18.     if (msg->findInt32("render", &render) && render) {  
  19.         int64_t timestampNs;  
  20.         CHECK(msg->findInt64("timestampNs", ×tampNs));  
  21.         err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);//Decoder发给MediaCodec渲染加release  
  22.     } else {  
  23.         mNumOutputFramesDropped += !mIsAudio;  
  24.         err = mCodec->releaseOutputBuffer(bufferIx);//不渲染直接release  
  25.     }  
  26.     if (err != OK) {  
  27.         ALOGE("failed to release output buffer for %s (err=%d)",  
  28.                 mComponentName.c_str(), err);  
  29.         handleError(err);  
  30.     }  
  31.     if (msg->findInt32("eos", &eos) && eos  
  32.             && isDiscontinuityPending()) {  
  33.         finishHandleDiscontinuity(true /* flushOnTimeChange */);  
  34.     }  
  35. }  

6.Decoder到MediaCodec
MediaCodec的mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs)或者mCodec->releaseOutputBuffer(bufferIx),一个会真的渲染一个不渲染.
最终会到MediaCodec的onReleaseOutputBuffer(msg)处理.
   
status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
    sp msg = new AMessage(kWhatReleaseOutputBuffer, this);//发送消息
    msg->setSize("index", index);
    msg->setInt32("render", true);//设置是否渲染
    msg->setInt64("timestampNs", timestampNs);//timestampNs


    sp response;
    return PostAndAwaitResponse(msg, &response);
}


status_t MediaCodec::releaseOutputBuffer(size_t index) {
    sp msg = new AMessage(kWhatReleaseOutputBuffer, this);//发送消息
    msg->setSize("index", index);


    sp response;
    return PostAndAwaitResponse(msg, &response);
}


然后到MediaCodec的onReleaseOutputBuffer(msg)处理;
        case kWhatReleaseOutputBuffer:
        {
            sp replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));


            if (!isExecuting()) {
                PostReplyWithError(replyID, INVALID_OPERATION);
                break;
            } else if (mFlags & kFlagStickyError) {
                PostReplyWithError(replyID, getStickyError());
                break;
            }


            status_t err = onReleaseOutputBuffer(msg);//onReleaseOutputBuffer(msg)处理


            PostReplyWithError(replyID, err);
            break;
        }


//onReleaseOutputBuffer

[cpp]  view plain  copy
  1. status_t MediaCodec::onReleaseOutputBuffer(const sp &msg) {  
  2.     size_t index;  
  3.     CHECK(msg->findSize("index", &index));  
  4.   
  5.     int32_t render;  
  6.     if (!msg->findInt32("render", &render)) { //设置了render为true则渲染,否则不渲染直接release buffer  
  7.         render = 0;  
  8.     }  
  9.   
  10.     if (!isExecuting()) {  
  11.         return -EINVAL;  
  12.     }  
  13.   
  14.     if (index >= mPortBuffers[kPortIndexOutput].size()) {  
  15.         return -ERANGE;  
  16.     }  
  17.   
  18.     BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);  
  19.   
  20.     if (info->mNotify == NULL || !info->mOwnedByClient) {  
  21.         return -EACCES;  
  22.     }  
  23.   
  24.     // synchronization boundary for getBufferAndFormat  
  25.     {  
  26.         Mutex::Autolock al(mBufferLock);  
  27.         info->mOwnedByClient = false;  
  28.     }  
  29.   
  30.     if (render && info->mData != NULL && info->mData->size() != 0) { //render是否为true  
  31.         info->mNotify->setInt32("render"true);//reply设置render为true  
  32.   
  33.         int64_t mediaTimeUs = -1;  
  34.         info->mData->meta()->findInt64("timeUs", &mediaTimeUs);  
  35.   
  36.         int64_t renderTimeNs = 0;  
  37.         if (!msg->findInt64("timestampNs", &renderTimeNs)) {//Renderer给的timestampNs  
  38.             // use media timestamp if client did not request a specific render timestamp  
  39.             ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);  
  40.             renderTimeNs = mediaTimeUs * 1000;  
  41.         }  
  42.         info->mNotify->setInt64("timestampNs", renderTimeNs);  
  43.   
  44.         if (mSoftRenderer != NULL) {//是否用softRender,如果设置过SoftwareRender而则用软件渲染,不然就让ACodec去硬件渲染  
  45.             std::list doneFrames = mSoftRenderer->render(  
  46.                     info->mData->data(), info->mData->size(),  
  47.                     mediaTimeUs, renderTimeNs, NULL, info->mFormat);  
  48.   
  49.             // if we are running, notify rendered frames  
  50.             if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {  
  51.                 sp notify = mOnFrameRenderedNotification->dup();  
  52.                 sp data = new AMessage;  
  53.                 if (CreateFramesRenderedMessage(doneFrames, data)) {  
  54.                     notify->setMessage("data", data);  
  55.                     notify->post();  
  56.                 }  
  57.             }  
  58.         }  
  59.     }  
  60.   
  61.     info->mNotify->post();//info-mNotify保存着ACodec传过来的reply消息,ACdoec会硬件渲染,不管硬件渲染还是软件熏染都会fillbuffer  
  62.     info->mNotify = NULL;  
  63.   
  64.     return OK;  
  65. }  

7.MediaCodec到ACodec,MediaCodec::onReleaseOutputBuffer中判断使用硬件渲染后者软件渲染,并使用info->mNotify中ACodec传过来的reply消息,最终发给ACodec接受并处理。
ACodec接受消息后调用onOutputBufferDrained(msg),看是正在的硬件渲染。
[cpp]  view plain  copy
  1. bool ACodec::BaseState::onMessageReceived(const sp &msg) {  
  2.     switch (msg->what()) {  
  3.         case kWhatInputBufferFilled:  
  4.         {  
  5.             onInputBufferFilled(msg);  
  6.             break;  
  7.         }  
  8.   
  9.         case kWhatOutputBufferDrained://MediaCodec消费reply消息  
  10.         {  
  11.             onOutputBufferDrained(msg);  
  12.             break;  
  13.         }  
  14.   
  15.         case ACodec::kWhatOMXMessageList:  
  16.         {  
  17.             return checkOMXMessage(msg) ? onOMXMessageList(msg) : true;  
  18.         }  
  19.   
  20.         case ACodec::kWhatOMXMessageItem:  
  21.         {  
  22.             // no need to check as we already did it for kWhatOMXMessageList  
  23.             return onOMXMessage(msg);  
  24.         }  
  25.   
  26.         case ACodec::kWhatOMXMessage:  
  27.         {  
  28.             return checkOMXMessage(msg) ? onOMXMessage(msg) : true;  
  29.         }  
  30.   
  31.         case ACodec::kWhatSetSurface:  
  32.         {  
  33.             sp replyID;  
  34.             CHECK(msg->senderAwaitsResponse(&replyID));  
  35.   
  36.             sp obj;  
  37.             CHECK(msg->findObject("surface", &obj));  
  38.   
  39.             status_t err = mCodec->handleSetSurface(static_cast(obj.get()));  
  40.   
  41.             sp response = new AMessage;  
  42.             response->setInt32("err", err);  
  43.             response->postReply(replyID);  
  44.             break;  
  45.         }  
  46.   
  47.         case ACodec::kWhatCreateInputSurface:  
  48.         case ACodec::kWhatSetInputSurface:  
  49.         case ACodec::kWhatSignalEndOfInputStream:  
  50.         {  
  51.             // This may result in an app illegal state exception.  
  52.             ALOGE("Message 0x%x was not handled", msg->what());  
  53.             mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);  
  54.             return true;  
  55.         }  
  56.   
  57.         case ACodec::kWhatOMXDied:  
  58.         {  
  59.             // This will result in kFlagSawMediaServerDie handling in MediaCodec.  
  60.             ALOGE("OMX/mediaserver died, signalling error!");  
  61.             mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);  
  62.             break;  
  63.         }  
  64.   
  65.         case ACodec::kWhatReleaseCodecInstance:  
  66.         {  
  67.             ALOGI("[%s] forcing the release of codec",  
  68.                     mCodec->mComponentName.c_str());  
  69.             status_t err = mCodec->mOMX->freeNode(mCodec->mNode);  
  70.             ALOGE_IF("[%s] failed to release codec instance: err=%d",  
  71.                        mCodec->mComponentName.c_str(), err);  
  72.             sp notify = mCodec->mNotify->dup();  
  73.             notify->setInt32("what", CodecBase::kWhatShutdownCompleted);  
  74.             notify->post();  
  75.             break;  
  76.         }  
  77.   
  78.         default:  
  79.             return false;  
  80.     }  
  81.   
  82.     return true;  
  83. }  


8.ACodec的onOutputBufferDrained(msg);//真正的硬件渲染
[cpp]  view plain  copy
  1. void ACodec::BaseState::onOutputBufferDrained(const sp &msg) {  
  2.     IOMX::buffer_id bufferID;  
  3.     CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));//找到bufferID  
  4.     ssize_t index;  
  5.     BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);//根据bufferID找到ACodec的BufferInfo  
  6.     BufferInfo::Status status = BufferInfo::getSafeStatus(info);  
  7.     if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {  
  8.         ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);  
  9.         mCodec->dumpBuffers(kPortIndexOutput);  
  10.         mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);  
  11.         return;  
  12.     }  
  13.   
  14.     android_native_rect_t crop;  
  15.     if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {  
  16.         status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);  
  17.         ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);  
  18.     }  
  19.   
  20.     bool skip = mCodec->getDSModeHint(msg);  
  21.     int32_t render;  
  22.     if (!skip && mCodec->mNativeWindow != NULL //mCodec->mNativeWindow != NULL 才用硬件渲染。软件渲染在MediaCodec的onReleaseOutputBuffer已经用SoftwareRender处理  
  23.             && msg->findInt32("render", &render) && render != 0  
  24.             && info->mData != NULL && info->mData->size() != 0) {  
  25.         ATRACE_NAME("render");  
  26.         // The client wants this buffer to be rendered.  
  27.   
  28.         // save buffers sent to the surface so we can get render time when they return  
  29.         int64_t mediaTimeUs = -1;  
  30.         info->mData->meta()->findInt64("timeUs", &mediaTimeUs);  
  31.         if (mediaTimeUs >= 0) {  
  32.             mCodec->mRenderTracker.onFrameQueued(  
  33.                     mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));  
  34.         }  
  35.   
  36.         int64_t timestampNs = 0;  
  37.         if (!msg->findInt64("timestampNs", ×tampNs)) {  
  38.             // use media timestamp if client did not request a specific render timestamp  
  39.             if (info->mData->meta()->findInt64("timeUs", ×tampNs)) {  
  40.                 ALOGV("using buffer PTS of %lld", (long long)timestampNs);  
  41.                 timestampNs *= 1000;  
  42.             }  
  43.         }  
  44.   
  45.         status_t err;  
  46.         err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);//使用timestampNs  
  47.         ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);  
  48.   
  49.         info->checkReadFence("onOutputBufferDrained before queueBuffer");  
  50.         err = mCodec->mNativeWindow->queueBuffer(  
  51.                     mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);//插入mNaiveWindow(surface)进行渲染  
  52.         info->mFenceFd = -1;  
  53.         if (err == OK) {  
  54.             info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;  
  55.         } else {  
  56.             ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);  
  57.             mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));  
  58.             info->mStatus = BufferInfo::OWNED_BY_US;  
  59.             // keeping read fence as write fence to avoid clobbering  
  60.             info->mIsReadFence = false;  
  61.         }  
  62.     } else {  
  63.         if (mCodec->mNativeWindow != NULL &&  
  64.             (info->mData == NULL || info->mData->size() != 0)) {  
  65.             // move read fence into write fence to avoid clobbering  
  66.             info->mIsReadFence = false;  
  67.             ATRACE_NAME("frame-drop");  
  68.         }  
  69.         info->mStatus = BufferInfo::OWNED_BY_US;  
  70.     }  
  71.   
  72.     PortMode mode = getPortMode(kPortIndexOutput);  
  73.   
  74.     switch (mode) {  
  75.         case KEEP_BUFFERS:  
  76.         {  
  77.             // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?  
  78.   
  79.             if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {  
  80.                 // We cannot resubmit the buffer we just rendered, dequeue  
  81.                 // the spare instead.  
  82.   
  83.                 info = mCodec->dequeueBufferFromNativeWindow();  
  84.             }  
  85.             break;  
  86.         }  
  87.   
  88.         case RESUBMIT_BUFFERS:  
  89.         {  
  90.             if (!mCodec->mPortEOS[kPortIndexOutput]) {  
  91.                 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {  
  92.                     // We cannot resubmit the buffer we just rendered, dequeue  
  93.                     // the spare instead.  
  94.   
  95.                     info = mCodec->dequeueBufferFromNativeWindow();  
  96.                 }  
  97.   
  98.                 if (info != NULL) {  
  99.                     ALOGV("[%s] calling fillBuffer %u",  
  100.                          mCodec->mComponentName.c_str(), info->mBufferID);  
  101.                     info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");  
  102.                     status_t err = mCodec->mOMX->fillBuffer(  
  103.                             mCodec->mNode, info->mBufferID, info->mFenceFd);//渲染之后重新填充buffer,然后回调onOMXFillBufferDone  
  104.                     info->mFenceFd = -1;  
  105.                     if (err == OK) {  
  106.                         info->mStatus = BufferInfo::OWNED_BY_COMPONENT;  
  107.                     } else {  
  108.                         mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));  
  109.                     }  
  110.                 }  
  111.             }  
  112.             break;  
  113.         }  
  114.   
  115.         case FREE_BUFFERS:  
  116.         {  
  117.             status_t err = mCodec->freeBuffer(kPortIndexOutput, index);  
  118.             if (err != OK) {  
  119.                 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));  
  120.             }  
  121.             break;  
  122.         }  
  123.   
  124.         default:  
  125.             ALOGE("Invalid port mode: %d", mode);  
  126.             return;  
  127.     }  
  128. }  






你可能感兴趣的:(media)