Fix the new color converter to respect the destination crop rect.
Also fixes the SoftwareRenderer to request blitting the correct crop rectangles. Change-Id: I38706cf9b42d96c6d5b35a9380f006ea4fbbf1ea
This commit is contained in:
@@ -14,6 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "ColorConverter"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <media/stagefright/ColorConverter.h>
|
||||
#include <media/stagefright/MediaDebug.h>
|
||||
#include <media/stagefright/MediaErrors.h>
|
||||
@@ -424,61 +428,30 @@ status_t ColorConverter::convertYUV420SemiPlanar(
|
||||
|
||||
status_t ColorConverter::convertTIYUV420PackedSemiPlanar(
|
||||
const BitmapParams &src, const BitmapParams &dst) {
|
||||
|
||||
/*
|
||||
The TIYUV420PackedSemiPlanar format is same as YUV420PackedSemiPlanar but with
|
||||
additional padding as shown in the diagram below. The padded width and padded
|
||||
height is different for different compression formats and it is read from the
|
||||
codec. In this color conversion routine, the padded resolution is obtained from
|
||||
src bitmap.
|
||||
|
||||
------------------------------------
|
||||
| |
|
||||
| |
|
||||
| ------------------------- |
|
||||
| | | |
|
||||
| | | |
|
||||
| | Y DATA | |
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| ------------------------- |
|
||||
| |
|
||||
| ------------ |
|
||||
| | | |
|
||||
| | | |
|
||||
| | UV DATA | |
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| ------------ |
|
||||
| |
|
||||
| |
|
||||
------------------------------------
|
||||
*/
|
||||
|
||||
LOGV("src.mCropLeft = %d src.mCropTop =%d src.mWidth = %d src.mHeight = %d"
|
||||
" dst.mWidth = %d dst.mHeight = %d", src.mCropLeft , src.mCropTop,
|
||||
src.mWidth, src.mHeight, dst.mWidth, dst.mHeight);
|
||||
|
||||
size_t offset = (src.mWidth * src.mCropTop) + src.mCropLeft;
|
||||
|
||||
uint8_t *kAdjustedClip = initClip();
|
||||
|
||||
uint32_t *dst_ptr = (uint32_t *)dst.mBits;
|
||||
if (!((dst.mWidth & 3) == 0
|
||||
&& (src.mCropLeft & 1) == 0
|
||||
&& src.cropWidth() == dst.cropWidth()
|
||||
&& src.cropHeight() == dst.cropHeight())) {
|
||||
return ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
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;
|
||||
const uint8_t *src_u = (const uint8_t *)(src_y-offset) + (src.mWidth * src.mHeight);
|
||||
src_u += ( ( src.mWidth * (src.mCropTop/2) ) + src.mCropLeft );
|
||||
const uint8_t *src_v = src_u + 1;
|
||||
|
||||
for (size_t y = 0; y < dst.mHeight; ++y) {
|
||||
for (size_t x = 0; x < dst.mWidth; x += 2) {
|
||||
const uint8_t *src_u =
|
||||
(const uint8_t *)src_y + src.mWidth * (src.mHeight - src.mCropTop / 2);
|
||||
|
||||
signed y1 = (signed)src_y[x] - 16; //Y pixel
|
||||
signed y2 = (signed)src_y[x + 1] - 16; //2nd Y pixel
|
||||
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;
|
||||
|
||||
signed u = (signed)src_u[x & ~1] - 128; //U component
|
||||
signed v = (signed)src_u[(x & ~1) + 1] - 128; //V component
|
||||
signed u = (signed)src_u[x & ~1] - 128;
|
||||
signed v = (signed)src_u[(x & ~1) + 1] - 128;
|
||||
|
||||
signed u_b = u * 517;
|
||||
signed u_g = -u * 100;
|
||||
@@ -502,19 +475,21 @@ src bitmap.
|
||||
|
||||
uint32_t rgb2 =
|
||||
((kAdjustedClip[r2] >> 3) << 11)
|
||||
| ((kAdjustedClip[g1] >> 2) << 5)
|
||||
| (kAdjustedClip[b1] >> 3);
|
||||
| ((kAdjustedClip[g2] >> 2) << 5)
|
||||
| (kAdjustedClip[b2] >> 3);
|
||||
|
||||
dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
|
||||
}
|
||||
|
||||
src_y += src.mWidth; //increment Y-pixel line
|
||||
if (y&1) {
|
||||
src_u += src.mWidth; //increment U-V line
|
||||
src_y += src.mWidth;
|
||||
|
||||
if (y & 1) {
|
||||
src_u += src.mWidth;
|
||||
}
|
||||
|
||||
dst_ptr += dst.mWidth / 2;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ SoftwareRenderer::SoftwareRenderer(
|
||||
mCropBottom = mHeight - 1;
|
||||
}
|
||||
|
||||
mCropWidth = mCropRight - mCropLeft + 1;
|
||||
mCropHeight = mCropBottom - mCropTop + 1;
|
||||
|
||||
int32_t rotationDegrees;
|
||||
if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
|
||||
rotationDegrees = 0;
|
||||
@@ -60,17 +63,18 @@ SoftwareRenderer::SoftwareRenderer(
|
||||
|
||||
switch (mColorFormat) {
|
||||
case OMX_COLOR_FormatYUV420Planar:
|
||||
case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
|
||||
{
|
||||
halFormat = HAL_PIXEL_FORMAT_YV12;
|
||||
bufWidth = (mWidth + 1) & ~1;
|
||||
bufHeight = (mHeight + 1) & ~1;
|
||||
bufWidth = (mCropWidth + 1) & ~1;
|
||||
bufHeight = (mCropHeight + 1) & ~1;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
halFormat = HAL_PIXEL_FORMAT_RGB_565;
|
||||
bufWidth = mWidth;
|
||||
bufHeight = mHeight;
|
||||
bufWidth = mCropWidth;
|
||||
bufHeight = mCropHeight;
|
||||
|
||||
mConverter = new ColorConverter(
|
||||
mColorFormat, OMX_COLOR_Format16bitRGB565);
|
||||
@@ -79,8 +83,8 @@ SoftwareRenderer::SoftwareRenderer(
|
||||
}
|
||||
|
||||
CHECK(mNativeWindow != NULL);
|
||||
CHECK(mWidth > 0);
|
||||
CHECK(mHeight > 0);
|
||||
CHECK(mCropWidth > 0);
|
||||
CHECK(mCropHeight > 0);
|
||||
CHECK(mConverter == NULL || mConverter->isValid());
|
||||
|
||||
CHECK_EQ(0,
|
||||
@@ -109,14 +113,6 @@ SoftwareRenderer::SoftwareRenderer(
|
||||
CHECK_EQ(0, native_window_set_buffers_transform(
|
||||
mNativeWindow.get(), transform));
|
||||
}
|
||||
|
||||
android_native_rect_t crop;
|
||||
crop.left = mCropLeft;
|
||||
crop.top = mCropTop;
|
||||
crop.right = mCropRight + 1;
|
||||
crop.bottom = mCropBottom + 1;
|
||||
|
||||
CHECK_EQ(0, native_window_set_crop(mNativeWindow.get(), &crop));
|
||||
}
|
||||
|
||||
SoftwareRenderer::~SoftwareRenderer() {
|
||||
@@ -142,7 +138,7 @@ void SoftwareRenderer::render(
|
||||
|
||||
GraphicBufferMapper &mapper = GraphicBufferMapper::get();
|
||||
|
||||
Rect bounds(mWidth, mHeight);
|
||||
Rect bounds(mCropWidth, mCropHeight);
|
||||
|
||||
void *dst;
|
||||
CHECK_EQ(0, mapper.lock(
|
||||
@@ -152,13 +148,11 @@ void SoftwareRenderer::render(
|
||||
mConverter->convert(
|
||||
data,
|
||||
mWidth, mHeight,
|
||||
0, 0, mWidth - 1, mHeight - 1,
|
||||
mCropLeft, mCropTop, mCropRight, mCropBottom,
|
||||
dst,
|
||||
buf->stride, buf->height,
|
||||
0, 0, mWidth - 1, mHeight - 1);
|
||||
} else {
|
||||
CHECK_EQ(mColorFormat, OMX_COLOR_FormatYUV420Planar);
|
||||
|
||||
0, 0, mCropWidth - 1, mCropHeight - 1);
|
||||
} else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
|
||||
const uint8_t *src_y = (const uint8_t *)data;
|
||||
const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
|
||||
const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
|
||||
@@ -170,22 +164,57 @@ void SoftwareRenderer::render(
|
||||
uint8_t *dst_v = dst_y + dst_y_size;
|
||||
uint8_t *dst_u = dst_v + dst_c_size;
|
||||
|
||||
for (int y = 0; y < mHeight; ++y) {
|
||||
memcpy(dst_y, src_y, mWidth);
|
||||
for (int y = 0; y < mCropHeight; ++y) {
|
||||
memcpy(dst_y, src_y, mCropWidth);
|
||||
|
||||
src_y += mWidth;
|
||||
dst_y += buf->stride;
|
||||
}
|
||||
|
||||
for (int y = 0; y < (mHeight + 1) / 2; ++y) {
|
||||
memcpy(dst_u, src_u, (mWidth + 1) / 2);
|
||||
memcpy(dst_v, src_v, (mWidth + 1) / 2);
|
||||
for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
|
||||
memcpy(dst_u, src_u, (mCropWidth + 1) / 2);
|
||||
memcpy(dst_v, src_v, (mCropWidth + 1) / 2);
|
||||
|
||||
src_u += mWidth / 2;
|
||||
src_v += mWidth / 2;
|
||||
dst_u += dst_c_stride;
|
||||
dst_v += dst_c_stride;
|
||||
}
|
||||
} else {
|
||||
CHECK_EQ(mColorFormat, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar);
|
||||
|
||||
const uint8_t *src_y =
|
||||
(const uint8_t *)data;
|
||||
|
||||
const uint8_t *src_uv =
|
||||
(const uint8_t *)data + mWidth * (mHeight - mCropTop / 2);
|
||||
|
||||
uint8_t *dst_y = (uint8_t *)dst;
|
||||
|
||||
size_t dst_y_size = buf->stride * buf->height;
|
||||
size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
|
||||
size_t dst_c_size = dst_c_stride * buf->height / 2;
|
||||
uint8_t *dst_v = dst_y + dst_y_size;
|
||||
uint8_t *dst_u = dst_v + dst_c_size;
|
||||
|
||||
for (int y = 0; y < mCropHeight; ++y) {
|
||||
memcpy(dst_y, src_y, mCropWidth);
|
||||
|
||||
src_y += mWidth;
|
||||
dst_y += buf->stride;
|
||||
}
|
||||
|
||||
for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
|
||||
size_t tmp = (mCropWidth + 1) / 2;
|
||||
for (size_t x = 0; x < tmp; ++x) {
|
||||
dst_u[x] = src_uv[2 * x];
|
||||
dst_v[x] = src_uv[2 * x + 1];
|
||||
}
|
||||
|
||||
src_uv += mWidth;
|
||||
dst_u += dst_c_stride;
|
||||
dst_v += dst_c_stride;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_EQ(0, mapper.unlock(buf->handle));
|
||||
|
||||
@@ -47,6 +47,7 @@ private:
|
||||
sp<ANativeWindow> mNativeWindow;
|
||||
int32_t mWidth, mHeight;
|
||||
int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;
|
||||
int32_t mCropWidth, mCropHeight;
|
||||
|
||||
SoftwareRenderer(const SoftwareRenderer &);
|
||||
SoftwareRenderer &operator=(const SoftwareRenderer &);
|
||||
|
||||
Reference in New Issue
Block a user