diff options
Diffstat (limited to 'service/src')
6 files changed, 153 insertions, 65 deletions
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/utils/ImsMediaImageRotate.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/utils/ImsMediaImageRotate.h index 939cd670..a0d46ddf 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/utils/ImsMediaImageRotate.h +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/utils/ImsMediaImageRotate.h @@ -24,7 +24,7 @@ class ImsMediaImageRotate public: /** * @brief Rotates YUVImage_420_Planar Image by 90 degrees and flips. - * Supports zero pixel and zero row stride. + * Supports input row stride equal to width. * * Source Image Destination Image * + - - - - + + - - - - + @@ -33,17 +33,18 @@ public: * | 7 8 9 | | 7 4 1 | * + - - - - + + - - - - + * - * @param pbDst Destination buffer with size nDstWidth*nDstHeight*1.5. + * @param pOutBuffer Pointer to output buffer with size nDstWidth*nDstHeight*1.5. * @param pbSrc Source buffer with size nDstWidth*nDstHeight*1.5. * @param nSrcWidth Source Image width. * @param nSrcHeight Source Image height. */ static void YUV420_Planar_Rotate90_Flip( - uint8_t* pbDst, uint8_t* pbSrc, uint16_t nSrcWidth, uint16_t nSrcHeight); + uint8_t* pOutBuffer, uint8_t* pbSrc, uint16_t nSrcWidth, uint16_t nSrcHeight); /** * @brief Rotates YUVImage_420_888 Image by 90 degrees. - * Supports zero pixel stride and zero row stride. + * Supports input row stride equal to width and adds padding when outputStride is not same + * as output image width. * * Source Image Destination Image * + - - - - + + - - - - + @@ -52,18 +53,22 @@ public: * | 7 8 9 | | 9 6 3 | * + - - - - + + - - - - + * - * @param pbDst Destination buffer with size nDstWidth*nDstHeight*1.5. + * @param pOutBuffer Pointer to output buffer with size outputStride*nDstHeight*1.5. + * @param nOutBufSize size of output buffer. + * @param outputStride Stride of the output image >= nDstWidth. * @param pYPlane Y-Plane data of size nDstWidth*nDstHeight. * @param pUVPlane UV-Plane data of size (nDstWidth*nDstHeight)/2. * @param nSrcWidth Source Image width. * @param nSrcHeight Source Image height. + * + * @return -1 on error and 0 on success. */ - static void YUV420_SP_Rotate90(uint8_t* pbDst, uint8_t* pYPlane, uint8_t* pUVPlane, - uint16_t nSrcWidth, uint16_t nSrcHeight); + static int YUV420_SP_Rotate90(uint8_t* pOutBuffer, size_t nOutBufSize, uint16_t outputStride, + uint8_t* pYPlane, uint8_t* pUVPlane, uint16_t nSrcWidth, uint16_t nSrcHeight); /** * @brief Rotates YUVImage_420_888 Image by 90 degrees and flip. - * Supports zero pixel stride and zero row stride. + * Supports input row stride equal to width. * * Source Image Destination Image * + - - - - + + - - - - + @@ -72,18 +77,19 @@ public: * | 7 8 9 | | 7 4 1 | * + - - - - + + - - - - + * - * @param pbDst Destination buffer with size nDstWidth*nDstHeight*1.5. + * @param pOutBuffer Pointer to output buffer with size nDstWidth*nDstHeight*1.5. * @param pYPlane Y-Plane data of size nDstWidth*nDstHeight. * @param pUVPlane UV-Plane data of size (nDstWidth*nDstHeight)/2. * @param nSrcWidth Source Image width. * @param nSrcHeight Source Image height. */ - static void YUV420_SP_Rotate90_Flip(uint8_t* pbDst, uint8_t* pYPlane, uint8_t* pUVPlane, + static void YUV420_SP_Rotate90_Flip(uint8_t* pOutBuffer, uint8_t* pYPlane, uint8_t* pUVPlane, uint16_t nSrcWidth, uint16_t nSrcHeight); /** * @brief Rotates YUVImage_420_888 Image by 270 degrees. - * Supports zero pixel stride and zero row stride. + * Supports input row stride equal to width and adds padding when outputStride is not same + * as output image width. * * Source Image Destination Image * + - - - - + + - - - - + @@ -92,14 +98,18 @@ public: * | 7 8 9 | | 1 4 7 | * + - - - - + + - - - - + * - * @param pbDst Destination buffer with size nDstWidth*nDstHeight*1.5. + * @param pOutBuffer Pointer to output buffer with size nDstWidth*nDstHeight*1.5. + * @param nOutBufSize size of output buffer. + * @param outputStride Stride of the output image >= nDstWidth. * @param pYPlane Y-Plane data of size nDstWidth*nDstHeight. * @param pUVPlane UV-Plane data of size (nDstWidth*nDstHeight)/2. * @param nSrcWidth Source Image width. * @param nSrcHeight Source Image height. + * + * @return -1 on error and 0 on success. */ - static void YUV420_SP_Rotate270(uint8_t* pbDst, uint8_t* pYPlane, uint8_t* pUVPlane, - uint16_t nSrcWidth, uint16_t nSrcHeight); + static int YUV420_SP_Rotate270(uint8_t* pOutBuffer, size_t nOutBufSize, uint16_t outputStride, + uint8_t* pYPlane, uint8_t* pUVPlane, uint16_t nSrcWidth, uint16_t nSrcHeight); }; #endif // IMS_MEDIA_IMAGE_ROTATE
\ No newline at end of file diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaPauseImageSource.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaPauseImageSource.h index 723499b9..66022fc2 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaPauseImageSource.h +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaPauseImageSource.h @@ -31,10 +31,11 @@ public: * * @param width width of the video frames. * @param height height of the video frames. + * @param stride stride of the video frames. * * @return returns true if the image is loaded and false in case of failure. */ - bool Initialize(int width, int height); + bool Initialize(int width, int height, int stride); /** * @brief Image YUV buffer loaded in memory is freed. @@ -58,7 +59,7 @@ private: AAsset* getImageAsset(); const char* getImageFilePath(); - int8_t* ConvertRgbaToYuv(int8_t* pixels, int width, int height); + int8_t* ConvertRgbaToYuv(int8_t* pixels, int width, int height, int stride); }; #endif // IMSMEDIA_JPEG_SOURCE_H_INCLUDED diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaVideoSource.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaVideoSource.h index f74a9caf..83a6d7ac 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaVideoSource.h +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/android/ImsMediaVideoSource.h @@ -167,6 +167,7 @@ private: uint32_t mCameraZoom; uint32_t mWidth; uint32_t mHeight; + int32_t mCodecStride; uint32_t mFramerate; uint32_t mBitrate; uint32_t mIntraInterval; diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaImageRotate.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaImageRotate.cpp index 90947c19..46d01ceb 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaImageRotate.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/ImsMediaImageRotate.cpp @@ -15,13 +15,14 @@ */ #include "ImsMediaImageRotate.h" +#include <ImsMediaTrace.h> void ImsMediaImageRotate::YUV420_Planar_Rotate90_Flip( uint8_t* pbDst, uint8_t* pbSrc, uint16_t nSrcWidth, uint16_t nSrcHeight) { uint16_t x, y; uint64_t srcIdx, dstIdx; - const uint64_t size = nSrcWidth * nSrcHeight; + const size_t size = nSrcWidth * nSrcHeight; dstIdx = size - 1; // Rotate Y buffer @@ -57,41 +58,59 @@ void ImsMediaImageRotate::YUV420_Planar_Rotate90_Flip( } } -void ImsMediaImageRotate::YUV420_SP_Rotate90(uint8_t* pbDst, uint8_t* pYPlane, uint8_t* pUVPlane, - uint16_t nSrcWidth, uint16_t nSrcHeight) +int ImsMediaImageRotate::YUV420_SP_Rotate90(uint8_t* pOutBuffer, size_t nOutBufSize, + uint16_t outputStride, uint8_t* pYPlane, uint8_t* pUVPlane, uint16_t nSrcWidth, + uint16_t nSrcHeight) { - uint16_t x, y; - uint64_t srcIdx, dstIdx; - const uint64_t size = nSrcWidth * nSrcHeight; - dstIdx = size - 1; + uint16_t x, y, nDstWidth = nSrcHeight, nDstHt = nSrcWidth, nPadWidth = outputStride - nDstWidth; + uint64_t srcIdx, dstIdx = (outputStride * nDstHt) - 1; + const size_t dstSize = outputStride * nDstHt * 1.5f; + + if (nOutBufSize < (dstSize - nPadWidth)) + { + IMLOGE4("Output buffer size is not sufficient. \ + Required(outputStride[%d] * outputHeight[%d] * 1.5 = %d) but passed[%d]", + outputStride, nDstHt, dstSize, nOutBufSize); + return -1; + } + + if (nDstWidth > outputStride) + { + IMLOGE2("Destination width[%d] cannot be bigger than stride[%d]", nDstWidth, outputStride); + return -1; + } // Rotate Y buffer for (y = 0; y < nSrcWidth; y++) { + dstIdx -= nPadWidth; srcIdx = nSrcWidth - y - 1; for (x = 0; x < nSrcHeight; x++) { - pbDst[dstIdx] = pYPlane[srcIdx]; // Y + pOutBuffer[dstIdx] = pYPlane[srcIdx]; // Y srcIdx += nSrcWidth; dstIdx--; } } - dstIdx = (size * 1.5f) - 1; + dstIdx = dstSize - 1; nSrcWidth /= 2; nSrcHeight /= 2; // Rotate UV buffer for (y = 0; y < nSrcWidth; y++) { + dstIdx -= nPadWidth; srcIdx = (nSrcWidth - y - 1) * 2; for (x = 0; x < nSrcHeight; x++) { - pbDst[dstIdx--] = pUVPlane[srcIdx + 1]; // V - pbDst[dstIdx--] = pUVPlane[srcIdx]; // U + pOutBuffer[dstIdx--] = pUVPlane[srcIdx + 1]; // V + pOutBuffer[dstIdx--] = pUVPlane[srcIdx]; // U srcIdx += nSrcWidth * 2; } } + + return 0; } void ImsMediaImageRotate::YUV420_SP_Rotate90_Flip(uint8_t* pbDst, uint8_t* pYPlane, @@ -99,7 +118,7 @@ void ImsMediaImageRotate::YUV420_SP_Rotate90_Flip(uint8_t* pbDst, uint8_t* pYPla { uint16_t x, y; uint64_t srcIdx, dstIdx; - const uint64_t size = nSrcWidth * nSrcHeight; + const size_t size = nSrcWidth * nSrcHeight; dstIdx = size - 1; @@ -132,40 +151,58 @@ void ImsMediaImageRotate::YUV420_SP_Rotate90_Flip(uint8_t* pbDst, uint8_t* pYPla } } -void ImsMediaImageRotate::YUV420_SP_Rotate270(uint8_t* pbDst, uint8_t* pYPlane, uint8_t* pUVPlane, - uint16_t nSrcWidth, uint16_t nSrcHeight) +int ImsMediaImageRotate::YUV420_SP_Rotate270(uint8_t* pOutBuffer, size_t nOutBufSize, + uint16_t outputStride, uint8_t* pYPlane, uint8_t* pUVPlane, uint16_t nSrcWidth, + uint16_t nSrcHeight) { - uint16_t x, y; - uint64_t srcIdx, dstIdx; - const uint64_t size = nSrcWidth * nSrcHeight; + uint16_t x, y, nDstWth = nSrcHeight, nDstHt = nSrcWidth, nPadWidth = outputStride - nDstWth; + uint64_t srcIdx, dstIdx = outputStride * nDstHt - 1; + const size_t size = nSrcWidth * nSrcHeight; + const size_t dstSize = outputStride * nDstHt * 1.5f; - dstIdx = size - 1; + if (nOutBufSize < (dstSize - nPadWidth)) + { + IMLOGE4("Output buffer size is not sufficient. \ + Required(outputStride[%d] * outputHeight[%d] * 1.5 = %d) but passed[%d]", + outputStride, nDstHt, dstSize, nOutBufSize); + return -1; + } + + if (nDstWth > outputStride) + { + IMLOGE2("Destination width[%d] cannot be bigger than stride[%d]", nDstWth, outputStride); + return -1; + } // Rotate Y buffer for (y = 0; y < nSrcWidth; y++) { + dstIdx -= nPadWidth; srcIdx = size - nSrcWidth + y; for (x = 0; x < nSrcHeight; x++) { - pbDst[dstIdx] = pYPlane[srcIdx]; // Y + pOutBuffer[dstIdx] = pYPlane[srcIdx]; // Y srcIdx -= nSrcWidth; dstIdx--; } } - dstIdx = (size * 1.5f) - 1; + dstIdx = dstSize - 1; nSrcWidth /= 2; nSrcHeight /= 2; // Rotate UV buffer for (y = 0; y < nSrcWidth; y++) { + dstIdx -= nPadWidth; srcIdx = (size / 2) - (nSrcWidth - y) * 2; for (x = 0; x < nSrcHeight; x++) { - pbDst[dstIdx--] = pUVPlane[srcIdx + 1]; // V - pbDst[dstIdx--] = pUVPlane[srcIdx]; // U + pOutBuffer[dstIdx--] = pUVPlane[srcIdx + 1]; // V + pOutBuffer[dstIdx--] = pUVPlane[srcIdx]; // U srcIdx -= nSrcWidth * 2; } } + + return 0; }
\ No newline at end of file diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaPauseImageSource.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaPauseImageSource.cpp index 29a472aa..58c2f9fa 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaPauseImageSource.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaPauseImageSource.cpp @@ -63,9 +63,10 @@ void ImsMediaPauseImageSource::Uninitialize() } } -bool ImsMediaPauseImageSource::Initialize(int width, int height) +bool ImsMediaPauseImageSource::Initialize(int width, int height, int stride) { - IMLOGD2("[ImsMediaPauseImageSource] Init(width:%d, height:%d)", width, height); + IMLOGD3("[ImsMediaPauseImageSource] Init(width:%d, height:%d, stride:%d)", width, height, + stride); mWidth = width; mHeight = height; @@ -105,12 +106,12 @@ bool ImsMediaPauseImageSource::Initialize(int width, int height) * (AndroidBitmapFormat)AImageDecoderHeaderInfo_getAndroidBitmapFormat(info); */ - size_t stride = AImageDecoder_getMinimumStride(decoder); // Image decoder does not + size_t decStride = AImageDecoder_getMinimumStride(decoder); // Image decoder does not // use padding by default - size_t size = height * stride; + size_t size = height * decStride; int8_t* pixels = reinterpret_cast<int8_t*>(malloc(size)); - result = AImageDecoder_decodeImage(decoder, pixels, stride, size); + result = AImageDecoder_decodeImage(decoder, pixels, decStride, size); if (result != ANDROID_IMAGE_DECODER_SUCCESS) { IMLOGE0("[ImsMediaPauseImageSource] error occurred, and the file could not be decoded."); @@ -119,7 +120,7 @@ bool ImsMediaPauseImageSource::Initialize(int width, int height) return false; } - mYuvImageBuffer = ConvertRgbaToYuv(pixels, width, height); + mYuvImageBuffer = ConvertRgbaToYuv(pixels, width, height, stride); AImageDecoder_delete(decoder); free(pixels); @@ -141,7 +142,8 @@ size_t ImsMediaPauseImageSource::GetYuvImage(uint8_t* buffer, size_t len) return mBufferSize; } - IMLOGE0("[ImsMediaPauseImageSource] buffer size is smaller. Cannot copy"); + IMLOGE2("[ImsMediaPauseImageSource] buffer size is smaller. Expected Bufsize[%d], passed[%d]", + mBufferSize, len); return 0; } @@ -200,31 +202,27 @@ const char* ImsMediaPauseImageSource::getImageFilePath() return nullptr; } -int8_t* ImsMediaPauseImageSource::ConvertRgbaToYuv(int8_t* pixels, int width, int height) +int8_t* ImsMediaPauseImageSource::ConvertRgbaToYuv( + int8_t* pixels, int width, int height, int stride) { // src array must be integer array, data have no padding alignment int32_t* pSrcArray = reinterpret_cast<int32_t*>(pixels); - mBufferSize = width * height * 1.5; + mBufferSize = stride * height * 1.5; int8_t* pDstArray = reinterpret_cast<int8_t*>(malloc(mBufferSize)); int32_t nYIndex = 0; - int32_t nUVIndex = width * height; - int32_t r, g, b; + int32_t nUVIndex = stride * height; + int32_t r, g, b, padLen = stride - width; double y, u, v; for (int32_t j = 0; j < height; j++) { + int32_t nIndex = width * j; for (int32_t i = 0; i < width; i++) { - int32_t nIndex = width * j + i; - - /* - * TODO: Decode alpha - * a = (pSrcArray[nIndex] & 0xff000000) >> 24; - */ - r = (pSrcArray[nIndex] & 0xff0000) >> 16; g = (pSrcArray[nIndex] & 0xff00) >> 8; b = (pSrcArray[nIndex] & 0xff) >> 0; + nIndex++; // rgb to yuv y = 0.257 * r + 0.504 * g + 0.098 * b + 16; @@ -240,7 +238,19 @@ int8_t* ImsMediaPauseImageSource::ConvertRgbaToYuv(int8_t* pixels, int width, in pDstArray[nUVIndex++] = (uint8_t)((u < 0) ? 0 : ((u > 255) ? 255 : u)); } } + + // Add padding if stride > width + if (padLen > 0) + { + nYIndex += padLen; + + if (j % 2 == 0) + { + nUVIndex += padLen; + } + } } + mBufferSize -= padLen; return pDstArray; } diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoSource.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoSource.cpp index a035443f..591b6d05 100644 --- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoSource.cpp +++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/android/ImsMediaVideoSource.cpp @@ -220,6 +220,26 @@ bool ImsMediaVideoSource::Start() return false; } + mCodecStride = mWidth; + AMediaFormat* encoderInputFormat = AMediaCodec_getInputFormat(mCodec); + + if (encoderInputFormat != nullptr) + { + // Check if encoder is initialized with the expected configurations. + int32_t width = 0, height = 0; + AMediaFormat_getInt32(encoderInputFormat, AMEDIAFORMAT_KEY_WIDTH, &width); + AMediaFormat_getInt32(encoderInputFormat, AMEDIAFORMAT_KEY_HEIGHT, &height); + AMediaFormat_getInt32(encoderInputFormat, AMEDIAFORMAT_KEY_STRIDE, &mCodecStride); + AMediaFormat_delete(encoderInputFormat); + + // TODO: More configuration checks should be added + if (mWidth != width || mHeight != height || width > mCodecStride) + { + IMLOGE0("Encoder doesn't support requested configuration."); + return false; + } + } + err = AMediaCodec_start(mCodec); if (err != AMEDIA_OK) @@ -273,7 +293,7 @@ bool ImsMediaVideoSource::Start() } else if (mVideoMode == kVideoModePauseImage) { - mPauseImageSource.Initialize(mWidth, mHeight); + mPauseImageSource.Initialize(mWidth, mHeight, mCodecStride); // start encoder output thread if (mCodec != nullptr) { @@ -355,7 +375,6 @@ void ImsMediaVideoSource::onCameraFrame(AImage* pImage) { size_t buffCapacity = 0; uint8_t* encoderBuf = AMediaCodec_getInputBuffer(mCodec, index, &buffCapacity); - if (!encoderBuf || !buffCapacity) { IMLOGE1("[onCameraFrame] returned null buffer pointer or buffCapacity[%d]", @@ -363,7 +382,7 @@ void ImsMediaVideoSource::onCameraFrame(AImage* pImage) return; } - int32_t width, height, ylen, uvlen; + int32_t width, height, ylen, uvlen, result = 0; uint8_t *yPlane, *uvPlane; AImage_getWidth(pImage, &width); AImage_getHeight(pImage, &height); @@ -384,15 +403,15 @@ void ImsMediaVideoSource::onCameraFrame(AImage* pImage) { case ACAMERA_LENS_FACING_FRONT: { - ImsMediaImageRotate::YUV420_SP_Rotate270( - encoderBuf, yPlane, uvPlane, width, height); + result = ImsMediaImageRotate::YUV420_SP_Rotate270( + encoderBuf, buffCapacity, mCodecStride, yPlane, uvPlane, width, height); } break; case ACAMERA_LENS_FACING_BACK: { - ImsMediaImageRotate::YUV420_SP_Rotate90( - encoderBuf, yPlane, uvPlane, width, height); + result = ImsMediaImageRotate::YUV420_SP_Rotate90( + encoderBuf, buffCapacity, mCodecStride, yPlane, uvPlane, width, height); } break; @@ -408,8 +427,18 @@ void ImsMediaVideoSource::onCameraFrame(AImage* pImage) IMLOGD_PACKET1(IM_PACKET_LOG_VIDEO, "[onCameraFrame] queue buffer size[%d]", ylen + uvlen); - AMediaCodec_queueInputBuffer( - mCodec, index, 0, ylen + uvlen, ImsMediaTimer::GetTimeInMicroSeconds(), 0); + if (result == 0) + { + AMediaCodec_queueInputBuffer( + mCodec, index, 0, ylen + uvlen, ImsMediaTimer::GetTimeInMicroSeconds(), 0); + } + else + { + IMLOGE5("Camera image resolution[%dx%d]. Encoder resolution[%dx%d] buffer size[%d]", + width, height, mWidth, mHeight, buffCapacity); + AMediaCodec_queueInputBuffer(mCodec, index, 0, 0, 0, 0); + return; + } } else { |