summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2010-02-11 10:58:05 -0800
committerAndreas Huber <andih@google.com>2010-02-11 10:58:05 -0800
commit5c64d74cc0e1506e287df1a7abd7b67ac3274d47 (patch)
treed0163e41c3166b98badde7ea43c9e67571d81ddc
parent696f1c1dcc846f4e1ba6754776b3c4542a9c62a8 (diff)
downloadomap3-5c64d74cc0e1506e287df1a7abd7b67ac3274d47.tar.gz
Support for both OMX_COLOR_FormatCbYCrY and OMX_COLOR_FormatYUV420Planar in the overlay rendering code.
-rw-r--r--libstagefrighthw/TIHardwareRenderer.cpp77
-rw-r--r--libstagefrighthw/TIHardwareRenderer.h9
-rw-r--r--libstagefrighthw/stagefright_overlay_output.cpp18
3 files changed, 94 insertions, 10 deletions
diff --git a/libstagefrighthw/TIHardwareRenderer.cpp b/libstagefrighthw/TIHardwareRenderer.cpp
index 2a23585..c7494e2 100644
--- a/libstagefrighthw/TIHardwareRenderer.cpp
+++ b/libstagefrighthw/TIHardwareRenderer.cpp
@@ -34,12 +34,15 @@ namespace android {
TIHardwareRenderer::TIHardwareRenderer(
const sp<ISurface> &surface,
size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight)
+ size_t decodedWidth, size_t decodedHeight,
+ OMX_COLOR_FORMATTYPE colorFormat)
: mISurface(surface),
mDisplayWidth(displayWidth),
mDisplayHeight(displayHeight),
mDecodedWidth(decodedWidth),
mDecodedHeight(decodedHeight),
+ mColorFormat(colorFormat),
+ mInitCheck(NO_INIT),
mFrameSize(mDecodedWidth * mDecodedHeight * 2),
mIsFirstFrame(true),
mIndex(0) {
@@ -47,6 +50,11 @@ TIHardwareRenderer::TIHardwareRenderer(
CHECK(mDecodedWidth > 0);
CHECK(mDecodedHeight > 0);
+ if (colorFormat != OMX_COLOR_FormatCbYCrY
+ && colorFormat != OMX_COLOR_FormatYUV420Planar) {
+ return;
+ }
+
sp<OverlayRef> ref = mISurface->createOverlay(
mDecodedWidth, mDecodedHeight, OVERLAY_FORMAT_CbYCrY_422_I, 0);
@@ -64,6 +72,8 @@ TIHardwareRenderer::TIHardwareRenderer(
mOverlayAddresses.push(data->ptr);
}
+
+ mInitCheck = OK;
}
TIHardwareRenderer::~TIHardwareRenderer() {
@@ -76,6 +86,62 @@ TIHardwareRenderer::~TIHardwareRenderer() {
}
}
+// return a byte offset from any pointer
+static inline const void *byteOffset(const void* p, size_t offset) {
+ return ((uint8_t*)p + offset);
+}
+
+static void convertYuv420ToYuv422(
+ int width, int height, const void *src, void *dst) {
+ // calculate total number of pixels, and offsets to U and V planes
+ int pixelCount = height * width;
+ int srcLineLength = width / 4;
+ int destLineLength = width / 2;
+ uint32_t* ySrc = (uint32_t*) src;
+ const uint16_t* uSrc = (const uint16_t*) byteOffset(src, pixelCount);
+ const uint16_t* vSrc = (const uint16_t*) byteOffset(uSrc, pixelCount >> 2);
+ uint32_t *p = (uint32_t*) dst;
+
+ // convert lines
+ for (int i = 0; i < height; i += 2) {
+
+ // upsample by repeating the UV values on adjacent lines
+ // to save memory accesses, we handle 2 adjacent lines at a time
+ // convert 4 pixels in 2 adjacent lines at a time
+ for (int j = 0; j < srcLineLength; j++) {
+
+ // fetch 4 Y values for each line
+ uint32_t y0 = ySrc[0];
+ uint32_t y1 = ySrc[srcLineLength];
+ ySrc++;
+
+ // fetch 2 U/V values
+ uint32_t u = *uSrc++;
+ uint32_t v = *vSrc++;
+
+ // assemble first U/V pair, leave holes for Y's
+ uint32_t uv = (u | (v << 16)) & 0x00ff00ff;
+
+ // OR y values and write to memory
+ p[0] = ((y0 & 0xff) << 8) | ((y0 & 0xff00) << 16) | uv;
+ p[destLineLength] = ((y1 & 0xff) << 8) | ((y1 & 0xff00) << 16) | uv;
+ p++;
+
+ // assemble second U/V pair, leave holes for Y's
+ uv = ((u >> 8) | (v << 8)) & 0x00ff00ff;
+
+ // OR y values and write to memory
+ p[0] = ((y0 >> 8) & 0xff00) | (y0 & 0xff000000) | uv;
+ p[destLineLength] = ((y1 >> 8) & 0xff00) | (y1 & 0xff000000) | uv;
+ p++;
+ }
+
+ // skip the next y line, we already converted it
+ ySrc += srcLineLength;
+ p += destLineLength;
+ }
+}
+
void TIHardwareRenderer::render(
const void *data, size_t size, void *platformPrivate) {
// CHECK_EQ(size, mFrameSize);
@@ -110,7 +176,14 @@ void TIHardwareRenderer::render(
mIsFirstFrame = false;
}
#else
- memcpy(mOverlayAddresses[mIndex], data, size);
+ if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
+ convertYuv420ToYuv422(
+ mDecodedWidth, mDecodedHeight, data, mOverlayAddresses[mIndex]);
+ } else {
+ CHECK_EQ(mColorFormat, OMX_COLOR_FormatCbYCrY);
+
+ memcpy(mOverlayAddresses[mIndex], data, size);
+ }
mOverlay->queueBuffer((void *)mIndex);
diff --git a/libstagefrighthw/TIHardwareRenderer.h b/libstagefrighthw/TIHardwareRenderer.h
index ef42648..86bab6b 100644
--- a/libstagefrighthw/TIHardwareRenderer.h
+++ b/libstagefrighthw/TIHardwareRenderer.h
@@ -22,6 +22,8 @@
#include <utils/RefBase.h>
#include <utils/Vector.h>
+#include <OMX_Component.h>
+
namespace android {
class ISurface;
@@ -32,10 +34,13 @@ public:
TIHardwareRenderer(
const sp<ISurface> &surface,
size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight);
+ size_t decodedWidth, size_t decodedHeight,
+ OMX_COLOR_FORMATTYPE colorFormat);
virtual ~TIHardwareRenderer();
+ status_t initCheck() const { return mInitCheck; }
+
virtual void render(
const void *data, size_t size, void *platformPrivate);
@@ -43,6 +48,8 @@ private:
sp<ISurface> mISurface;
size_t mDisplayWidth, mDisplayHeight;
size_t mDecodedWidth, mDecodedHeight;
+ OMX_COLOR_FORMATTYPE mColorFormat;
+ status_t mInitCheck;
size_t mFrameSize;
sp<Overlay> mOverlay;
Vector<void *> mOverlayAddresses;
diff --git a/libstagefrighthw/stagefright_overlay_output.cpp b/libstagefrighthw/stagefright_overlay_output.cpp
index 263d55f..5cd8606 100644
--- a/libstagefrighthw/stagefright_overlay_output.cpp
+++ b/libstagefrighthw/stagefright_overlay_output.cpp
@@ -1,7 +1,7 @@
-#include <media/stagefright/HardwareAPI.h>
-
#include "TIHardwareRenderer.h"
+#include <media/stagefright/HardwareAPI.h>
+
using android::sp;
using android::ISurface;
using android::VideoRenderer;
@@ -14,13 +14,17 @@ VideoRenderer *createRenderer(
size_t decodedWidth, size_t decodedHeight) {
using android::TIHardwareRenderer;
- if (colorFormat == OMX_COLOR_FormatCbYCrY
- && !strcmp(componentName, "OMX.TI.Video.Decoder")) {
- return new TIHardwareRenderer(
+ TIHardwareRenderer *renderer =
+ new TIHardwareRenderer(
surface, displayWidth, displayHeight,
- decodedWidth, decodedHeight);
+ decodedWidth, decodedHeight,
+ colorFormat);
+
+ if (renderer->initCheck() != android::OK) {
+ delete renderer;
+ renderer = NULL;
}
- return NULL;
+ return renderer;
}