summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/colorconversion
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/colorconversion')
-rw-r--r--media/libstagefright/colorconversion/Android.mk16
-rw-r--r--media/libstagefright/colorconversion/ColorConverter.cpp192
-rw-r--r--media/libstagefright/colorconversion/SoftwareRenderer.cpp147
3 files changed, 159 insertions, 196 deletions
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index ef2dba0..62ba40f 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -9,20 +9,6 @@ LOCAL_C_INCLUDES := \
$(TOP)/frameworks/base/include/media/stagefright/openmax \
$(TOP)/hardware/msm7k
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libmedia \
- libutils \
- libui \
- libcutils \
- 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)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 5b16997..600f040 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -50,31 +50,64 @@ bool ColorConverter::isValid() const {
}
}
-void ColorConverter::convert(
+ColorConverter::BitmapParams::BitmapParams(
+ void *bits,
size_t width, size_t height,
- const void *srcBits, size_t srcSkip,
- void *dstBits, size_t dstSkip) {
+ size_t cropLeft, size_t cropTop,
+ size_t cropRight, size_t cropBottom)
+ : mBits(bits),
+ mWidth(width),
+ mHeight(height),
+ mCropLeft(cropLeft),
+ mCropTop(cropTop),
+ mCropRight(cropRight),
+ mCropBottom(cropBottom) {
+}
+
+size_t ColorConverter::BitmapParams::cropWidth() const {
+ return mCropRight - mCropLeft + 1;
+}
+
+size_t ColorConverter::BitmapParams::cropHeight() const {
+ return mCropBottom - mCropTop + 1;
+}
+
+void ColorConverter::convert(
+ const void *srcBits,
+ size_t srcWidth, size_t srcHeight,
+ size_t srcCropLeft, size_t srcCropTop,
+ size_t srcCropRight, size_t srcCropBottom,
+ void *dstBits,
+ size_t dstWidth, size_t dstHeight,
+ size_t dstCropLeft, size_t dstCropTop,
+ size_t dstCropRight, size_t dstCropBottom) {
CHECK_EQ(mDstFormat, OMX_COLOR_Format16bitRGB565);
+ BitmapParams src(
+ const_cast<void *>(srcBits),
+ srcWidth, srcHeight,
+ srcCropLeft, srcCropTop, srcCropRight, srcCropBottom);
+
+ BitmapParams dst(
+ dstBits,
+ dstWidth, dstHeight,
+ dstCropLeft, dstCropTop, dstCropRight, dstCropBottom);
+
switch (mSrcFormat) {
case OMX_COLOR_FormatYUV420Planar:
- convertYUV420Planar(
- width, height, srcBits, srcSkip, dstBits, dstSkip);
+ convertYUV420Planar(src, dst);
break;
case OMX_COLOR_FormatCbYCrY:
- convertCbYCrY(
- width, height, srcBits, srcSkip, dstBits, dstSkip);
+ convertCbYCrY(src, dst);
break;
case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
- convertQCOMYUV420SemiPlanar(
- width, height, srcBits, srcSkip, dstBits, dstSkip);
+ convertQCOMYUV420SemiPlanar(src, dst);
break;
case OMX_COLOR_FormatYUV420SemiPlanar:
- convertYUV420SemiPlanar(
- width, height, srcBits, srcSkip, dstBits, dstSkip);
+ convertYUV420SemiPlanar(src, dst);
break;
default:
@@ -86,25 +119,27 @@ void ColorConverter::convert(
}
void ColorConverter::convertCbYCrY(
- size_t width, size_t height,
- const void *srcBits, size_t srcSkip,
- void *dstBits, size_t dstSkip) {
- CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats.
- CHECK(dstSkip >= width * 2);
- CHECK((dstSkip & 3) == 0);
+ const BitmapParams &src, const BitmapParams &dst) {
+ // XXX Untested
uint8_t *kAdjustedClip = initClip();
- uint32_t *dst_ptr = (uint32_t *)dstBits;
+ CHECK((src.mCropLeft & 1) == 0);
+ CHECK_EQ(src.cropWidth(), dst.cropWidth());
+ CHECK_EQ(src.cropHeight(), dst.cropHeight());
+
+ uint32_t *dst_ptr = (uint32_t *)dst.mBits
+ + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
- const uint8_t *src = (const uint8_t *)srcBits;
+ const uint8_t *src_ptr = (const uint8_t *)src.mBits
+ + (src.mCropTop * dst.mWidth + src.mCropLeft) * 2;
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; x += 2) {
- signed y1 = (signed)src[2 * x + 1] - 16;
- signed y2 = (signed)src[2 * x + 3] - 16;
- signed u = (signed)src[2 * x] - 128;
- signed v = (signed)src[2 * x + 2] - 128;
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
+ signed y1 = (signed)src_ptr[2 * x + 1] - 16;
+ signed y2 = (signed)src_ptr[2 * x + 3] - 16;
+ signed u = (signed)src_ptr[2 * x] - 128;
+ signed v = (signed)src_ptr[2 * x + 2] - 128;
signed u_b = u * 517;
signed u_g = -u * 100;
@@ -134,32 +169,35 @@ void ColorConverter::convertCbYCrY(
dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
}
- src += width * 2;
- dst_ptr += dstSkip / 4;
+ src_ptr += src.mWidth * 2;
+ dst_ptr += dst.mWidth / 2;
}
}
void ColorConverter::convertYUV420Planar(
- size_t width, size_t height,
- const void *srcBits, size_t srcSkip,
- void *dstBits, size_t dstSkip) {
- CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats.
- CHECK(dstSkip >= width * 2);
- CHECK((dstSkip & 3) == 0);
-
+ const BitmapParams &src, const BitmapParams &dst) {
uint8_t *kAdjustedClip = initClip();
- uint32_t *dst_ptr = (uint32_t *)dstBits;
- const uint8_t *src_y = (const uint8_t *)srcBits;
+ CHECK((dst.mWidth & 3) == 0);
+ CHECK((src.mCropLeft & 1) == 0);
+ CHECK_EQ(src.cropWidth(), dst.cropWidth());
+ CHECK_EQ(src.cropHeight(), dst.cropHeight());
+
+ uint32_t *dst_ptr = (uint32_t *)dst.mBits
+ + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
+
+ const uint8_t *src_y =
+ (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
const uint8_t *src_u =
- (const uint8_t *)src_y + width * height;
+ (const uint8_t *)src_y + src.mWidth * src.mHeight
+ + src.mCropTop * (src.mWidth / 2) + src.mCropLeft / 2;
const uint8_t *src_v =
- (const uint8_t *)src_u + (width / 2) * (height / 2);
+ src_u + (src.mWidth / 2) * (src.mHeight / 2);
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; x += 2) {
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); 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)
@@ -212,35 +250,38 @@ void ColorConverter::convertYUV420Planar(
dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
}
- src_y += width;
+ src_y += src.mWidth;
if (y & 1) {
- src_u += width / 2;
- src_v += width / 2;
+ src_u += src.mWidth / 2;
+ src_v += src.mWidth / 2;
}
- dst_ptr += dstSkip / 4;
+ dst_ptr += dst.mWidth / 2;
}
}
void ColorConverter::convertQCOMYUV420SemiPlanar(
- size_t width, size_t height,
- const void *srcBits, size_t srcSkip,
- void *dstBits, size_t dstSkip) {
- CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats.
- CHECK(dstSkip >= width * 2);
- CHECK((dstSkip & 3) == 0);
-
+ const BitmapParams &src, const BitmapParams &dst) {
uint8_t *kAdjustedClip = initClip();
- uint32_t *dst_ptr = (uint32_t *)dstBits;
- const uint8_t *src_y = (const uint8_t *)srcBits;
+ CHECK((dst.mWidth & 3) == 0);
+ CHECK((src.mCropLeft & 1) == 0);
+ CHECK_EQ(src.cropWidth(), dst.cropWidth());
+ CHECK_EQ(src.cropHeight(), dst.cropHeight());
+
+ uint32_t *dst_ptr = (uint32_t *)dst.mBits
+ + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
+
+ const uint8_t *src_y =
+ (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
const uint8_t *src_u =
- (const uint8_t *)src_y + width * height;
+ (const uint8_t *)src_y + src.mWidth * src.mHeight
+ + src.mCropTop * src.mWidth + src.mCropLeft;
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; x += 2) {
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
signed y1 = (signed)src_y[x] - 16;
signed y2 = (signed)src_y[x + 1] - 16;
@@ -275,34 +316,39 @@ void ColorConverter::convertQCOMYUV420SemiPlanar(
dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
}
- src_y += width;
+ src_y += src.mWidth;
if (y & 1) {
- src_u += width;
+ src_u += src.mWidth;
}
- dst_ptr += dstSkip / 4;
+ dst_ptr += dst.mWidth / 2;
}
}
void ColorConverter::convertYUV420SemiPlanar(
- size_t width, size_t height,
- const void *srcBits, size_t srcSkip,
- void *dstBits, size_t dstSkip) {
- CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats.
- CHECK(dstSkip >= width * 2);
- CHECK((dstSkip & 3) == 0);
+ const BitmapParams &src, const BitmapParams &dst) {
+ // XXX Untested
uint8_t *kAdjustedClip = initClip();
- uint32_t *dst_ptr = (uint32_t *)dstBits;
- const uint8_t *src_y = (const uint8_t *)srcBits;
+ CHECK((dst.mWidth & 3) == 0);
+ CHECK((src.mCropLeft & 1) == 0);
+ CHECK_EQ(src.cropWidth(), dst.cropWidth());
+ CHECK_EQ(src.cropHeight(), dst.cropHeight());
+
+ uint32_t *dst_ptr = (uint32_t *)dst.mBits
+ + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
+
+ const uint8_t *src_y =
+ (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
const uint8_t *src_u =
- (const uint8_t *)src_y + width * height;
+ (const uint8_t *)src_y + src.mWidth * src.mHeight
+ + src.mCropTop * src.mWidth + src.mCropLeft;
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; x += 2) {
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
signed y1 = (signed)src_y[x] - 16;
signed y2 = (signed)src_y[x + 1] - 16;
@@ -337,13 +383,13 @@ void ColorConverter::convertYUV420SemiPlanar(
dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
}
- src_y += width;
+ src_y += src.mWidth;
if (y & 1) {
- src_u += width;
+ src_u += src.mWidth;
}
- dst_ptr += dstSkip / 4;
+ dst_ptr += dst.mWidth / 2;
}
}
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index acbea05..70408d7 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -21,55 +21,41 @@
#include <binder/MemoryHeapBase.h>
#include <binder/MemoryHeapPmem.h>
-#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MetaData.h>
#include <surfaceflinger/Surface.h>
#include <ui/android_native_buffer.h>
#include <ui/GraphicBufferMapper.h>
-// XXX: Temporary hack to allow referencing the _ADRENO pixel format here.
-#include <libgralloc-qsd8k/gralloc_priv.h>
-
namespace android {
SoftwareRenderer::SoftwareRenderer(
- OMX_COLOR_FORMATTYPE colorFormat,
- const sp<Surface> &surface,
- size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight,
- int32_t rotationDegrees)
- : mColorFormat(colorFormat),
- mConverter(NULL),
+ const sp<Surface> &surface, const sp<MetaData> &meta)
+ : mConverter(NULL),
mYUVMode(None),
- mSurface(surface),
- mDisplayWidth(displayWidth),
- mDisplayHeight(displayHeight),
- mDecodedWidth(decodedWidth),
- mDecodedHeight(decodedHeight) {
- LOGI("input format = %d", mColorFormat);
- LOGI("display = %d x %d, decoded = %d x %d",
- mDisplayWidth, mDisplayHeight, mDecodedWidth, mDecodedHeight);
-
- mDecodedWidth = mDisplayWidth;
- mDecodedHeight = mDisplayHeight;
+ mSurface(surface) {
+ int32_t tmp;
+ CHECK(meta->findInt32(kKeyColorFormat, &tmp));
+ mColorFormat = (OMX_COLOR_FORMATTYPE)tmp;
+
+ CHECK(meta->findInt32(kKeyWidth, &mWidth));
+ CHECK(meta->findInt32(kKeyHeight, &mHeight));
+
+ if (!meta->findRect(
+ kKeyCropRect,
+ &mCropLeft, &mCropTop, &mCropRight, &mCropBottom)) {
+ mCropLeft = mCropTop = 0;
+ mCropRight = mWidth - 1;
+ mCropBottom = mHeight - 1;
+ }
+
+ int32_t rotationDegrees;
+ if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
+ rotationDegrees = 0;
+ }
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;
@@ -80,8 +66,8 @@ SoftwareRenderer::SoftwareRenderer(
}
CHECK(mSurface.get() != NULL);
- CHECK(mDecodedWidth > 0);
- CHECK(mDecodedHeight > 0);
+ CHECK(mWidth > 0);
+ CHECK(mHeight > 0);
CHECK(mConverter == NULL || mConverter->isValid());
CHECK_EQ(0,
@@ -94,7 +80,9 @@ SoftwareRenderer::SoftwareRenderer(
// Width must be multiple of 32???
CHECK_EQ(0, native_window_set_buffers_geometry(
- mSurface.get(), mDecodedWidth, mDecodedHeight,
+ mSurface.get(),
+ mCropRight - mCropLeft + 1,
+ mCropBottom - mCropTop + 1,
halFormat));
uint32_t transform;
@@ -117,10 +105,6 @@ SoftwareRenderer::~SoftwareRenderer() {
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) {
android_native_buffer_t *buf;
@@ -134,7 +118,7 @@ void SoftwareRenderer::render(
GraphicBufferMapper &mapper = GraphicBufferMapper::get();
- Rect bounds(mDecodedWidth, mDecodedHeight);
+ Rect bounds(mWidth, mHeight);
void *dst;
CHECK_EQ(0, mapper.lock(
@@ -142,69 +126,16 @@ void SoftwareRenderer::render(
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;
- }
+ data,
+ mWidth, mHeight,
+ mCropLeft, mCropTop, mCropRight, mCropBottom,
+ dst,
+ buf->stride, buf->height,
+ 0, 0,
+ mCropRight - mCropLeft,
+ mCropBottom - mCropTop);
} else {
- memcpy(dst, data, size);
+ TRESPASS();
}
CHECK_EQ(0, mapper.unlock(buf->handle));