summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/ACodec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/ACodec.cpp')
-rw-r--r--media/libstagefright/ACodec.cpp3492
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(&params);
- params.nPortIndex = kPortIndexOutput;
-
- for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
- status_t err = mOMX->getParameter(
- mNode,
- OMX_IndexParamVideoProfileLevelQuerySupported,
- &params,
- 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(&params);
- params.nPortIndex = kPortIndexOutput;
-
- CHECK_EQ(mOMX->getParameter(
- mNode, OMX_IndexParamAudioPcm,
- &params, 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