diff options
-rw-r--r-- | cmds/stagefright/Android.mk | 20 | ||||
-rw-r--r-- | cmds/stagefright/play.cpp | 295 | ||||
-rw-r--r-- | cmds/stagefright/record.cpp | 13 | ||||
-rw-r--r-- | cmds/stagefright/stagefright.cpp | 8 | ||||
-rw-r--r-- | include/media/IOMX.h | 19 | ||||
-rw-r--r-- | include/media/stagefright/OMXClient.h | 61 | ||||
-rw-r--r-- | include/media/stagefright/OMXDecoder.h | 185 | ||||
-rw-r--r-- | media/libstagefright/Android.mk | 1 | ||||
-rw-r--r-- | media/libstagefright/MediaPlayerImpl.cpp | 13 | ||||
-rw-r--r-- | media/libstagefright/OMXClient.cpp | 174 | ||||
-rw-r--r-- | media/libstagefright/OMXDecoder.cpp | 1650 |
11 files changed, 3 insertions, 2436 deletions
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk index 697d67a..ef67611 100644 --- a/cmds/stagefright/Android.mk +++ b/cmds/stagefright/Android.mk @@ -38,23 +38,3 @@ LOCAL_CFLAGS += -Wno-multichar LOCAL_MODULE:= record include $(BUILD_EXECUTABLE) - -################################################################################ - -# include $(CLEAR_VARS) -# -# LOCAL_SRC_FILES:= \ -# play.cpp -# -# LOCAL_SHARED_LIBRARIES := \ -# libstagefright -# -# LOCAL_C_INCLUDES:= \ -# frameworks/base/media/libstagefright \ -# $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include -# -# LOCAL_CFLAGS += -Wno-multichar -# -# LOCAL_MODULE:= play -# -# include $(BUILD_EXECUTABLE) diff --git a/cmds/stagefright/play.cpp b/cmds/stagefright/play.cpp deleted file mode 100644 index c6e778e..0000000 --- a/cmds/stagefright/play.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#include <binder/ProcessState.h> -#include <media/stagefright/OMXClient.h> -#include <media/stagefright/TimedEventQueue.h> -#include <media/stagefright/MPEG4Extractor.h> -#include <media/stagefright/MediaSource.h> -#include <media/stagefright/MetaData.h> -#include <media/stagefright/MmapSource.h> -#include <media/stagefright/OMXDecoder.h> - -using namespace android; - -struct NewPlayer { - NewPlayer(); - ~NewPlayer(); - - void setSource(const char *uri); - void start(); - void pause(); - void stop(); - -private: - struct PlayerEvent : public TimedEventQueue::Event { - PlayerEvent(NewPlayer *player, - void (NewPlayer::*method)(int64_t realtime_us)) - : mPlayer(player), - mMethod(method) { - } - - virtual void fire(TimedEventQueue *queue, int64_t realtime_us) { - (mPlayer->*mMethod)(realtime_us); - } - - private: - NewPlayer *mPlayer; - void (NewPlayer::*mMethod)(int64_t realtime_us); - - PlayerEvent(const PlayerEvent &); - PlayerEvent &operator=(const PlayerEvent &); - }; - - struct PlayVideoFrameEvent : public TimedEventQueue::Event { - PlayVideoFrameEvent(NewPlayer *player, MediaBuffer *buffer) - : mPlayer(player), - mBuffer(buffer) { - } - - virtual ~PlayVideoFrameEvent() { - if (mBuffer != NULL) { - mBuffer->release(); - mBuffer = NULL; - } - } - - virtual void fire(TimedEventQueue *queue, int64_t realtime_us) { - mPlayer->onPlayVideoFrame(realtime_us, mBuffer); - mBuffer = NULL; - } - - private: - NewPlayer *mPlayer; - MediaBuffer *mBuffer; - - PlayVideoFrameEvent(const PlayVideoFrameEvent &); - PlayVideoFrameEvent &operator=(const PlayVideoFrameEvent &); - }; - - OMXClient mClient; - - MPEG4Extractor *mExtractor; - MediaSource *mAudioSource; - OMXDecoder *mAudioDecoder; - MediaSource *mVideoSource; - OMXDecoder *mVideoDecoder; - - int32_t mVideoWidth, mVideoHeight; - - TimedEventQueue mQueue; - wp<TimedEventQueue::Event> mPlayVideoFrameEvent; - - int64_t mMediaTimeUsStart; - int64_t mRealTimeUsStart; - - void setAudioSource(MediaSource *source); - void setVideoSource(MediaSource *source); - - int64_t approxRealTime(int64_t mediatime_us) const; - - void onStart(int64_t realtime_us); - void onPause(int64_t realtime_us); - void onFetchVideoFrame(int64_t realtime_us); - void onPlayVideoFrame(int64_t realtime_us, MediaBuffer *buffer); - - static int64_t getMediaBufferTimeUs(MediaBuffer *buffer); - - NewPlayer(const NewPlayer &); - NewPlayer &operator=(const NewPlayer &); -}; - -NewPlayer::NewPlayer() - : mExtractor(NULL), - mAudioSource(NULL), - mAudioDecoder(NULL), - mVideoSource(NULL), - mVideoDecoder(NULL), - mVideoWidth(0), - mVideoHeight(0) { - status_t err = mClient.connect(); - assert(err == OK); -} - -NewPlayer::~NewPlayer() { - stop(); - - mClient.disconnect(); -} - -void NewPlayer::setSource(const char *uri) { - stop(); - - mExtractor = new MPEG4Extractor(new MmapSource(uri)); - - int num_tracks; - status_t err = mExtractor->countTracks(&num_tracks); - assert(err == OK); - - for (int i = 0; i < num_tracks; ++i) { - const sp<MetaData> meta = mExtractor->getTrackMetaData(i); - assert(meta != NULL); - - const char *mime; - if (!meta->findCString(kKeyMIMEType, &mime)) { - continue; - } - - bool is_audio = false; - bool is_acceptable = false; - if (!strncasecmp(mime, "audio/", 6)) { - is_audio = true; - is_acceptable = (mAudioSource == NULL); - } else if (!strncasecmp(mime, "video/", 6)) { - is_acceptable = (mVideoSource == NULL); - } - - if (!is_acceptable) { - continue; - } - - MediaSource *source; - if (mExtractor->getTrack(i, &source) != OK) { - continue; - } - - if (is_audio) { - setAudioSource(source); - } else { - setVideoSource(source); - } - } -} - -void NewPlayer::setAudioSource(MediaSource *source) { - mAudioSource = source; - - sp<MetaData> meta = source->getFormat(); - - mAudioDecoder = OMXDecoder::Create(&mClient, meta); - mAudioDecoder->setSource(source); -} - -void NewPlayer::setVideoSource(MediaSource *source) { - mVideoSource = source; - - sp<MetaData> meta = source->getFormat(); - - bool success = meta->findInt32(kKeyWidth, &mVideoWidth); - assert(success); - - success = meta->findInt32(kKeyHeight, &mVideoHeight); - assert(success); - - mVideoDecoder = OMXDecoder::Create(&mClient, meta); - mVideoDecoder->setSource(source); -} - -void NewPlayer::start() { - mQueue.start(); - mQueue.postEvent(new PlayerEvent(this, &NewPlayer::onStart)); -} - -void NewPlayer::pause() { - mQueue.postEvent(new PlayerEvent(this, &NewPlayer::onPause)); -} - -void NewPlayer::stop() { - mQueue.stop(); - - delete mVideoDecoder; - mVideoDecoder = NULL; - delete mVideoSource; - mVideoSource = NULL; - mVideoWidth = mVideoHeight = 0; - - delete mAudioDecoder; - mAudioDecoder = NULL; - delete mAudioSource; - mAudioSource = NULL; - - delete mExtractor; - mExtractor = NULL; -} - -int64_t NewPlayer::approxRealTime(int64_t mediatime_us) const { - return mRealTimeUsStart + (mediatime_us - mMediaTimeUsStart); -} - -void NewPlayer::onStart(int64_t realtime_us) { - mRealTimeUsStart = TimedEventQueue::getRealTimeUs(); - - if (mVideoDecoder != NULL) { - mQueue.postEvent(new PlayerEvent(this, &NewPlayer::onFetchVideoFrame)); - } -} - -void NewPlayer::onFetchVideoFrame(int64_t realtime_us) { - MediaBuffer *buffer; - status_t err = mVideoDecoder->read(&buffer); - assert(err == OK); - - int64_t mediatime_us = getMediaBufferTimeUs(buffer); - - sp<TimedEventQueue::Event> event = new PlayVideoFrameEvent(this, buffer); - mPlayVideoFrameEvent = event; - - mQueue.postTimedEvent(event, approxRealTime(mediatime_us)); -} - -// static -int64_t NewPlayer::getMediaBufferTimeUs(MediaBuffer *buffer) { - int32_t units, scale; - bool success = - buffer->meta_data()->findInt32(kKeyTimeUnits, &units); - assert(success); - success = - buffer->meta_data()->findInt32(kKeyTimeScale, &scale); - assert(success); - - return (int64_t)units * 1000000 / scale; -} - -void NewPlayer::onPlayVideoFrame(int64_t realtime_us, MediaBuffer *buffer) { - LOGI("playing video frame (mediatime: %.2f sec)\n", - getMediaBufferTimeUs(buffer) / 1E6); - fflush(stdout); - - buffer->release(); - buffer = NULL; - - mQueue.postEvent(new PlayerEvent(this, &NewPlayer::onFetchVideoFrame)); -} - -void NewPlayer::onPause(int64_t realtime_us) { -} - -int main(int argc, char **argv) { - android::ProcessState::self()->startThreadPool(); - - if (argc != 2) { - fprintf(stderr, "usage: %s filename\n", argv[0]); - return 1; - } - - NewPlayer player; - player.setSource(argv[1]); - player.start(); - sleep(10); - player.stop(); - - return 0; -} diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp index cf2962b..9a2416b 100644 --- a/cmds/stagefright/record.cpp +++ b/cmds/stagefright/record.cpp @@ -26,7 +26,6 @@ #include <media/stagefright/MmapSource.h> #include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXCodec.h> -#include <media/stagefright/OMXDecoder.h> using namespace android; @@ -87,8 +86,6 @@ private: DummySource &operator=(const DummySource &); }; -#define USE_OMX_CODEC 1 - sp<MediaSource> createSource(const char *filename) { sp<MediaSource> source; @@ -140,13 +137,8 @@ int main(int argc, char **argv) { sp<MetaData> meta = source->getFormat(); -#if USE_OMX_CODEC sp<OMXCodec> decoder = OMXCodec::Create( client.interface(), meta, false /* createEncoder */, source); -#else - sp<OMXDecoder> decoder = OMXDecoder::Create( - &client, meta, false /* createEncoder */, source); -#endif int width, height; bool success = meta->findInt32(kKeyWidth, &width); @@ -164,14 +156,9 @@ int main(int argc, char **argv) { enc_meta->setInt32(kKeyWidth, width); enc_meta->setInt32(kKeyHeight, height); -#if USE_OMX_CODEC sp<OMXCodec> encoder = OMXCodec::Create( client.interface(), enc_meta, true /* createEncoder */, decoder); -#else - sp<OMXDecoder> encoder = OMXDecoder::Create( - &client, enc_meta, true /* createEncoder */, decoder); -#endif #if 1 sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4"); diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index e927aae..baa00da 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -33,7 +33,6 @@ #include <media/stagefright/MmapSource.h> #include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXCodec.h> -#include <media/stagefright/OMXDecoder.h> #include "JPEGSource.h" @@ -50,18 +49,11 @@ static int64_t getNowUs() { return (int64_t)tv.tv_usec + tv.tv_sec * 1000000; } -#define USE_OMX_CODEC 1 - static void playSource(OMXClient *client, const sp<MediaSource> &source) { sp<MetaData> meta = source->getFormat(); -#if !USE_OMX_CODEC - sp<OMXDecoder> decoder = OMXDecoder::Create( - client, meta, false /* createEncoder */, source); -#else sp<OMXCodec> decoder = OMXCodec::Create( client->interface(), meta, false /* createEncoder */, source); -#endif if (decoder == NULL) { return; diff --git a/include/media/IOMX.h b/include/media/IOMX.h index 58a74c7..0014d5c 100644 --- a/include/media/IOMX.h +++ b/include/media/IOMX.h @@ -119,12 +119,6 @@ struct omx_message { EMPTY_BUFFER_DONE, FILL_BUFFER_DONE, - // reserved for OMXDecoder use. - START, - INITIAL_FILL_BUFFER, - - // reserved for OMXObserver use. - QUIT_OBSERVER, } type; IOMX::node_id node; @@ -137,28 +131,21 @@ struct omx_message { OMX_U32 data2; } event_data; - // if type == EMPTY_BUFFER_DONE || type == FILL_BUFFER - // || type == INITIAL_FILL_BUFFER + // if type == EMPTY_BUFFER_DONE struct { IOMX::buffer_id buffer; } buffer_data; - // if type == EMPTY_BUFFER || type == FILL_BUFFER_DONE + // if type == FILL_BUFFER_DONE struct { IOMX::buffer_id buffer; OMX_U32 range_offset; OMX_U32 range_length; OMX_U32 flags; OMX_TICKS timestamp; - OMX_PTR platform_private; // ignored if type == EMPTY_BUFFER + OMX_PTR platform_private; } extended_buffer_data; - // if type == SEND_COMMAND - struct { - OMX_COMMANDTYPE cmd; - OMX_S32 param; - } send_command_data; - } u; }; diff --git a/include/media/stagefright/OMXClient.h b/include/media/stagefright/OMXClient.h index 7027e1b..2f14d06 100644 --- a/include/media/stagefright/OMXClient.h +++ b/include/media/stagefright/OMXClient.h @@ -20,62 +20,11 @@ #include <media/IOMX.h> -#include <utils/KeyedVector.h> -#include <utils/List.h> -#include <utils/threads.h> - namespace android { -class OMXObserver { -public: - OMXObserver(); - virtual ~OMXObserver(); - - void postMessage(const omx_message &msg); - -protected: - virtual void onOMXMessage(const omx_message &msg) = 0; - -private: - friend class OMXClient; - - pthread_t mThread; - Mutex mLock; - Condition mQueueNotEmpty; - List<omx_message> mQueue; - - void start(); - void stop(); - - static void *ThreadWrapper(void *me); - void threadEntry(); - - OMXObserver(const OMXObserver &); - OMXObserver &operator=(const OMXObserver &); -}; - -class OMXClient; - -class OMXClientReflector : public BnOMXObserver { -public: - OMXClientReflector(OMXClient *client); - - virtual void on_message(const omx_message &msg); - void reset(); - -private: - OMXClient *mClient; - - OMXClientReflector(const OMXClientReflector &); - OMXClientReflector &operator=(const OMXClientReflector &); -}; - class OMXClient { public: - friend class OMXClientReflector; - OMXClient(); - ~OMXClient(); status_t connect(); void disconnect(); @@ -84,18 +33,8 @@ public: return mOMX; } - status_t registerObserver(IOMX::node_id node, OMXObserver *observer); - void unregisterObserver(IOMX::node_id node); - private: sp<IOMX> mOMX; - Mutex mLock; - - KeyedVector<IOMX::node_id, OMXObserver *> mObservers; - - sp<OMXClientReflector> mReflector; - - bool onOMXMessage(const omx_message &msg); OMXClient(const OMXClient &); OMXClient &operator=(const OMXClient &); diff --git a/include/media/stagefright/OMXDecoder.h b/include/media/stagefright/OMXDecoder.h deleted file mode 100644 index 99d803a..0000000 --- a/include/media/stagefright/OMXDecoder.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef OMX_DECODER_H_ - -#define OMX_DECODER_H_ - -#include <binder/MemoryDealer.h> -#include <media/stagefright/MediaBuffer.h> -#include <media/stagefright/MediaSource.h> -#include <media/stagefright/OMXClient.h> -#include <utils/KeyedVector.h> -#include <utils/List.h> -#include <utils/threads.h> - -#include <OMX_Video.h> - -namespace android { - -class OMXMediaBuffer; - -class OMXDecoder : public MediaSource, - public OMXObserver, - public MediaBufferObserver { -public: - static sp<OMXDecoder> Create( - OMXClient *client, const sp<MetaData> &data, - bool createEncoder, - const sp<MediaSource> &source); - - virtual status_t start(MetaData *params = NULL); - virtual status_t stop(); - - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options = NULL); - - void addCodecSpecificData(const void *data, size_t size); - - // from OMXObserver - virtual void onOMXMessage(const omx_message &msg); - - // from MediaBufferObserver - virtual void signalBufferReturned(MediaBuffer *buffer); - -protected: - virtual ~OMXDecoder(); - -private: - enum { - kPortIndexInput = 0, - kPortIndexOutput = 1 - }; - - enum PortStatus { - kPortStatusActive = 0, - kPortStatusDisabled = 1, - kPortStatusShutdown = 2, - kPortStatusFlushing = 3, - kPortStatusFlushingToDisabled = 4, - kPortStatusFlushingToShutdown = 5, - }; - - enum Quirks { - kWantsNALFragments = 1, - kDoesntReturnBuffersOnDisable = 2, - kDoesntFlushOnExecutingToIdle = 4, - kDoesntProperlyFlushAllPortsAtOnce = 8, - kRequiresAllocateBufferOnInputPorts = 16, - kRequiresAllocateBufferOnOutputPorts = 32, - kRequiresLoadedToIdleAfterAllocation = 64, - kMeasuresTimeInMilliseconds = 128, - }; - - OMXClient *mClient; - sp<IOMX> mOMX; - IOMX::node_id mNode; - char *mComponentName; - char *mMIME; - bool mIsMP3; - bool mIsAVC; - bool mIsEncoder; - uint32_t mQuirks; - - sp<MediaSource> mSource; - sp<MetaData> mOutputFormat; - - Mutex mLock; - Condition mOutputBufferAvailable; - - List<MediaBuffer *> mOutputBuffers; - - struct CodecSpecificData { - void *data; - size_t size; - }; - - List<CodecSpecificData> mCodecSpecificData; - List<CodecSpecificData>::iterator mCodecSpecificDataIterator; - - volatile OMX_STATETYPE mState; - OMX_U32 mPortStatusMask; - bool mShutdownInitiated; - - typedef List<IOMX::buffer_id> BufferList; - Vector<BufferList> mBuffers; - - KeyedVector<IOMX::buffer_id, sp<IMemory> > mBufferMap; - KeyedVector<IOMX::buffer_id, OMXMediaBuffer *> mMediaBufferMap; - - sp<MemoryDealer> mDealer; - - bool mSeeking; - int64_t mSeekTimeUs; - - bool mStarted; - status_t mErrorCondition; - bool mReachedEndOfInput; - - OMXDecoder(OMXClient *client, IOMX::node_id node, - const char *mime, const char *codec, - bool is_encoder, - uint32_t quirks, - const sp<MediaSource> &source); - - void setPortStatus(OMX_U32 port_index, PortStatus status); - PortStatus getPortStatus(OMX_U32 port_index) const; - - void allocateBuffers(OMX_U32 port_index); - - void setAMRFormat(); - void setAACFormat(); - - status_t setVideoPortFormatType( - OMX_U32 portIndex, - OMX_VIDEO_CODINGTYPE compressionFormat, - OMX_COLOR_FORMATTYPE colorFormat); - - void setVideoOutputFormat(const char *mime, OMX_U32 width, OMX_U32 height); - void setVideoInputFormat(const char *mime, OMX_U32 width, OMX_U32 height); - void setup(); - void dumpPortDefinition(OMX_U32 port_index); - - void onStart(); - void onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); - void onEventCmdComplete(OMX_COMMANDTYPE type, OMX_U32 data); - void onEventPortSettingsChanged(OMX_U32 port_index); - void onStateChanged(OMX_STATETYPE to); - void onEmptyBufferDone(IOMX::buffer_id buffer); - void onFillBufferDone(const omx_message &msg); - - void onRealEmptyBufferDone(IOMX::buffer_id buffer); - void onRealFillBufferDone(const omx_message &msg); - - void initiateShutdown(); - - void freeInputBuffer(IOMX::buffer_id buffer); - void freeOutputBuffer(IOMX::buffer_id buffer); - void freePortBuffers(OMX_U32 port_index); - - void postStart(); - void postEmptyBufferDone(IOMX::buffer_id buffer); - void postInitialFillBuffer(IOMX::buffer_id buffer); - - OMXDecoder(const OMXDecoder &); - OMXDecoder &operator=(const OMXDecoder &); -}; - -} // namespace android - -#endif // OMX_DECODER_H_ diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 0c40b91..20b0da2 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -26,7 +26,6 @@ LOCAL_SRC_FILES:= \ AudioPlayer.cpp \ ESDS.cpp \ OMXClient.cpp \ - OMXDecoder.cpp \ string.cpp LOCAL_C_INCLUDES:= \ diff --git a/media/libstagefright/MediaPlayerImpl.cpp b/media/libstagefright/MediaPlayerImpl.cpp index e5301bb..2e609e3 100644 --- a/media/libstagefright/MediaPlayerImpl.cpp +++ b/media/libstagefright/MediaPlayerImpl.cpp @@ -33,14 +33,11 @@ #include <media/stagefright/MetaData.h> #include <media/stagefright/MmapSource.h> #include <media/stagefright/OMXCodec.h> -#include <media/stagefright/OMXDecoder.h> #include <media/stagefright/ShoutcastSource.h> #include <media/stagefright/TimeSource.h> #include <ui/PixelFormat.h> #include <ui/Surface.h> -#define USE_OMX_CODEC 1 - namespace android { MediaPlayerImpl::MediaPlayerImpl(const char *uri) @@ -406,13 +403,8 @@ void MediaPlayerImpl::setAudioSource(const sp<MediaSource> &source) { sp<MetaData> meta = source->getFormat(); -#if !USE_OMX_CODEC - mAudioDecoder = OMXDecoder::Create( - &mClient, meta, false /* createEncoder */, source); -#else mAudioDecoder = OMXCodec::Create( mClient.interface(), meta, false /* createEncoder */, source); -#endif } void MediaPlayerImpl::setVideoSource(const sp<MediaSource> &source) { @@ -427,13 +419,8 @@ void MediaPlayerImpl::setVideoSource(const sp<MediaSource> &source) { success = meta->findInt32(kKeyHeight, &mVideoHeight); CHECK(success); -#if !USE_OMX_CODEC - mVideoDecoder = OMXDecoder::Create( - &mClient, meta, false /* createEncoder */, source); -#else mVideoDecoder = OMXCodec::Create( mClient.interface(), meta, false /* createEncoder */, source); -#endif if (mISurface.get() != NULL || mSurface.get() != NULL) { depopulateISurface(); diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp index 2a32b4c..dba7a2a 100644 --- a/media/libstagefright/OMXClient.cpp +++ b/media/libstagefright/OMXClient.cpp @@ -18,11 +18,8 @@ #define LOG_TAG "OMXClient" #include <utils/Log.h> -#include <sys/socket.h> - #include <binder/IServiceManager.h> #include <media/IMediaPlayerService.h> -#include <media/IOMX.h> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/OMXClient.h> @@ -31,13 +28,7 @@ namespace android { OMXClient::OMXClient() { } -OMXClient::~OMXClient() { - disconnect(); -} - status_t OMXClient::connect() { - Mutex::Autolock autoLock(mLock); - sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(String16("media.player")); sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); @@ -47,175 +38,10 @@ status_t OMXClient::connect() { mOMX = service->createOMX(); CHECK(mOMX.get() != NULL); - mReflector = new OMXClientReflector(this); - return OK; } void OMXClient::disconnect() { - Mutex::Autolock autoLock(mLock); - - if (mReflector.get() != NULL) { - return; - } - - CHECK(mObservers.isEmpty()); - - mReflector->reset(); - mReflector.clear(); -} - -status_t OMXClient::registerObserver( - IOMX::node_id node, OMXObserver *observer) { - Mutex::Autolock autoLock(&mLock); - - ssize_t index = mObservers.indexOfKey(node); - if (index >= 0) { - return UNKNOWN_ERROR; - } - - mObservers.add(node, observer); - observer->start(); - - mOMX->observe_node(node, mReflector); - - return OK; -} - -void OMXClient::unregisterObserver(IOMX::node_id node) { - Mutex::Autolock autoLock(mLock); - - ssize_t index = mObservers.indexOfKey(node); - CHECK(index >= 0); - - if (index < 0) { - return; - } - - OMXObserver *observer = mObservers.valueAt(index); - observer->stop(); - mObservers.removeItemsAt(index); -} - -bool OMXClient::onOMXMessage(const omx_message &msg) { - bool done = false; - - switch (msg.type) { - case omx_message::EVENT: - { - LOGV("OnEvent node:%p event:%d data1:%ld data2:%ld", - msg.u.event_data.node, - msg.u.event_data.event, - msg.u.event_data.data1, - msg.u.event_data.data2); - - break; - } - - case omx_message::FILL_BUFFER_DONE: - { - LOGV("FillBufferDone %p", msg.u.extended_buffer_data.buffer); - break; - } - - case omx_message::EMPTY_BUFFER_DONE: - { - LOGV("EmptyBufferDone %p", msg.u.buffer_data.buffer); - break; - } - - default: - LOGE("received unknown omx_message type %d", msg.type); - break; - } - - Mutex::Autolock autoLock(mLock); - ssize_t index = mObservers.indexOfKey(msg.node); - - if (index >= 0) { - mObservers.editValueAt(index)->postMessage(msg); - } - - return done; -} - -//////////////////////////////////////////////////////////////////////////////// - -OMXObserver::OMXObserver() { -} - -OMXObserver::~OMXObserver() { -} - -void OMXObserver::start() { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - int err = pthread_create(&mThread, &attr, ThreadWrapper, this); - CHECK_EQ(err, 0); - - pthread_attr_destroy(&attr); -} - -void OMXObserver::stop() { - omx_message msg; - msg.type = omx_message::QUIT_OBSERVER; - postMessage(msg); - - void *dummy; - pthread_join(mThread, &dummy); -} - -void OMXObserver::postMessage(const omx_message &msg) { - Mutex::Autolock autoLock(mLock); - mQueue.push_back(msg); - mQueueNotEmpty.signal(); -} - -// static -void *OMXObserver::ThreadWrapper(void *me) { - static_cast<OMXObserver *>(me)->threadEntry(); - - return NULL; -} - -void OMXObserver::threadEntry() { - for (;;) { - omx_message msg; - - { - Mutex::Autolock autoLock(mLock); - while (mQueue.empty()) { - mQueueNotEmpty.wait(mLock); - } - - msg = *mQueue.begin(); - mQueue.erase(mQueue.begin()); - } - - if (msg.type == omx_message::QUIT_OBSERVER) { - break; - } - - onOMXMessage(msg); - } -} - -//////////////////////////////////////////////////////////////////////////////// - -OMXClientReflector::OMXClientReflector(OMXClient *client) - : mClient(client) { -} - -void OMXClientReflector::on_message(const omx_message &msg) { - if (mClient != NULL) { - mClient->onOMXMessage(msg); - } -} - -void OMXClientReflector::reset() { - mClient = NULL; } } // namespace android diff --git a/media/libstagefright/OMXDecoder.cpp b/media/libstagefright/OMXDecoder.cpp deleted file mode 100644 index a3172ed..0000000 --- a/media/libstagefright/OMXDecoder.cpp +++ /dev/null @@ -1,1650 +0,0 @@ -/* - * Copyright (C) 2009 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 "OMXDecoder" -#include <utils/Log.h> - -#include <ctype.h> - -#include <OMX_Component.h> - -#include <media/stagefright/ESDS.h> -#include <media/stagefright/MediaDebug.h> -#include <media/stagefright/MetaData.h> -#include <media/stagefright/OMXDecoder.h> - -namespace android { - -class OMXMediaBuffer : public MediaBuffer { -public: - OMXMediaBuffer(IOMX::buffer_id buffer_id, const sp<IMemory> &mem) - : MediaBuffer(mem->pointer(), - mem->size()), - mBufferID(buffer_id), - mMem(mem) { - } - - IOMX::buffer_id buffer_id() const { return mBufferID; } - -private: - IOMX::buffer_id mBufferID; - sp<IMemory> mMem; - - OMXMediaBuffer(const OMXMediaBuffer &); - OMXMediaBuffer &operator=(const OMXMediaBuffer &); -}; - -struct CodecInfo { - const char *mime; - const char *codec; -}; - -static const CodecInfo kDecoderInfo[] = { - { "audio/mpeg", "OMX.TI.MP3.decode" }, - { "audio/mpeg", "OMX.PV.mp3dec" }, - { "audio/3gpp", "OMX.TI.AMR.decode" }, - { "audio/3gpp", "OMX.PV.amrdec" }, - { "audio/mp4a-latm", "OMX.TI.AAC.decode" }, - { "audio/mp4a-latm", "OMX.PV.aacdec" }, - { "video/mp4v-es", "OMX.qcom.video.decoder.mpeg4" }, - { "video/mp4v-es", "OMX.TI.Video.Decoder" }, - { "video/mp4v-es", "OMX.PV.mpeg4dec" }, - { "video/3gpp", "OMX.qcom.video.decoder.h263" }, - { "video/3gpp", "OMX.TI.Video.Decoder" }, - { "video/3gpp", "OMX.PV.h263dec" }, - { "video/avc", "OMX.qcom.video.decoder.avc" }, - { "video/avc", "OMX.TI.Video.Decoder" }, - { "video/avc", "OMX.PV.avcdec" }, -}; - -static const CodecInfo kEncoderInfo[] = { - { "audio/3gpp", "OMX.PV.amrencnb" }, - { "audio/mp4a-latm", "OMX.PV.aacenc" }, - { "video/mp4v-es", "OMX.qcom.video.encoder.mpeg4" }, - { "video/mp4v-es", "OMX.TI.Video.encoder" }, - { "video/mp4v-es", "OMX.PV.mpeg4enc" }, - { "video/3gpp", "OMX.qcom.video.encoder.h263" }, - { "video/3gpp", "OMX.TI.Video.encoder" }, - { "video/3gpp", "OMX.PV.h263enc" }, - { "video/avc", "OMX.TI.Video.encoder" }, - { "video/avc", "OMX.PV.avcenc" }, -}; - -static const char *GetCodec(const CodecInfo *info, size_t numInfos, - const char *mime, int index) { - CHECK(index >= 0); - for(size_t i = 0; i < numInfos; ++i) { - if (!strcasecmp(mime, info[i].mime)) { - if (index == 0) { - return info[i].codec; - } - - --index; - } - } - - return NULL; -} - -// static -sp<OMXDecoder> OMXDecoder::Create( - OMXClient *client, const sp<MetaData> &meta, - bool createEncoder, - const sp<MediaSource> &source) { - const char *mime; - bool success = meta->findCString(kKeyMIMEType, &mime); - CHECK(success); - - sp<IOMX> omx = client->interface(); - - const char *codec = NULL; - IOMX::node_id node = 0; - for (int index = 0;; ++index) { - if (createEncoder) { - codec = GetCodec( - kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]), - mime, index); - } else { - codec = GetCodec( - kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]), - mime, index); - } - - if (!codec) { - return NULL; - } - - LOGI("Attempting to allocate OMX node '%s'", codec); - - status_t err = omx->allocate_node(codec, &node); - if (err == OK) { - break; - } - } - - uint32_t quirks = 0; - if (!strcmp(codec, "OMX.PV.avcdec")) { - quirks |= kWantsNALFragments; - } - if (!strcmp(codec, "OMX.TI.AAC.decode") - || !strcmp(codec, "OMX.TI.MP3.decode")) { - quirks |= kDoesntReturnBuffersOnDisable; - } - if (!strcmp(codec, "OMX.TI.AAC.decode")) { - quirks |= kDoesntFlushOnExecutingToIdle; - quirks |= kDoesntProperlyFlushAllPortsAtOnce; - } - if (!strncmp(codec, "OMX.qcom.video.encoder.", 23)) { - quirks |= kRequiresAllocateBufferOnInputPorts; - } - if (!strncmp(codec, "OMX.qcom.video.decoder.", 23)) { - quirks |= kRequiresAllocateBufferOnOutputPorts; - } - if (!strncmp(codec, "OMX.qcom.video.", 15)) { - quirks |= kRequiresLoadedToIdleAfterAllocation; - } - - sp<OMXDecoder> decoder = new OMXDecoder( - client, node, mime, codec, createEncoder, quirks, - source); - - uint32_t type; - const void *data; - size_t size; - if (meta->findData(kKeyESDS, &type, &data, &size)) { - ESDS esds((const char *)data, size); - CHECK_EQ(esds.InitCheck(), OK); - - const void *codec_specific_data; - size_t codec_specific_data_size; - esds.getCodecSpecificInfo( - &codec_specific_data, &codec_specific_data_size); - - printf("found codec specific data of size %d\n", - codec_specific_data_size); - - decoder->addCodecSpecificData( - codec_specific_data, codec_specific_data_size); - } else if (meta->findData(kKeyAVCC, &type, &data, &size)) { - printf("found avcc of size %d\n", size); - - const uint8_t *ptr = (const uint8_t *)data + 6; - size -= 6; - while (size >= 2) { - size_t length = ptr[0] << 8 | ptr[1]; - - ptr += 2; - size -= 2; - - // printf("length = %d, size = %d\n", length, size); - - CHECK(size >= length); - - decoder->addCodecSpecificData(ptr, length); - - ptr += length; - size -= length; - - if (size <= 1) { - break; - } - - ptr++; // XXX skip trailing 0x01 byte??? - --size; - } - } - - return decoder; -} - -OMXDecoder::OMXDecoder(OMXClient *client, IOMX::node_id node, - const char *mime, const char *codec, - bool is_encoder, - uint32_t quirks, - const sp<MediaSource> &source) - : mClient(client), - mOMX(mClient->interface()), - mNode(node), - mComponentName(strdup(codec)), - mMIME(strdup(mime)), - mIsMP3(!strcasecmp(mime, "audio/mpeg")), - mIsAVC(!strcasecmp(mime, "video/avc")), - mIsEncoder(is_encoder), - mQuirks(quirks), - mSource(source), - mCodecSpecificDataIterator(mCodecSpecificData.begin()), - mState(OMX_StateLoaded), - mPortStatusMask(kPortStatusActive << 2 | kPortStatusActive), - mShutdownInitiated(false), - mDealer(new MemoryDealer(5 * 1024 * 1024)), - mSeeking(false), - mStarted(false), - mErrorCondition(OK), - mReachedEndOfInput(false) { - mClient->registerObserver(mNode, this); - - mBuffers.push(); // input buffers - mBuffers.push(); // output buffers - - setup(); -} - -OMXDecoder::~OMXDecoder() { - if (mStarted) { - stop(); - } - - for (List<CodecSpecificData>::iterator it = mCodecSpecificData.begin(); - it != mCodecSpecificData.end(); ++it) { - free((*it).data); - } - mCodecSpecificData.clear(); - - mClient->unregisterObserver(mNode); - - status_t err = mOMX->free_node(mNode); - CHECK_EQ(err, OK); - mNode = 0; - - free(mMIME); - mMIME = NULL; - - free(mComponentName); - mComponentName = NULL; -} - -status_t OMXDecoder::start(MetaData *) { - CHECK(!mStarted); - - // mDealer->dump("Decoder Dealer"); - - sp<MetaData> params = new MetaData; - if (mQuirks & kWantsNALFragments) { - params->setInt32(kKeyWantsNALFragments, true); - } - - status_t err = mSource->start(params.get()); - - if (err != OK) { - return err; - } - - postStart(); - - mStarted = true; - - return OK; -} - -status_t OMXDecoder::stop() { - CHECK(mStarted); - - LOGI("Initiating OMX Node shutdown, busy polling."); - initiateShutdown(); - - // Important: initiateShutdown must be called first, _then_ release - // buffers we're holding onto. - while (!mOutputBuffers.empty()) { - MediaBuffer *buffer = *mOutputBuffers.begin(); - mOutputBuffers.erase(mOutputBuffers.begin()); - - LOGV("releasing buffer %p.", buffer->data()); - - buffer->release(); - buffer = NULL; - } - - int attempt = 1; - while (mState != OMX_StateLoaded && attempt < 20) { - usleep(100000); - - ++attempt; - } - - if (mState != OMX_StateLoaded) { - LOGE("!!! OMX Node '%s' did NOT shutdown cleanly !!!", mComponentName); - } else { - LOGI("OMX Node '%s' has shutdown cleanly.", mComponentName); - } - - mSource->stop(); - - mCodecSpecificDataIterator = mCodecSpecificData.begin(); - mShutdownInitiated = false; - mSeeking = false; - mStarted = false; - mErrorCondition = OK; - mReachedEndOfInput = false; - - return OK; -} - -sp<MetaData> OMXDecoder::getFormat() { - return mOutputFormat; -} - -status_t OMXDecoder::read( - MediaBuffer **out, const ReadOptions *options) { - CHECK(mStarted); - - *out = NULL; - - Mutex::Autolock autoLock(mLock); - - if (mErrorCondition != OK && mErrorCondition != ERROR_END_OF_STREAM) { - // Errors are sticky. - return mErrorCondition; - } - - int64_t seekTimeUs; - if (options && options->getSeekTo(&seekTimeUs)) { - LOGI("[%s] seeking to %lld us", mComponentName, seekTimeUs); - - mErrorCondition = OK; - mReachedEndOfInput = false; - - setPortStatus(kPortIndexInput, kPortStatusFlushing); - setPortStatus(kPortIndexOutput, kPortStatusFlushing); - - mSeeking = true; - mSeekTimeUs = seekTimeUs; - - while (!mOutputBuffers.empty()) { - OMXMediaBuffer *buffer = - static_cast<OMXMediaBuffer *>(*mOutputBuffers.begin()); - - // We could have used buffer->release() instead, but we're - // holding the lock and signalBufferReturned attempts to acquire - // the lock. - buffer->claim(); - mBuffers.editItemAt( - kPortIndexOutput).push_back(buffer->buffer_id()); - buffer = NULL; - - mOutputBuffers.erase(mOutputBuffers.begin()); - } - - // XXX One of TI's decoders appears to ignore a flush if it doesn't - // currently hold on to any buffers on the port in question and - // never sends the completion event... FIXME - - status_t err = mOMX->send_command(mNode, OMX_CommandFlush, OMX_ALL); - CHECK_EQ(err, OK); - - // Once flushing is completed buffers will again be scheduled to be - // filled/emptied. - } - - while (mErrorCondition == OK && mOutputBuffers.empty()) { - mOutputBufferAvailable.wait(mLock); - } - - if (!mOutputBuffers.empty()) { - MediaBuffer *buffer = *mOutputBuffers.begin(); - mOutputBuffers.erase(mOutputBuffers.begin()); - - *out = buffer; - - return OK; - } else { - CHECK(mErrorCondition != OK); - return mErrorCondition; - } -} - -void OMXDecoder::addCodecSpecificData(const void *data, size_t size) { - CodecSpecificData specific; - specific.data = malloc(size); - memcpy(specific.data, data, size); - specific.size = size; - - mCodecSpecificData.push_back(specific); - mCodecSpecificDataIterator = mCodecSpecificData.begin(); -} - -void OMXDecoder::onOMXMessage(const omx_message &msg) { - Mutex::Autolock autoLock(mLock); - - switch (msg.type) { - case omx_message::START: - { - onStart(); - break; - } - - case omx_message::EVENT: - { - onEvent(msg.u.event_data.event, msg.u.event_data.data1, - msg.u.event_data.data2); - break; - } - - case omx_message::EMPTY_BUFFER_DONE: - { - onEmptyBufferDone(msg.u.buffer_data.buffer); - break; - } - - case omx_message::FILL_BUFFER_DONE: - case omx_message::INITIAL_FILL_BUFFER: - { - onFillBufferDone(msg); - break; - } - - default: - LOGE("received unknown omx_message type %d", msg.type); - break; - } -} - -void OMXDecoder::setAMRFormat() { - OMX_AUDIO_PARAM_AMRTYPE def; - def.nSize = sizeof(def); - def.nVersion.s.nVersionMajor = 1; - def.nVersion.s.nVersionMinor = 1; - def.nPortIndex = kPortIndexInput; - - status_t err = - mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); - - CHECK_EQ(err, NO_ERROR); - - def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; - def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0; - - err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); -} - -void OMXDecoder::setAACFormat() { - OMX_AUDIO_PARAM_AACPROFILETYPE def; - def.nSize = sizeof(def); - def.nVersion.s.nVersionMajor = 1; - def.nVersion.s.nVersionMinor = 1; - def.nPortIndex = kPortIndexInput; - - status_t err = - mOMX->get_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); - - def.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; - - err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); -} - -status_t OMXDecoder::setVideoPortFormatType( - OMX_U32 portIndex, - OMX_VIDEO_CODINGTYPE compressionFormat, - OMX_COLOR_FORMATTYPE colorFormat) { - OMX_VIDEO_PARAM_PORTFORMATTYPE format; - format.nSize = sizeof(format); - format.nVersion.s.nVersionMajor = 1; - format.nVersion.s.nVersionMinor = 1; - format.nPortIndex = portIndex; - format.nIndex = 0; - bool found = false; - - OMX_U32 index = 0; - for (;;) { - format.nIndex = index; - status_t err = mOMX->get_parameter( - mNode, OMX_IndexParamVideoPortFormat, - &format, sizeof(format)); - - if (err != OK) { - return err; - } - - // The following CHECKion is violated by TI's video decoder. - // CHECK_EQ(format.nIndex, index); - -#if 1 - LOGI("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d", - portIndex, - index, format.eCompressionFormat, format.eColorFormat); -#endif - - if (!strcmp("OMX.TI.Video.encoder", mComponentName)) { - 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; - } - - LOGI("found a match."); - status_t err = mOMX->set_parameter( - mNode, OMX_IndexParamVideoPortFormat, - &format, sizeof(format)); - - return err; -} - -void OMXDecoder::setVideoInputFormat( - const char *mime, OMX_U32 width, OMX_U32 height) { - LOGI("setVideoInputFormat width=%ld, height=%ld", width, height); - - OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; - if (!strcasecmp("video/avc", mMIME)) { - compressionFormat = OMX_VIDEO_CodingAVC; - } else if (!strcasecmp("video/mp4v-es", mMIME)) { - compressionFormat = OMX_VIDEO_CodingMPEG4; - } else if (!strcasecmp("video/3gpp", mMIME)) { - compressionFormat = OMX_VIDEO_CodingH263; - } else { - LOGE("Not a supported video mime type: %s", mime); - CHECK(!"Should not be here. Not a supported video mime type."); - } - - OMX_COLOR_FORMATTYPE colorFormat = - 0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY; - - if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) { - colorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - } - - setVideoPortFormatType( - kPortIndexInput, OMX_VIDEO_CodingUnused, - colorFormat); - - setVideoPortFormatType( - kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); - - OMX_PARAM_PORTDEFINITIONTYPE def; - OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; - - def.nSize = sizeof(def); - def.nVersion.s.nVersionMajor = 1; - def.nVersion.s.nVersionMinor = 1; - def.nPortIndex = kPortIndexOutput; - - status_t err = mOMX->get_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - CHECK_EQ(err, NO_ERROR); - - CHECK_EQ(def.eDomain, OMX_PortDomainVideo); - - video_def->nFrameWidth = width; - video_def->nFrameHeight = height; - - video_def->eCompressionFormat = compressionFormat; - video_def->eColorFormat = OMX_COLOR_FormatUnused; - - err = mOMX->set_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); - - //////////////////////////////////////////////////////////////////////////// - - def.nSize = sizeof(def); - def.nVersion.s.nVersionMajor = 1; - def.nVersion.s.nVersionMinor = 1; - def.nPortIndex = kPortIndexInput; - - err = mOMX->get_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); - - def.nBufferSize = (width * height * 2); // (width * height * 3) / 2; - LOGI("setting nBufferSize = %ld", def.nBufferSize); - - CHECK_EQ(def.eDomain, OMX_PortDomainVideo); - - video_def->nFrameWidth = width; - video_def->nFrameHeight = height; - video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; - video_def->eColorFormat = colorFormat; - - err = mOMX->set_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); -} - -void OMXDecoder::setVideoOutputFormat( - const char *mime, OMX_U32 width, OMX_U32 height) { - LOGI("setVideoOutputFormat width=%ld, height=%ld", width, height); - -#if 1 - // Enabling this code appears to be the right thing(tm), but,... - // the TI decoder then loses the ability to output YUV420 and only outputs - // YCbYCr (16bit) - if (!strcmp("OMX.TI.Video.Decoder", mComponentName) - && !strcasecmp("video/avc", mime)) { - OMX_PARAM_COMPONENTROLETYPE role; - role.nSize = sizeof(role); - role.nVersion.s.nVersionMajor = 1; - role.nVersion.s.nVersionMinor = 1; - strncpy((char *)role.cRole, "video_decoder.avc", - OMX_MAX_STRINGNAME_SIZE - 1); - role.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; - - status_t err = mOMX->set_parameter( - mNode, OMX_IndexParamStandardComponentRole, - &role, sizeof(role)); - CHECK_EQ(err, OK); - } -#endif - - OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; - if (!strcasecmp("video/avc", mime)) { - compressionFormat = OMX_VIDEO_CodingAVC; - } else if (!strcasecmp("video/mp4v-es", mime)) { - compressionFormat = OMX_VIDEO_CodingMPEG4; - } else if (!strcasecmp("video/3gpp", mime)) { - compressionFormat = OMX_VIDEO_CodingH263; - } else { - LOGE("Not a supported video mime type: %s", mime); - CHECK(!"Should not be here. Not a supported video mime type."); - } - - setVideoPortFormatType( - kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); - -#if 1 - { - OMX_VIDEO_PARAM_PORTFORMATTYPE format; - format.nSize = sizeof(format); - format.nVersion.s.nVersionMajor = 1; - format.nVersion.s.nVersionMinor = 1; - format.nPortIndex = kPortIndexOutput; - format.nIndex = 0; - - status_t err = mOMX->get_parameter( - mNode, OMX_IndexParamVideoPortFormat, - &format, sizeof(format)); - CHECK_EQ(err, OK); - - CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused); - - static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; - - CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar - || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar - || format.eColorFormat == OMX_COLOR_FormatCbYCrY - || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); - - err = mOMX->set_parameter( - mNode, OMX_IndexParamVideoPortFormat, - &format, sizeof(format)); - CHECK_EQ(err, OK); - } -#endif - - OMX_PARAM_PORTDEFINITIONTYPE def; - OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; - - def.nSize = sizeof(def); - def.nVersion.s.nVersionMajor = 1; - def.nVersion.s.nVersionMinor = 1; - def.nPortIndex = kPortIndexInput; - - status_t err = mOMX->get_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - - CHECK_EQ(err, NO_ERROR); - -#if 1 - // XXX Need a (much) better heuristic to compute input buffer sizes. - const size_t X = 64 * 1024; - if (def.nBufferSize < X) { - def.nBufferSize = X; - } -#endif - - CHECK_EQ(def.eDomain, OMX_PortDomainVideo); - - video_def->nFrameWidth = width; - video_def->nFrameHeight = height; - - video_def->eColorFormat = OMX_COLOR_FormatUnused; - - err = mOMX->set_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); - - //////////////////////////////////////////////////////////////////////////// - - def.nSize = sizeof(def); - def.nVersion.s.nVersionMajor = 1; - def.nVersion.s.nVersionMinor = 1; - def.nPortIndex = kPortIndexOutput; - - err = mOMX->get_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); - - CHECK_EQ(def.eDomain, OMX_PortDomainVideo); - -#if 0 - def.nBufferSize = - (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420 -#endif - - video_def->nFrameWidth = width; - video_def->nFrameHeight = height; - - err = mOMX->set_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); -} - -void OMXDecoder::setup() { - const sp<MetaData> &meta = mSource->getFormat(); - - const char *mime; - bool success = meta->findCString(kKeyMIMEType, &mime); - CHECK(success); - - if (!strcasecmp(mime, "audio/3gpp")) { - setAMRFormat(); - } else if (!strcasecmp(mime, "audio/mp4a-latm")) { - setAACFormat(); - } else if (!strncasecmp(mime, "video/", 6)) { - int32_t width, height; - bool success = meta->findInt32(kKeyWidth, &width); - success = success && meta->findInt32(kKeyHeight, &height); - CHECK(success); - - if (mIsEncoder) { - setVideoInputFormat(mime, width, height); - } else { - setVideoOutputFormat(mime, width, height); - } - } - - // dumpPortDefinition(0); - // dumpPortDefinition(1); - - mOutputFormat = new MetaData; - mOutputFormat->setCString(kKeyDecoderComponent, mComponentName); - - OMX_PARAM_PORTDEFINITIONTYPE def; - def.nSize = sizeof(def); - def.nVersion.s.nVersionMajor = 1; - def.nVersion.s.nVersionMinor = 1; - def.nPortIndex = kPortIndexOutput; - - status_t err = mOMX->get_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); - - switch (def.eDomain) { - case OMX_PortDomainAudio: - { - OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio; - - CHECK_EQ(audio_def->eEncoding, OMX_AUDIO_CodingPCM); - - OMX_AUDIO_PARAM_PCMMODETYPE params; - params.nSize = sizeof(params); - params.nVersion.s.nVersionMajor = 1; - params.nVersion.s.nVersionMinor = 1; - params.nPortIndex = kPortIndexOutput; - - err = mOMX->get_parameter( - mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); - CHECK_EQ(err, OK); - - CHECK_EQ(params.eNumData, OMX_NumericalDataSigned); - CHECK_EQ(params.nBitPerSample, 16); - CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear); - - int32_t numChannels, sampleRate; - meta->findInt32(kKeyChannelCount, &numChannels); - meta->findInt32(kKeySampleRate, &sampleRate); - - mOutputFormat->setCString(kKeyMIMEType, "audio/raw"); - mOutputFormat->setInt32(kKeyChannelCount, numChannels); - mOutputFormat->setInt32(kKeySampleRate, sampleRate); - break; - } - - case OMX_PortDomainVideo: - { - OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; - - if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) { - mOutputFormat->setCString(kKeyMIMEType, "video/raw"); - } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) { - mOutputFormat->setCString(kKeyMIMEType, "video/mp4v-es"); - } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) { - mOutputFormat->setCString(kKeyMIMEType, "video/3gpp"); - } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) { - mOutputFormat->setCString(kKeyMIMEType, "video/avc"); - } else { - CHECK(!"Unknown compression format."); - } - - if (!strcmp(mComponentName, "OMX.PV.avcdec")) { - // This component appears to be lying to me. - mOutputFormat->setInt32( - kKeyWidth, (video_def->nFrameWidth + 15) & -16); - mOutputFormat->setInt32( - kKeyHeight, (video_def->nFrameHeight + 15) & -16); - } else { - mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth); - mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight); - } - - mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat); - break; - } - - default: - { - CHECK(!"should not be here, neither audio nor video."); - break; - } - } -} - -void OMXDecoder::onStart() { - if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) { - status_t err = - mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle); - CHECK_EQ(err, NO_ERROR); - } - - allocateBuffers(kPortIndexInput); - allocateBuffers(kPortIndexOutput); - - if (mQuirks & kRequiresLoadedToIdleAfterAllocation) { - // XXX this should happen before AllocateBuffers, but qcom's - // h264 vdec disagrees. - status_t err = - mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle); - CHECK_EQ(err, NO_ERROR); - } -} - -void OMXDecoder::allocateBuffers(OMX_U32 port_index) { - CHECK(mBuffers[port_index].empty()); - - OMX_U32 num_buffers; - OMX_U32 buffer_size; - - OMX_PARAM_PORTDEFINITIONTYPE def; - def.nSize = sizeof(def); - def.nVersion.s.nVersionMajor = 1; - def.nVersion.s.nVersionMinor = 1; - def.nVersion.s.nRevision = 0; - def.nVersion.s.nStep = 0; - def.nPortIndex = port_index; - - status_t err = mOMX->get_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); - - num_buffers = def.nBufferCountActual; - buffer_size = def.nBufferSize; - - LOGV("[%s] port %ld: allocating %ld buffers of size %ld each\n", - mComponentName, port_index, num_buffers, buffer_size); - - for (OMX_U32 i = 0; i < num_buffers; ++i) { - sp<IMemory> mem = mDealer->allocate(buffer_size); - if (mem.get() == NULL) { - LOGE("[%s] allocating IMemory of size %ld FAILED.", - mComponentName, buffer_size); - } - CHECK(mem.get() != NULL); - - IOMX::buffer_id buffer; - status_t err; - - if (port_index == kPortIndexInput - && (mQuirks & kRequiresAllocateBufferOnInputPorts)) { - // qcom's H.263 encoder appears to want to allocate its own input - // buffers. - err = mOMX->allocate_buffer_with_backup(mNode, port_index, mem, &buffer); - if (err != OK) { - LOGE("[%s] allocate_buffer_with_backup failed with error %d", - mComponentName, err); - } - } else if (port_index == kPortIndexOutput - && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) { -#if 1 - err = mOMX->allocate_buffer_with_backup(mNode, port_index, mem, &buffer); -#else - // XXX This is fine as long as we are either running the player - // inside the media server process or we are using the - // QComHardwareRenderer to output the frames. - err = mOMX->allocate_buffer(mNode, port_index, buffer_size, &buffer); -#endif - if (err != OK) { - LOGE("[%s] allocate_buffer_with_backup failed with error %d", - mComponentName, err); - } - } else { - err = mOMX->use_buffer(mNode, port_index, mem, &buffer); - if (err != OK) { - LOGE("[%s] use_buffer failed with error %d", - mComponentName, err); - } - } - CHECK_EQ(err, OK); - - LOGV("allocated %s buffer %p.", - port_index == kPortIndexInput ? "INPUT" : "OUTPUT", - buffer); - - mBuffers.editItemAt(port_index).push_back(buffer); - mBufferMap.add(buffer, mem); - - if (port_index == kPortIndexOutput) { - OMXMediaBuffer *media_buffer = new OMXMediaBuffer(buffer, mem); - media_buffer->setObserver(this); - - mMediaBufferMap.add(buffer, media_buffer); - } - } - - LOGV("allocate %s buffers done.", - port_index == kPortIndexInput ? "INPUT" : "OUTPUT"); -} - -void OMXDecoder::onEvent( - OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { - LOGV("[%s] onEvent event=%d, data1=%ld, data2=%ld", - mComponentName, event, data1, data2); - - switch (event) { - case OMX_EventCmdComplete: { - onEventCmdComplete( - static_cast<OMX_COMMANDTYPE>(data1), data2); - - break; - } - - case OMX_EventPortSettingsChanged: { - onEventPortSettingsChanged(data1); - break; - } - - case OMX_EventBufferFlag: { - // initiateShutdown(); - break; - } - - default: - break; - } -} - -void OMXDecoder::onEventCmdComplete(OMX_COMMANDTYPE type, OMX_U32 data) { - switch (type) { - case OMX_CommandStateSet: { - OMX_STATETYPE state = static_cast<OMX_STATETYPE>(data); - onStateChanged(state); - break; - } - - case OMX_CommandPortDisable: { - OMX_U32 port_index = data; - CHECK_EQ(getPortStatus(port_index), kPortStatusDisabled); - - status_t err = - mOMX->send_command(mNode, OMX_CommandPortEnable, port_index); - - allocateBuffers(port_index); - - break; - } - - case OMX_CommandPortEnable: { - OMX_U32 port_index = data; - CHECK(getPortStatus(port_index) ==kPortStatusDisabled); - setPortStatus(port_index, kPortStatusActive); - - CHECK_EQ(port_index, kPortIndexOutput); - - BufferList *obuffers = &mBuffers.editItemAt(kPortIndexOutput); - while (!obuffers->empty()) { - IOMX::buffer_id buffer = *obuffers->begin(); - obuffers->erase(obuffers->begin()); - - mOMX->fill_buffer(mNode, buffer); - } - - break; - } - - case OMX_CommandFlush: { - OMX_U32 port_index = data; - LOGV("Port %ld flush complete.", port_index); - - PortStatus status = getPortStatus(port_index); - - CHECK(status == kPortStatusFlushing - || status == kPortStatusFlushingToDisabled - || status == kPortStatusFlushingToShutdown); - - switch (status) { - case kPortStatusFlushing: - { - // This happens when we're flushing before a seek. - setPortStatus(port_index, kPortStatusActive); - BufferList *buffers = &mBuffers.editItemAt(port_index); - while (!buffers->empty()) { - IOMX::buffer_id buffer = *buffers->begin(); - buffers->erase(buffers->begin()); - - if (port_index == kPortIndexInput) { - postEmptyBufferDone(buffer); - } else { - postInitialFillBuffer(buffer); - } - } - break; - } - - case kPortStatusFlushingToDisabled: - { - // Port settings have changed and the (buggy) OMX component - // does not properly return buffers on disabling, we need to - // do a flush first and _then_ disable the port in question. - - setPortStatus(port_index, kPortStatusDisabled); - status_t err = mOMX->send_command( - mNode, OMX_CommandPortDisable, port_index); - CHECK_EQ(err, OK); - - freePortBuffers(port_index); - break; - } - - default: - { - CHECK_EQ(status, kPortStatusFlushingToShutdown); - - setPortStatus(port_index, kPortStatusShutdown); - if (getPortStatus(kPortIndexInput) == kPortStatusShutdown - && getPortStatus(kPortIndexOutput) == kPortStatusShutdown) { - status_t err = mOMX->send_command( - mNode, OMX_CommandStateSet, OMX_StateIdle); - CHECK_EQ(err, OK); - } - break; - } - } - break; - } - - default: - break; - } -} - -void OMXDecoder::onEventPortSettingsChanged(OMX_U32 port_index) { - CHECK_EQ(getPortStatus(port_index), kPortStatusActive); - - status_t err; - - if (mQuirks & kDoesntReturnBuffersOnDisable) { - // Decoder does not properly return our buffers when disabled... - // Need to flush port instead and _then_ disable. - - setPortStatus(port_index, kPortStatusFlushingToDisabled); - - err = mOMX->send_command(mNode, OMX_CommandFlush, port_index); - } else { - setPortStatus(port_index, kPortStatusDisabled); - - err = mOMX->send_command(mNode, OMX_CommandPortDisable, port_index); - } - - CHECK_EQ(err, NO_ERROR); -} - -void OMXDecoder::onStateChanged(OMX_STATETYPE to) { - if (mState == OMX_StateLoaded) { - CHECK_EQ(to, OMX_StateIdle); - - mState = to; - - status_t err = - mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateExecuting); - CHECK_EQ(err, NO_ERROR); - } else if (mState == OMX_StateIdle) { - if (to == OMX_StateExecuting) { - mState = to; - - BufferList *ibuffers = &mBuffers.editItemAt(kPortIndexInput); - while (!ibuffers->empty()) { - IOMX::buffer_id buffer = *ibuffers->begin(); - ibuffers->erase(ibuffers->begin()); - - postEmptyBufferDone(buffer); - } - - BufferList *obuffers = &mBuffers.editItemAt(kPortIndexOutput); - while (!obuffers->empty()) { - IOMX::buffer_id buffer = *obuffers->begin(); - obuffers->erase(obuffers->begin()); - - postInitialFillBuffer(buffer); - } - } else { - CHECK_EQ(to, OMX_StateLoaded); - - mState = to; - - setPortStatus(kPortIndexInput, kPortStatusActive); - setPortStatus(kPortIndexOutput, kPortStatusActive); - } - } else if (mState == OMX_StateExecuting) { - CHECK_EQ(to, OMX_StateIdle); - - mState = to; - - LOGV("Executing->Idle complete, initiating Idle->Loaded"); - status_t err = - mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateLoaded); - CHECK_EQ(err, NO_ERROR); - - freePortBuffers(kPortIndexInput); - freePortBuffers(kPortIndexOutput); - } -} - -void OMXDecoder::initiateShutdown() { - Mutex::Autolock autoLock(mLock); - - if (mShutdownInitiated) { - return; - } - - if (mState == OMX_StateLoaded) { - return; - } - - CHECK_EQ(mState, OMX_StateExecuting); - - mShutdownInitiated = true; - - status_t err; - if (mQuirks & kDoesntFlushOnExecutingToIdle) { - if (mQuirks & kDoesntProperlyFlushAllPortsAtOnce) { - err = mOMX->send_command(mNode, OMX_CommandFlush, kPortIndexInput); - CHECK_EQ(err, OK); - - err = mOMX->send_command(mNode, OMX_CommandFlush, kPortIndexOutput); - } else { - err = mOMX->send_command(mNode, OMX_CommandFlush, OMX_ALL); - } - - setPortStatus(kPortIndexInput, kPortStatusFlushingToShutdown); - setPortStatus(kPortIndexOutput, kPortStatusFlushingToShutdown); - } else { - err = mOMX->send_command( - mNode, OMX_CommandStateSet, OMX_StateIdle); - - setPortStatus(kPortIndexInput, kPortStatusShutdown); - setPortStatus(kPortIndexOutput, kPortStatusShutdown); - } - CHECK_EQ(err, OK); -} - -void OMXDecoder::setPortStatus(OMX_U32 port_index, PortStatus status) { - int shift = 3 * port_index; - - mPortStatusMask &= ~(7 << shift); - mPortStatusMask |= status << shift; -} - -OMXDecoder::PortStatus OMXDecoder::getPortStatus( - OMX_U32 port_index) const { - int shift = 3 * port_index; - - return static_cast<PortStatus>((mPortStatusMask >> shift) & 7); -} - -void OMXDecoder::onEmptyBufferDone(IOMX::buffer_id buffer) { - LOGV("[%s] onEmptyBufferDone (%p)", mComponentName, buffer); - - status_t err; - switch (getPortStatus(kPortIndexInput)) { - case kPortStatusDisabled: - freeInputBuffer(buffer); - err = NO_ERROR; - break; - - case kPortStatusShutdown: - LOGV("We're shutting down, enqueue INPUT buffer %p.", buffer); - mBuffers.editItemAt(kPortIndexInput).push_back(buffer); - err = NO_ERROR; - break; - - case kPortStatusFlushing: - case kPortStatusFlushingToDisabled: - case kPortStatusFlushingToShutdown: - LOGV("We're currently flushing, enqueue INPUT buffer %p.", buffer); - mBuffers.editItemAt(kPortIndexInput).push_back(buffer); - err = NO_ERROR; - break; - - default: - onRealEmptyBufferDone(buffer); - err = NO_ERROR; - break; - } - CHECK_EQ(err, NO_ERROR); -} - -void OMXDecoder::onFillBufferDone(const omx_message &msg) { - IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer; - - LOGV("[%s] on%sFillBufferDone (%p, size:%ld)", mComponentName, - msg.type == omx_message::INITIAL_FILL_BUFFER ? "Initial" : "", - buffer, msg.u.extended_buffer_data.range_length); - - status_t err; - switch (getPortStatus(kPortIndexOutput)) { - case kPortStatusDisabled: - freeOutputBuffer(buffer); - err = NO_ERROR; - break; - case kPortStatusShutdown: - LOGV("We're shutting down, enqueue OUTPUT buffer %p.", buffer); - mBuffers.editItemAt(kPortIndexOutput).push_back(buffer); - err = NO_ERROR; - break; - - case kPortStatusFlushing: - case kPortStatusFlushingToDisabled: - case kPortStatusFlushingToShutdown: - LOGV("We're currently flushing, enqueue OUTPUT buffer %p.", buffer); - mBuffers.editItemAt(kPortIndexOutput).push_back(buffer); - err = NO_ERROR; - break; - - default: - { - if (msg.type == omx_message::INITIAL_FILL_BUFFER) { - mOMX->fill_buffer(mNode, buffer); - } else { - LOGV("[%s] Filled OUTPUT buffer %p, flags=0x%08lx.", - mComponentName, buffer, msg.u.extended_buffer_data.flags); - - onRealFillBufferDone(msg); - } - err = NO_ERROR; - break; - } - } - CHECK_EQ(err, NO_ERROR); -} - -void OMXDecoder::onRealEmptyBufferDone(IOMX::buffer_id buffer) { - if (mReachedEndOfInput) { - // We already sent the EOS notification. - - mBuffers.editItemAt(kPortIndexInput).push_back(buffer); - return; - } - - const sp<IMemory> mem = mBufferMap.valueFor(buffer); - CHECK(mem.get() != NULL); - - static const uint8_t kNALStartCode[4] = { 0x00, 0x00, 0x00, 0x01 }; - - if (mCodecSpecificDataIterator != mCodecSpecificData.end()) { - List<CodecSpecificData>::iterator it = mCodecSpecificDataIterator; - - size_t range_length = 0; - - if (mIsAVC && !(mQuirks & kWantsNALFragments)) { - CHECK((*mCodecSpecificDataIterator).size + 4 <= mem->size()); - - memcpy(mem->pointer(), kNALStartCode, 4); - - memcpy((uint8_t *)mem->pointer() + 4, (*it).data, (*it).size); - range_length = (*it).size + 4; - } else { - CHECK((*mCodecSpecificDataIterator).size <= mem->size()); - - memcpy((uint8_t *)mem->pointer(), (*it).data, (*it).size); - range_length = (*it).size; - } - - ++mCodecSpecificDataIterator; - - mOMX->empty_buffer( - mNode, buffer, 0, range_length, - OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG, - 0); - - return; - } - - LOGV("[%s] waiting for input data", mComponentName); - - MediaBuffer *input_buffer; - for (;;) { - status_t err; - - if (mSeeking) { - MediaSource::ReadOptions options; - options.setSeekTo(mSeekTimeUs); - - mSeeking = false; - - err = mSource->read(&input_buffer, &options); - } else { - err = mSource->read(&input_buffer); - } - CHECK((err == OK && input_buffer != NULL) - || (err != OK && input_buffer == NULL)); - - if (err == ERROR_END_OF_STREAM) { - LOGE("[%s] Reached end of stream.", mComponentName); - mReachedEndOfInput = true; - } else { - LOGV("[%s] got input data", mComponentName); - } - - if (err != OK) { - mOMX->empty_buffer( - mNode, buffer, 0, 0, OMX_BUFFERFLAG_EOS, 0); - - return; - } - - if (mSeeking) { - input_buffer->release(); - input_buffer = NULL; - - continue; - } - - break; - } - - const uint8_t *src_data = - (const uint8_t *)input_buffer->data() + input_buffer->range_offset(); - - size_t src_length = input_buffer->range_length(); - if (src_length == 195840) { - // When feeding the output of the AVC decoder into the H263 encoder, - // buffer sizes mismatch if width % 16 != 0 || height % 16 != 0. - src_length = 194400; // XXX HACK - } else if (src_length == 115200) { - src_length = 114240; // XXX HACK - } - - if (src_length > mem->size()) { - LOGE("src_length=%d > mem->size() = %d\n", - src_length, mem->size()); - } - - CHECK(src_length <= mem->size()); - memcpy(mem->pointer(), src_data, src_length); - - OMX_U32 flags = 0; - if (!mIsMP3) { - // Only mp3 audio data may be streamed, all other data is assumed - // to be fed into the decoder at frame boundaries. - flags |= OMX_BUFFERFLAG_ENDOFFRAME; - } - - int32_t units, scale; - bool success = - input_buffer->meta_data()->findInt32(kKeyTimeUnits, &units); - - success = success && - input_buffer->meta_data()->findInt32(kKeyTimeScale, &scale); - - OMX_TICKS timestamp = 0; - - if (success) { - if (mQuirks & kMeasuresTimeInMilliseconds) { - timestamp = ((OMX_S64)units * 1000) / scale; - } else { - timestamp = ((OMX_S64)units * 1000000) / scale; - } - } - - input_buffer->release(); - input_buffer = NULL; - - LOGV("[%s] Calling EmptyBuffer on buffer %p size:%d flags:0x%08lx", - mComponentName, buffer, src_length, flags); - - mOMX->empty_buffer( - mNode, buffer, 0, src_length, flags, timestamp); -} - -void OMXDecoder::onRealFillBufferDone(const omx_message &msg) { - OMXMediaBuffer *media_buffer = - mMediaBufferMap.valueFor(msg.u.extended_buffer_data.buffer); - - media_buffer->set_range( - msg.u.extended_buffer_data.range_offset, - msg.u.extended_buffer_data.range_length); - - media_buffer->add_ref(); - - media_buffer->meta_data()->clear(); - - if (mQuirks & kMeasuresTimeInMilliseconds) { - media_buffer->meta_data()->setInt32( - kKeyTimeUnits, - msg.u.extended_buffer_data.timestamp); - } else { - media_buffer->meta_data()->setInt32( - kKeyTimeUnits, - (msg.u.extended_buffer_data.timestamp + 500) / 1000); - } - - media_buffer->meta_data()->setInt32(kKeyTimeScale, 1000); - - if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) { - media_buffer->meta_data()->setInt32(kKeyIsSyncFrame, true); - } - - media_buffer->meta_data()->setPointer( - kKeyPlatformPrivate, - msg.u.extended_buffer_data.platform_private); - - media_buffer->meta_data()->setPointer( - kKeyBufferID, - msg.u.extended_buffer_data.buffer); - - if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) { - mErrorCondition = ERROR_END_OF_STREAM; - } - - mOutputBuffers.push_back(media_buffer); - mOutputBufferAvailable.signal(); -} - -void OMXDecoder::signalBufferReturned(MediaBuffer *_buffer) { - Mutex::Autolock autoLock(mLock); - - OMXMediaBuffer *media_buffer = static_cast<OMXMediaBuffer *>(_buffer); - - IOMX::buffer_id buffer = media_buffer->buffer_id(); - - PortStatus outputStatus = getPortStatus(kPortIndexOutput); - if (outputStatus == kPortStatusShutdown - || outputStatus == kPortStatusFlushing - || outputStatus == kPortStatusFlushingToDisabled - || outputStatus == kPortStatusFlushingToShutdown) { - mBuffers.editItemAt(kPortIndexOutput).push_back(buffer); - } else { - LOGV("[%s] Calling FillBuffer on buffer %p.", mComponentName, buffer); - - mOMX->fill_buffer(mNode, buffer); - } -} - -void OMXDecoder::freeInputBuffer(IOMX::buffer_id buffer) { - LOGV("freeInputBuffer %p", buffer); - - status_t err = mOMX->free_buffer(mNode, kPortIndexInput, buffer); - CHECK_EQ(err, NO_ERROR); - mBufferMap.removeItem(buffer); - - LOGV("freeInputBuffer %p done", buffer); -} - -void OMXDecoder::freeOutputBuffer(IOMX::buffer_id buffer) { - LOGV("freeOutputBuffer %p", buffer); - - status_t err = mOMX->free_buffer(mNode, kPortIndexOutput, buffer); - CHECK_EQ(err, NO_ERROR); - mBufferMap.removeItem(buffer); - - ssize_t index = mMediaBufferMap.indexOfKey(buffer); - CHECK(index >= 0); - MediaBuffer *mbuffer = mMediaBufferMap.editValueAt(index); - mMediaBufferMap.removeItemsAt(index); - mbuffer->setObserver(NULL); - mbuffer->release(); - mbuffer = NULL; - - LOGV("freeOutputBuffer %p done", buffer); -} - -void OMXDecoder::dumpPortDefinition(OMX_U32 port_index) { - OMX_PARAM_PORTDEFINITIONTYPE def; - def.nSize = sizeof(def); - def.nVersion.s.nVersionMajor = 1; - def.nVersion.s.nVersionMinor = 1; - def.nPortIndex = port_index; - - status_t err = mOMX->get_parameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, NO_ERROR); - - LOGI("DumpPortDefinition on port %ld", port_index); - LOGI("nBufferCountActual = %ld, nBufferCountMin = %ld, nBufferSize = %ld", - def.nBufferCountActual, def.nBufferCountMin, def.nBufferSize); - switch (def.eDomain) { - case OMX_PortDomainAudio: - { - LOGI("eDomain = AUDIO"); - - if (port_index == kPortIndexOutput) { - OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio; - CHECK_EQ(audio_def->eEncoding, OMX_AUDIO_CodingPCM); - - OMX_AUDIO_PARAM_PCMMODETYPE params; - params.nSize = sizeof(params); - params.nVersion.s.nVersionMajor = 1; - params.nVersion.s.nVersionMinor = 1; - params.nPortIndex = port_index; - - err = mOMX->get_parameter( - mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); - CHECK_EQ(err, OK); - - CHECK(params.nChannels == 1 || params.bInterleaved); - CHECK_EQ(params.eNumData, OMX_NumericalDataSigned); - CHECK_EQ(params.nBitPerSample, 16); - CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear); - - LOGI("nChannels = %ld, nSamplingRate = %ld", - params.nChannels, params.nSamplingRate); - } - - break; - } - - case OMX_PortDomainVideo: - { - LOGI("eDomain = VIDEO"); - - OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; - LOGI("nFrameWidth = %ld, nFrameHeight = %ld, nStride = %ld, " - "nSliceHeight = %ld", - video_def->nFrameWidth, video_def->nFrameHeight, - video_def->nStride, video_def->nSliceHeight); - LOGI("nBitrate = %ld, xFrameRate = %.2f", - video_def->nBitrate, video_def->xFramerate / 65536.0f); - LOGI("eCompressionFormat = %d, eColorFormat = %d", - video_def->eCompressionFormat, video_def->eColorFormat); - - break; - } - - default: - LOGI("eDomain = UNKNOWN"); - break; - } -} - -void OMXDecoder::postStart() { - omx_message msg; - msg.type = omx_message::START; - postMessage(msg); -} - -void OMXDecoder::postEmptyBufferDone(IOMX::buffer_id buffer) { - omx_message msg; - msg.type = omx_message::EMPTY_BUFFER_DONE; - msg.node = mNode; - msg.u.buffer_data.buffer = buffer; - postMessage(msg); -} - -void OMXDecoder::postInitialFillBuffer(IOMX::buffer_id buffer) { - omx_message msg; - msg.type = omx_message::INITIAL_FILL_BUFFER; - msg.node = mNode; - msg.u.buffer_data.buffer = buffer; - postMessage(msg); -} - -void OMXDecoder::freePortBuffers(OMX_U32 port_index) { - BufferList *buffers = &mBuffers.editItemAt(port_index); - while (!buffers->empty()) { - IOMX::buffer_id buffer = *buffers->begin(); - buffers->erase(buffers->begin()); - - if (port_index == kPortIndexInput) { - freeInputBuffer(buffer); - } else { - freeOutputBuffer(buffer); - } - } -} - -} // namespace android |