From 5daeb129a2c2ba3d14ccd94af283b5f561c783ea Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 16 Aug 2010 08:49:37 -0700 Subject: Squashed commit of the following: commit 35cc68814a9537c31fde146e171e7b0bbdfe211e Author: Andreas Huber Date: Mon Aug 16 08:48:42 2010 -0700 Only enable support for yuv to yuv conversion on passion, where it's available, use the slower yuv->rgb565 path everywhere else. commit d8ac5a8814103e60d11d2acf61997fc31a1dc58d Author: Andreas Huber Date: Fri Aug 13 13:56:44 2010 -0700 The software renderer takes over all rendering, converting from yuv to yuv if possible and rgb565 otherwise. commit 684972074b74318bdcb826ed9b5b0864d2d2e273 Author: Andreas Huber Date: Fri Aug 13 09:34:35 2010 -0700 A first shot at supporting the new rendering APIs. Change-Id: Iea9b32856da46950501f1a700f616b5feac710fd --- include/media/IMediaPlayer.h | 4 +- include/media/MediaPlayerInterface.h | 4 +- include/media/PVPlayer.h | 3 +- media/libmedia/IMediaPlayer.cpp | 21 ++- media/libmedia/mediaplayer.cpp | 13 +- media/libmediaplayerservice/MediaPlayerService.cpp | 10 +- media/libmediaplayerservice/MediaPlayerService.h | 3 +- media/libmediaplayerservice/MidiFile.h | 3 +- media/libmediaplayerservice/StagefrightPlayer.cpp | 11 +- media/libmediaplayerservice/StagefrightPlayer.h | 3 +- media/libmediaplayerservice/TestPlayerStub.h | 5 +- media/libstagefright/AwesomePlayer.cpp | 65 +++++--- media/libstagefright/colorconversion/Android.mk | 5 + .../colorconversion/SoftwareRenderer.cpp | 170 +++++++++++++++++---- media/libstagefright/include/AwesomePlayer.h | 3 + media/libstagefright/include/SoftwareRenderer.h | 18 ++- media/libstagefright/omx/OMX.cpp | 5 + 17 files changed, 269 insertions(+), 77 deletions(-) diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h index af9a7ed..a1ce113 100644 --- a/include/media/IMediaPlayer.h +++ b/include/media/IMediaPlayer.h @@ -25,6 +25,7 @@ namespace android { class Parcel; class ISurface; +class Surface; class IMediaPlayer: public IInterface { @@ -33,7 +34,8 @@ public: virtual void disconnect() = 0; - virtual status_t setVideoSurface(const sp& surface) = 0; + virtual status_t setVideoISurface(const sp& surface) = 0; + virtual status_t setVideoSurface(const sp& surface) = 0; virtual status_t prepareAsync() = 0; virtual status_t start() = 0; virtual status_t stop() = 0; diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 3662983..13c73ac 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -33,6 +33,7 @@ namespace android { class Parcel; class ISurface; +class Surface; template class SortedVector; @@ -104,7 +105,8 @@ public: const KeyedVector *headers = NULL) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; - virtual status_t setVideoSurface(const sp& surface) = 0; + virtual status_t setVideoISurface(const sp& surface) = 0; + virtual status_t setVideoSurface(const sp& surface) = 0; virtual status_t prepare() = 0; virtual status_t prepareAsync() = 0; virtual status_t start() = 0; diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h index df50981..657e7a6 100644 --- a/include/media/PVPlayer.h +++ b/include/media/PVPlayer.h @@ -43,7 +43,8 @@ public: const char *url, const KeyedVector *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setVideoSurface(const sp& surface); + virtual status_t setVideoISurface(const sp& surface); + virtual status_t setVideoSurface(const sp& surface); virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index 0f55b19..9dfdcb0 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -22,12 +22,14 @@ #include #include +#include namespace android { enum { DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, SET_VIDEO_SURFACE, + SET_VIDEO_ISURFACE, PREPARE_ASYNC, START, STOP, @@ -65,11 +67,20 @@ public: remote()->transact(DISCONNECT, data, &reply); } - status_t setVideoSurface(const sp& surface) + status_t setVideoISurface(const sp& surface) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); data.writeStrongBinder(surface->asBinder()); + remote()->transact(SET_VIDEO_ISURFACE, data, &reply); + return reply.readInt32(); + } + + status_t setVideoSurface(const sp& surface) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + Surface::writeToParcel(surface, &data); remote()->transact(SET_VIDEO_SURFACE, data, &reply); return reply.readInt32(); } @@ -256,9 +267,15 @@ status_t BnMediaPlayer::onTransact( disconnect(); return NO_ERROR; } break; - case SET_VIDEO_SURFACE: { + case SET_VIDEO_ISURFACE: { CHECK_INTERFACE(IMediaPlayer, data, reply); sp surface = interface_cast(data.readStrongBinder()); + reply->writeInt32(setVideoISurface(surface)); + return NO_ERROR; + } break; + case SET_VIDEO_SURFACE: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + sp surface = Surface::readFromParcel(data); reply->writeInt32(setVideoSurface(surface)); return NO_ERROR; } break; diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index f3229c0..32b20c7 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -206,10 +206,15 @@ status_t MediaPlayer::setVideoSurface(const sp& surface) LOGV("setVideoSurface"); Mutex::Autolock _l(mLock); if (mPlayer == 0) return NO_INIT; - if (surface != NULL) - return mPlayer->setVideoSurface(surface->getISurface()); - else - return mPlayer->setVideoSurface(NULL); + + status_t err = mPlayer->setVideoISurface( + surface == NULL ? NULL : surface->getISurface()); + + if (err != OK) { + return err; + } + + return mPlayer->setVideoSurface(surface); } // must call with lock held diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index b5972e7..d9b0c69 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -889,7 +889,15 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64 return mStatus; } -status_t MediaPlayerService::Client::setVideoSurface(const sp& surface) +status_t MediaPlayerService::Client::setVideoISurface(const sp& surface) +{ + LOGV("[%d] setVideoISurface(%p)", mConnId, surface.get()); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->setVideoISurface(surface); +} + +status_t MediaPlayerService::Client::setVideoSurface(const sp& surface) { LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get()); sp p = getPlayer(); diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index a967ee2..deb458c 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -204,7 +204,8 @@ private: // IMediaPlayer interface virtual void disconnect(); - virtual status_t setVideoSurface(const sp& surface); + virtual status_t setVideoISurface(const sp& surface); + virtual status_t setVideoSurface(const sp& surface); virtual status_t prepareAsync(); virtual status_t start(); virtual status_t stop(); diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index 4a60ece..06e4b70 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -35,7 +35,8 @@ public: const char* path, const KeyedVector *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setVideoSurface(const sp& surface) { return UNKNOWN_ERROR; } + virtual status_t setVideoISurface(const sp& surface) { return UNKNOWN_ERROR; } + virtual status_t setVideoSurface(const sp& surface) { return UNKNOWN_ERROR; } virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index 2c96d6d..6b9bf85 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -44,13 +44,20 @@ status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length return mPlayer->setDataSource(dup(fd), offset, length); } -status_t StagefrightPlayer::setVideoSurface(const sp &surface) { - LOGV("setVideoSurface"); +status_t StagefrightPlayer::setVideoISurface(const sp &surface) { + LOGV("setVideoISurface"); mPlayer->setISurface(surface); return OK; } +status_t StagefrightPlayer::setVideoSurface(const sp &surface) { + LOGV("setVideoSurface"); + + mPlayer->setSurface(surface); + return OK; +} + status_t StagefrightPlayer::prepare() { return mPlayer->prepare(); } diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h index 781eb44..dd37102 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.h +++ b/media/libmediaplayerservice/StagefrightPlayer.h @@ -35,7 +35,8 @@ public: const char *url, const KeyedVector *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setVideoSurface(const sp &surface); + virtual status_t setVideoISurface(const sp &surface); + virtual status_t setVideoSurface(const sp &surface); virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h index 6e6c3cd..5eaf592 100644 --- a/media/libmediaplayerservice/TestPlayerStub.h +++ b/media/libmediaplayerservice/TestPlayerStub.h @@ -75,7 +75,10 @@ class TestPlayerStub : public MediaPlayerInterface { // All the methods below wrap the mPlayer instance. - virtual status_t setVideoSurface(const android::sp& s) { + virtual status_t setVideoISurface(const android::sp& s) { + return mPlayer->setVideoISurface(s); + } + virtual status_t setVideoSurface(const android::sp& s) { return mPlayer->setVideoSurface(s); } virtual status_t prepare() {return mPlayer->prepare();} diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index f2653cf..b7beb6b 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -44,7 +44,7 @@ #include #include -#include +#include #include @@ -97,13 +97,14 @@ struct AwesomeLocalRenderer : public AwesomeRenderer { bool previewOnly, const char *componentName, OMX_COLOR_FORMATTYPE colorFormat, - const sp &surface, + const sp &isurface, + const sp &surface, size_t displayWidth, size_t displayHeight, size_t decodedWidth, size_t decodedHeight) : mTarget(NULL), mLibHandle(NULL) { init(previewOnly, componentName, - colorFormat, surface, displayWidth, + colorFormat, isurface, surface, displayWidth, displayHeight, decodedWidth, decodedHeight); } @@ -135,7 +136,8 @@ private: bool previewOnly, const char *componentName, OMX_COLOR_FORMATTYPE colorFormat, - const sp &surface, + const sp &isurface, + const sp &surface, size_t displayWidth, size_t displayHeight, size_t decodedWidth, size_t decodedHeight); @@ -147,7 +149,8 @@ void AwesomeLocalRenderer::init( bool previewOnly, const char *componentName, OMX_COLOR_FORMATTYPE colorFormat, - const sp &surface, + const sp &isurface, + const sp &surface, size_t displayWidth, size_t displayHeight, size_t decodedWidth, size_t decodedHeight) { if (!previewOnly) { @@ -173,7 +176,7 @@ void AwesomeLocalRenderer::init( if (func) { mTarget = - (*func)(surface, componentName, colorFormat, + (*func)(isurface, componentName, colorFormat, displayWidth, displayHeight, decodedWidth, decodedHeight); } @@ -619,8 +622,18 @@ status_t AwesomePlayer::play_l() { return OK; } +void AwesomePlayer::notifyVideoSize_l() { + sp meta = mVideoSource->getFormat(); + + int32_t decodedWidth, decodedHeight; + CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); + CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); + + notifyListener_l(MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight); +} + void AwesomePlayer::initRenderer_l() { - if (mISurface != NULL) { + if (mSurface != NULL || mISurface != NULL) { sp meta = mVideoSource->getFormat(); int32_t format; @@ -637,17 +650,7 @@ void AwesomePlayer::initRenderer_l() { // before creating a new one. IPCThreadState::self()->flushCommands(); - if (!strncmp("OMX.", component, 4)) { - // Our OMX codecs allocate buffers on the media_server side - // therefore they require a remote IOMXRenderer that knows how - // to display them. - mVideoRenderer = new AwesomeRemoteRenderer( - mClient.interface()->createRenderer( - mISurface, component, - (OMX_COLOR_FORMATTYPE)format, - decodedWidth, decodedHeight, - mVideoWidth, mVideoHeight)); - } else { + if (mSurface != NULL) { // Other decoders are instantiated locally and as a consequence // allocate their buffers in local address space. mVideoRenderer = new AwesomeLocalRenderer( @@ -655,8 +658,19 @@ void AwesomePlayer::initRenderer_l() { component, (OMX_COLOR_FORMATTYPE)format, mISurface, + mSurface, mVideoWidth, mVideoHeight, decodedWidth, decodedHeight); + } else { + // Our OMX codecs allocate buffers on the media_server side + // therefore they require a remote IOMXRenderer that knows how + // to display them. + mVideoRenderer = new AwesomeRemoteRenderer( + mClient.interface()->createRenderer( + mISurface, component, + (OMX_COLOR_FORMATTYPE)format, + decodedWidth, decodedHeight, + mVideoWidth, mVideoHeight)); } } } @@ -695,6 +709,12 @@ void AwesomePlayer::setISurface(const sp &isurface) { mISurface = isurface; } +void AwesomePlayer::setSurface(const sp &surface) { + Mutex::Autolock autoLock(mLock); + + mSurface = surface; +} + void AwesomePlayer::setAudioSink( const sp &audioSink) { Mutex::Autolock autoLock(mLock); @@ -937,6 +957,8 @@ void AwesomePlayer::onVideoEvent() { if (err == INFO_FORMAT_CHANGED) { LOGV("VideoSource signalled format change."); + notifyVideoSize_l(); + if (mVideoRenderer != NULL) { mVideoRendererIsPreview = false; initRenderer_l(); @@ -1422,10 +1444,10 @@ void AwesomePlayer::onPrepareAsyncEvent() { Mutex::Autolock autoLock(mLock); if (mIsAsyncPrepare) { - if (mVideoWidth < 0 || mVideoHeight < 0) { + if (mVideoSource == NULL) { notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); } else { - notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight); + notifyVideoSize_l(); } notifyListener_l(MEDIA_PREPARED); @@ -1540,13 +1562,14 @@ status_t AwesomePlayer::resume() { mFlags = state->mFlags & (LOOPING | AT_EOS); - if (state->mLastVideoFrame && mISurface != NULL) { + if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) { mVideoRenderer = new AwesomeLocalRenderer( true, // previewOnly "", (OMX_COLOR_FORMATTYPE)state->mColorFormat, mISurface, + mSurface, state->mVideoWidth, state->mVideoHeight, state->mDecodedWidth, diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk index b9ba1be..4a924c8 100644 --- a/media/libstagefright/colorconversion/Android.mk +++ b/media/libstagefright/colorconversion/Android.mk @@ -17,6 +17,11 @@ LOCAL_SHARED_LIBRARIES := \ libsurfaceflinger_client\ libcamera_client +# ifeq ($(TARGET_BOARD_PLATFORM),msm7k) +ifeq ($(TARGET_PRODUCT),passion) + LOCAL_CFLAGS += -DHAS_YCBCR420_SP_ADRENO +endif + LOCAL_MODULE:= libstagefright_color_conversion include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp index a6dbf69..6d1dd25 100644 --- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp +++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp @@ -22,65 +22,169 @@ #include #include #include -#include +#include +#include +#include namespace android { SoftwareRenderer::SoftwareRenderer( OMX_COLOR_FORMATTYPE colorFormat, - const sp &surface, + const sp &surface, size_t displayWidth, size_t displayHeight, size_t decodedWidth, size_t decodedHeight) : mColorFormat(colorFormat), - mConverter(colorFormat, OMX_COLOR_Format16bitRGB565), - mISurface(surface), + mConverter(NULL), + mYUVMode(None), + mSurface(surface), mDisplayWidth(displayWidth), mDisplayHeight(displayHeight), mDecodedWidth(decodedWidth), - mDecodedHeight(decodedHeight), - mFrameSize(mDecodedWidth * mDecodedHeight * 2), // RGB565 - mIndex(0) { - mMemoryHeap = new MemoryHeapBase("/dev/pmem_adsp", 2 * mFrameSize); - if (mMemoryHeap->heapID() < 0) { - LOGI("Creating physical memory heap failed, reverting to regular heap."); - mMemoryHeap = new MemoryHeapBase(2 * mFrameSize); - } else { - sp pmemHeap = new MemoryHeapPmem(mMemoryHeap); - pmemHeap->slap(); - mMemoryHeap = pmemHeap; + mDecodedHeight(decodedHeight) { + LOGI("input format = %d", mColorFormat); + LOGI("display = %d x %d, decoded = %d x %d", + mDisplayWidth, mDisplayHeight, mDecodedWidth, mDecodedHeight); + + int halFormat; + switch (mColorFormat) { +#if HAS_YCBCR420_SP_ADRENO + case OMX_COLOR_FormatYUV420Planar: + { + halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO; + mYUVMode = YUV420ToYUV420sp; + break; + } + + case 0x7fa30c00: + { + halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO; + mYUVMode = YUV420spToYUV420sp; + break; + } +#endif + + default: + halFormat = HAL_PIXEL_FORMAT_RGB_565; + + mConverter = new ColorConverter( + mColorFormat, OMX_COLOR_Format16bitRGB565); + CHECK(mConverter->isValid()); + break; } - CHECK(mISurface.get() != NULL); + CHECK(mSurface.get() != NULL); CHECK(mDecodedWidth > 0); CHECK(mDecodedHeight > 0); - CHECK(mMemoryHeap->heapID() >= 0); - CHECK(mConverter.isValid()); + CHECK(mConverter == NULL || mConverter->isValid()); + + CHECK_EQ(0, + native_window_set_usage( + mSurface.get(), + GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN + | GRALLOC_USAGE_HW_TEXTURE)); - ISurface::BufferHeap bufferHeap( - mDisplayWidth, mDisplayHeight, - mDecodedWidth, mDecodedHeight, - PIXEL_FORMAT_RGB_565, - mMemoryHeap); + CHECK_EQ(0, native_window_set_buffer_count(mSurface.get(), 2)); - status_t err = mISurface->registerBuffers(bufferHeap); - CHECK_EQ(err, OK); + // Width must be multiple of 32??? + CHECK_EQ(0, native_window_set_buffers_geometry( + mSurface.get(), mDecodedWidth, mDecodedHeight, + halFormat)); } SoftwareRenderer::~SoftwareRenderer() { - mISurface->unregisterBuffers(); + delete mConverter; + mConverter = NULL; +} + +static inline size_t ALIGN(size_t x, size_t alignment) { + return (x + alignment - 1) & ~(alignment - 1); } void SoftwareRenderer::render( const void *data, size_t size, void *platformPrivate) { - size_t offset = mIndex * mFrameSize; - void *dst = (uint8_t *)mMemoryHeap->getBase() + offset; + android_native_buffer_t *buf; + CHECK_EQ(0, mSurface->dequeueBuffer(mSurface.get(), &buf)); + CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), buf)); + + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + + Rect bounds(mDecodedWidth, mDecodedHeight); + + void *dst; + CHECK_EQ(0, mapper.lock( + buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst)); + + if (mConverter) { + mConverter->convert( + mDecodedWidth, mDecodedHeight, + data, 0, dst, buf->stride * 2); + } else if (mYUVMode == YUV420spToYUV420sp) { + // Input and output are both YUV420sp, but the alignment requirements + // are different. + size_t srcYStride = mDecodedWidth; + const uint8_t *srcY = (const uint8_t *)data; + uint8_t *dstY = (uint8_t *)dst; + for (size_t i = 0; i < mDecodedHeight; ++i) { + memcpy(dstY, srcY, mDecodedWidth); + srcY += srcYStride; + dstY += buf->stride; + } + + size_t srcUVStride = (mDecodedWidth + 1) & ~1; + size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2; + + const uint8_t *srcUV = (const uint8_t *)data + + mDecodedHeight * mDecodedWidth; + + size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096); + uint8_t *dstUV = (uint8_t *)dst + dstUVOffset; + + for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) { + memcpy(dstUV, srcUV, (mDecodedWidth + 1) & ~1); + srcUV += srcUVStride; + dstUV += dstUVStride; + } + } else if (mYUVMode == YUV420ToYUV420sp) { + // Input is YUV420 planar, output is YUV420sp, adhere to proper + // alignment requirements. + size_t srcYStride = mDecodedWidth; + const uint8_t *srcY = (const uint8_t *)data; + uint8_t *dstY = (uint8_t *)dst; + for (size_t i = 0; i < mDecodedHeight; ++i) { + memcpy(dstY, srcY, mDecodedWidth); + srcY += srcYStride; + dstY += buf->stride; + } + + size_t srcUVStride = (mDecodedWidth + 1) / 2; + size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2; + + const uint8_t *srcU = (const uint8_t *)data + + mDecodedHeight * mDecodedWidth; + + const uint8_t *srcV = + srcU + ((mDecodedWidth + 1) / 2) * ((mDecodedHeight + 1) / 2); + + size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096); + uint8_t *dstUV = (uint8_t *)dst + dstUVOffset; + + for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) { + for (size_t j = 0; j < (mDecodedWidth + 1) / 2; ++j) { + dstUV[2 * j + 1] = srcU[j]; + dstUV[2 * j] = srcV[j]; + } + srcU += srcUVStride; + srcV += srcUVStride; + dstUV += dstUVStride; + } + } else { + memcpy(dst, data, size); + } - mConverter.convert( - mDecodedWidth, mDecodedHeight, - data, 0, dst, 2 * mDecodedWidth); + CHECK_EQ(0, mapper.unlock(buf->handle)); - mISurface->postBuffer(offset); - mIndex = 1 - mIndex; + CHECK_EQ(0, mSurface->queueBuffer(mSurface.get(), buf)); + buf = NULL; } } // namespace android diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 55e2c36..f34eb45 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -76,6 +76,7 @@ struct AwesomePlayer { bool isPlaying() const; void setISurface(const sp &isurface); + void setSurface(const sp &surface); void setAudioSink(const sp &audioSink); status_t setLooping(bool shouldLoop); @@ -117,6 +118,7 @@ private: wp mListener; sp mISurface; + sp mSurface; sp mAudioSink; SystemTimeSource mSystemTimeSource; @@ -219,6 +221,7 @@ private: status_t seekTo_l(int64_t timeUs); status_t pause_l(); void initRenderer_l(); + void notifyVideoSize_l(); void seekAudioIfNecessary_l(); void cancelPlayerEvents(bool keepBufferingGoing = false); diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h index 9eed089..8d58056 100644 --- a/media/libstagefright/include/SoftwareRenderer.h +++ b/media/libstagefright/include/SoftwareRenderer.h @@ -24,14 +24,14 @@ namespace android { -class ISurface; +class Surface; class MemoryHeapBase; class SoftwareRenderer : public VideoRenderer { public: SoftwareRenderer( OMX_COLOR_FORMATTYPE colorFormat, - const sp &surface, + const sp &surface, size_t displayWidth, size_t displayHeight, size_t decodedWidth, size_t decodedHeight); @@ -41,14 +41,18 @@ public: const void *data, size_t size, void *platformPrivate); private: + enum YUVMode { + None, + YUV420ToYUV420sp, + YUV420spToYUV420sp, + }; + OMX_COLOR_FORMATTYPE mColorFormat; - ColorConverter mConverter; - sp mISurface; + ColorConverter *mConverter; + YUVMode mYUVMode; + sp mSurface; size_t mDisplayWidth, mDisplayHeight; size_t mDecodedWidth, mDecodedHeight; - size_t mFrameSize; - sp mMemoryHeap; - int mIndex; SoftwareRenderer(const SoftwareRenderer &); SoftwareRenderer &operator=(const SoftwareRenderer &); diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp index 6de761f..88b9605 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -495,12 +495,17 @@ sp OMX::createRenderer( } if (!impl) { +#if 0 LOGW("Using software renderer."); impl = new SoftwareRenderer( colorFormat, surface, displayWidth, displayHeight, encodedWidth, encodedHeight); +#else + CHECK(!"Should not be here."); + return NULL; +#endif } return new OMXRenderer(impl); -- cgit v1.1