diff options
Diffstat (limited to 'media/libstagefright/ACodec.cpp')
-rw-r--r-- | media/libstagefright/ACodec.cpp | 3492 |
1 files changed, 0 insertions, 3492 deletions
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp deleted file mode 100644 index db2beda..0000000 --- a/media/libstagefright/ACodec.cpp +++ /dev/null @@ -1,3492 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "ACodec" - -#include <media/stagefright/ACodec.h> - -#include <binder/MemoryDealer.h> - -#include <media/stagefright/foundation/hexdump.h> -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AMessage.h> - -#include <media/stagefright/MediaCodecList.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/NativeWindowWrapper.h> -#include <media/stagefright/OMXClient.h> -#include <media/stagefright/OMXCodec.h> - -#include <OMX_Component.h> - -namespace android { - -template<class T> -static void InitOMXParams(T *params) { - params->nSize = sizeof(T); - params->nVersion.s.nVersionMajor = 1; - params->nVersion.s.nVersionMinor = 0; - params->nVersion.s.nRevision = 0; - params->nVersion.s.nStep = 0; -} - -struct CodecObserver : public BnOMXObserver { - CodecObserver() {} - - void setNotificationMessage(const sp<AMessage> &msg) { - mNotify = msg; - } - - // from IOMXObserver - virtual void onMessage(const omx_message &omx_msg) { - sp<AMessage> msg = mNotify->dup(); - - msg->setInt32("type", omx_msg.type); - msg->setPointer("node", omx_msg.node); - - switch (omx_msg.type) { - case omx_message::EVENT: - { - msg->setInt32("event", omx_msg.u.event_data.event); - msg->setInt32("data1", omx_msg.u.event_data.data1); - msg->setInt32("data2", omx_msg.u.event_data.data2); - break; - } - - case omx_message::EMPTY_BUFFER_DONE: - { - msg->setPointer("buffer", omx_msg.u.buffer_data.buffer); - break; - } - - case omx_message::FILL_BUFFER_DONE: - { - msg->setPointer( - "buffer", omx_msg.u.extended_buffer_data.buffer); - msg->setInt32( - "range_offset", - omx_msg.u.extended_buffer_data.range_offset); - msg->setInt32( - "range_length", - omx_msg.u.extended_buffer_data.range_length); - msg->setInt32( - "flags", - omx_msg.u.extended_buffer_data.flags); - msg->setInt64( - "timestamp", - omx_msg.u.extended_buffer_data.timestamp); - msg->setPointer( - "platform_private", - omx_msg.u.extended_buffer_data.platform_private); - msg->setPointer( - "data_ptr", - omx_msg.u.extended_buffer_data.data_ptr); - break; - } - - default: - TRESPASS(); - break; - } - - msg->post(); - } - -protected: - virtual ~CodecObserver() {} - -private: - sp<AMessage> mNotify; - - DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::BaseState : public AState { - BaseState(ACodec *codec, const sp<AState> &parentState = NULL); - -protected: - enum PortMode { - KEEP_BUFFERS, - RESUBMIT_BUFFERS, - FREE_BUFFERS, - }; - - ACodec *mCodec; - - virtual PortMode getPortMode(OMX_U32 portIndex); - - virtual bool onMessageReceived(const sp<AMessage> &msg); - - virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - - virtual void onOutputBufferDrained(const sp<AMessage> &msg); - virtual void onInputBufferFilled(const sp<AMessage> &msg); - - void postFillThisBuffer(BufferInfo *info); - -private: - bool onOMXMessage(const sp<AMessage> &msg); - - bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID); - - bool onOMXFillBufferDone( - IOMX::buffer_id bufferID, - size_t rangeOffset, size_t rangeLength, - OMX_U32 flags, - int64_t timeUs, - void *platformPrivate, - void *dataPtr); - - void getMoreInputDataIfPossible(); - - DISALLOW_EVIL_CONSTRUCTORS(BaseState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::UninitializedState : public ACodec::BaseState { - UninitializedState(ACodec *codec); - -protected: - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual void stateEntered(); - -private: - void onSetup(const sp<AMessage> &msg); - bool onAllocateComponent(const sp<AMessage> &msg); - - DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::LoadedState : public ACodec::BaseState { - LoadedState(ACodec *codec); - -protected: - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual void stateEntered(); - -private: - friend struct ACodec::UninitializedState; - - bool onConfigureComponent(const sp<AMessage> &msg); - void onStart(); - void onShutdown(bool keepComponentAllocated); - - DISALLOW_EVIL_CONSTRUCTORS(LoadedState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::LoadedToIdleState : public ACodec::BaseState { - LoadedToIdleState(ACodec *codec); - -protected: - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - virtual void stateEntered(); - -private: - status_t allocateBuffers(); - - DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::IdleToExecutingState : public ACodec::BaseState { - IdleToExecutingState(ACodec *codec); - -protected: - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - virtual void stateEntered(); - -private: - DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::ExecutingState : public ACodec::BaseState { - ExecutingState(ACodec *codec); - - void submitOutputBuffers(); - - // Submit output buffers to the decoder, submit input buffers to client - // to fill with data. - void resume(); - - // Returns true iff input and output buffers are in play. - bool active() const { return mActive; } - -protected: - virtual PortMode getPortMode(OMX_U32 portIndex); - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual void stateEntered(); - - virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - -private: - bool mActive; - - DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { - OutputPortSettingsChangedState(ACodec *codec); - -protected: - virtual PortMode getPortMode(OMX_U32 portIndex); - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual void stateEntered(); - - virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - -private: - DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::ExecutingToIdleState : public ACodec::BaseState { - ExecutingToIdleState(ACodec *codec); - -protected: - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual void stateEntered(); - - virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - - virtual void onOutputBufferDrained(const sp<AMessage> &msg); - virtual void onInputBufferFilled(const sp<AMessage> &msg); - -private: - void changeStateIfWeOwnAllBuffers(); - - bool mComponentNowIdle; - - DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::IdleToLoadedState : public ACodec::BaseState { - IdleToLoadedState(ACodec *codec); - -protected: - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual void stateEntered(); - - virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - -private: - DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct ACodec::FlushingState : public ACodec::BaseState { - FlushingState(ACodec *codec); - -protected: - virtual bool onMessageReceived(const sp<AMessage> &msg); - virtual void stateEntered(); - - virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - - virtual void onOutputBufferDrained(const sp<AMessage> &msg); - virtual void onInputBufferFilled(const sp<AMessage> &msg); - -private: - bool mFlushComplete[2]; - - void changeStateIfWeOwnAllBuffers(); - - DISALLOW_EVIL_CONSTRUCTORS(FlushingState); -}; - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::ACodec() - : mQuirks(0), - mNode(NULL), - mSentFormat(false), - mIsEncoder(false), - mShutdownInProgress(false) { - 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::~ACodec() { -} - -void ACodec::setNotificationMessage(const sp<AMessage> &msg) { - mNotify = msg; -} - -void ACodec::initiateSetup(const sp<AMessage> &msg) { - msg->setWhat(kWhatSetup); - msg->setTarget(id()); - msg->post(); -} - -void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { - msg->setWhat(kWhatAllocateComponent); - msg->setTarget(id()); - msg->post(); -} - -void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { - msg->setWhat(kWhatConfigureComponent); - msg->setTarget(id()); - msg->post(); -} - -void ACodec::initiateStart() { - (new AMessage(kWhatStart, id()))->post(); -} - -void ACodec::signalFlush() { - ALOGV("[%s] signalFlush", mComponentName.c_str()); - (new AMessage(kWhatFlush, id()))->post(); -} - -void ACodec::signalResume() { - (new AMessage(kWhatResume, id()))->post(); -} - -void ACodec::initiateShutdown(bool keepComponentAllocated) { - sp<AMessage> msg = new AMessage(kWhatShutdown, id()); - msg->setInt32("keepComponentAllocated", keepComponentAllocated); - msg->post(); -} - -status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { - CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); - - CHECK(mDealer[portIndex] == NULL); - CHECK(mBuffers[portIndex].isEmpty()); - - status_t err; - if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { - err = allocateOutputBuffersFromNativeWindow(); - } else { - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - def.nPortIndex = portIndex; - - err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err == OK) { - ALOGV("[%s] Allocating %lu buffers of size %lu on %s port", - mComponentName.c_str(), - def.nBufferCountActual, def.nBufferSize, - portIndex == kPortIndexInput ? "input" : "output"); - - size_t totalSize = def.nBufferCountActual * def.nBufferSize; - mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); - - for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { - sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); - CHECK(mem.get() != NULL); - - BufferInfo info; - info.mStatus = BufferInfo::OWNED_BY_US; - - uint32_t requiresAllocateBufferBit = - (portIndex == kPortIndexInput) - ? OMXCodec::kRequiresAllocateBufferOnInputPorts - : OMXCodec::kRequiresAllocateBufferOnOutputPorts; - - if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) { - mem.clear(); - - void *ptr; - err = mOMX->allocateBuffer( - mNode, portIndex, def.nBufferSize, &info.mBufferID, - &ptr); - - info.mData = new ABuffer(ptr, def.nBufferSize); - } else if (mQuirks & requiresAllocateBufferBit) { - err = mOMX->allocateBufferWithBackup( - mNode, portIndex, mem, &info.mBufferID); - } else { - err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID); - } - - if (mem != NULL) { - info.mData = new ABuffer(mem->pointer(), def.nBufferSize); - } - - mBuffers[portIndex].push(info); - } - } - } - - if (err != OK) { - return err; - } - - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", ACodec::kWhatBuffersAllocated); - - notify->setInt32("portIndex", portIndex); - for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { - AString name = StringPrintf("buffer-id_%d", i); - notify->setPointer(name.c_str(), mBuffers[portIndex][i].mBufferID); - - name = StringPrintf("data_%d", i); - notify->setBuffer(name.c_str(), mBuffers[portIndex][i].mData); - } - - notify->post(); - - return OK; -} - -status_t ACodec::allocateOutputBuffersFromNativeWindow() { - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - def.nPortIndex = kPortIndexOutput; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - err = native_window_set_scaling_mode(mNativeWindow.get(), - NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - - if (err != OK) { - return err; - } - - err = native_window_set_buffers_geometry( - mNativeWindow.get(), - def.format.video.nFrameWidth, - def.format.video.nFrameHeight, - def.format.video.eColorFormat); - - if (err != 0) { - ALOGE("native_window_set_buffers_geometry failed: %s (%d)", - strerror(-err), -err); - return err; - } - - // Set up the native window. - OMX_U32 usage = 0; - err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); - if (err != 0) { - ALOGW("querying usage flags from OMX IL component failed: %d", err); - // XXX: Currently this error is logged, but not fatal. - usage = 0; - } - - err = native_window_set_usage( - mNativeWindow.get(), - usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); - - if (err != 0) { - ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); - return err; - } - - int minUndequeuedBufs = 0; - err = mNativeWindow->query( - mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, - &minUndequeuedBufs); - - if (err != 0) { - ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", - strerror(-err), -err); - return err; - } - - // XXX: Is this the right logic to use? It's not clear to me what the OMX - // buffer counts refer to - how do they account for the renderer holding on - // to buffers? - if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) { - OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs; - def.nBufferCountActual = newBufferCount; - err = mOMX->setParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - ALOGE("[%s] setting nBufferCountActual to %lu failed: %d", - mComponentName.c_str(), newBufferCount, err); - return err; - } - } - - err = native_window_set_buffer_count( - mNativeWindow.get(), def.nBufferCountActual); - - if (err != 0) { - ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), - -err); - return err; - } - - ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on " - "output port", - mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize); - - // Dequeue buffers and send them to OMX - for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) { - ANativeWindowBuffer *buf; - err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf); - if (err != 0) { - ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); - break; - } - - sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); - BufferInfo info; - info.mStatus = BufferInfo::OWNED_BY_US; - info.mData = new ABuffer(0); - info.mGraphicBuffer = graphicBuffer; - mBuffers[kPortIndexOutput].push(info); - - IOMX::buffer_id bufferId; - err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, - &bufferId); - if (err != 0) { - ALOGE("registering GraphicBuffer %lu with OMX IL component failed: " - "%d", i, err); - break; - } - - mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; - - ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)", - mComponentName.c_str(), - bufferId, graphicBuffer.get()); - } - - OMX_U32 cancelStart; - OMX_U32 cancelEnd; - - if (err != 0) { - // If an error occurred while dequeuing we need to cancel any buffers - // that were dequeued. - cancelStart = 0; - cancelEnd = mBuffers[kPortIndexOutput].size(); - } else { - // Return the last two buffers to the native window. - cancelStart = def.nBufferCountActual - minUndequeuedBufs; - cancelEnd = def.nBufferCountActual; - } - - for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { - BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); - cancelBufferToNativeWindow(info); - } - - return err; -} - -status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { - CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); - - ALOGV("[%s] Calling cancelBuffer on buffer %p", - mComponentName.c_str(), info->mBufferID); - - int err = mNativeWindow->cancelBuffer( - mNativeWindow.get(), info->mGraphicBuffer.get()); - - CHECK_EQ(err, 0); - - info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; - - return OK; -} - -ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { - ANativeWindowBuffer *buf; - if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) { - ALOGE("dequeueBuffer failed."); - return NULL; - } - - for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { - BufferInfo *info = - &mBuffers[kPortIndexOutput].editItemAt(i); - - if (info->mGraphicBuffer->handle == buf->handle) { - CHECK_EQ((int)info->mStatus, - (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); - - info->mStatus = BufferInfo::OWNED_BY_US; - - return info; - } - } - - TRESPASS(); - - return NULL; -} - -status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { - for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { - CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); - } - - mDealer[portIndex].clear(); - - return OK; -} - -status_t ACodec::freeOutputBuffersNotOwnedByComponent() { - for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { - BufferInfo *info = - &mBuffers[kPortIndexOutput].editItemAt(i); - - if (info->mStatus != - BufferInfo::OWNED_BY_COMPONENT) { - // We shouldn't have sent out any buffers to the client at this - // point. - CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); - - CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); - } - } - - return OK; -} - -status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { - BufferInfo *info = &mBuffers[portIndex].editItemAt(i); - - CHECK(info->mStatus == BufferInfo::OWNED_BY_US - || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); - - if (portIndex == kPortIndexOutput && mNativeWindow != NULL - && info->mStatus == BufferInfo::OWNED_BY_US) { - CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info)); - } - - CHECK_EQ(mOMX->freeBuffer( - mNode, portIndex, info->mBufferID), - (status_t)OK); - - mBuffers[portIndex].removeAt(i); - - return OK; -} - -ACodec::BufferInfo *ACodec::findBufferByID( - uint32_t portIndex, IOMX::buffer_id bufferID, - ssize_t *index) { - for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { - BufferInfo *info = &mBuffers[portIndex].editItemAt(i); - - if (info->mBufferID == bufferID) { - if (index != NULL) { - *index = i; - } - return info; - } - } - - TRESPASS(); - - return NULL; -} - -status_t ACodec::setComponentRole( - bool isEncoder, const char *mime) { - struct MimeToRole { - const char *mime; - const char *decoderRole; - const char *encoderRole; - }; - - static const MimeToRole kMimeToRole[] = { - { MEDIA_MIMETYPE_AUDIO_MPEG, - "audio_decoder.mp3", "audio_encoder.mp3" }, - { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, - "audio_decoder.mp1", "audio_encoder.mp1" }, - { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, - "audio_decoder.mp2", "audio_encoder.mp2" }, - { MEDIA_MIMETYPE_AUDIO_AMR_NB, - "audio_decoder.amrnb", "audio_encoder.amrnb" }, - { MEDIA_MIMETYPE_AUDIO_AMR_WB, - "audio_decoder.amrwb", "audio_encoder.amrwb" }, - { MEDIA_MIMETYPE_AUDIO_AAC, - "audio_decoder.aac", "audio_encoder.aac" }, - { MEDIA_MIMETYPE_AUDIO_VORBIS, - "audio_decoder.vorbis", "audio_encoder.vorbis" }, - { MEDIA_MIMETYPE_AUDIO_G711_MLAW, - "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, - { MEDIA_MIMETYPE_AUDIO_G711_ALAW, - "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, - { MEDIA_MIMETYPE_VIDEO_AVC, - "video_decoder.avc", "video_encoder.avc" }, - { MEDIA_MIMETYPE_VIDEO_MPEG4, - "video_decoder.mpeg4", "video_encoder.mpeg4" }, - { MEDIA_MIMETYPE_VIDEO_H263, - "video_decoder.h263", "video_encoder.h263" }, - { MEDIA_MIMETYPE_VIDEO_VPX, - "video_decoder.vpx", "video_encoder.vpx" }, - }; - - static const size_t kNumMimeToRole = - sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); - - size_t i; - for (i = 0; i < kNumMimeToRole; ++i) { - if (!strcasecmp(mime, kMimeToRole[i].mime)) { - break; - } - } - - if (i == kNumMimeToRole) { - return ERROR_UNSUPPORTED; - } - - const char *role = - isEncoder ? kMimeToRole[i].encoderRole - : kMimeToRole[i].decoderRole; - - if (role != NULL) { - OMX_PARAM_COMPONENTROLETYPE roleParams; - InitOMXParams(&roleParams); - - strncpy((char *)roleParams.cRole, - role, OMX_MAX_STRINGNAME_SIZE - 1); - - roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; - - status_t err = mOMX->setParameter( - mNode, OMX_IndexParamStandardComponentRole, - &roleParams, sizeof(roleParams)); - - if (err != OK) { - ALOGW("[%s] Failed to set standard component role '%s'.", - mComponentName.c_str(), role); - - return err; - } - } - - return OK; -} - -status_t ACodec::configureCodec( - const char *mime, const sp<AMessage> &msg) { - int32_t encoder; - if (!msg->findInt32("encoder", &encoder)) { - encoder = false; - } - - mIsEncoder = encoder; - - status_t err = setComponentRole(encoder /* isEncoder */, mime); - - if (err != OK) { - return err; - } - - int32_t bitRate = 0; - if (encoder && !msg->findInt32("bitrate", &bitRate)) { - return INVALID_OPERATION; - } - - if (!strncasecmp(mime, "video/", 6)) { - if (encoder) { - err = setupVideoEncoder(mime, msg); - } else { - int32_t width, height; - if (!msg->findInt32("width", &width) - || !msg->findInt32("height", &height)) { - err = INVALID_OPERATION; - } else { - err = setupVideoDecoder(mime, width, height); - } - } - } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { - int32_t numChannels, sampleRate; - if (!msg->findInt32("channel-count", &numChannels) - || !msg->findInt32("sample-rate", &sampleRate)) { - err = INVALID_OPERATION; - } else { - int32_t isADTS; - if (!msg->findInt32("is-adts", &isADTS)) { - isADTS = 0; - } - - err = setupAACCodec( - encoder, numChannels, sampleRate, bitRate, isADTS != 0); - } - } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { - err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); - } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { - err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); - } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) - || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { - // These are PCM-like formats with a fixed sample rate but - // a variable number of channels. - - int32_t numChannels; - if (!msg->findInt32("channel-count", &numChannels)) { - err = INVALID_OPERATION; - } else { - err = setupG711Codec(encoder, numChannels); - } - } - - int32_t maxInputSize; - if (msg->findInt32("max-input-size", &maxInputSize)) { - err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); - } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { - err = setMinBufferSize(kPortIndexInput, 8192); // XXX - } - - return err; -} - -status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - def.nPortIndex = portIndex; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - if (def.nBufferSize >= size) { - return OK; - } - - def.nBufferSize = size; - - err = mOMX->setParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - CHECK(def.nBufferSize >= size); - - return OK; -} - -status_t ACodec::selectAudioPortFormat( - OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { - OMX_AUDIO_PARAM_PORTFORMATTYPE format; - InitOMXParams(&format); - - format.nPortIndex = portIndex; - for (OMX_U32 index = 0;; ++index) { - format.nIndex = index; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamAudioPortFormat, - &format, sizeof(format)); - - if (err != OK) { - return err; - } - - if (format.eEncoding == desiredFormat) { - break; - } - } - - return mOMX->setParameter( - mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); -} - -status_t ACodec::setupAACCodec( - bool encoder, - int32_t numChannels, int32_t sampleRate, int32_t bitRate, bool isADTS) { - if (encoder && isADTS) { - return -EINVAL; - } - - status_t err = setupRawAudioFormat( - encoder ? kPortIndexInput : kPortIndexOutput, - sampleRate, - numChannels); - - if (err != OK) { - return err; - } - - if (encoder) { - err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); - - if (err != OK) { - return err; - } - - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - def.nPortIndex = kPortIndexOutput; - - err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - def.format.audio.bFlagErrorConcealment = OMX_TRUE; - def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; - - err = mOMX->setParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - OMX_AUDIO_PARAM_AACPROFILETYPE profile; - InitOMXParams(&profile); - profile.nPortIndex = kPortIndexOutput; - - err = mOMX->getParameter( - mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); - - if (err != OK) { - return err; - } - - profile.nChannels = numChannels; - - profile.eChannelMode = - (numChannels == 1) - ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; - - profile.nSampleRate = sampleRate; - profile.nBitRate = bitRate; - profile.nAudioBandWidth = 0; - profile.nFrameLength = 0; - profile.nAACtools = OMX_AUDIO_AACToolAll; - profile.nAACERtools = OMX_AUDIO_AACERNone; - profile.eAACProfile = OMX_AUDIO_AACObjectLC; - profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; - - err = mOMX->setParameter( - mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); - - if (err != OK) { - return err; - } - - return err; - } - - OMX_AUDIO_PARAM_AACPROFILETYPE profile; - InitOMXParams(&profile); - profile.nPortIndex = kPortIndexInput; - - err = mOMX->getParameter( - mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); - - if (err != OK) { - return err; - } - - profile.nChannels = numChannels; - profile.nSampleRate = sampleRate; - - profile.eAACStreamFormat = - isADTS - ? OMX_AUDIO_AACStreamFormatMP4ADTS - : OMX_AUDIO_AACStreamFormatMP4FF; - - return mOMX->setParameter( - mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); -} - -static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( - bool isAMRWB, int32_t bps) { - if (isAMRWB) { - if (bps <= 6600) { - return OMX_AUDIO_AMRBandModeWB0; - } else if (bps <= 8850) { - return OMX_AUDIO_AMRBandModeWB1; - } else if (bps <= 12650) { - return OMX_AUDIO_AMRBandModeWB2; - } else if (bps <= 14250) { - return OMX_AUDIO_AMRBandModeWB3; - } else if (bps <= 15850) { - return OMX_AUDIO_AMRBandModeWB4; - } else if (bps <= 18250) { - return OMX_AUDIO_AMRBandModeWB5; - } else if (bps <= 19850) { - return OMX_AUDIO_AMRBandModeWB6; - } else if (bps <= 23050) { - return OMX_AUDIO_AMRBandModeWB7; - } - - // 23850 bps - return OMX_AUDIO_AMRBandModeWB8; - } else { // AMRNB - if (bps <= 4750) { - return OMX_AUDIO_AMRBandModeNB0; - } else if (bps <= 5150) { - return OMX_AUDIO_AMRBandModeNB1; - } else if (bps <= 5900) { - return OMX_AUDIO_AMRBandModeNB2; - } else if (bps <= 6700) { - return OMX_AUDIO_AMRBandModeNB3; - } else if (bps <= 7400) { - return OMX_AUDIO_AMRBandModeNB4; - } else if (bps <= 7950) { - return OMX_AUDIO_AMRBandModeNB5; - } else if (bps <= 10200) { - return OMX_AUDIO_AMRBandModeNB6; - } - - // 12200 bps - return OMX_AUDIO_AMRBandModeNB7; - } -} - -status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { - OMX_AUDIO_PARAM_AMRTYPE def; - InitOMXParams(&def); - def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; - - status_t err = - mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; - def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); - - err = mOMX->setParameter( - mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - return setupRawAudioFormat( - encoder ? kPortIndexInput : kPortIndexOutput, - isWAMR ? 16000 : 8000 /* sampleRate */, - 1 /* numChannels */); -} - -status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) { - CHECK(!encoder); // XXX TODO - - return setupRawAudioFormat( - kPortIndexInput, 8000 /* sampleRate */, numChannels); -} - -status_t ACodec::setupRawAudioFormat( - OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - def.nPortIndex = portIndex; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; - - err = mOMX->setParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; - InitOMXParams(&pcmParams); - pcmParams.nPortIndex = portIndex; - - err = mOMX->getParameter( - mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); - - if (err != OK) { - return err; - } - - pcmParams.nChannels = numChannels; - pcmParams.eNumData = OMX_NumericalDataSigned; - pcmParams.bInterleaved = OMX_TRUE; - pcmParams.nBitPerSample = 16; - pcmParams.nSamplingRate = sampleRate; - pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; - - if (numChannels == 1) { - pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF; - } else { - CHECK_EQ(numChannels, 2); - - pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF; - pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF; - } - - return mOMX->setParameter( - mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); -} - -status_t ACodec::setVideoPortFormatType( - OMX_U32 portIndex, - OMX_VIDEO_CODINGTYPE compressionFormat, - OMX_COLOR_FORMATTYPE colorFormat) { - OMX_VIDEO_PARAM_PORTFORMATTYPE format; - InitOMXParams(&format); - format.nPortIndex = portIndex; - format.nIndex = 0; - bool found = false; - - OMX_U32 index = 0; - for (;;) { - format.nIndex = index; - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamVideoPortFormat, - &format, sizeof(format)); - - if (err != OK) { - return err; - } - - // The following assertion is violated by TI's video decoder. - // CHECK_EQ(format.nIndex, index); - - if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { - if (portIndex == kPortIndexInput - && colorFormat == format.eColorFormat) { - // eCompressionFormat does not seem right. - found = true; - break; - } - if (portIndex == kPortIndexOutput - && compressionFormat == format.eCompressionFormat) { - // eColorFormat does not seem right. - found = true; - break; - } - } - - if (format.eCompressionFormat == compressionFormat - && format.eColorFormat == colorFormat) { - found = true; - break; - } - - ++index; - } - - if (!found) { - return UNKNOWN_ERROR; - } - - status_t err = mOMX->setParameter( - mNode, OMX_IndexParamVideoPortFormat, - &format, sizeof(format)); - - return err; -} - -status_t ACodec::setSupportedOutputFormat() { - OMX_VIDEO_PARAM_PORTFORMATTYPE format; - InitOMXParams(&format); - format.nPortIndex = kPortIndexOutput; - format.nIndex = 0; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamVideoPortFormat, - &format, sizeof(format)); - CHECK_EQ(err, (status_t)OK); - CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); - - CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar - || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar - || format.eColorFormat == OMX_COLOR_FormatCbYCrY - || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar - || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); - - return mOMX->setParameter( - mNode, OMX_IndexParamVideoPortFormat, - &format, sizeof(format)); -} - -static status_t GetVideoCodingTypeFromMime( - const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { - if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { - *codingType = OMX_VIDEO_CodingAVC; - } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { - *codingType = OMX_VIDEO_CodingMPEG4; - } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { - *codingType = OMX_VIDEO_CodingH263; - } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { - *codingType = OMX_VIDEO_CodingMPEG2; - } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) { - *codingType = OMX_VIDEO_CodingVPX; - } else { - *codingType = OMX_VIDEO_CodingUnused; - return ERROR_UNSUPPORTED; - } - - return OK; -} - -status_t ACodec::setupVideoDecoder( - const char *mime, int32_t width, int32_t height) { - OMX_VIDEO_CODINGTYPE compressionFormat; - status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); - - if (err != OK) { - return err; - } - - err = setVideoPortFormatType( - kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); - - if (err != OK) { - return err; - } - - err = setSupportedOutputFormat(); - - if (err != OK) { - return err; - } - - err = setVideoFormatOnPort( - kPortIndexInput, width, height, compressionFormat); - - if (err != OK) { - return err; - } - - err = setVideoFormatOnPort( - kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); - - if (err != OK) { - return err; - } - - return OK; -} - -status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { - int32_t tmp; - if (!msg->findInt32("color-format", &tmp)) { - return INVALID_OPERATION; - } - - OMX_COLOR_FORMATTYPE colorFormat = - static_cast<OMX_COLOR_FORMATTYPE>(tmp); - - status_t err = setVideoPortFormatType( - kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); - - if (err != OK) { - ALOGE("[%s] does not support color format %d", - mComponentName.c_str(), colorFormat); - - return err; - } - - /* Input port configuration */ - - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - - OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; - - def.nPortIndex = kPortIndexInput; - - err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - int32_t width, height, bitrate; - if (!msg->findInt32("width", &width) - || !msg->findInt32("height", &height) - || !msg->findInt32("bitrate", &bitrate)) { - return INVALID_OPERATION; - } - - video_def->nFrameWidth = width; - video_def->nFrameHeight = height; - - int32_t stride; - if (!msg->findInt32("stride", &stride)) { - stride = width; - } - - video_def->nStride = stride; - - int32_t sliceHeight; - if (!msg->findInt32("slice-height", &sliceHeight)) { - sliceHeight = height; - } - - video_def->nSliceHeight = sliceHeight; - - def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; - - float frameRate; - if (!msg->findFloat("frame-rate", &frameRate)) { - int32_t tmp; - if (!msg->findInt32("frame-rate", &tmp)) { - return INVALID_OPERATION; - } - frameRate = (float)tmp; - } - - video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); - video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; - video_def->eColorFormat = colorFormat; - - err = mOMX->setParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - ALOGE("[%s] failed to set input port definition parameters.", - mComponentName.c_str()); - - return err; - } - - /* Output port configuration */ - - OMX_VIDEO_CODINGTYPE compressionFormat; - err = GetVideoCodingTypeFromMime(mime, &compressionFormat); - - if (err != OK) { - return err; - } - - err = setVideoPortFormatType( - kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); - - if (err != OK) { - ALOGE("[%s] does not support compression format %d", - mComponentName.c_str(), compressionFormat); - - return err; - } - - def.nPortIndex = kPortIndexOutput; - - err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - return err; - } - - video_def->nFrameWidth = width; - video_def->nFrameHeight = height; - video_def->xFramerate = 0; - video_def->nBitrate = bitrate; - video_def->eCompressionFormat = compressionFormat; - video_def->eColorFormat = OMX_COLOR_FormatUnused; - - err = mOMX->setParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - if (err != OK) { - ALOGE("[%s] failed to set output port definition parameters.", - mComponentName.c_str()); - - return err; - } - - switch (compressionFormat) { - case OMX_VIDEO_CodingMPEG4: - err = setupMPEG4EncoderParameters(msg); - break; - - case OMX_VIDEO_CodingH263: - err = setupH263EncoderParameters(msg); - break; - - case OMX_VIDEO_CodingAVC: - err = setupAVCEncoderParameters(msg); - break; - - default: - break; - } - - ALOGI("setupVideoEncoder succeeded"); - - return err; -} - -static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { - if (iFramesInterval < 0) { - return 0xFFFFFFFF; - } else if (iFramesInterval == 0) { - return 0; - } - OMX_U32 ret = frameRate * iFramesInterval; - CHECK(ret > 1); - return ret; -} - -status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { - int32_t bitrate, iFrameInterval; - if (!msg->findInt32("bitrate", &bitrate) - || !msg->findInt32("i-frame-interval", &iFrameInterval)) { - return INVALID_OPERATION; - } - - float frameRate; - if (!msg->findFloat("frame-rate", &frameRate)) { - int32_t tmp; - if (!msg->findInt32("frame-rate", &tmp)) { - return INVALID_OPERATION; - } - frameRate = (float)tmp; - } - - OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; - InitOMXParams(&mpeg4type); - mpeg4type.nPortIndex = kPortIndexOutput; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); - - if (err != OK) { - return err; - } - - mpeg4type.nSliceHeaderSpacing = 0; - mpeg4type.bSVH = OMX_FALSE; - mpeg4type.bGov = OMX_FALSE; - - mpeg4type.nAllowedPictureTypes = - OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; - - mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); - if (mpeg4type.nPFrames == 0) { - mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; - } - mpeg4type.nBFrames = 0; - mpeg4type.nIDCVLCThreshold = 0; - mpeg4type.bACPred = OMX_TRUE; - mpeg4type.nMaxPacketSize = 256; - mpeg4type.nTimeIncRes = 1000; - mpeg4type.nHeaderExtension = 0; - mpeg4type.bReversibleVLC = OMX_FALSE; - - int32_t profile; - if (msg->findInt32("profile", &profile)) { - int32_t level; - if (!msg->findInt32("level", &level)) { - return INVALID_OPERATION; - } - - err = verifySupportForProfileAndLevel(profile, level); - - if (err != OK) { - return err; - } - - mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); - mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); - } - - err = mOMX->setParameter( - mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); - - if (err != OK) { - return err; - } - - err = configureBitrate(bitrate); - - if (err != OK) { - return err; - } - - return setupErrorCorrectionParameters(); -} - -status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { - int32_t bitrate, iFrameInterval; - if (!msg->findInt32("bitrate", &bitrate) - || !msg->findInt32("i-frame-interval", &iFrameInterval)) { - return INVALID_OPERATION; - } - - float frameRate; - if (!msg->findFloat("frame-rate", &frameRate)) { - int32_t tmp; - if (!msg->findInt32("frame-rate", &tmp)) { - return INVALID_OPERATION; - } - frameRate = (float)tmp; - } - - OMX_VIDEO_PARAM_H263TYPE h263type; - InitOMXParams(&h263type); - h263type.nPortIndex = kPortIndexOutput; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); - - if (err != OK) { - return err; - } - - h263type.nAllowedPictureTypes = - OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; - - h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); - if (h263type.nPFrames == 0) { - h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; - } - h263type.nBFrames = 0; - - int32_t profile; - if (msg->findInt32("profile", &profile)) { - int32_t level; - if (!msg->findInt32("level", &level)) { - return INVALID_OPERATION; - } - - err = verifySupportForProfileAndLevel(profile, level); - - if (err != OK) { - return err; - } - - h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); - h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); - } - - h263type.bPLUSPTYPEAllowed = OMX_FALSE; - h263type.bForceRoundingTypeToZero = OMX_FALSE; - h263type.nPictureHeaderRepetition = 0; - h263type.nGOBHeaderInterval = 0; - - err = mOMX->setParameter( - mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); - - if (err != OK) { - return err; - } - - err = configureBitrate(bitrate); - - if (err != OK) { - return err; - } - - return setupErrorCorrectionParameters(); -} - -status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { - int32_t bitrate, iFrameInterval; - if (!msg->findInt32("bitrate", &bitrate) - || !msg->findInt32("i-frame-interval", &iFrameInterval)) { - return INVALID_OPERATION; - } - - float frameRate; - if (!msg->findFloat("frame-rate", &frameRate)) { - int32_t tmp; - if (!msg->findInt32("frame-rate", &tmp)) { - return INVALID_OPERATION; - } - frameRate = (float)tmp; - } - - OMX_VIDEO_PARAM_AVCTYPE h264type; - InitOMXParams(&h264type); - h264type.nPortIndex = kPortIndexOutput; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); - - if (err != OK) { - return err; - } - - h264type.nAllowedPictureTypes = - OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; - - int32_t profile; - if (msg->findInt32("profile", &profile)) { - int32_t level; - if (!msg->findInt32("level", &level)) { - return INVALID_OPERATION; - } - - err = verifySupportForProfileAndLevel(profile, level); - - if (err != OK) { - return err; - } - - h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); - h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); - } - - // XXX - if (!strncmp(mComponentName.c_str(), "OMX.TI.DUCATI1", 14)) { - h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; - } - - if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { - h264type.nSliceHeaderSpacing = 0; - h264type.bUseHadamard = OMX_TRUE; - h264type.nRefFrames = 1; - h264type.nBFrames = 0; - h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); - if (h264type.nPFrames == 0) { - h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; - } - h264type.nRefIdx10ActiveMinus1 = 0; - h264type.nRefIdx11ActiveMinus1 = 0; - h264type.bEntropyCodingCABAC = OMX_FALSE; - h264type.bWeightedPPrediction = OMX_FALSE; - h264type.bconstIpred = OMX_FALSE; - h264type.bDirect8x8Inference = OMX_FALSE; - h264type.bDirectSpatialTemporal = OMX_FALSE; - h264type.nCabacInitIdc = 0; - } - - if (h264type.nBFrames != 0) { - h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; - } - - h264type.bEnableUEP = OMX_FALSE; - h264type.bEnableFMO = OMX_FALSE; - h264type.bEnableASO = OMX_FALSE; - h264type.bEnableRS = OMX_FALSE; - h264type.bFrameMBsOnly = OMX_TRUE; - h264type.bMBAFF = OMX_FALSE; - h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; - - if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName.c_str())) { - h264type.eLevel = OMX_VIDEO_AVCLevelMax; - } - - err = mOMX->setParameter( - mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); - - if (err != OK) { - return err; - } - - return configureBitrate(bitrate); -} - -status_t ACodec::verifySupportForProfileAndLevel( - int32_t profile, int32_t level) { - OMX_VIDEO_PARAM_PROFILELEVELTYPE params; - InitOMXParams(¶ms); - params.nPortIndex = kPortIndexOutput; - - for (params.nProfileIndex = 0;; ++params.nProfileIndex) { - status_t err = mOMX->getParameter( - mNode, - OMX_IndexParamVideoProfileLevelQuerySupported, - ¶ms, - sizeof(params)); - - if (err != OK) { - return err; - } - - int32_t supportedProfile = static_cast<int32_t>(params.eProfile); - int32_t supportedLevel = static_cast<int32_t>(params.eLevel); - - if (profile == supportedProfile && level <= supportedLevel) { - return OK; - } - } -} - -status_t ACodec::configureBitrate(int32_t bitrate) { - OMX_VIDEO_PARAM_BITRATETYPE bitrateType; - InitOMXParams(&bitrateType); - bitrateType.nPortIndex = kPortIndexOutput; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamVideoBitrate, - &bitrateType, sizeof(bitrateType)); - - if (err != OK) { - return err; - } - - bitrateType.eControlRate = OMX_Video_ControlRateVariable; - bitrateType.nTargetBitrate = bitrate; - - return mOMX->setParameter( - mNode, OMX_IndexParamVideoBitrate, - &bitrateType, sizeof(bitrateType)); -} - -status_t ACodec::setupErrorCorrectionParameters() { - OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; - InitOMXParams(&errorCorrectionType); - errorCorrectionType.nPortIndex = kPortIndexOutput; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamVideoErrorCorrection, - &errorCorrectionType, sizeof(errorCorrectionType)); - - if (err != OK) { - return OK; // Optional feature. Ignore this failure - } - - errorCorrectionType.bEnableHEC = OMX_FALSE; - errorCorrectionType.bEnableResync = OMX_TRUE; - errorCorrectionType.nResynchMarkerSpacing = 256; - errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; - errorCorrectionType.bEnableRVLC = OMX_FALSE; - - return mOMX->setParameter( - mNode, OMX_IndexParamVideoErrorCorrection, - &errorCorrectionType, sizeof(errorCorrectionType)); -} - -status_t ACodec::setVideoFormatOnPort( - OMX_U32 portIndex, - int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - def.nPortIndex = portIndex; - - OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; - - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - CHECK_EQ(err, (status_t)OK); - - if (portIndex == kPortIndexInput) { - // XXX Need a (much) better heuristic to compute input buffer sizes. - const size_t X = 64 * 1024; - if (def.nBufferSize < X) { - def.nBufferSize = X; - } - } - - CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); - - video_def->nFrameWidth = width; - video_def->nFrameHeight = height; - - if (portIndex == kPortIndexInput) { - video_def->eCompressionFormat = compressionFormat; - video_def->eColorFormat = OMX_COLOR_FormatUnused; - } - - err = mOMX->setParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - return err; -} - -status_t ACodec::initNativeWindow() { - if (mNativeWindow != NULL) { - return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); - } - - mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); - return OK; -} - -size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { - size_t n = 0; - - for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { - const BufferInfo &info = mBuffers[portIndex].itemAt(i); - - if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { - ++n; - } - } - - return n; -} - -bool ACodec::allYourBuffersAreBelongToUs( - OMX_U32 portIndex) { - for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { - BufferInfo *info = &mBuffers[portIndex].editItemAt(i); - - if (info->mStatus != BufferInfo::OWNED_BY_US - && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { - ALOGV("[%s] Buffer %p on port %ld still has status %d", - mComponentName.c_str(), - info->mBufferID, portIndex, info->mStatus); - return false; - } - } - - return true; -} - -bool ACodec::allYourBuffersAreBelongToUs() { - return allYourBuffersAreBelongToUs(kPortIndexInput) - && allYourBuffersAreBelongToUs(kPortIndexOutput); -} - -void ACodec::deferMessage(const sp<AMessage> &msg) { - bool wasEmptyBefore = mDeferredQueue.empty(); - mDeferredQueue.push_back(msg); -} - -void ACodec::processDeferredMessages() { - List<sp<AMessage> > queue = mDeferredQueue; - mDeferredQueue.clear(); - - List<sp<AMessage> >::iterator it = queue.begin(); - while (it != queue.end()) { - onMessageReceived(*it++); - } -} - -void ACodec::sendFormatChange() { - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", kWhatOutputFormatChanged); - - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - def.nPortIndex = kPortIndexOutput; - - CHECK_EQ(mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), - (status_t)OK); - - CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); - - switch (def.eDomain) { - case OMX_PortDomainVideo: - { - OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; - - notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); - notify->setInt32("width", videoDef->nFrameWidth); - notify->setInt32("height", videoDef->nFrameHeight); - notify->setInt32("stride", videoDef->nStride); - notify->setInt32("slice-height", videoDef->nSliceHeight); - notify->setInt32("color-format", videoDef->eColorFormat); - - OMX_CONFIG_RECTTYPE rect; - InitOMXParams(&rect); - rect.nPortIndex = kPortIndexOutput; - - if (mOMX->getConfig( - mNode, OMX_IndexConfigCommonOutputCrop, - &rect, sizeof(rect)) != OK) { - rect.nLeft = 0; - rect.nTop = 0; - rect.nWidth = videoDef->nFrameWidth; - rect.nHeight = videoDef->nFrameHeight; - } - - CHECK_GE(rect.nLeft, 0); - CHECK_GE(rect.nTop, 0); - CHECK_GE(rect.nWidth, 0u); - CHECK_GE(rect.nHeight, 0u); - CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); - CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); - - notify->setRect( - "crop", - rect.nLeft, - rect.nTop, - rect.nLeft + rect.nWidth - 1, - rect.nTop + rect.nHeight - 1); - - if (mNativeWindow != NULL) { - android_native_rect_t crop; - crop.left = rect.nLeft; - crop.top = rect.nTop; - crop.right = rect.nLeft + rect.nWidth; - crop.bottom = rect.nTop + rect.nHeight; - - CHECK_EQ(0, native_window_set_crop( - mNativeWindow.get(), &crop)); - } - break; - } - - case OMX_PortDomainAudio: - { - OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; - CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); - - OMX_AUDIO_PARAM_PCMMODETYPE params; - InitOMXParams(¶ms); - params.nPortIndex = kPortIndexOutput; - - CHECK_EQ(mOMX->getParameter( - mNode, OMX_IndexParamAudioPcm, - ¶ms, sizeof(params)), - (status_t)OK); - - CHECK(params.nChannels == 1 || params.bInterleaved); - CHECK_EQ(params.nBitPerSample, 16u); - CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); - CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); - - notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); - notify->setInt32("channel-count", params.nChannels); - notify->setInt32("sample-rate", params.nSamplingRate); - break; - } - - default: - TRESPASS(); - } - - notify->post(); - - mSentFormat = true; -} - -void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", ACodec::kWhatError); - notify->setInt32("omx-error", error); - notify->setInt32("err", internalError); - notify->post(); -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) - : AState(parentState), - mCodec(codec) { -} - -ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { - return KEEP_BUFFERS; -} - -bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatInputBufferFilled: - { - onInputBufferFilled(msg); - break; - } - - case kWhatOutputBufferDrained: - { - onOutputBufferDrained(msg); - break; - } - - case ACodec::kWhatOMXMessage: - { - return onOMXMessage(msg); - } - - default: - return false; - } - - return true; -} - -bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { - int32_t type; - CHECK(msg->findInt32("type", &type)); - - IOMX::node_id nodeID; - CHECK(msg->findPointer("node", &nodeID)); - CHECK_EQ(nodeID, mCodec->mNode); - - switch (type) { - case omx_message::EVENT: - { - int32_t event, data1, data2; - CHECK(msg->findInt32("event", &event)); - CHECK(msg->findInt32("data1", &data1)); - CHECK(msg->findInt32("data2", &data2)); - - if (event == OMX_EventCmdComplete - && data1 == OMX_CommandFlush - && data2 == (int32_t)OMX_ALL) { - // Use of this notification is not consistent across - // implementations. We'll drop this notification and rely - // on flush-complete notifications on the individual port - // indices instead. - - return true; - } - - return onOMXEvent( - static_cast<OMX_EVENTTYPE>(event), - static_cast<OMX_U32>(data1), - static_cast<OMX_U32>(data2)); - } - - case omx_message::EMPTY_BUFFER_DONE: - { - IOMX::buffer_id bufferID; - CHECK(msg->findPointer("buffer", &bufferID)); - - return onOMXEmptyBufferDone(bufferID); - } - - case omx_message::FILL_BUFFER_DONE: - { - IOMX::buffer_id bufferID; - CHECK(msg->findPointer("buffer", &bufferID)); - - int32_t rangeOffset, rangeLength, flags; - int64_t timeUs; - void *platformPrivate; - void *dataPtr; - - CHECK(msg->findInt32("range_offset", &rangeOffset)); - CHECK(msg->findInt32("range_length", &rangeLength)); - CHECK(msg->findInt32("flags", &flags)); - CHECK(msg->findInt64("timestamp", &timeUs)); - CHECK(msg->findPointer("platform_private", &platformPrivate)); - CHECK(msg->findPointer("data_ptr", &dataPtr)); - - return onOMXFillBufferDone( - bufferID, - (size_t)rangeOffset, (size_t)rangeLength, - (OMX_U32)flags, - timeUs, - platformPrivate, - dataPtr); - } - - default: - TRESPASS(); - break; - } -} - -bool ACodec::BaseState::onOMXEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - if (event != OMX_EventError) { - ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", - mCodec->mComponentName.c_str(), event, data1, data2); - - return false; - } - - ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); - - mCodec->signalError((OMX_ERRORTYPE)data1); - - return true; -} - -bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { - ALOGV("[%s] onOMXEmptyBufferDone %p", - mCodec->mComponentName.c_str(), bufferID); - - BufferInfo *info = - mCodec->findBufferByID(kPortIndexInput, bufferID); - - CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); - info->mStatus = BufferInfo::OWNED_BY_US; - - PortMode mode = getPortMode(kPortIndexInput); - - switch (mode) { - case KEEP_BUFFERS: - break; - - case RESUBMIT_BUFFERS: - postFillThisBuffer(info); - break; - - default: - { - CHECK_EQ((int)mode, (int)FREE_BUFFERS); - TRESPASS(); // Not currently used - break; - } - } - - return true; -} - -void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { - if (mCodec->mPortEOS[kPortIndexInput]) { - return; - } - - CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); - - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatFillThisBuffer); - notify->setPointer("buffer-id", info->mBufferID); - - info->mData->meta()->clear(); - notify->setBuffer("buffer", info->mData); - - sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); - reply->setPointer("buffer-id", info->mBufferID); - - notify->setMessage("reply", reply); - - notify->post(); - - info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; -} - -void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { - IOMX::buffer_id bufferID; - CHECK(msg->findPointer("buffer-id", &bufferID)); - - sp<ABuffer> buffer; - int32_t err = OK; - bool eos = false; - - if (!msg->findBuffer("buffer", &buffer)) { - CHECK(msg->findInt32("err", &err)); - - ALOGV("[%s] saw error %d instead of an input buffer", - mCodec->mComponentName.c_str(), err); - - buffer.clear(); - - eos = true; - } - - int32_t tmp; - if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { - eos = true; - err = ERROR_END_OF_STREAM; - } - - BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); - CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); - - info->mStatus = BufferInfo::OWNED_BY_US; - - PortMode mode = getPortMode(kPortIndexInput); - - switch (mode) { - case KEEP_BUFFERS: - { - if (eos) { - if (!mCodec->mPortEOS[kPortIndexInput]) { - mCodec->mPortEOS[kPortIndexInput] = true; - mCodec->mInputEOSResult = err; - } - } - break; - } - - case RESUBMIT_BUFFERS: - { - if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { - int64_t timeUs; - CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); - - OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; - - int32_t isCSD; - if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { - flags |= OMX_BUFFERFLAG_CODECCONFIG; - } - - if (eos) { - flags |= OMX_BUFFERFLAG_EOS; - } - - if (buffer != info->mData) { - if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) { - ALOGV("[%s] Needs to copy input data.", - mCodec->mComponentName.c_str()); - } - - CHECK_LE(buffer->size(), info->mData->capacity()); - memcpy(info->mData->data(), buffer->data(), buffer->size()); - } - - if (flags & OMX_BUFFERFLAG_CODECCONFIG) { - ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", - mCodec->mComponentName.c_str(), bufferID); - } else if (flags & OMX_BUFFERFLAG_EOS) { - ALOGV("[%s] calling emptyBuffer %p w/ EOS", - mCodec->mComponentName.c_str(), bufferID); - } else { - ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", - mCodec->mComponentName.c_str(), bufferID, timeUs); - } - - CHECK_EQ(mCodec->mOMX->emptyBuffer( - mCodec->mNode, - bufferID, - 0, - buffer->size(), - flags, - timeUs), - (status_t)OK); - - info->mStatus = BufferInfo::OWNED_BY_COMPONENT; - - if (!eos) { - getMoreInputDataIfPossible(); - } else { - ALOGV("[%s] Signalled EOS on the input port", - mCodec->mComponentName.c_str()); - - mCodec->mPortEOS[kPortIndexInput] = true; - mCodec->mInputEOSResult = err; - } - } else if (!mCodec->mPortEOS[kPortIndexInput]) { - if (err != ERROR_END_OF_STREAM) { - ALOGV("[%s] Signalling EOS on the input port " - "due to error %d", - mCodec->mComponentName.c_str(), err); - } else { - ALOGV("[%s] Signalling EOS on the input port", - mCodec->mComponentName.c_str()); - } - - ALOGV("[%s] calling emptyBuffer %p signalling EOS", - mCodec->mComponentName.c_str(), bufferID); - - CHECK_EQ(mCodec->mOMX->emptyBuffer( - mCodec->mNode, - bufferID, - 0, - 0, - OMX_BUFFERFLAG_EOS, - 0), - (status_t)OK); - - info->mStatus = BufferInfo::OWNED_BY_COMPONENT; - - mCodec->mPortEOS[kPortIndexInput] = true; - mCodec->mInputEOSResult = err; - } - break; - - default: - CHECK_EQ((int)mode, (int)FREE_BUFFERS); - break; - } - } -} - -void ACodec::BaseState::getMoreInputDataIfPossible() { - if (mCodec->mPortEOS[kPortIndexInput]) { - return; - } - - BufferInfo *eligible = NULL; - - for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { - BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); - -#if 0 - if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { - // There's already a "read" pending. - return; - } -#endif - - if (info->mStatus == BufferInfo::OWNED_BY_US) { - eligible = info; - } - } - - if (eligible == NULL) { - return; - } - - postFillThisBuffer(eligible); -} - -bool ACodec::BaseState::onOMXFillBufferDone( - IOMX::buffer_id bufferID, - size_t rangeOffset, size_t rangeLength, - OMX_U32 flags, - int64_t timeUs, - void *platformPrivate, - void *dataPtr) { - ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", - mCodec->mComponentName.c_str(), bufferID, timeUs, flags); - - ssize_t index; - BufferInfo *info = - mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); - - CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); - - info->mStatus = BufferInfo::OWNED_BY_US; - - PortMode mode = getPortMode(kPortIndexOutput); - - switch (mode) { - case KEEP_BUFFERS: - break; - - case RESUBMIT_BUFFERS: - { - if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { - ALOGV("[%s] calling fillBuffer %p", - mCodec->mComponentName.c_str(), info->mBufferID); - - CHECK_EQ(mCodec->mOMX->fillBuffer( - mCodec->mNode, info->mBufferID), - (status_t)OK); - - info->mStatus = BufferInfo::OWNED_BY_COMPONENT; - break; - } - - if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { - mCodec->sendFormatChange(); - } - - if (mCodec->mNativeWindow == NULL) { - info->mData->setRange(rangeOffset, rangeLength); - } - - info->mData->meta()->setInt64("timeUs", timeUs); - - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatDrainThisBuffer); - notify->setPointer("buffer-id", info->mBufferID); - notify->setBuffer("buffer", info->mData); - notify->setInt32("flags", flags); - - sp<AMessage> reply = - new AMessage(kWhatOutputBufferDrained, mCodec->id()); - - reply->setPointer("buffer-id", info->mBufferID); - - notify->setMessage("reply", reply); - - notify->post(); - - info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; - - if (flags & OMX_BUFFERFLAG_EOS) { - ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); - - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatEOS); - notify->setInt32("err", mCodec->mInputEOSResult); - notify->post(); - - mCodec->mPortEOS[kPortIndexOutput] = true; - } - break; - } - - default: - { - CHECK_EQ((int)mode, (int)FREE_BUFFERS); - - CHECK_EQ((status_t)OK, - mCodec->freeBuffer(kPortIndexOutput, index)); - break; - } - } - - return true; -} - -void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { - IOMX::buffer_id bufferID; - CHECK(msg->findPointer("buffer-id", &bufferID)); - - ssize_t index; - BufferInfo *info = - mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); - CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); - - int32_t render; - if (mCodec->mNativeWindow != NULL - && msg->findInt32("render", &render) && render != 0) { - // The client wants this buffer to be rendered. - - status_t err; - if ((err = mCodec->mNativeWindow->queueBuffer( - mCodec->mNativeWindow.get(), - info->mGraphicBuffer.get())) == OK) { - info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; - } else { - mCodec->signalError(OMX_ErrorUndefined, err); - info->mStatus = BufferInfo::OWNED_BY_US; - } - } else { - info->mStatus = BufferInfo::OWNED_BY_US; - } - - PortMode mode = getPortMode(kPortIndexOutput); - - switch (mode) { - case KEEP_BUFFERS: - { - // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? - - if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { - // We cannot resubmit the buffer we just rendered, dequeue - // the spare instead. - - info = mCodec->dequeueBufferFromNativeWindow(); - } - break; - } - - case RESUBMIT_BUFFERS: - { - if (!mCodec->mPortEOS[kPortIndexOutput]) { - if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { - // We cannot resubmit the buffer we just rendered, dequeue - // the spare instead. - - info = mCodec->dequeueBufferFromNativeWindow(); - } - - if (info != NULL) { - ALOGV("[%s] calling fillBuffer %p", - mCodec->mComponentName.c_str(), info->mBufferID); - - CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), - (status_t)OK); - - info->mStatus = BufferInfo::OWNED_BY_COMPONENT; - } - } - break; - } - - default: - { - CHECK_EQ((int)mode, (int)FREE_BUFFERS); - - CHECK_EQ((status_t)OK, - mCodec->freeBuffer(kPortIndexOutput, index)); - break; - } - } -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::UninitializedState::UninitializedState(ACodec *codec) - : BaseState(codec) { -} - -void ACodec::UninitializedState::stateEntered() { - ALOGV("Now uninitialized"); -} - -bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { - bool handled = false; - - switch (msg->what()) { - case ACodec::kWhatSetup: - { - onSetup(msg); - - handled = true; - break; - } - - case ACodec::kWhatAllocateComponent: - { - onAllocateComponent(msg); - handled = true; - break; - } - - case ACodec::kWhatShutdown: - { - int32_t keepComponentAllocated; - CHECK(msg->findInt32( - "keepComponentAllocated", &keepComponentAllocated)); - CHECK(!keepComponentAllocated); - - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatShutdownCompleted); - notify->post(); - - handled = true; - break; - } - - case ACodec::kWhatFlush: - { - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatFlushCompleted); - notify->post(); - - handled = true; - break; - } - - default: - return BaseState::onMessageReceived(msg); - } - - return handled; -} - -void ACodec::UninitializedState::onSetup( - const sp<AMessage> &msg) { - if (onAllocateComponent(msg) - && mCodec->mLoadedState->onConfigureComponent(msg)) { - mCodec->mLoadedState->onStart(); - } -} - -bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { - ALOGV("onAllocateComponent"); - - CHECK(mCodec->mNode == NULL); - - OMXClient client; - CHECK_EQ(client.connect(), (status_t)OK); - - sp<IOMX> omx = client.interface(); - - Vector<String8> matchingCodecs; - Vector<uint32_t> matchingCodecQuirks; - - AString mime; - - AString componentName; - uint32_t quirks; - if (msg->findString("componentName", &componentName)) { - matchingCodecs.push_back(String8(componentName.c_str())); - - if (!OMXCodec::findCodecQuirks(componentName.c_str(), &quirks)) { - quirks = 0; - } - matchingCodecQuirks.push_back(quirks); - } else { - CHECK(msg->findString("mime", &mime)); - - int32_t encoder; - if (!msg->findInt32("encoder", &encoder)) { - encoder = false; - } - - OMXCodec::findMatchingCodecs( - mime.c_str(), - encoder, // createEncoder - NULL, // matchComponentName - 0, // flags - &matchingCodecs, - &matchingCodecQuirks); - } - - sp<CodecObserver> observer = new CodecObserver; - IOMX::node_id node = NULL; - - for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); - ++matchIndex) { - componentName = matchingCodecs.itemAt(matchIndex).string(); - quirks = matchingCodecQuirks.itemAt(matchIndex); - - pid_t tid = androidGetTid(); - int prevPriority = androidGetThreadPriority(tid); - androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); - status_t err = omx->allocateNode(componentName.c_str(), observer, &node); - androidSetThreadPriority(tid, prevPriority); - - if (err == OK) { - break; - } - - node = NULL; - } - - if (node == NULL) { - if (!mime.empty()) { - ALOGE("Unable to instantiate a decoder for type '%s'.", - mime.c_str()); - } else { - ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); - } - - mCodec->signalError(OMX_ErrorComponentNotFound); - return false; - } - - sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); - observer->setNotificationMessage(notify); - - mCodec->mComponentName = componentName; - mCodec->mFlags = 0; - - if (componentName.endsWith(".secure")) { - mCodec->mFlags |= kFlagIsSecure; - } - - mCodec->mQuirks = quirks; - mCodec->mOMX = omx; - mCodec->mNode = node; - - mCodec->mPortEOS[kPortIndexInput] = - mCodec->mPortEOS[kPortIndexOutput] = false; - - mCodec->mInputEOSResult = OK; - - { - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatComponentAllocated); - notify->setString("componentName", mCodec->mComponentName.c_str()); - notify->post(); - } - - mCodec->changeState(mCodec->mLoadedState); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::LoadedState::LoadedState(ACodec *codec) - : BaseState(codec) { -} - -void ACodec::LoadedState::stateEntered() { - ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); - - if (mCodec->mShutdownInProgress) { - bool keepComponentAllocated = mCodec->mKeepComponentAllocated; - - mCodec->mShutdownInProgress = false; - mCodec->mKeepComponentAllocated = false; - - onShutdown(keepComponentAllocated); - } -} - -void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { - if (!keepComponentAllocated) { - CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); - - mCodec->mNativeWindow.clear(); - mCodec->mNode = NULL; - mCodec->mOMX.clear(); - mCodec->mQuirks = 0; - mCodec->mFlags = 0; - mCodec->mComponentName.clear(); - - mCodec->changeState(mCodec->mUninitializedState); - } - - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatShutdownCompleted); - notify->post(); -} - -bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { - bool handled = false; - - switch (msg->what()) { - case ACodec::kWhatConfigureComponent: - { - onConfigureComponent(msg); - handled = true; - break; - } - - case ACodec::kWhatStart: - { - onStart(); - handled = true; - break; - } - - case ACodec::kWhatShutdown: - { - int32_t keepComponentAllocated; - CHECK(msg->findInt32( - "keepComponentAllocated", &keepComponentAllocated)); - - onShutdown(keepComponentAllocated); - - handled = true; - break; - } - - case ACodec::kWhatFlush: - { - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatFlushCompleted); - notify->post(); - - handled = true; - break; - } - - default: - return BaseState::onMessageReceived(msg); - } - - return handled; -} - -bool ACodec::LoadedState::onConfigureComponent( - const sp<AMessage> &msg) { - ALOGV("onConfigureComponent"); - - CHECK(mCodec->mNode != NULL); - - AString mime; - CHECK(msg->findString("mime", &mime)); - - status_t err = mCodec->configureCodec(mime.c_str(), msg); - - if (err != OK) { - ALOGE("[%s] configureCodec returning error %d", - mCodec->mComponentName.c_str(), err); - - mCodec->signalError(OMX_ErrorUndefined, err); - return false; - } - - sp<RefBase> obj; - if (msg->findObject("native-window", &obj) - && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { - sp<NativeWindowWrapper> nativeWindow( - static_cast<NativeWindowWrapper *>(obj.get())); - CHECK(nativeWindow != NULL); - mCodec->mNativeWindow = nativeWindow->getNativeWindow(); - } - CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); - - { - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatComponentConfigured); - notify->post(); - } - - return true; -} - -void ACodec::LoadedState::onStart() { - ALOGV("onStart"); - - CHECK_EQ(mCodec->mOMX->sendCommand( - mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), - (status_t)OK); - - mCodec->changeState(mCodec->mLoadedToIdleState); -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) - : BaseState(codec) { -} - -void ACodec::LoadedToIdleState::stateEntered() { - ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); - - status_t err; - if ((err = allocateBuffers()) != OK) { - ALOGE("Failed to allocate buffers after transitioning to IDLE state " - "(error 0x%08x)", - err); - - mCodec->signalError(OMX_ErrorUndefined, err); - } -} - -status_t ACodec::LoadedToIdleState::allocateBuffers() { - status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); - - if (err != OK) { - return err; - } - - return mCodec->allocateBuffersOnPort(kPortIndexOutput); -} - -bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatShutdown: - { - mCodec->deferMessage(msg); - return true; - } - - default: - return BaseState::onMessageReceived(msg); - } -} - -bool ACodec::LoadedToIdleState::onOMXEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - switch (event) { - case OMX_EventCmdComplete: - { - CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); - CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); - - CHECK_EQ(mCodec->mOMX->sendCommand( - mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), - (status_t)OK); - - mCodec->changeState(mCodec->mIdleToExecutingState); - - return true; - } - - default: - return BaseState::onOMXEvent(event, data1, data2); - } -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) - : BaseState(codec) { -} - -void ACodec::IdleToExecutingState::stateEntered() { - ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); -} - -bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatShutdown: - { - mCodec->deferMessage(msg); - return true; - } - - default: - return BaseState::onMessageReceived(msg); - } -} - -bool ACodec::IdleToExecutingState::onOMXEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - switch (event) { - case OMX_EventCmdComplete: - { - CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); - CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); - - mCodec->mExecutingState->resume(); - mCodec->changeState(mCodec->mExecutingState); - - return true; - } - - default: - return BaseState::onOMXEvent(event, data1, data2); - } -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::ExecutingState::ExecutingState(ACodec *codec) - : BaseState(codec), - mActive(false) { -} - -ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( - OMX_U32 portIndex) { - return RESUBMIT_BUFFERS; -} - -void ACodec::ExecutingState::submitOutputBuffers() { - for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { - BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); - - if (mCodec->mNativeWindow != NULL) { - CHECK(info->mStatus == BufferInfo::OWNED_BY_US - || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); - - if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { - continue; - } - - status_t err = mCodec->mNativeWindow->lockBuffer( - mCodec->mNativeWindow.get(), - info->mGraphicBuffer.get()); - CHECK_EQ(err, (status_t)OK); - } else { - CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); - } - - ALOGV("[%s] calling fillBuffer %p", - mCodec->mComponentName.c_str(), info->mBufferID); - - CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), - (status_t)OK); - - info->mStatus = BufferInfo::OWNED_BY_COMPONENT; - } -} - -void ACodec::ExecutingState::resume() { - if (mActive) { - ALOGV("[%s] We're already active, no need to resume.", - mCodec->mComponentName.c_str()); - - return; - } - - submitOutputBuffers(); - - // Post the first input buffer. - CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); - BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); - - postFillThisBuffer(info); - - mActive = true; -} - -void ACodec::ExecutingState::stateEntered() { - ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); - - mCodec->processDeferredMessages(); -} - -bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { - bool handled = false; - - switch (msg->what()) { - case kWhatShutdown: - { - int32_t keepComponentAllocated; - CHECK(msg->findInt32( - "keepComponentAllocated", &keepComponentAllocated)); - - mCodec->mShutdownInProgress = true; - mCodec->mKeepComponentAllocated = keepComponentAllocated; - - mActive = false; - - CHECK_EQ(mCodec->mOMX->sendCommand( - mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), - (status_t)OK); - - mCodec->changeState(mCodec->mExecutingToIdleState); - - handled = true; - break; - } - - case kWhatFlush: - { - ALOGV("[%s] ExecutingState flushing now " - "(codec owns %d/%d input, %d/%d output).", - mCodec->mComponentName.c_str(), - mCodec->countBuffersOwnedByComponent(kPortIndexInput), - mCodec->mBuffers[kPortIndexInput].size(), - mCodec->countBuffersOwnedByComponent(kPortIndexOutput), - mCodec->mBuffers[kPortIndexOutput].size()); - - mActive = false; - - CHECK_EQ(mCodec->mOMX->sendCommand( - mCodec->mNode, OMX_CommandFlush, OMX_ALL), - (status_t)OK); - - mCodec->changeState(mCodec->mFlushingState); - - handled = true; - break; - } - - case kWhatResume: - { - resume(); - - handled = true; - break; - } - - default: - handled = BaseState::onMessageReceived(msg); - break; - } - - return handled; -} - -bool ACodec::ExecutingState::onOMXEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - switch (event) { - case OMX_EventPortSettingsChanged: - { - CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); - - if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { - CHECK_EQ(mCodec->mOMX->sendCommand( - mCodec->mNode, - OMX_CommandPortDisable, kPortIndexOutput), - (status_t)OK); - - mCodec->freeOutputBuffersNotOwnedByComponent(); - - mCodec->changeState(mCodec->mOutputPortSettingsChangedState); - } else if (data2 == OMX_IndexConfigCommonOutputCrop) { - mCodec->mSentFormat = false; - } else { - ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", - mCodec->mComponentName.c_str(), data2); - } - - return true; - } - - case OMX_EventBufferFlag: - { - return true; - } - - default: - return BaseState::onOMXEvent(event, data1, data2); - } -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( - ACodec *codec) - : BaseState(codec) { -} - -ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( - OMX_U32 portIndex) { - if (portIndex == kPortIndexOutput) { - return FREE_BUFFERS; - } - - CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); - - return RESUBMIT_BUFFERS; -} - -bool ACodec::OutputPortSettingsChangedState::onMessageReceived( - const sp<AMessage> &msg) { - bool handled = false; - - switch (msg->what()) { - case kWhatFlush: - case kWhatShutdown: - case kWhatResume: - { - if (msg->what() == kWhatResume) { - ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); - } - - mCodec->deferMessage(msg); - handled = true; - break; - } - - default: - handled = BaseState::onMessageReceived(msg); - break; - } - - return handled; -} - -void ACodec::OutputPortSettingsChangedState::stateEntered() { - ALOGV("[%s] Now handling output port settings change", - mCodec->mComponentName.c_str()); -} - -bool ACodec::OutputPortSettingsChangedState::onOMXEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - switch (event) { - case OMX_EventCmdComplete: - { - if (data1 == (OMX_U32)OMX_CommandPortDisable) { - CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); - - ALOGV("[%s] Output port now disabled.", - mCodec->mComponentName.c_str()); - - CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); - mCodec->mDealer[kPortIndexOutput].clear(); - - CHECK_EQ(mCodec->mOMX->sendCommand( - mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), - (status_t)OK); - - status_t err; - if ((err = mCodec->allocateBuffersOnPort( - kPortIndexOutput)) != OK) { - ALOGE("Failed to allocate output port buffers after " - "port reconfiguration (error 0x%08x)", - err); - - mCodec->signalError(OMX_ErrorUndefined, err); - - // This is technically not correct, since we were unable - // to allocate output buffers and therefore the output port - // remains disabled. It is necessary however to allow us - // to shutdown the codec properly. - mCodec->changeState(mCodec->mExecutingState); - } - - return true; - } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { - CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); - - mCodec->mSentFormat = false; - - ALOGV("[%s] Output port now reenabled.", - mCodec->mComponentName.c_str()); - - if (mCodec->mExecutingState->active()) { - mCodec->mExecutingState->submitOutputBuffers(); - } - - mCodec->changeState(mCodec->mExecutingState); - - return true; - } - - return false; - } - - default: - return false; - } -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) - : BaseState(codec), - mComponentNowIdle(false) { -} - -bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { - bool handled = false; - - switch (msg->what()) { - case kWhatFlush: - { - // Don't send me a flush request if you previously wanted me - // to shutdown. - TRESPASS(); - break; - } - - case kWhatShutdown: - { - // We're already doing that... - - handled = true; - break; - } - - default: - handled = BaseState::onMessageReceived(msg); - break; - } - - return handled; -} - -void ACodec::ExecutingToIdleState::stateEntered() { - ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); - - mComponentNowIdle = false; - mCodec->mSentFormat = false; -} - -bool ACodec::ExecutingToIdleState::onOMXEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - switch (event) { - case OMX_EventCmdComplete: - { - CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); - CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); - - mComponentNowIdle = true; - - changeStateIfWeOwnAllBuffers(); - - return true; - } - - case OMX_EventPortSettingsChanged: - case OMX_EventBufferFlag: - { - // We're shutting down and don't care about this anymore. - return true; - } - - default: - return BaseState::onOMXEvent(event, data1, data2); - } -} - -void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { - if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { - CHECK_EQ(mCodec->mOMX->sendCommand( - mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), - (status_t)OK); - - CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); - CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); - - mCodec->changeState(mCodec->mIdleToLoadedState); - } -} - -void ACodec::ExecutingToIdleState::onInputBufferFilled( - const sp<AMessage> &msg) { - BaseState::onInputBufferFilled(msg); - - changeStateIfWeOwnAllBuffers(); -} - -void ACodec::ExecutingToIdleState::onOutputBufferDrained( - const sp<AMessage> &msg) { - BaseState::onOutputBufferDrained(msg); - - changeStateIfWeOwnAllBuffers(); -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) - : BaseState(codec) { -} - -bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { - bool handled = false; - - switch (msg->what()) { - case kWhatShutdown: - { - // We're already doing that... - - handled = true; - break; - } - - case kWhatFlush: - { - // Don't send me a flush request if you previously wanted me - // to shutdown. - TRESPASS(); - break; - } - - default: - handled = BaseState::onMessageReceived(msg); - break; - } - - return handled; -} - -void ACodec::IdleToLoadedState::stateEntered() { - ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); -} - -bool ACodec::IdleToLoadedState::onOMXEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - switch (event) { - case OMX_EventCmdComplete: - { - CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); - CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); - - mCodec->changeState(mCodec->mLoadedState); - - return true; - } - - default: - return BaseState::onOMXEvent(event, data1, data2); - } -} - -//////////////////////////////////////////////////////////////////////////////// - -ACodec::FlushingState::FlushingState(ACodec *codec) - : BaseState(codec) { -} - -void ACodec::FlushingState::stateEntered() { - ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); - - mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; -} - -bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { - bool handled = false; - - switch (msg->what()) { - case kWhatShutdown: - { - mCodec->deferMessage(msg); - break; - } - - case kWhatFlush: - { - // We're already doing this right now. - handled = true; - break; - } - - default: - handled = BaseState::onMessageReceived(msg); - break; - } - - return handled; -} - -bool ACodec::FlushingState::onOMXEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", - mCodec->mComponentName.c_str(), event, data1); - - switch (event) { - case OMX_EventCmdComplete: - { - CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); - - if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { - CHECK(!mFlushComplete[data2]); - mFlushComplete[data2] = true; - - if (mFlushComplete[kPortIndexInput] - && mFlushComplete[kPortIndexOutput]) { - changeStateIfWeOwnAllBuffers(); - } - } else { - CHECK_EQ(data2, OMX_ALL); - CHECK(mFlushComplete[kPortIndexInput]); - CHECK(mFlushComplete[kPortIndexOutput]); - - changeStateIfWeOwnAllBuffers(); - } - - return true; - } - - case OMX_EventPortSettingsChanged: - { - sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); - msg->setInt32("type", omx_message::EVENT); - msg->setPointer("node", mCodec->mNode); - msg->setInt32("event", event); - msg->setInt32("data1", data1); - msg->setInt32("data2", data2); - - ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", - mCodec->mComponentName.c_str()); - - mCodec->deferMessage(msg); - - return true; - } - - default: - return BaseState::onOMXEvent(event, data1, data2); - } - - return true; -} - -void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { - BaseState::onOutputBufferDrained(msg); - - changeStateIfWeOwnAllBuffers(); -} - -void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { - BaseState::onInputBufferFilled(msg); - - changeStateIfWeOwnAllBuffers(); -} - -void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { - if (mFlushComplete[kPortIndexInput] - && mFlushComplete[kPortIndexOutput] - && mCodec->allYourBuffersAreBelongToUs()) { - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatFlushCompleted); - notify->post(); - - mCodec->mPortEOS[kPortIndexInput] = - mCodec->mPortEOS[kPortIndexOutput] = false; - - mCodec->mInputEOSResult = OK; - - mCodec->changeState(mCodec->mExecutingState); - } -} - -} // namespace android |