From 97e487c5b9dc2c9716c8b7b60f3cb5a797a70a98 Mon Sep 17 00:00:00 2001 From: Jinkun Jang Date: Sat, 16 Mar 2013 01:16:50 +0900 Subject: [PATCH] merge with master --- CMakeLists.txt | 29 +++-- inc/FMediaImageTypes.h | 49 +++++-- packaging/osp-image-core.spec | 5 +- src/FMedia_BmpDecoder.cpp | 29 ++--- src/FMedia_BmpEncoder.cpp | 150 +++++---------------- src/FMedia_BmpEncoder.h | 3 - src/FMedia_ColorConverter.cpp | 26 +++- src/FMedia_ExifUtil.cpp | 279 ++++++++++++++++++++++++++++++++++++++++ src/FMedia_Ffmpeg.cpp | 35 +++++ src/FMedia_ImageDecoder.cpp | 98 ++++++++++++-- src/FMedia_ImageUtil.cpp | 115 +++++++++++++++++ src/FMedia_JpegTurboDecoder.cpp | 6 + src/inc/FMedia_ColorConverter.h | 4 +- src/inc/FMedia_ExifUtil.h | 72 +++++++++++ src/inc/FMedia_Ffmpeg.h | 41 ++++++ src/inc/FMedia_ImageDecoder.h | 9 +- src/inc/FMedia_ImageUtil.h | 20 +++ 17 files changed, 787 insertions(+), 183 deletions(-) mode change 100644 => 100755 src/FMedia_BmpDecoder.cpp mode change 100644 => 100755 src/FMedia_BmpEncoder.cpp mode change 100644 => 100755 src/FMedia_BmpEncoder.h create mode 100644 src/FMedia_ExifUtil.cpp create mode 100755 src/FMedia_Ffmpeg.cpp create mode 100644 src/inc/FMedia_ExifUtil.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 150dc48..5abb7b6 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,15 +5,15 @@ SET (this_target osp-image-core) SET(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/cmake_build_tmp/output) INCLUDE_DIRECTORIES( - inc - src - src/inc - /usr/include/chromium - /usr/include/ecore-1 - /usr/include/eina-1 - /usr/include/eina-1/eina - /usr/include/evas-1 - /usr/include/media + inc + src + src/inc + /usr/include/chromium + /usr/include/ecore-1 + /usr/include/eina-1 + /usr/include/eina-1/eina + /usr/include/evas-1 + /usr/include/media /usr/include/osp /usr/include/osp/base /usr/include/osp/app @@ -38,6 +38,8 @@ SET (${this_target}_SOURCE_FILES src/FMedia_BmpEncoder.cpp src/FMedia_SlpUtil.cpp src/FMedia_MediaUtil.cpp + src/FMedia_ExifUtil.cpp + src/FMedia_Ffmpeg.cpp ) ## Definitions @@ -59,7 +61,6 @@ SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined - TARGET_LINK_LIBRARIES(${this_target} "-L/usr/lib/osp -losp-appfw" ) TARGET_LINK_LIBRARIES(${this_target} "-lglib-2.0" ) TARGET_LINK_LIBRARIES(${this_target} "-leina" ) -TARGET_LINK_LIBRARIES(${this_target} "-lnetwork" ) TARGET_LINK_LIBRARIES(${this_target} "-lcurl" ) TARGET_LINK_LIBRARIES(${this_target} "-lpng -lz" ) TARGET_LINK_LIBRARIES(${this_target} "-lavcodec" ) @@ -73,7 +74,7 @@ TARGET_LINK_LIBRARIES(${this_target} "-lecore_evas" ) TARGET_LINK_LIBRARIES(${this_target} "-lcapi-media-image-util" ) TARGET_LINK_LIBRARIES(${this_target} "-lturbojpeg" ) TARGET_LINK_LIBRARIES(${this_target} "-ltiff" ) - +TARGET_LINK_LIBRARIES(${this_target} "-lexif" ) SET_TARGET_PROPERTIES(${this_target} PROPERTIES @@ -83,7 +84,7 @@ SET_TARGET_PROPERTIES(${this_target} ) ADD_CUSTOM_COMMAND(TARGET ${this_target} - POST_BUILD + POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${LIBRARY_OUTPUT_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX} ${LIBRARY_OUTPUT_PATH}/debug/${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX}.${FULLVER} COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX}.${FULLVER} ${LIBRARY_OUTPUT_PATH}/debug/${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX}.${MAJORVER} COMMAND ${CMAKE_STRIP} --strip-unneeded ${LIBRARY_OUTPUT_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX} @@ -93,8 +94,8 @@ ADD_CUSTOM_COMMAND(TARGET ${this_target} INSTALL(DIRECTORY ${LIBRARY_OUTPUT_PATH}/ DESTINATION lib/osp FILES_MATCHING PATTERN "*.so*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ - GROUP_EXECUTE GROUP_READ - WORLD_EXECUTE WORLD_READ) + GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ) INSTALL(DIRECTORY ${LIBRARY_OUTPUT_PATH}/debug/ DESTINATION lib/osp/debug FILES_MATCHING PATTERN "*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ diff --git a/inc/FMediaImageTypes.h b/inc/FMediaImageTypes.h index ad9ad38..7ea9ea8 100644 --- a/inc/FMediaImageTypes.h +++ b/inc/FMediaImageTypes.h @@ -16,7 +16,7 @@ // /** - * @file FMediaImageTypes.h + * @file FMediaImageTypes.h * @brief This is the header file for the common types of the Image class. * * This header file contains the declarations of the enumerations for the Image class. @@ -59,7 +59,7 @@ enum ImageRotationType IMAGE_ROTATION_90, /**< The 90 degree rotation in clockwise direction */ IMAGE_ROTATION_180, /**< The 180 degree rotation in clockwise direction */ IMAGE_ROTATION_270, /**< The 270 degree rotation in clockwise direction */ -} ; +}; /** * @enum ImageFlipType @@ -73,7 +73,7 @@ enum ImageFlipType IMAGE_FLIP_NONE = 0x00, /**< The no-flip type */ IMAGE_FLIP_HORIZONTAL, /**< The horizontal flip */ IMAGE_FLIP_VERTICAL, /**< The vertical flip */ -} ; +}; /** * @enum MediaPixelFormat @@ -94,11 +94,44 @@ enum MediaPixelFormat MEDIA_PIXEL_FORMAT_YUV420P = 0x0200, /**< The YUV420 Planar format */ MEDIA_PIXEL_FORMAT_NV12, /**< The NV12 format */ MEDIA_PIXEL_FORMAT_NV12_TILE, /**< The NV12 tiled format */ - MEDIA_PIXEL_FORMAT_NV21, /**< @if OSPCOMPAT @since 2.0 @endif The NV21 format */ - MEDIA_PIXEL_FORMAT_YUV444P, /**< @if OSPCOMPAT @since 2.0 @endif The YUV444 Planar format */ - MEDIA_PIXEL_FORMAT_YUYV422, /**< @if OSPCOMPAT @since 2.0 @endif The YUYV422 format */ - MEDIA_PIXEL_FORMAT_UYVY422, /**< @if OSPCOMPAT @since 2.0 @endif The UYVY422 format */ - MEDIA_PIXEL_FORMAT_GRAY, /**< @if OSPCOMPAT @since 2.0 @endif The gray pixel format */ + MEDIA_PIXEL_FORMAT_NV21, /**< @since 2.0 The NV21 format */ + MEDIA_PIXEL_FORMAT_YUV444P, /**< @since 2.0 The YUV444 Planar format */ + MEDIA_PIXEL_FORMAT_YUYV422, /**< @since 2.0 The YUYV422 format */ + MEDIA_PIXEL_FORMAT_UYVY422, /**< @since 2.0 The UYVY422 format */ + MEDIA_PIXEL_FORMAT_GRAY, /**< @since 2.0 The gray pixel format */ +}; + +/** + * @enum ImageScalingMethod + * + * Defines the image sacling method. + * + * @since 2.1 + */ +enum ImageScalingMethod +{ + IMAGE_SCALING_METHOD_FAST_BILINEAR, /** fast bilinear interpolation method */ + IMAGE_SCALING_METHOD_BILINEAR, /** bilinear interpolation method */ + IMAGE_SCALING_METHOD_BICUBIC, /** bicubic interpolation method */ +}; + +/** + * @enum ExifOrientation + * + * Defines the image's EXIF orientation flags. + * + * @since 2.1 + */ +enum ExifOrientation +{ + EXIF_ORIENTATION_TOP_LEFT = 0x01, /**< The row #0 is top, column #0 is left */ + EXIF_ORIENTATION_TOP_RIGHT, /**< The row #0 is top, column #0 is right */ + EXIF_ORIENTATION_BOTTOM_RIGHT, /**< The row #0 is bottom, column #0 is right */ + EXIF_ORIENTATION_BOTTOM_LEFT, /**< The row #0 is bottom, column #0 is left */ + EXIF_ORIENTATION_LEFT_TOP, /**< The row #0 is left, column #0 is top */ + EXIF_ORIENTATION_RIGHT_TOP, /**< The row #0 is right, column #0 is top */ + EXIF_ORIENTATION_RIGHT_BOTTOM, /**< The row #0 is right, column #0 is bottom */ + EXIF_ORIENTATION_LEFT_BOTTOM, /**< The row #0 is left, column #0 is bottom */ }; }; diff --git a/packaging/osp-image-core.spec b/packaging/osp-image-core.spec index 160e7a6..1eb4e2b 100755 --- a/packaging/osp-image-core.spec +++ b/packaging/osp-image-core.spec @@ -3,7 +3,7 @@ Name: osp-image-core Summary: The Media Image Core library of OSP -Version: 1.2.0.0 +Version: 1.2.1.0 Release: 1 Group: TO_BE/FILLED_IN License: TO BE FILLED IN @@ -19,9 +19,12 @@ BuildRequires: pkgconfig(libavformat) BuildRequires: pkgconfig(libavutil) BuildRequires: pkgconfig(libswscale) BuildRequires: pkgconfig(pango) +BuildRequires: pkgconfig(evas) +BuildRequires: pkgconfig(libpng) BuildRequires: giflib-devel BuildRequires: libjpeg-turbo-devel BuildRequires: libtiff-devel +BuildRequires: libexif-devel # runtime requires Requires: osp-appfw diff --git a/src/FMedia_BmpDecoder.cpp b/src/FMedia_BmpDecoder.cpp old mode 100644 new mode 100755 index d671d32..b40cea0 --- a/src/FMedia_BmpDecoder.cpp +++ b/src/FMedia_BmpDecoder.cpp @@ -65,18 +65,15 @@ _BmpDecoder::OpenCodec(void) result r = E_SUCCESS; int res = 0; - //avcodec_init(); avcodec_register_all(); - __pCodecCtx = avcodec_alloc_context(); - SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM, - "[E_SYSTEM] avcodec context allocation failed."); - __pCodec = avcodec_find_decoder(CODEC_ID_BMP); - SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM, - "[E_SYSTEM] Failed to find bmp decoder."); + SysTryReturnResult(NID_MEDIA, __pCodec != null, E_UNSUPPORTED_CODEC, "Failed to find bmp decoder."); + + __pCodecCtx = avcodec_alloc_context3(__pCodec); + SysTryReturnResult(NID_MEDIA, __pCodecCtx != null, E_OUT_OF_MEMORY, "context allocation failed."); - res = avcodec_open(__pCodecCtx, __pCodec); + res = avcodec_open2(__pCodecCtx, __pCodec, null); SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to open bmp decoder."); @@ -223,28 +220,20 @@ _BmpDecoder::SetDecodingRegion(int x, int y, int width, int height) result _BmpDecoder::GetDimension(int& width, int& height) { - result r = E_SUCCESS; + SysTryReturnResult(NID_MEDIA, __pCodecCtx, E_INVALID_STATE, "Not Constructed."); - SysTryCatch(NID_MEDIA, __pCodecCtx, r = E_INVALID_STATE, - E_INVALID_STATE, "[E_INVALID_STATE] Not Constructed."); + SysTryReturnResult(NID_MEDIA, __pCodecCtx->width > 0 && __pCodecCtx->height > 0, E_INVALID_STATE, + "Invalid dimensions : (%d x %d)", __pCodecCtx->width, __pCodecCtx->height); width = __pCodecCtx->width; height = __pCodecCtx->height; - if ((width <= 0) || (height <= 0)) - { - SysLog(NID_MEDIA, "Invalid dimensions! Should be greater than zero : (%d x %d)", width, height); - r = E_SYSTEM; - } - -CATCH: - return r; + return E_SUCCESS; } MediaPixelFormat _BmpDecoder::GetPixelFormat(void) { - result r = E_SUCCESS; MediaPixelFormat pixel_format = MEDIA_PIXEL_FORMAT_NONE; SysTryReturn(NID_MEDIA, __pCodecCtx, pixel_format, E_INVALID_STATE, diff --git a/src/FMedia_BmpEncoder.cpp b/src/FMedia_BmpEncoder.cpp old mode 100644 new mode 100755 index 820a75a..00cede8 --- a/src/FMedia_BmpEncoder.cpp +++ b/src/FMedia_BmpEncoder.cpp @@ -28,11 +28,13 @@ #include "FMedia_BmpEncoder.h" #include "FMedia_ImageUtil.h" +using namespace std; using namespace Tizen::Base; namespace Tizen { namespace Media { + _BmpEncoder::_BmpEncoder(void) { __pCodecCtx = null; @@ -61,7 +63,7 @@ _BmpEncoder::Construct(int width, int height, MediaPixelFormat& reqPixelFormat, int quality) { - result r = E_SUCCESS; + int res; SysTryReturnResult(NID_MEDIA, width >= MIN_WIDTH, E_INVALID_ARG, "Width (%d) < minimum bmp width (%d)", width, MIN_WIDTH); @@ -72,6 +74,7 @@ _BmpEncoder::Construct(int width, int height, SysTryReturnResult(NID_MEDIA, quality <= 100, E_INVALID_ARG, "Quality should be lesser than 100 (%d)", quality); + // TODO: add BGRA8888 support __width = width; __height = height; __quality = quality; @@ -79,93 +82,50 @@ _BmpEncoder::Construct(int width, int height, reqPixelFormat = MEDIA_PIXEL_FORMAT_BGR888; __quality = quality; - r = OpenCodec(width, height, __pixelFormat); - SysTryCatch(NID_MEDIA, (r == E_SUCCESS), r = E_SYSTEM, E_SYSTEM, "Failed to initialize FFMPEG."); - - return E_SUCCESS; -CATCH: - return r; -} - -result -_BmpEncoder::OpenCodec(int width, int height, MediaPixelFormat pixelFormat) -{ - result r = E_SUCCESS; - int res = 0; - - //avcodec_init(); avcodec_register_all(); - __pCodecCtx = avcodec_alloc_context(); - SysTryCatch(NID_MEDIA, __pCodecCtx != null, r = E_SYSTEM, E_SYSTEM, - "[E_SYSTEM] avcodec context allocation failed."); - __pCodec = avcodec_find_encoder(CODEC_ID_BMP); - SysTryCatch(NID_MEDIA, __pCodec != null, r = E_SYSTEM, E_SYSTEM, - "[E_SYSTEM] Failed to find bmp decoder."); + SysTryReturnResult(NID_MEDIA, __pCodec != null, E_UNSUPPORTED_CODEC, "Failed to find bmp encoder."); + + __pCodecCtx = avcodec_alloc_context3(__pCodec); + SysTryReturnResult(NID_MEDIA, __pCodecCtx != null, E_OUT_OF_MEMORY, "context allocation failed."); // Context required for opening BMP encoder. // Specifying output image format - __pCodecCtx->pix_fmt = (PixelFormat)_ImageUtil::ToFfmpegPixelFormat(pixelFormat); + __pCodecCtx->pix_fmt = (PixelFormat)_ImageUtil::ToFfmpegPixelFormat(__pixelFormat); // Dimensions of the image __pCodecCtx->height = height; __pCodecCtx->width = width; - res = avcodec_open(__pCodecCtx, __pCodec); - SysTryCatch(NID_MEDIA, res >= 0, r = E_SYSTEM, E_SYSTEM, - "[E_SYSTEM] Failed to open bmp decoder."); - - return r; - -CATCH: - CloseCodec(); - return r; -} + res = avcodec_open2(__pCodecCtx, __pCodec, null); + SysTryReturnResult(NID_MEDIA, res >= 0, E_OUT_OF_MEMORY, "codec open failed:%d", res); -void -_BmpEncoder::CloseCodec(void) -{ - if (__pCodecCtx) - { - avcodec_close(__pCodecCtx); - av_free(__pCodecCtx); - __pCodecCtx = null; - __pCodec = null; - } + return E_SUCCESS; } Tizen::Base::ByteBuffer* -_BmpEncoder::EncodeN(const byte* srcBuf, int srcLength) +_BmpEncoder::EncodeN(const byte* pSrcBuf, int srcLength) { result r = E_SUCCESS; - int outSize = 0; - int widthPadding = 0; - int tmpDstLength = 0; - AVFrame* pVideoFrame = null; - std::unique_ptr pInputData; - std::unique_ptr pTmpDstBuf; - std::unique_ptr pRetBuf; + int ret = 0; + unique_ptr pVideoFrame(avcodec_alloc_frame(), ffmpegDeleter); + unique_ptr pRetBuf(new (std::nothrow) ByteBuffer()); + unique_ptr pPkt(new (std::nothrow) AVPacket, ffmpegDeleter); + int gotOutput; // TODO: apply pixel format - SysTryCatch(NID_MEDIA, (srcBuf != null && srcLength > 0), r = E_INVALID_ARG, E_INVALID_ARG, - "[E_INVALID_ARG] Encode Failed. Check inputs."); - - pInputData.reset(new (std::nothrow) byte[srcLength + FF_PADDING_BYTES]); - SysTryCatch(NID_MEDIA, (pInputData.get() != null), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, - "[E_OUT_OF_MEMORY] Could not allocate memory for input to encoder."); + SysTryReturn(NID_MEDIA, pSrcBuf != null && srcLength > 0, null, E_INVALID_ARG, + "[E_INVALID_ARG] pSrcBuf=0x%x srcLength=%d", pSrcBuf, srcLength); - memcpy(pInputData.get(), srcBuf, srcLength); - memset(pInputData.get() + srcLength, 0, FF_PADDING_BYTES); - - pVideoFrame = avcodec_alloc_frame(); - SysTryCatch(NID_MEDIA, (pVideoFrame != null), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, - "[E_OUT_OF_MEMORY] Could not allocate memory for encoder output."); + SysTryReturn(NID_MEDIA, pVideoFrame.get() != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] avcodec_alloc_frame() failed"); + SysTryReturn(NID_MEDIA, pRetBuf.get() != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] new ByteBuffer() failed."); + SysTryReturn(NID_MEDIA, pPkt.get() != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] new AVPacket failed."); // Input buffer is a BGR888, so no need for explicit color conversion // to BGR888. // pVideoFrame is the input to encoder. - pVideoFrame->data[0] = (uint8_t*) pInputData.get(); + pVideoFrame->data[0] = (uint8_t*)pSrcBuf; pVideoFrame->data[1] = 0; pVideoFrame->data[2] = 0; pVideoFrame->data[3] = 0; @@ -174,63 +134,23 @@ _BmpEncoder::EncodeN(const byte* srcBuf, int srcLength) pVideoFrame->linesize[2] = 0; pVideoFrame->linesize[3] = 0; - // BMP images have width 4 byte aligned. So, if image width is not a - // multiple of 4, every row will be padded to make it a multiple of 4. - // extraBytes = ((dim.width * 3) % 4) - widthPadding = ((__width * BYTES_PER_PIXEL_RGB) % 4); - if (widthPadding) - { - widthPadding = 4 - widthPadding; - } + av_init_packet(pPkt.get()); + pPkt->data = NULL; // packet data will be allocated by the encoder + pPkt->size = 0; + gotOutput = 0; - tmpDstLength = BMP_HEADER_SIZE_ - + (((__width * BYTES_PER_PIXEL_RGB) + widthPadding) * __height); + ret = avcodec_encode_video2(__pCodecCtx, pPkt.get(), pVideoFrame.get(), &gotOutput); + SysTryReturn(NID_MEDIA, ret >= 0 && gotOutput > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] Encode Failed:%d %d", ret, gotOutput); - // Check if destination buffer length is lesser than the minimum buffer size - // supported by ffmpeg. If not, pass a buffer of size equal to the minimum size. - if (tmpDstLength < FF_MIN_BUFFER_SIZE) - { - tmpDstLength = FF_MIN_BUFFER_SIZE; - } + r = pRetBuf->Construct(pPkt->size); + SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ByteBuffer.Construct(%d) failed", GetErrorMessage(r), pPkt->size); - pTmpDstBuf.reset(new (std::nothrow) byte[tmpDstLength]); - SysTryCatch(NID_MEDIA, (pTmpDstBuf.get() != null), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, - "[E_OUT_OF_MEMORY] Could not allocate memory for encoder output."); - - outSize = avcodec_encode_video(__pCodecCtx, (uint8_t*) pTmpDstBuf.get(), (tmpDstLength), pVideoFrame); - SysTryCatch(NID_MEDIA, outSize > 0, r = E_INVALID_ARG, E_INVALID_ARG, - "[E_SYSTEM] Encode Failed"); - - // The data that has been encoded is of length same as dstLength. If they are not equal, - // something is wrong with the data, or with the encoding. - SysTryCatch(NID_MEDIA, outSize <= tmpDstLength, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, - "[E_OUT_OF_MEMORY] Insufficient memory for encoder output out (%d) != allocated (%d).", outSize, tmpDstLength); - - pRetBuf.reset(new (std::nothrow) ByteBuffer()); - SysTryCatch(NID_MEDIA, pRetBuf.get() != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, - "[E_OUT_OF_MEMORY] Could not create new ByteBuffer."); - - r = pRetBuf->Construct(outSize); - SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, - "[%s] Propagated. ByteBuffer.Construct failed for %d bytes", - GetErrorMessage(r), outSize); - - r = pRetBuf->SetArray(pTmpDstBuf.get(), 0, outSize); - SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, - "[%s] Propagated. ByteBuffer.SetArray failed, buffer size = %d", - GetErrorMessage(r), outSize); + r = pRetBuf->SetArray(pPkt->data, 0, pPkt->size); + SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated. ByteBuffer.SetArray(%x, 0, %d) failed", + GetErrorMessage(r), pPkt->data, pPkt->size); pRetBuf->Flip(); - av_free(pVideoFrame); - return pRetBuf.release(); - -CATCH: - if (pVideoFrame != null) - { - av_free(pVideoFrame); - } - return null; } result diff --git a/src/FMedia_BmpEncoder.h b/src/FMedia_BmpEncoder.h old mode 100644 new mode 100755 index 497b175..0df1317 --- a/src/FMedia_BmpEncoder.h +++ b/src/FMedia_BmpEncoder.h @@ -93,9 +93,6 @@ protected: private: - result OpenCodec(int width, int height, MediaPixelFormat pixelFormat); - void CloseCodec(void); - int __width; int __height; int __quality; diff --git a/src/FMedia_ColorConverter.cpp b/src/FMedia_ColorConverter.cpp index 4ed14a3..eec16ee 100644 --- a/src/FMedia_ColorConverter.cpp +++ b/src/FMedia_ColorConverter.cpp @@ -65,7 +65,8 @@ _ColorConverter::~_ColorConverter(void) result _ColorConverter::Construct(MediaPixelFormat srcFormat, int srcWidth, int srcHeight, - MediaPixelFormat dstFormat, int dstWidth, int dstHeight) + MediaPixelFormat dstFormat, int dstWidth, int dstHeight, + ImageScalingMethod scalingMethod) { result r = E_SUCCESS; @@ -117,14 +118,27 @@ _ColorConverter::Construct(MediaPixelFormat srcFormat, int srcWidth, int srcHeig r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT, "[E_UNSUPPORTED_FORMAT] Destination pixel format (%d) is not supported.", __dstFormat); - //avcodec_init(); avcodec_register_all(); // Create scale context - __pCvtCtxt = sws_getContext(__srcWidth, __srcHeight, __ffSrcFormat, - __dstWidth, __dstHeight, __ffDstFormat, - SWS_FAST_BILINEAR, null, null, null); - + if ( scalingMethod == IMAGE_SCALING_METHOD_BILINEAR) + { + __pCvtCtxt = sws_getContext(__srcWidth, __srcHeight, __ffSrcFormat, + __dstWidth, __dstHeight, __ffDstFormat, + SWS_BILINEAR, null, null, null); + } + else if ( scalingMethod == IMAGE_SCALING_METHOD_BICUBIC) + { + __pCvtCtxt = sws_getContext(__srcWidth, __srcHeight, __ffSrcFormat, + __dstWidth, __dstHeight, __ffDstFormat, + SWS_BICUBIC, null, null, null); + } + else + { + __pCvtCtxt = sws_getContext(__srcWidth, __srcHeight, __ffSrcFormat, + __dstWidth, __dstHeight, __ffDstFormat, + SWS_FAST_BILINEAR, null, null, null); + } SysTryReturn(NID_MEDIA, __pCvtCtxt != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] sws_getContext failed. src (%d x %d, pix = %d), dst (%d x %d, pix = %d)", __srcWidth, __srcHeight, __ffSrcFormat, diff --git a/src/FMedia_ExifUtil.cpp b/src/FMedia_ExifUtil.cpp new file mode 100644 index 0000000..29478a3 --- /dev/null +++ b/src/FMedia_ExifUtil.cpp @@ -0,0 +1,279 @@ +// +// Open Service Platform +// Copyright (c) 2012 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "FMedia_ExifUtil.h" + +namespace Tizen { namespace Media +{ + +const wchar_t* const EXIF_TAG_IMAGE_ORIENTATION = L"Exif.Orientation"; +const wchar_t* const EXIF_TAG_IMAGE_GPS_ALTITUDE = L"Exif.Gps.Altitude"; +const wchar_t* const EXIF_TAG_IMAGE_GPS_LONGITUDE = L"Exif.Gps.Longitude"; +const wchar_t* const EXIF_TAG_IMAGE_GPS_LATITUDE = L"Exif.Gps.Latitude"; + +_ExifUtil::_ExifUtil() +: __pExifData(null) +, __pExifLog(null) +, __orientation(-1) +, __gpsLongitude(0.0) +, __gpsLatitude(0.0) +, __gpsAltitude(0.0) +, __gpsLongitudeExist(false) +, __gpsAltitudeExist(false) +, __gpsLatitudeExist(false) +, __orientationExist(false) +{ +} + +_ExifUtil::~_ExifUtil() +{ + if (__pExifData) + { + exif_data_free(__pExifData); + } + if (__pExifLog) + { + exif_log_free(__pExifLog); + } +} + +result _ExifUtil::Construct(const byte* pBuf, int length) +{ + result r = E_SUCCESS; + + SysTryCatch(NID_MEDIA, pBuf != null, r = E_INVALID_DATA, E_INVALID_DATA, "[E_INVALID_DATA] Buffer is null. length: %d", length); + + __pExifData = exif_data_new_from_data(pBuf, length); + SysTryCatch(NID_MEDIA, __pExifData != null, r = E_INVALID_DATA, E_INVALID_DATA, "[E_INVALID_DATA] exi data is null. length: %d", length); + + __pExifLog = exif_log_new(); + SysTryCatch(NID_MEDIA, __pExifLog != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] exif_log_new fail"); + +#if defined _EXIF_UTIL_LOG_ + //exif_log_set_func(__pExifLog, _ExifUtil::ExifLogFuncStatic, this); + //exif_data_log(__pExifData, __pExifLog); +#endif + exif_data_foreach_content(__pExifData, _ExifUtil::ForEachContentStatic, this); + return r; + +CATCH: + if (__pExifLog) + { + exif_log_free(__pExifLog); + } + return r; +} + +#if defined _EXIF_UTIL_LOG_ +//void _ExifUtil::ExifLogFuncStatic(ExifLog *log, ExifLogCode code, const char *domain, const char *format, va_list args, void *data) +//{ +// ((_ExifUtil*)data)->ExifLogFunc(log, code, domain, format, args); +//} + +//void _ExifUtil::ExifLogFunc(ExifLog *log, ExifLogCode code, const char *domain, const char *format, va_list args) +//{ +// char msg[1024]; +// vsprintf(msg, format, args); +// TLog("ExifLog : %s", msg); +//} +#endif + +void _ExifUtil::ForEachContentStatic(struct _ExifContent *pContent, void *pUserData) +{ + SysTryReturnVoidResult(NID_MEDIA, pContent != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] ExifContent instance is not available."); + + _ExifUtil* pUtil = static_cast<_ExifUtil*>(pUserData); + SysTryReturnVoidResult(NID_MEDIA, pUtil != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] _ExifUtil instance is not available."); + + pUtil->ForEachContent(pContent); +} + +void _ExifUtil::ForEachContent(struct _ExifContent *pContent) +{ + SysTryReturnVoidResult(NID_MEDIA, pContent != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] ExifContent instance is not available."); + + exif_content_log(pContent, __pExifLog); + exif_content_dump(pContent, 0); + + exif_content_foreach_entry(pContent, _ExifUtil::ForEachEntryStatic, this); +} + +void _ExifUtil::ForEachEntryStatic(struct _ExifEntry *pEntry, void *pUserData) +{ + SysTryReturnVoidResult(NID_MEDIA, pEntry != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] ExifEntry instance is not available."); + + _ExifUtil* pUtil = static_cast<_ExifUtil*>(pUserData); + SysTryReturnVoidResult(NID_MEDIA, pUtil != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] _ExifUtil instance is not available."); + + pUtil->ForEachEntry(pEntry); +} + +void _ExifUtil::ForEachEntry(struct _ExifEntry *pEntry) +{ + SysTryReturnVoidResult(NID_MEDIA, pEntry != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] ExifEntry instance is not available."); + SysTryReturnVoidResult(NID_MEDIA, pEntry->parent != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] Entry's parent instance is not available."); + + const ExifByteOrder o = exif_data_get_byte_order (pEntry->parent->parent); + ExifRational exifRational; + +#if defined (_EXIF_UTIL_LOG_) + char value[1024]; +#endif + + switch ((int)pEntry->tag) + { + case EXIF_TAG_ORIENTATION: + if (pEntry->format == EXIF_FORMAT_SHORT && pEntry->size == 2) + { + __orientation = *(short*)(pEntry->data); + __orientationExist = true; + } + break; + + case EXIF_TAG_GPS_LATITUDE: + if (pEntry->format == EXIF_FORMAT_RATIONAL) + { + /* + exifRational = exif_get_rational (pEntry->data, o); + + if (exifRational.denominator && exifRational.denominator != 1) { + __gpsLatitude = (double)exifRational.numerator / (double)exifRational.denominator; + } + else + { + __gpsLatitude = (double)exifRational.numerator; + } + */ + __gpsLatitude = 0.0; + for (int i = 0; i < (int)pEntry->components; i++) + { + exifRational = exif_get_rational (pEntry->data + 8 * i, o); + if (exifRational.denominator) + { + __gpsLatitude += ((double)exifRational.numerator / (double)exifRational.denominator) / pow((float)60.0, i); + } + else + { + __gpsLatitude += (double)exifRational.numerator / pow((float)60.0, i); + } + } + __gpsLatitudeExist = true; + } + break; + + case EXIF_TAG_GPS_LONGITUDE: + if (pEntry->format == EXIF_FORMAT_RATIONAL) + { + /* + exifRational = exif_get_rational (pEntry->data, o); + + if (exifRational.denominator && exifRational.denominator != 1) { + __gpsLatitude = (double)exifRational.numerator / (double)exifRational.denominator; + } else { + __gpsLatitude = (double)exifRational.numerator; + } + */ + __gpsLongitude = 0.0; + + for (int i = 0; i < (int)pEntry->components; i++) + { + exifRational = exif_get_rational (pEntry->data + 8 * i, o); + if (exifRational.denominator && exifRational.denominator != 1) + { + __gpsLongitude += ((double)exifRational.numerator / (double)exifRational.denominator) / pow((float)60.0, i); + } + else + { + __gpsLongitude += (double)exifRational.numerator / pow((float)60.0, i); + } + } + __gpsLongitudeExist = true; + } + break; + + case EXIF_TAG_GPS_ALTITUDE: + if (pEntry->format == EXIF_FORMAT_RATIONAL) + { + exifRational = exif_get_rational (pEntry->data, o); + + if (exifRational.denominator && exifRational.denominator != 1) + { + __gpsAltitude = (double)exifRational.numerator / (double)exifRational.denominator; + } + else + { + __gpsAltitude = (double)exifRational.numerator; + } + __gpsAltitudeExist = true; + } + break; + + default: + break; + } +} + +result _ExifUtil::GetValue(const Tizen::Base::String& key, int &value) +{ + if (key.Equals(EXIF_TAG_IMAGE_ORIENTATION, true)) + { + SysTryReturn(NID_MEDIA, __orientationExist, E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] bool instance is not available. Orientation value was not found."); + value = __orientation; + } + else + { + SysLogException(NID_MEDIA, E_INVALID_ARG, "[E_INVALID_ARG] Key:%S was wrong.", key.GetPointer()); + return E_INVALID_ARG; + } + + return E_SUCCESS; +} + +result _ExifUtil::GetValue(const Tizen::Base::String& key, double &value) +{ + if (key.Equals(EXIF_TAG_IMAGE_GPS_ALTITUDE, true)) + { + SysTryReturn(NID_MEDIA, __gpsAltitudeExist, E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] bool instance is not available. Altitude value was not found."); + value = __gpsAltitude; + } + else if (key.Equals(EXIF_TAG_IMAGE_GPS_LONGITUDE, true)) + { + SysTryReturn(NID_MEDIA, __gpsLongitude, E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] bool instance is not available. Longitude value was not found."); + value = __gpsLongitude; + } else if (key.Equals(EXIF_TAG_IMAGE_GPS_LATITUDE, true)) + { + SysTryReturn(NID_MEDIA, __gpsLatitude, E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] bool instance is not available. Latitude value was not found."); + value = __gpsLatitude; + } else + { + SysLogException(NID_MEDIA, E_INVALID_ARG, "[E_INVALID_ARG] Key:%S was wrong.", key.GetPointer()); + return E_INVALID_ARG; + } + + return E_SUCCESS; +} + +}} + diff --git a/src/FMedia_Ffmpeg.cpp b/src/FMedia_Ffmpeg.cpp new file mode 100755 index 0000000..b7f342e --- /dev/null +++ b/src/FMedia_Ffmpeg.cpp @@ -0,0 +1,35 @@ +// +// Open Service Platform +// Copyright (c) 2012 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FMedia_Ffmpeg.cpp + * @brief This is the implementation file for the ffmpeg related utility. + * + * This file contains the implementations for the ffmpeg related utility. + * + */ +#include +#include "FMedia_Ffmpeg.h" + +using namespace Tizen::Base; + +namespace Tizen { namespace Media +{ + +struct _FfmpegDeleter ffmpegDeleter; + +}} // Tizen::Media diff --git a/src/FMedia_ImageDecoder.cpp b/src/FMedia_ImageDecoder.cpp index c67f59c..a6499bc 100644 --- a/src/FMedia_ImageDecoder.cpp +++ b/src/FMedia_ImageDecoder.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -38,6 +37,7 @@ #include "FMedia_TiffDecoder.h" #include "FMedia_WbmpDecoder.h" #include "FMedia_ImageUtil.h" +#include "FMedia_ExifUtil.h" using namespace Tizen::Base; using namespace Tizen::Io; @@ -49,11 +49,30 @@ namespace Tizen { namespace Media ((x == MEDIA_PIXEL_FORMAT_RGB565LE) || (x == MEDIA_PIXEL_FORMAT_BGRA8888) \ || (x == MEDIA_PIXEL_FORMAT_RGBA8888)) +typedef struct { + ImageRotationType rotateType; + ImageFlipType flipType; + bool dimensionSwitch; +} _ImageExifInfo; + +static const _ImageExifInfo _IMAGE_ROTATE_FLIP_MAP[] = { + { IMAGE_ROTATION_0, IMAGE_FLIP_NONE, false }, /* NONE */ + { IMAGE_ROTATION_0, IMAGE_FLIP_NONE, false }, /* TOP_LEFT */ + { IMAGE_ROTATION_0, IMAGE_FLIP_VERTICAL, false }, /* TOP_RIGHT */ + { IMAGE_ROTATION_180, IMAGE_FLIP_NONE, false }, /* BOTTOM_RIGHT */ + { IMAGE_ROTATION_0, IMAGE_FLIP_HORIZONTAL, false }, /* BOTTOM_LEFT */ + { IMAGE_ROTATION_90, IMAGE_FLIP_VERTICAL, true }, /* LEFT_TOP */ + { IMAGE_ROTATION_90, IMAGE_FLIP_NONE, true }, /* RIGHT_TOP */ + { IMAGE_ROTATION_90, IMAGE_FLIP_HORIZONTAL, true }, /* RIGHT_BOTTOM */ + { IMAGE_ROTATION_270, IMAGE_FLIP_NONE, true } /* LEFT_BOTTOM */ +}; + Tizen::Base::ByteBuffer* _ImageDecoder::DecodeToBufferN(const Tizen::Base::String& filePath, - MediaPixelFormat pixelFormat, int &width, int &height) + MediaPixelFormat pixelFormat, int &width, int &height, bool autoRotate) { result r = E_SUCCESS; + std::unique_ptr pBuf; _ImageDecoder dec; @@ -62,7 +81,7 @@ _ImageDecoder::DecodeToBufferN(const Tizen::Base::String& filePath, SysTryReturn(NID_MEDIA, File::IsFileExist(filePath), null, E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] filePath:%ls", filePath.GetPointer()); - r = dec.Construct(filePath, pixelFormat); + r = dec.Construct(filePath, pixelFormat, IMG_FORMAT_NONE, autoRotate); SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Decoder construct failed.", GetErrorMessage(r)); @@ -204,6 +223,8 @@ _ImageDecoder::_ImageDecoder(void) __outDim.width = 0; __outDim.height = 0; __pSrcBuf = null; + __autoRotate = false; + __orientationInfo = 0; } _ImageDecoder::~_ImageDecoder(void) @@ -260,7 +281,7 @@ _ImageDecoder::CreateDecoderN(ImageFormat srcFormat) result _ImageDecoder::Construct(const Tizen::Base::String& srcPath, MediaPixelFormat pixelFormat, - ImageFormat imgFormat) + ImageFormat imgFormat, bool autoRotate) { result r = E_SUCCESS; std::unique_ptr pBuf; @@ -272,6 +293,17 @@ _ImageDecoder::Construct(const Tizen::Base::String& srcPath, r = Construct(*pBuf.get(), pixelFormat, imgFormat); SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated.", GetErrorMessage(r)); + + if (autoRotate == true) + { + __autoRotate = true; + _ExifUtil imgExif; + imgExif.Construct(pBuf->GetPointer(), pBuf->GetCapacity()); + imgExif.GetValue(EXIF_TAG_IMAGE_ORIENTATION, __orientationInfo); + // imgExif.GetValue() will return "r = E_OBJ_NOT_FOUND" if it could not be found exif infomation. + // However, the result should be decided by result of construct in this function. + SetLastResult(E_SUCCESS); + } return r; } @@ -283,7 +315,7 @@ _ImageDecoder::Construct(const Tizen::Base::ByteBuffer& srcBuf, result r = E_SUCCESS; SysTryReturnResult(NID_MEDIA, __pDec.get() == null, E_INVALID_STATE, "Already constructed"); - SysTryCatch(NID_MEDIA, + SysTryCatch(NID_MEDIA, (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE)|| (pixelFormat == MEDIA_PIXEL_FORMAT_BGRA8888) || (pixelFormat == MEDIA_PIXEL_FORMAT_RGBA8888), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] pixelFormat:%d", pixelFormat); @@ -327,18 +359,19 @@ CATCH: } byte* -_ImageDecoder::DecodeN(int& outLength) +_ImageDecoder::DecodeN(int& outLength, ImageScalingMethod scalingMethod) { result r = E_SUCCESS; int rawLength = 0; - byte* outBuf = null; + std::unique_ptr pOutBuf; std::unique_ptr pRawBuf; + std::unique_ptr pDstBuf; SysTryReturn(NID_MEDIA, __pDec.get() != null, null, E_INVALID_STATE, "Not yet constructed"); // Decode pRawBuf.reset(__pDec->DecodeN(rawLength)); SysTryReturn(NID_MEDIA, pRawBuf.get() != null, null, GetLastResult(), - "[%s] buffer is null (%x), buffer length is %d.", + "[%s] buffer is null (%x), buffer length is %d.", GetErrorMessage(GetLastResult()),pRawBuf.get(), rawLength); // Get working dimension @@ -353,7 +386,7 @@ _ImageDecoder::DecodeN(int& outLength) && (__orgDim.width == __outDim.width) && (__orgDim.height == __outDim.height)) { - outBuf = pRawBuf.release(); + pOutBuf.swap(pRawBuf); outLength = rawLength; } else @@ -362,16 +395,57 @@ _ImageDecoder::DecodeN(int& outLength) // Converter construction r = cvt.Construct(__pDec->GetPixelFormat(), __orgDim.width, __orgDim.height, - __pixelFormat, __outDim.width, __outDim.height); + __pixelFormat, __outDim.width, __outDim.height, scalingMethod); SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r)); // Convert to output format - outBuf = cvt.ConvertN(pRawBuf.get(), rawLength, outLength); + pOutBuf.reset(cvt.ConvertN(pRawBuf.get(), rawLength, outLength)); r = GetLastResult(); SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r)); } + + if (__autoRotate == true) + { + int dstWidth = 0; + int dstHeight = 0; + + if (__orientationInfo == EXIF_ORIENTATION_TOP_LEFT || __orientationInfo == 0) + { + SetLastResult(E_SUCCESS); + return pOutBuf.release(); + } + + if (__orientationInfo > EXIF_ORIENTATION_LEFT_BOTTOM || __orientationInfo < EXIF_ORIENTATION_TOP_LEFT) + { + SetLastResult(E_SUCCESS); + return pOutBuf.release(); + } + + pDstBuf.reset(new (std::nothrow) byte[outLength]); + SysTryReturn(NID_MEDIA, pDstBuf.get() != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]"); + + ImageRotationType rotateType = _IMAGE_ROTATE_FLIP_MAP[__orientationInfo].rotateType; + ImageFlipType flipType = _IMAGE_ROTATE_FLIP_MAP[__orientationInfo].flipType; + + pDstBuf.reset(_ImageUtil::RotateN(pOutBuf.get(), __pixelFormat, __outDim.width, __outDim.height, rotateType, dstWidth, dstHeight)); + r = GetLastResult(); + SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] _ImageUtil:Resize", GetErrorMessage(r)); + + __outDim.width = dstWidth; + __outDim.height = dstHeight; + + pOutBuf.swap(pDstBuf); + if (flipType != IMAGE_FLIP_NONE) + { + pDstBuf.reset(_ImageUtil::FlipN(pOutBuf.get(), __pixelFormat, __outDim.width, __outDim.height, flipType)); + r = GetLastResult(); + SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] _ImageUtil:Flip", GetErrorMessage(r)); + + pOutBuf.swap(pDstBuf); + } + } SetLastResult(E_SUCCESS); - return outBuf; + return pOutBuf.release(); } // TODO: Change return type to ByteBuffer* diff --git a/src/FMedia_ImageUtil.cpp b/src/FMedia_ImageUtil.cpp index 5f22cc8..dbba81d 100644 --- a/src/FMedia_ImageUtil.cpp +++ b/src/FMedia_ImageUtil.cpp @@ -22,6 +22,9 @@ #include #include +#include +#include +#include #include #include #include @@ -2470,6 +2473,87 @@ _ImageUtil::CropN(const Tizen::Base::ByteBuffer &srcBuf, return pOutBuf.release(); } +byte* +_ImageUtil::CropN(const byte *srcBuf, + MediaPixelFormat pixelFormat, + int srcWidth, int srcHeight, + int dstX, int dstY, int dstWidth, int dstHeight) +{ + int bufSize = 0; + std::unique_ptr pOutBuf; + result r = E_SUCCESS; + + bufSize = GetBufferSize(pixelFormat, dstWidth, dstHeight); + SysTryReturn(NID_MEDIA, bufSize > 0, null, GetLastResult(), + "[%s] Check dimensions (%d x %d) and pixel format (%d)", + GetErrorMessage(GetLastResult()), dstWidth, dstHeight, pixelFormat); + + pOutBuf.reset(new (std::nothrow) byte[bufSize]); + SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY, + "[E_OUT_OF_MEMORY] Could not create new ByteBuffer."); + + r = CropBuffer(srcBuf, pixelFormat, srcWidth, srcHeight, pOutBuf.get(), dstX, dstY, dstWidth, dstHeight); + SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, + "[%s] ImageUtil.CropN failed.", GetErrorMessage(r)); + + SetLastResult(E_SUCCESS); + return pOutBuf.release(); +} + +byte* +_ImageUtil::RotateN(const byte *srcBuf, + MediaPixelFormat pixelFormat, + int srcWidth, int srcHeight, + ImageRotationType rotate, + int &dstWidth, int &dstHeight) +{ + int bufSize = 0; + std::unique_ptr pOutBuf; + result r = E_SUCCESS; + + bufSize = GetBufferSize(pixelFormat, srcWidth, srcHeight); + SysTryReturn(NID_MEDIA, bufSize > 0, null, GetLastResult(), + "[%s] Check dimensions (%d x %d) and pixel format (%d)", + GetErrorMessage(GetLastResult()), dstWidth, dstHeight, pixelFormat); + + pOutBuf.reset(new (std::nothrow) byte[bufSize]); + SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY, + "[E_OUT_OF_MEMORY] Could not create new ByteBuffer."); + + r = RotateBuffer(srcBuf, pixelFormat, srcWidth, srcHeight, pOutBuf.get(), dstWidth, dstHeight, rotate); + SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, + "[%s] ImageUtil.RotateN failed.", GetErrorMessage(r)); + + SetLastResult(E_SUCCESS); + return pOutBuf.release(); +} + +byte* +_ImageUtil::FlipN(const byte* srcBuf, + MediaPixelFormat pixelFormat, int width, int height, + ImageFlipType flip) +{ + int bufSize = 0; + std::unique_ptr pOutBuf; + result r = E_SUCCESS; + + bufSize = GetBufferSize(pixelFormat, width, height); + SysTryReturn(NID_MEDIA, bufSize > 0, null, GetLastResult(), + "[%s] Check dimensions (%d x %d) and pixel format (%d)", + GetErrorMessage(GetLastResult()), width, height, pixelFormat); + + pOutBuf.reset(new (std::nothrow) byte[bufSize]); + SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY, + "[E_OUT_OF_MEMORY] Could not create new ByteBuffer."); + + r = FlipBuffer(srcBuf, pixelFormat, width, height, pOutBuf.get(), flip); + SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, + "[%s] ImageUtil.FlipN failed.", GetErrorMessage(r)); + + SetLastResult(E_SUCCESS); + return pOutBuf.release(); +} + int _ImageUtil::GetBufferSize(MediaPixelFormat pixelFormat, int width, int height) { @@ -2567,4 +2651,35 @@ _ImageUtil::ToMediaPixelFormatFromFfmpeg(int pixelFormat) return MEDIA_PIXEL_FORMAT_NONE; } +result +_ImageUtil::GetResizedDimension(int srcWidth, int srcHeight, float dstWidth, float dstHeight, + float &outWidth, float &outHeight) +{ + + SysTryReturn(NID_MEDIA, (srcWidth > 0 && srcHeight > 0 && dstWidth > 0 && dstHeight > 0), + E_INVALID_ARG, E_INVALID_ARG, + "[E_INVALID_ARG] Dimensions should be greater than zero Source size(%d x %d), \ + Destination size(%f x %f)", srcWidth, srcHeight, dstWidth, dstHeight); + + double xRatio = Float(dstWidth).ToDouble() / Integer(srcWidth).ToDouble(); + double yRatio = Float(dstHeight).ToDouble() / Integer(srcHeight).ToDouble(); + + if (xRatio >= 1.0 || yRatio >= 1.0) + { + outWidth = Integer(srcWidth).ToFloat(); + outHeight = Integer(srcHeight).ToFloat(); + } + else if (xRatio < yRatio) + { + outWidth = Double(srcWidth * yRatio).ToFloat(); + outHeight = dstHeight; + } + else + { + outWidth = dstWidth; + outHeight = Double(srcHeight * xRatio).ToFloat(); + } + return E_SUCCESS; +} + }} // Tizen::Media diff --git a/src/FMedia_JpegTurboDecoder.cpp b/src/FMedia_JpegTurboDecoder.cpp index d4d861f..45c5cb8 100644 --- a/src/FMedia_JpegTurboDecoder.cpp +++ b/src/FMedia_JpegTurboDecoder.cpp @@ -85,9 +85,15 @@ _JpegTurboDecoder::Construct(const byte* buffer, int length, MediaPixelFormat pi CATCH: if ( __tjDecodingHandle ) + { tjDestroy(__tjDecodingHandle); + __tjDecodingHandle = null; + } if ( __tjTransformHandle ) + { tjDestroy(__tjTransformHandle); + __tjTransformHandle = null; + } return r; } diff --git a/src/inc/FMedia_ColorConverter.h b/src/inc/FMedia_ColorConverter.h index 71e8ae7..56acb8c 100644 --- a/src/inc/FMedia_ColorConverter.h +++ b/src/inc/FMedia_ColorConverter.h @@ -26,6 +26,7 @@ #define _FMEDIA_INTERNAL_COLORCONVERTER_H_ #include +#include namespace Tizen { namespace Media { @@ -49,7 +50,8 @@ public: * @exception E_SYSTEM A system error has occurred. */ result Construct(MediaPixelFormat srcFormat, int srcWidth, int srcHeight, - MediaPixelFormat dstFormat, int dstWidth, int dstHeight); + MediaPixelFormat dstFormat, int dstWidth, int dstHeight, + ImageScalingMethod scalingMethod = IMAGE_SCALING_METHOD_FAST_BILINEAR); public: /** diff --git a/src/inc/FMedia_ExifUtil.h b/src/inc/FMedia_ExifUtil.h new file mode 100644 index 0000000..4074714 --- /dev/null +++ b/src/inc/FMedia_ExifUtil.h @@ -0,0 +1,72 @@ +// +// Open Service Platform +// Copyright (c) 2012 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef __FMEDIA_INTERNAL_EXIF_UTIL_H__ +#define __FMEDIA_INTERNAL_EXIF_UTIL_H__ + +#include + +#define _EXIF_UTIL_LOG_ 1 + +namespace Tizen { namespace Media +{ + +_OSP_EXPORT_ extern const wchar_t* const EXIF_TAG_IMAGE_ORIENTATION; +_OSP_EXPORT_ extern const wchar_t* const EXIF_TAG_IMAGE_GPS_ALTITUDE; +_OSP_EXPORT_ extern const wchar_t* const EXIF_TAG_IMAGE_GPS_LONGITUDE; +_OSP_EXPORT_ extern const wchar_t* const EXIF_TAG_IMAGE_GPS_LATITUDE; + +class _OSP_EXPORT_ _ExifUtil + : public Tizen::Base::Object +{ +public: + _ExifUtil(); + ~_ExifUtil(); + + result Construct(const byte *buf, int length); + result GetValue(const Tizen::Base::String& key, int &value); + result GetValue(const Tizen::Base::String& key, double &value); + +protected: + void ForEachEntry(struct _ExifEntry *pEntry); + static void ForEachEntryStatic(struct _ExifEntry *pEntry, void *pUserData); + + void ForEachContent(struct _ExifContent *pContent); + static void ForEachContentStatic(struct _ExifContent *pContent, void *pUserData); + +#if defined _EXIF_UTIL_LOG_ +// static void ExifLogFuncStatic(ExifLog *log, ExifLogCode code, const char *domain, const char *format, va_list args, void *data); +// void ExifLogFunc(ExifLog *log, ExifLogCode code, const char *domain, const char *format, va_list args); +#endif + +private: + struct _ExifData*__pExifData; + struct _ExifLog*__pExifLog; + + short __orientation; + double __gpsLongitude; + double __gpsLatitude; + float __gpsAltitude; + + bool __gpsLongitudeExist; + bool __gpsAltitudeExist; + bool __gpsLatitudeExist; + bool __orientationExist; +}; + +}} + +#endif diff --git a/src/inc/FMedia_Ffmpeg.h b/src/inc/FMedia_Ffmpeg.h index 363c3bd..d6fa52a 100644 --- a/src/inc/FMedia_Ffmpeg.h +++ b/src/inc/FMedia_Ffmpeg.h @@ -44,5 +44,46 @@ extern "C" { #include }; +#include + +namespace Tizen { namespace Media +{ + +struct _FfmpegDeleter +{ + void operator() (AVCodecContext* pCodecCtxt) const + { + if (pCodecCtxt != null) + { + avcodec_close(pCodecCtxt); + av_free(pCodecCtxt); + pCodecCtxt = null; + } + } + + void operator() (AVFrame* pFrame) const + { + if (pFrame != null) + { + av_free(pFrame); + pFrame = null; + } + } + + void operator() (AVPacket* pPacket) const + { + if (pPacket != null) + { + av_free_packet(pPacket); + delete pPacket; + pPacket = null; + } + } +}; + +_OSP_EXPORT_ extern struct _FfmpegDeleter ffmpegDeleter; + +}} // Tizen::Media + #endif diff --git a/src/inc/FMedia_ImageDecoder.h b/src/inc/FMedia_ImageDecoder.h index 0d6401e..a9cff01 100644 --- a/src/inc/FMedia_ImageDecoder.h +++ b/src/inc/FMedia_ImageDecoder.h @@ -70,7 +70,7 @@ public: */ static Tizen::Base::ByteBuffer* DecodeToBufferN(const Tizen::Base::String& filePath, MediaPixelFormat pixelFormat, - int &width, int &height); + int &width, int &height, bool autoRotate = false); /** * Decodes a region of image data into the decoded byte buffer container without resizing. @n @@ -159,7 +159,8 @@ public: */ result Construct(const Tizen::Base::String& srcPath, MediaPixelFormat pixelFormat = MEDIA_PIXEL_FORMAT_BGRA8888, - ImageFormat imgFormat = IMG_FORMAT_NONE); + ImageFormat imgFormat = IMG_FORMAT_NONE, + bool autoRotate = false); /** * Initializes this instance of ImageDecode. @@ -183,7 +184,7 @@ public: * @exception E_SUCCESS The method is successful. * @remark */ - byte* DecodeN(int& outLength); + byte* DecodeN(int& outLength, ImageScalingMethod scalingMethod = IMAGE_SCALING_METHOD_FAST_BILINEAR); /** * Decodes image buffer. @@ -266,6 +267,8 @@ private: int width; int height; } __outDim; + bool __autoRotate; + int __orientationInfo; MediaPixelFormat __pixelFormat; std::unique_ptr __pSrcBuf; diff --git a/src/inc/FMedia_ImageUtil.h b/src/inc/FMedia_ImageUtil.h index f4bf486..e9bd8a8 100644 --- a/src/inc/FMedia_ImageUtil.h +++ b/src/inc/FMedia_ImageUtil.h @@ -135,6 +135,26 @@ public: static int ToFfmpegPixelFormat(MediaPixelFormat pixelFmt); static MediaPixelFormat ToMediaPixelFormatFromFfmpeg(int pixelFormat); + + static byte* CropN(const byte *srcBuf, + MediaPixelFormat pixelFormat, + int srcWidth, int srcHeight, + int dstX, int dstY, int dstWidth, int dstHeight); + + static byte* RotateN(const byte *srcBuf, + MediaPixelFormat pixelFormat, + int srcWidth, int srcHeight, + ImageRotationType rotate, + int &dstWidth, int &dstHeight); + + static byte* FlipN(const byte* srcBuf, + MediaPixelFormat pixelFormat, int width, int height, + ImageFlipType flip); + + static result GetResizedDimension(int srcWidth, int srcHeight, + float dstWidth, float dstHeight, + float &outWidth, float &outHeight); + private: _ImageUtil(); -- 2.7.4