Loading media/libstagefright/colorconversion/ColorConverter.cpp +28 −53 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -424,61 +428,30 @@ status_t ColorConverter::convertYUV420SemiPlanar( status_t ColorConverter::convertTIYUV420PackedSemiPlanar( const BitmapParams &src, const BitmapParams &dst) { uint8_t *kAdjustedClip = initClip(); /* 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; if (!((dst.mWidth & 3) == 0 && (src.mCropLeft & 1) == 0 && src.cropWidth() == dst.cropWidth() && src.cropHeight() == dst.cropHeight())) { return ERROR_UNSUPPORTED; } uint8_t *kAdjustedClip = initClip(); uint32_t *dst_ptr = (uint32_t *)dst.mBits + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2; uint32_t *dst_ptr = (uint32_t *)dst.mBits; 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; Loading @@ -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 src_y += src.mWidth; if (y & 1) { src_u += src.mWidth; //increment U-V line src_u += src.mWidth; } dst_ptr += dst.mWidth / 2; } return OK; } Loading media/libstagefright/colorconversion/SoftwareRenderer.cpp +54 −25 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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, Loading Loading @@ -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() { Loading @@ -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( Loading @@ -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); Loading @@ -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)); Loading media/libstagefright/include/SoftwareRenderer.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 &); Loading Loading
media/libstagefright/colorconversion/ColorConverter.cpp +28 −53 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -424,61 +428,30 @@ status_t ColorConverter::convertYUV420SemiPlanar( status_t ColorConverter::convertTIYUV420PackedSemiPlanar( const BitmapParams &src, const BitmapParams &dst) { uint8_t *kAdjustedClip = initClip(); /* 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; if (!((dst.mWidth & 3) == 0 && (src.mCropLeft & 1) == 0 && src.cropWidth() == dst.cropWidth() && src.cropHeight() == dst.cropHeight())) { return ERROR_UNSUPPORTED; } uint8_t *kAdjustedClip = initClip(); uint32_t *dst_ptr = (uint32_t *)dst.mBits + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2; uint32_t *dst_ptr = (uint32_t *)dst.mBits; 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; Loading @@ -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 src_y += src.mWidth; if (y & 1) { src_u += src.mWidth; //increment U-V line src_u += src.mWidth; } dst_ptr += dst.mWidth / 2; } return OK; } Loading
media/libstagefright/colorconversion/SoftwareRenderer.cpp +54 −25 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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, Loading Loading @@ -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() { Loading @@ -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( Loading @@ -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); Loading @@ -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)); Loading
media/libstagefright/include/SoftwareRenderer.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 &); Loading