From 1de13168a9d9f55464dc98748ea28ef785f1048e Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Fri, 31 Jul 2009 11:52:50 -0700 Subject: The IOMX interface now instantiates IOMXRenderers to hide the details of hardware accelerated blitting. --- include/media/IOMX.h | 24 +++ include/media/stagefright/MediaPlayerImpl.h | 4 +- include/media/stagefright/MetaData.h | 1 + include/media/stagefright/SurfaceRenderer.h | 51 ------- include/ui/Surface.h | 2 + media/libmedia/IOMX.cpp | 92 +++++++++++ media/libstagefright/Android.mk | 4 - media/libstagefright/MediaPlayerImpl.cpp | 58 ++----- media/libstagefright/OMXDecoder.cpp | 7 +- media/libstagefright/QComHardwareRenderer.cpp | 139 ----------------- media/libstagefright/SoftwareRenderer.cpp | 173 --------------------- media/libstagefright/SurfaceRenderer.cpp | 69 --------- media/libstagefright/TIHardwareRenderer.cpp | 99 ------------ media/libstagefright/omx/Android.mk | 18 ++- media/libstagefright/omx/OMX.cpp | 63 ++++++++ media/libstagefright/omx/OMX.h | 7 + media/libstagefright/omx/OMXRenderer.h | 44 ++++++ media/libstagefright/omx/QComHardwareRenderer.cpp | 139 +++++++++++++++++ media/libstagefright/omx/SoftwareRenderer.cpp | 177 ++++++++++++++++++++++ media/libstagefright/omx/TIHardwareRenderer.cpp | 99 ++++++++++++ 20 files changed, 679 insertions(+), 591 deletions(-) delete mode 100644 include/media/stagefright/SurfaceRenderer.h delete mode 100644 media/libstagefright/QComHardwareRenderer.cpp delete mode 100644 media/libstagefright/SoftwareRenderer.cpp delete mode 100644 media/libstagefright/SurfaceRenderer.cpp delete mode 100644 media/libstagefright/TIHardwareRenderer.cpp create mode 100644 media/libstagefright/omx/OMXRenderer.h create mode 100644 media/libstagefright/omx/QComHardwareRenderer.cpp create mode 100644 media/libstagefright/omx/SoftwareRenderer.cpp create mode 100644 media/libstagefright/omx/TIHardwareRenderer.cpp diff --git a/include/media/IOMX.h b/include/media/IOMX.h index 5c61c50ee22b..0010d8482963 100644 --- a/include/media/IOMX.h +++ b/include/media/IOMX.h @@ -23,6 +23,7 @@ #include #include +#include #define IOMX_USES_SOCKETS 0 @@ -30,6 +31,8 @@ namespace android { class IMemory; class IOMXObserver; +class IOMXRenderer; +class ISurface; class IOMX : public IInterface { public: @@ -87,6 +90,13 @@ public: OMX_U32 range_offset, OMX_U32 range_length, OMX_U32 flags, OMX_TICKS timestamp) = 0; #endif + + virtual sp createRenderer( + const sp &surface, + const char *componentName, + OMX_COLOR_FORMATTYPE colorFormat, + size_t encodedWidth, size_t encodedHeight, + size_t displayWidth, size_t displayHeight) = 0; }; struct omx_message { @@ -155,6 +165,13 @@ public: virtual void on_message(const omx_message &msg) = 0; }; +class IOMXRenderer : public IInterface { +public: + DECLARE_META_INTERFACE(OMXRenderer); + + virtual void render(IOMX::buffer_id buffer) = 0; +}; + //////////////////////////////////////////////////////////////////////////////// class BnOMX : public BnInterface { @@ -171,6 +188,13 @@ public: uint32_t flags = 0); }; +class BnOMXRenderer : public BnInterface { +public: + virtual status_t onTransact( + uint32_t code, const Parcel &data, Parcel *reply, + uint32_t flags = 0); +}; + } // namespace android #endif // ANDROID_IOMX_H_ diff --git a/include/media/stagefright/MediaPlayerImpl.h b/include/media/stagefright/MediaPlayerImpl.h index c48400c530e9..e96e5e84834f 100644 --- a/include/media/stagefright/MediaPlayerImpl.h +++ b/include/media/stagefright/MediaPlayerImpl.h @@ -28,6 +28,7 @@ namespace android { class AudioPlayer; +class IOMXRenderer; class ISurface; class MediaExtractor; class MediaBuffer; @@ -37,7 +38,6 @@ class MetaData; class OMXDecoder; class Surface; class TimeSource; -class VideoRenderer; class MediaPlayerImpl { public: @@ -93,7 +93,7 @@ private: sp mSurface; sp mISurface; - VideoRenderer *mRenderer; + sp mVideoRenderer; sp mAudioSink; diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index 04805dab5c9d..2d5b8d886ea1 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -44,6 +44,7 @@ enum { kKeyColorFormat = 'colf', kKeyPlatformPrivate = 'priv', kKeyDecoderComponent = 'decC', + kKeyBufferID = 'bfID', }; enum { diff --git a/include/media/stagefright/SurfaceRenderer.h b/include/media/stagefright/SurfaceRenderer.h deleted file mode 100644 index 298ab50a87d4..000000000000 --- a/include/media/stagefright/SurfaceRenderer.h +++ /dev/null @@ -1,51 +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 SURFACE_RENDERER_H_ - -#define SURFACE_RENDERER_H_ - -#include -#include - -namespace android { - -class Surface; - -class SurfaceRenderer : public VideoRenderer { -public: - SurfaceRenderer( - const sp &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight); - - virtual ~SurfaceRenderer(); - - virtual void render( - const void *data, size_t size, void *platformPrivate); - -private: - sp mSurface; - size_t mDisplayWidth, mDisplayHeight; - size_t mDecodedWidth, mDecodedHeight; - - SurfaceRenderer(const SurfaceRenderer &); - SurfaceRenderer &operator=(const SurfaceRenderer &); -}; - -} // namespace android - -#endif // SURFACE_RENDERER_H_ diff --git a/include/ui/Surface.h b/include/ui/Surface.h index 156d453b2d20..5665c1fda46f 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -36,6 +36,7 @@ namespace android { class BufferMapper; class Rect; +class MediaPlayerImpl; class Surface; class SurfaceComposerClient; struct per_client_cblk_t; @@ -180,6 +181,7 @@ private: // mediaplayer needs access to ISurface for display friend class MediaPlayer; friend class Test; + friend class MediaPlayerImpl; const sp& getISurface() const { return mSurface; } status_t getBufferLocked(int index); diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index f2a657aa0357..4661af6c1f01 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace android { @@ -23,7 +24,9 @@ enum { OBSERVE_NODE, FILL_BUFFER, EMPTY_BUFFER, + CREATE_RENDERER, OBSERVER_ON_MSG, + RENDERER_RENDER, }; static void *readVoidStar(const Parcel *parcel) { @@ -262,6 +265,28 @@ public: remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); } #endif + + virtual sp createRenderer( + const sp &surface, + const char *componentName, + OMX_COLOR_FORMATTYPE colorFormat, + size_t encodedWidth, size_t encodedHeight, + size_t displayWidth, size_t displayHeight) { + Parcel data, reply; + data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); + + data.writeStrongBinder(surface->asBinder()); + data.writeCString(componentName); + data.writeInt32(colorFormat); + data.writeInt32(encodedWidth); + data.writeInt32(encodedHeight); + data.writeInt32(displayWidth); + data.writeInt32(displayHeight); + + remote()->transact(CREATE_RENDERER, data, &reply); + + return interface_cast(reply.readStrongBinder()); + } }; IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX"); @@ -513,6 +538,33 @@ status_t BnOMX::onTransact( } #endif + case CREATE_RENDERER: + { + CHECK_INTERFACE(IOMX, data, reply); + + sp isurface = + interface_cast(data.readStrongBinder()); + + const char *componentName = data.readCString(); + + OMX_COLOR_FORMATTYPE colorFormat = + static_cast(data.readInt32()); + + size_t encodedWidth = (size_t)data.readInt32(); + size_t encodedHeight = (size_t)data.readInt32(); + size_t displayWidth = (size_t)data.readInt32(); + size_t displayHeight = (size_t)data.readInt32(); + + sp renderer = + createRenderer(isurface, componentName, colorFormat, + encodedWidth, encodedHeight, + displayWidth, displayHeight); + + reply->writeStrongBinder(renderer->asBinder()); + + return OK; + } + default: return BBinder::onTransact(code, data, reply, flags); } @@ -558,4 +610,44 @@ status_t BnOMXObserver::onTransact( } } +//////////////////////////////////////////////////////////////////////////////// + +class BpOMXRenderer : public BpInterface { +public: + BpOMXRenderer(const sp &impl) + : BpInterface(impl) { + } + + virtual void render(IOMX::buffer_id buffer) { + Parcel data, reply; + data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor()); + writeVoidStar(buffer, &data); + + // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous + // so that the caller knows when to recycle the buffer. + remote()->transact(RENDERER_RENDER, data, &reply); + } +}; + +IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer"); + +status_t BnOMXRenderer::onTransact( + uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { + switch (code) { + case RENDERER_RENDER: + { + CHECK_INTERFACE(IOMXRenderer, data, reply); + + IOMX::buffer_id buffer = readVoidStar(&data); + + render(buffer); + + return NO_ERROR; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + } // namespace android diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 5be9224d6259..0a44762a258e 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -19,14 +19,10 @@ LOCAL_SRC_FILES:= \ MediaSource.cpp \ MetaData.cpp \ MmapSource.cpp \ - QComHardwareRenderer.cpp \ SampleTable.cpp \ ShoutcastSource.cpp \ - SoftwareRenderer.cpp \ - SurfaceRenderer.cpp \ TimeSource.cpp \ TimedEventQueue.cpp \ - TIHardwareRenderer.cpp \ Utils.cpp \ AudioPlayer.cpp \ ESDS.cpp \ diff --git a/media/libstagefright/MediaPlayerImpl.cpp b/media/libstagefright/MediaPlayerImpl.cpp index 04c9a11d96e8..341f002dc7f9 100644 --- a/media/libstagefright/MediaPlayerImpl.cpp +++ b/media/libstagefright/MediaPlayerImpl.cpp @@ -35,12 +35,8 @@ #include #include #include -#include #include -#include -#include #include -#include #include #include @@ -61,7 +57,6 @@ MediaPlayerImpl::MediaPlayerImpl(const char *uri) mDuration(0), mPlaying(false), mPaused(false), - mRenderer(NULL), mSeeking(false), mFrameSize(0), mUseSoftwareColorConversion(false) { @@ -121,7 +116,6 @@ MediaPlayerImpl::MediaPlayerImpl(int fd, int64_t offset, int64_t length) mDuration(0), mPlaying(false), mPaused(false), - mRenderer(NULL), mSeeking(false), mFrameSize(0), mUseSoftwareColorConversion(false) { @@ -379,7 +373,7 @@ void MediaPlayerImpl::displayOrDiscardFrame( { Mutex::Autolock autoLock(mLock); - if (mRenderer != NULL) { + if (mVideoRenderer.get() != NULL) { sendFrameToISurface(buffer); } } @@ -652,52 +646,26 @@ void MediaPlayerImpl::populateISurface() { success = success && meta->findInt32(kKeyHeight, &decodedHeight); assert(success); - static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; + const sp &isurface = + mSurface.get() != NULL ? mSurface->getISurface() : mISurface; - if (mSurface.get() != NULL) { - LOGW("Using SurfaceRenderer."); - mRenderer = - new SurfaceRenderer( - mSurface, mVideoWidth, mVideoHeight, - decodedWidth, decodedHeight); - } else if (format == OMX_QCOM_COLOR_FormatYVU420SemiPlanar - && !strncmp(component, "OMX.qcom.video.decoder.", 23)) { - LOGW("Using QComHardwareRenderer."); - mRenderer = - new QComHardwareRenderer( - mISurface, mVideoWidth, mVideoHeight, - decodedWidth, decodedHeight); - } else if (format == OMX_COLOR_FormatCbYCrY - && !strcmp(component, "OMX.TI.Video.Decoder")) { - LOGW("Using TIHardwareRenderer."); - mRenderer = - new TIHardwareRenderer( - mISurface, mVideoWidth, mVideoHeight, - decodedWidth, decodedHeight); - } else { - LOGW("Using software renderer."); - mRenderer = new SoftwareRenderer( - mISurface, mVideoWidth, mVideoHeight, - decodedWidth, decodedHeight); - } + mVideoRenderer = + mClient.interface()->createRenderer( + isurface, component, + (OMX_COLOR_FORMATTYPE)format, + decodedWidth, decodedHeight, + mVideoWidth, mVideoHeight); } void MediaPlayerImpl::depopulateISurface() { - delete mRenderer; - mRenderer = NULL; + mVideoRenderer.clear(); } void MediaPlayerImpl::sendFrameToISurface(MediaBuffer *buffer) { - void *platformPrivate; - if (!buffer->meta_data()->findPointer( - kKeyPlatformPrivate, &platformPrivate)) { - platformPrivate = NULL; + void *id; + if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { + mVideoRenderer->render((IOMX::buffer_id)id); } - - mRenderer->render( - (const uint8_t *)buffer->data() + buffer->range_offset(), - buffer->range_length(), - platformPrivate); } void MediaPlayerImpl::setAudioSink( diff --git a/media/libstagefright/OMXDecoder.cpp b/media/libstagefright/OMXDecoder.cpp index 5e449995a4e8..780cd2ea9b7b 100644 --- a/media/libstagefright/OMXDecoder.cpp +++ b/media/libstagefright/OMXDecoder.cpp @@ -154,8 +154,7 @@ OMXDecoder *OMXDecoder::Create( if (!strncmp(codec, "OMX.qcom.video.", 15)) { quirks |= kRequiresLoadedToIdleAfterAllocation; } - if (!strcmp(codec, "OMX.TI.AAC.decode") - || !strcmp(codec, "OMX.TI.MP3.decode")) { + if (!strcmp(codec, "OMX.TI.MP3.decode")) { quirks |= kMeasuresTimeInMilliseconds; } @@ -1551,6 +1550,10 @@ void OMXDecoder::onRealFillBufferDone(const omx_message &msg) { 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; } diff --git a/media/libstagefright/QComHardwareRenderer.cpp b/media/libstagefright/QComHardwareRenderer.cpp deleted file mode 100644 index 5a2379272cee..000000000000 --- a/media/libstagefright/QComHardwareRenderer.cpp +++ /dev/null @@ -1,139 +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. - */ - -#undef NDEBUG -#include - -#include -#include -#include -#include - -namespace android { - -//////////////////////////////////////////////////////////////////////////////// - -typedef struct PLATFORM_PRIVATE_ENTRY -{ - /* Entry type */ - uint32_t type; - - /* Pointer to platform specific entry */ - void *entry; - -} PLATFORM_PRIVATE_ENTRY; - -typedef struct PLATFORM_PRIVATE_LIST -{ - /* Number of entries */ - uint32_t nEntries; - - /* Pointer to array of platform specific entries * - * Contiguous block of PLATFORM_PRIVATE_ENTRY elements */ - PLATFORM_PRIVATE_ENTRY *entryList; - -} PLATFORM_PRIVATE_LIST; - -// data structures for tunneling buffers -typedef struct PLATFORM_PRIVATE_PMEM_INFO -{ - /* pmem file descriptor */ - uint32_t pmem_fd; - uint32_t offset; - -} PLATFORM_PRIVATE_PMEM_INFO; - -#define PLATFORM_PRIVATE_PMEM 1 - -QComHardwareRenderer::QComHardwareRenderer( - const sp &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight) - : mISurface(surface), - mDisplayWidth(displayWidth), - mDisplayHeight(displayHeight), - mDecodedWidth(decodedWidth), - mDecodedHeight(decodedHeight), - mFrameSize((mDecodedWidth * mDecodedHeight * 3) / 2) { - assert(mISurface.get() != NULL); - assert(mDecodedWidth > 0); - assert(mDecodedHeight > 0); -} - -QComHardwareRenderer::~QComHardwareRenderer() { - mISurface->unregisterBuffers(); -} - -void QComHardwareRenderer::render( - const void *data, size_t size, void *platformPrivate) { - size_t offset; - if (!getOffset(platformPrivate, &offset)) { - return; - } - - mISurface->postBuffer(offset); -} - -bool QComHardwareRenderer::getOffset(void *platformPrivate, size_t *offset) { - *offset = 0; - - PLATFORM_PRIVATE_LIST *list = (PLATFORM_PRIVATE_LIST *)platformPrivate; - for (uint32_t i = 0; i < list->nEntries; ++i) { - if (list->entryList[i].type != PLATFORM_PRIVATE_PMEM) { - continue; - } - - PLATFORM_PRIVATE_PMEM_INFO *info = - (PLATFORM_PRIVATE_PMEM_INFO *)list->entryList[i].entry; - - if (info != NULL) { - if (mMemoryHeap.get() == NULL) { - publishBuffers(info->pmem_fd); - } - - if (mMemoryHeap.get() == NULL) { - return false; - } - - *offset = info->offset; - - return true; - } - } - - return false; -} - -void QComHardwareRenderer::publishBuffers(uint32_t pmem_fd) { - sp master = - reinterpret_cast(pmem_fd); - - master->setDevice("/dev/pmem"); - - mMemoryHeap = new MemoryHeapPmem(master, 0); - mMemoryHeap->slap(); - - ISurface::BufferHeap bufferHeap( - mDisplayWidth, mDisplayHeight, - mDecodedWidth, mDecodedHeight, - PIXEL_FORMAT_YCbCr_420_SP, - mMemoryHeap); - - status_t err = mISurface->registerBuffers(bufferHeap); - assert(err == OK); -} - -} // namespace android diff --git a/media/libstagefright/SoftwareRenderer.cpp b/media/libstagefright/SoftwareRenderer.cpp deleted file mode 100644 index 66b6b07a6be2..000000000000 --- a/media/libstagefright/SoftwareRenderer.cpp +++ /dev/null @@ -1,173 +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_TAG "SoftwareRenderer" -#include - -#undef NDEBUG -#include - -#include -#include -#include - -namespace android { - -#define QCOM_YUV 0 - -SoftwareRenderer::SoftwareRenderer( - const sp &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight) - : mISurface(surface), - mDisplayWidth(displayWidth), - mDisplayHeight(displayHeight), - mDecodedWidth(decodedWidth), - mDecodedHeight(decodedHeight), - mFrameSize(mDecodedWidth * mDecodedHeight * 2), // RGB565 - mMemoryHeap(new MemoryHeapBase(2 * mFrameSize)), - mIndex(0) { - assert(mISurface.get() != NULL); - assert(mDecodedWidth > 0); - assert(mDecodedHeight > 0); - assert(mMemoryHeap->heapID() >= 0); - - ISurface::BufferHeap bufferHeap( - mDisplayWidth, mDisplayHeight, - mDecodedWidth, mDecodedHeight, - PIXEL_FORMAT_RGB_565, - mMemoryHeap); - - status_t err = mISurface->registerBuffers(bufferHeap); - assert(err == OK); -} - -SoftwareRenderer::~SoftwareRenderer() { - mISurface->unregisterBuffers(); -} - -void SoftwareRenderer::render( - const void *data, size_t size, void *platformPrivate) { - assert(size >= (mDecodedWidth * mDecodedHeight * 3) / 2); - - static const signed kClipMin = -278; - static const signed kClipMax = 535; - static uint8_t kClip[kClipMax - kClipMin + 1]; - static uint8_t *kAdjustedClip = &kClip[-kClipMin]; - - static bool clipInitialized = false; - - if (!clipInitialized) { - for (signed i = kClipMin; i <= kClipMax; ++i) { - kClip[i - kClipMin] = (i < 0) ? 0 : (i > 255) ? 255 : (uint8_t)i; - } - clipInitialized = true; - } - - size_t offset = mIndex * mFrameSize; - - void *dst = (uint8_t *)mMemoryHeap->getBase() + offset; - - uint32_t *dst_ptr = (uint32_t *)dst; - - const uint8_t *src_y = (const uint8_t *)data; - - const uint8_t *src_u = - (const uint8_t *)src_y + mDecodedWidth * mDecodedHeight; - -#if !QCOM_YUV - const uint8_t *src_v = - (const uint8_t *)src_u + (mDecodedWidth / 2) * (mDecodedHeight / 2); -#endif - - for (size_t y = 0; y < mDecodedHeight; ++y) { - for (size_t x = 0; x < mDecodedWidth; x += 2) { - // B = 1.164 * (Y - 16) + 2.018 * (U - 128) - // G = 1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128) - // R = 1.164 * (Y - 16) + 1.596 * (V - 128) - - // B = 298/256 * (Y - 16) + 517/256 * (U - 128) - // G = .................. - 208/256 * (V - 128) - 100/256 * (U - 128) - // R = .................. + 409/256 * (V - 128) - - // min_B = (298 * (- 16) + 517 * (- 128)) / 256 = -277 - // min_G = (298 * (- 16) - 208 * (255 - 128) - 100 * (255 - 128)) / 256 = -172 - // min_R = (298 * (- 16) + 409 * (- 128)) / 256 = -223 - - // max_B = (298 * (255 - 16) + 517 * (255 - 128)) / 256 = 534 - // max_G = (298 * (255 - 16) - 208 * (- 128) - 100 * (- 128)) / 256 = 432 - // max_R = (298 * (255 - 16) + 409 * (255 - 128)) / 256 = 481 - - // clip range -278 .. 535 - - signed y1 = (signed)src_y[x] - 16; - signed y2 = (signed)src_y[x + 1] - 16; - -#if QCOM_YUV - signed u = (signed)src_u[x & ~1] - 128; - signed v = (signed)src_u[(x & ~1) + 1] - 128; -#else - signed u = (signed)src_u[x / 2] - 128; - signed v = (signed)src_v[x / 2] - 128; -#endif - - signed u_b = u * 517; - signed u_g = -u * 100; - signed v_g = -v * 208; - signed v_r = v * 409; - - signed tmp1 = y1 * 298; - signed b1 = (tmp1 + u_b) / 256; - signed g1 = (tmp1 + v_g + u_g) / 256; - signed r1 = (tmp1 + v_r) / 256; - - signed tmp2 = y2 * 298; - signed b2 = (tmp2 + u_b) / 256; - signed g2 = (tmp2 + v_g + u_g) / 256; - signed r2 = (tmp2 + v_r) / 256; - - uint32_t rgb1 = - ((kAdjustedClip[r1] >> 3) << 11) - | ((kAdjustedClip[g1] >> 2) << 5) - | (kAdjustedClip[b1] >> 3); - - uint32_t rgb2 = - ((kAdjustedClip[r2] >> 3) << 11) - | ((kAdjustedClip[g2] >> 2) << 5) - | (kAdjustedClip[b2] >> 3); - - dst_ptr[x / 2] = (rgb2 << 16) | rgb1; - } - - src_y += mDecodedWidth; - - if (y & 1) { -#if QCOM_YUV - src_u += mDecodedWidth; -#else - src_u += mDecodedWidth / 2; - src_v += mDecodedWidth / 2; -#endif - } - - dst_ptr += mDecodedWidth / 2; - } - - mISurface->postBuffer(offset); - mIndex = 1 - mIndex; -} - -} // namespace android diff --git a/media/libstagefright/SurfaceRenderer.cpp b/media/libstagefright/SurfaceRenderer.cpp deleted file mode 100644 index e54288d97ab3..000000000000 --- a/media/libstagefright/SurfaceRenderer.cpp +++ /dev/null @@ -1,69 +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_TAG "SurfaceRenderer" -#include - -#undef NDEBUG -#include - -#include -#include - -namespace android { - -SurfaceRenderer::SurfaceRenderer( - const sp &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight) - : mSurface(surface), - mDisplayWidth(displayWidth), - mDisplayHeight(displayHeight), - mDecodedWidth(decodedWidth), - mDecodedHeight(decodedHeight) { -} - -SurfaceRenderer::~SurfaceRenderer() { -} - -void SurfaceRenderer::render( - const void *data, size_t size, void *platformPrivate) { - Surface::SurfaceInfo info; - status_t err = mSurface->lock(&info); - if (err != OK) { - return; - } - - const uint8_t *src = (const uint8_t *)data; - uint8_t *dst = (uint8_t *)info.bits; - - for (size_t i = 0; i < mDisplayHeight; ++i) { - memcpy(dst, src, mDisplayWidth); - src += mDecodedWidth; - dst += mDisplayWidth; - } - src += (mDecodedHeight - mDisplayHeight) * mDecodedWidth; - - for (size_t i = 0; i < (mDisplayHeight + 1) / 2; ++i) { - memcpy(dst, src, (mDisplayWidth + 1) & ~1); - src += (mDecodedWidth + 1) & ~1; - dst += (mDisplayWidth + 1) & ~1; - } - - mSurface->unlockAndPost(); -} - -} // namespace android diff --git a/media/libstagefright/TIHardwareRenderer.cpp b/media/libstagefright/TIHardwareRenderer.cpp deleted file mode 100644 index ba42ef4ea2d9..000000000000 --- a/media/libstagefright/TIHardwareRenderer.cpp +++ /dev/null @@ -1,99 +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_TAG "TIHardwareRenderer" -#include - -#undef NDEBUG -#include - -#include -#include -#include - -namespace android { - -//////////////////////////////////////////////////////////////////////////////// - -TIHardwareRenderer::TIHardwareRenderer( - const sp &surface, - size_t displayWidth, size_t displayHeight, - size_t decodedWidth, size_t decodedHeight) - : mISurface(surface), - mDisplayWidth(displayWidth), - mDisplayHeight(displayHeight), - mDecodedWidth(decodedWidth), - mDecodedHeight(decodedHeight), - mFrameSize((mDecodedWidth * mDecodedHeight * 3) / 2) { - assert(mISurface.get() != NULL); - assert(mDecodedWidth > 0); - assert(mDecodedHeight > 0); - - sp ref = mISurface->createOverlay( - mDisplayWidth, mDisplayHeight, OVERLAY_FORMAT_CbYCrY_422_I); - - if (ref.get() == NULL) { - LOGE("Unable to create the overlay!"); - return; - } - - mOverlay = new Overlay(ref); - - for (size_t i = 0; i < mOverlay->getBufferCount(); ++i) { - mOverlayAddresses.push(mOverlay->getBufferAddress((void *)i)); - } - mIndex = mOverlayAddresses.size() - 1; -} - -TIHardwareRenderer::~TIHardwareRenderer() { - if (mOverlay.get() != NULL) { - mOverlay->destroy(); - mOverlay.clear(); - - // XXX apparently destroying an overlay is an asynchronous process... - sleep(1); - } -} - -void TIHardwareRenderer::render( - const void *data, size_t size, void *platformPrivate) { - // assert(size == mFrameSize); - - if (mOverlay.get() == NULL) { - return; - } - -#if 0 - overlay_buffer_t buffer; - if (mOverlay->dequeueBuffer(&buffer) == OK) { - void *addr = mOverlay->getBufferAddress(buffer); - - memcpy(addr, data, size); - - mOverlay->queueBuffer(buffer); - } -#else - memcpy(mOverlayAddresses[mIndex], data, size); - mOverlay->queueBuffer((void *)mIndex); - - if (mIndex-- == 0) { - mIndex = mOverlayAddresses.size() - 1; - } -#endif -} - -} // namespace android - diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk index 9c6d475bbf50..2e564e9acfd3 100644 --- a/media/libstagefright/omx/Android.mk +++ b/media/libstagefright/omx/Android.mk @@ -9,13 +9,17 @@ LOCAL_C_INCLUDES := $(PV_INCLUDES) LOCAL_CFLAGS := $(PV_CFLAGS_MINUS_VISIBILITY) LOCAL_SRC_FILES:= \ - OMX.cpp - -LOCAL_SHARED_LIBRARIES := \ - libbinder \ - libmedia \ - libutils \ - libui \ + OMX.cpp \ + QComHardwareRenderer.cpp \ + SoftwareRenderer.cpp \ + TIHardwareRenderer.cpp + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libmedia \ + libutils \ + libui \ + libcutils \ libopencore_common LOCAL_PRELINK_MODULE:= false diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp index daaa741ed26c..062afd42405d 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -24,9 +24,15 @@ #include #include "OMX.h" +#include "OMXRenderer.h" + #include "pv_omxcore.h" #include +#include +#include +#include +#include #include @@ -619,5 +625,62 @@ void OMX::empty_buffer( } #endif +//////////////////////////////////////////////////////////////////////////////// + +sp OMX::createRenderer( + const sp &surface, + const char *componentName, + OMX_COLOR_FORMATTYPE colorFormat, + size_t encodedWidth, size_t encodedHeight, + size_t displayWidth, size_t displayHeight) { + VideoRenderer *impl = NULL; + + static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; + + if (colorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar + && !strncmp(componentName, "OMX.qcom.video.decoder.", 23)) { + LOGW("Using QComHardwareRenderer."); + impl = + new QComHardwareRenderer( + surface, + displayWidth, displayHeight, + encodedWidth, encodedHeight); + } else if (colorFormat == OMX_COLOR_FormatCbYCrY + && !strcmp(componentName, "OMX.TI.Video.Decoder")) { + LOGW("Using TIHardwareRenderer."); + impl = + new TIHardwareRenderer( + surface, + displayWidth, displayHeight, + encodedWidth, encodedHeight); + } else { + LOGW("Using software renderer."); + impl = new SoftwareRenderer( + surface, + displayWidth, displayHeight, + encodedWidth, encodedHeight); + } + + return new OMXRenderer(impl); +} + +OMXRenderer::OMXRenderer(VideoRenderer *impl) + : mImpl(impl) { +} + +OMXRenderer::~OMXRenderer() { + delete mImpl; + mImpl = NULL; +} + +void OMXRenderer::render(IOMX::buffer_id buffer) { + OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; + + mImpl->render( + header->pBuffer + header->nOffset, + header->nFilledLen, + header->pPlatformPrivate); +} + } // namespace android diff --git a/media/libstagefright/omx/OMX.h b/media/libstagefright/omx/OMX.h index ed4e5dd3238c..20430bba84c3 100644 --- a/media/libstagefright/omx/OMX.h +++ b/media/libstagefright/omx/OMX.h @@ -79,6 +79,13 @@ public: OMX_U32 flags, OMX_TICKS timestamp); #endif + virtual sp createRenderer( + const sp &surface, + const char *componentName, + OMX_COLOR_FORMATTYPE colorFormat, + size_t encodedWidth, size_t encodedHeight, + size_t displayWidth, size_t displayHeight); + private: static OMX_CALLBACKTYPE kCallbacks; diff --git a/media/libstagefright/omx/OMXRenderer.h b/media/libstagefright/omx/OMXRenderer.h new file mode 100644 index 000000000000..4d194ce73440 --- /dev/null +++ b/media/libstagefright/omx/OMXRenderer.h @@ -0,0 +1,44 @@ +/* + * 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_RENDERER_H_ + +#define OMX_RENDERER_H_ + +#include + +namespace android { + +class VideoRenderer; + +class OMXRenderer : public BnOMXRenderer { +public: + // Assumes ownership of "impl". + OMXRenderer(VideoRenderer *impl); + virtual ~OMXRenderer(); + + virtual void render(IOMX::buffer_id buffer); + +private: + VideoRenderer *mImpl; + + OMXRenderer(const OMXRenderer &); + OMXRenderer &operator=(const OMXRenderer &); +}; + +} // namespace android + +#endif // OMX_RENDERER_H_ diff --git a/media/libstagefright/omx/QComHardwareRenderer.cpp b/media/libstagefright/omx/QComHardwareRenderer.cpp new file mode 100644 index 000000000000..5a2379272cee --- /dev/null +++ b/media/libstagefright/omx/QComHardwareRenderer.cpp @@ -0,0 +1,139 @@ +/* + * 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. + */ + +#undef NDEBUG +#include + +#include +#include +#include +#include + +namespace android { + +//////////////////////////////////////////////////////////////////////////////// + +typedef struct PLATFORM_PRIVATE_ENTRY +{ + /* Entry type */ + uint32_t type; + + /* Pointer to platform specific entry */ + void *entry; + +} PLATFORM_PRIVATE_ENTRY; + +typedef struct PLATFORM_PRIVATE_LIST +{ + /* Number of entries */ + uint32_t nEntries; + + /* Pointer to array of platform specific entries * + * Contiguous block of PLATFORM_PRIVATE_ENTRY elements */ + PLATFORM_PRIVATE_ENTRY *entryList; + +} PLATFORM_PRIVATE_LIST; + +// data structures for tunneling buffers +typedef struct PLATFORM_PRIVATE_PMEM_INFO +{ + /* pmem file descriptor */ + uint32_t pmem_fd; + uint32_t offset; + +} PLATFORM_PRIVATE_PMEM_INFO; + +#define PLATFORM_PRIVATE_PMEM 1 + +QComHardwareRenderer::QComHardwareRenderer( + const sp &surface, + size_t displayWidth, size_t displayHeight, + size_t decodedWidth, size_t decodedHeight) + : mISurface(surface), + mDisplayWidth(displayWidth), + mDisplayHeight(displayHeight), + mDecodedWidth(decodedWidth), + mDecodedHeight(decodedHeight), + mFrameSize((mDecodedWidth * mDecodedHeight * 3) / 2) { + assert(mISurface.get() != NULL); + assert(mDecodedWidth > 0); + assert(mDecodedHeight > 0); +} + +QComHardwareRenderer::~QComHardwareRenderer() { + mISurface->unregisterBuffers(); +} + +void QComHardwareRenderer::render( + const void *data, size_t size, void *platformPrivate) { + size_t offset; + if (!getOffset(platformPrivate, &offset)) { + return; + } + + mISurface->postBuffer(offset); +} + +bool QComHardwareRenderer::getOffset(void *platformPrivate, size_t *offset) { + *offset = 0; + + PLATFORM_PRIVATE_LIST *list = (PLATFORM_PRIVATE_LIST *)platformPrivate; + for (uint32_t i = 0; i < list->nEntries; ++i) { + if (list->entryList[i].type != PLATFORM_PRIVATE_PMEM) { + continue; + } + + PLATFORM_PRIVATE_PMEM_INFO *info = + (PLATFORM_PRIVATE_PMEM_INFO *)list->entryList[i].entry; + + if (info != NULL) { + if (mMemoryHeap.get() == NULL) { + publishBuffers(info->pmem_fd); + } + + if (mMemoryHeap.get() == NULL) { + return false; + } + + *offset = info->offset; + + return true; + } + } + + return false; +} + +void QComHardwareRenderer::publishBuffers(uint32_t pmem_fd) { + sp master = + reinterpret_cast(pmem_fd); + + master->setDevice("/dev/pmem"); + + mMemoryHeap = new MemoryHeapPmem(master, 0); + mMemoryHeap->slap(); + + ISurface::BufferHeap bufferHeap( + mDisplayWidth, mDisplayHeight, + mDecodedWidth, mDecodedHeight, + PIXEL_FORMAT_YCbCr_420_SP, + mMemoryHeap); + + status_t err = mISurface->registerBuffers(bufferHeap); + assert(err == OK); +} + +} // namespace android diff --git a/media/libstagefright/omx/SoftwareRenderer.cpp b/media/libstagefright/omx/SoftwareRenderer.cpp new file mode 100644 index 000000000000..548323848f97 --- /dev/null +++ b/media/libstagefright/omx/SoftwareRenderer.cpp @@ -0,0 +1,177 @@ +/* + * 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_TAG "SoftwareRenderer" +#include + +#undef NDEBUG +#include + +#include +#include +#include + +namespace android { + +#define QCOM_YUV 0 + +SoftwareRenderer::SoftwareRenderer( + const sp &surface, + size_t displayWidth, size_t displayHeight, + size_t decodedWidth, size_t decodedHeight) + : mISurface(surface), + mDisplayWidth(displayWidth), + mDisplayHeight(displayHeight), + mDecodedWidth(decodedWidth), + mDecodedHeight(decodedHeight), + mFrameSize(mDecodedWidth * mDecodedHeight * 2), // RGB565 + mMemoryHeap(new MemoryHeapBase(2 * mFrameSize)), + mIndex(0) { + assert(mISurface.get() != NULL); + assert(mDecodedWidth > 0); + assert(mDecodedHeight > 0); + assert(mMemoryHeap->heapID() >= 0); + + ISurface::BufferHeap bufferHeap( + mDisplayWidth, mDisplayHeight, + mDecodedWidth, mDecodedHeight, + PIXEL_FORMAT_RGB_565, + mMemoryHeap); + + status_t err = mISurface->registerBuffers(bufferHeap); + assert(err == OK); +} + +SoftwareRenderer::~SoftwareRenderer() { + mISurface->unregisterBuffers(); +} + +void SoftwareRenderer::render( + const void *data, size_t size, void *platformPrivate) { + if (size != (mDecodedHeight * mDecodedWidth * 3) / 2) { + LOGE("size is %d, expected %d", + size, (mDecodedHeight * mDecodedWidth * 3) / 2); + } + assert(size >= (mDecodedWidth * mDecodedHeight * 3) / 2); + + static const signed kClipMin = -278; + static const signed kClipMax = 535; + static uint8_t kClip[kClipMax - kClipMin + 1]; + static uint8_t *kAdjustedClip = &kClip[-kClipMin]; + + static bool clipInitialized = false; + + if (!clipInitialized) { + for (signed i = kClipMin; i <= kClipMax; ++i) { + kClip[i - kClipMin] = (i < 0) ? 0 : (i > 255) ? 255 : (uint8_t)i; + } + clipInitialized = true; + } + + size_t offset = mIndex * mFrameSize; + + void *dst = (uint8_t *)mMemoryHeap->getBase() + offset; + + uint32_t *dst_ptr = (uint32_t *)dst; + + const uint8_t *src_y = (const uint8_t *)data; + + const uint8_t *src_u = + (const uint8_t *)src_y + mDecodedWidth * mDecodedHeight; + +#if !QCOM_YUV + const uint8_t *src_v = + (const uint8_t *)src_u + (mDecodedWidth / 2) * (mDecodedHeight / 2); +#endif + + for (size_t y = 0; y < mDecodedHeight; ++y) { + for (size_t x = 0; x < mDecodedWidth; x += 2) { + // B = 1.164 * (Y - 16) + 2.018 * (U - 128) + // G = 1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128) + // R = 1.164 * (Y - 16) + 1.596 * (V - 128) + + // B = 298/256 * (Y - 16) + 517/256 * (U - 128) + // G = .................. - 208/256 * (V - 128) - 100/256 * (U - 128) + // R = .................. + 409/256 * (V - 128) + + // min_B = (298 * (- 16) + 517 * (- 128)) / 256 = -277 + // min_G = (298 * (- 16) - 208 * (255 - 128) - 100 * (255 - 128)) / 256 = -172 + // min_R = (298 * (- 16) + 409 * (- 128)) / 256 = -223 + + // max_B = (298 * (255 - 16) + 517 * (255 - 128)) / 256 = 534 + // max_G = (298 * (255 - 16) - 208 * (- 128) - 100 * (- 128)) / 256 = 432 + // max_R = (298 * (255 - 16) + 409 * (255 - 128)) / 256 = 481 + + // clip range -278 .. 535 + + signed y1 = (signed)src_y[x] - 16; + signed y2 = (signed)src_y[x + 1] - 16; + +#if QCOM_YUV + signed u = (signed)src_u[x & ~1] - 128; + signed v = (signed)src_u[(x & ~1) + 1] - 128; +#else + signed u = (signed)src_u[x / 2] - 128; + signed v = (signed)src_v[x / 2] - 128; +#endif + + signed u_b = u * 517; + signed u_g = -u * 100; + signed v_g = -v * 208; + signed v_r = v * 409; + + signed tmp1 = y1 * 298; + signed b1 = (tmp1 + u_b) / 256; + signed g1 = (tmp1 + v_g + u_g) / 256; + signed r1 = (tmp1 + v_r) / 256; + + signed tmp2 = y2 * 298; + signed b2 = (tmp2 + u_b) / 256; + signed g2 = (tmp2 + v_g + u_g) / 256; + signed r2 = (tmp2 + v_r) / 256; + + uint32_t rgb1 = + ((kAdjustedClip[r1] >> 3) << 11) + | ((kAdjustedClip[g1] >> 2) << 5) + | (kAdjustedClip[b1] >> 3); + + uint32_t rgb2 = + ((kAdjustedClip[r2] >> 3) << 11) + | ((kAdjustedClip[g2] >> 2) << 5) + | (kAdjustedClip[b2] >> 3); + + dst_ptr[x / 2] = (rgb2 << 16) | rgb1; + } + + src_y += mDecodedWidth; + + if (y & 1) { +#if QCOM_YUV + src_u += mDecodedWidth; +#else + src_u += mDecodedWidth / 2; + src_v += mDecodedWidth / 2; +#endif + } + + dst_ptr += mDecodedWidth / 2; + } + + mISurface->postBuffer(offset); + mIndex = 1 - mIndex; +} + +} // namespace android diff --git a/media/libstagefright/omx/TIHardwareRenderer.cpp b/media/libstagefright/omx/TIHardwareRenderer.cpp new file mode 100644 index 000000000000..ba42ef4ea2d9 --- /dev/null +++ b/media/libstagefright/omx/TIHardwareRenderer.cpp @@ -0,0 +1,99 @@ +/* + * 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_TAG "TIHardwareRenderer" +#include + +#undef NDEBUG +#include + +#include +#include +#include + +namespace android { + +//////////////////////////////////////////////////////////////////////////////// + +TIHardwareRenderer::TIHardwareRenderer( + const sp &surface, + size_t displayWidth, size_t displayHeight, + size_t decodedWidth, size_t decodedHeight) + : mISurface(surface), + mDisplayWidth(displayWidth), + mDisplayHeight(displayHeight), + mDecodedWidth(decodedWidth), + mDecodedHeight(decodedHeight), + mFrameSize((mDecodedWidth * mDecodedHeight * 3) / 2) { + assert(mISurface.get() != NULL); + assert(mDecodedWidth > 0); + assert(mDecodedHeight > 0); + + sp ref = mISurface->createOverlay( + mDisplayWidth, mDisplayHeight, OVERLAY_FORMAT_CbYCrY_422_I); + + if (ref.get() == NULL) { + LOGE("Unable to create the overlay!"); + return; + } + + mOverlay = new Overlay(ref); + + for (size_t i = 0; i < mOverlay->getBufferCount(); ++i) { + mOverlayAddresses.push(mOverlay->getBufferAddress((void *)i)); + } + mIndex = mOverlayAddresses.size() - 1; +} + +TIHardwareRenderer::~TIHardwareRenderer() { + if (mOverlay.get() != NULL) { + mOverlay->destroy(); + mOverlay.clear(); + + // XXX apparently destroying an overlay is an asynchronous process... + sleep(1); + } +} + +void TIHardwareRenderer::render( + const void *data, size_t size, void *platformPrivate) { + // assert(size == mFrameSize); + + if (mOverlay.get() == NULL) { + return; + } + +#if 0 + overlay_buffer_t buffer; + if (mOverlay->dequeueBuffer(&buffer) == OK) { + void *addr = mOverlay->getBufferAddress(buffer); + + memcpy(addr, data, size); + + mOverlay->queueBuffer(buffer); + } +#else + memcpy(mOverlayAddresses[mIndex], data, size); + mOverlay->queueBuffer((void *)mIndex); + + if (mIndex-- == 0) { + mIndex = mOverlayAddresses.size() - 1; + } +#endif +} + +} // namespace android + -- cgit v1.2.3-59-g8ed1b