[ACR-1815] Add image_util_create_image_from_media_packet() 22/304322/4 accepted/tizen/unified/20240129.163411 accepted/tizen/unified/toolchain/20240311.065112 accepted/tizen/unified/x/20240205.063949
authorJiyong <jiyong.min@samsung.com>
Fri, 8 Dec 2023 08:19:30 +0000 (17:19 +0900)
committerJiyong <jiyong.min@samsung.com>
Wed, 24 Jan 2024 06:50:02 +0000 (15:50 +0900)
Change-Id: I4439958c2f4d79bc3ab309de35abcf97477f7577

include/image_util.h
packaging/capi-media-image-util.spec
src/image_util.c
src/image_util_private.c

index d55c4a3..b7f6f4c 100644 (file)
@@ -466,6 +466,28 @@ int image_util_transform_destroy(transformation_h handle);
 int image_util_create_image(unsigned int width, unsigned int height, image_util_colorspace_e colorspace, const unsigned char *data, size_t data_size, image_util_image_h *image);
 
 /**
+* @brief Creates an image handle from media packet.
+* @since_tizen 7.0
+*
+* @remarks The @a image should be released using image_util_destroy_image().
+*
+* @param[in] media_packet              The media_packet
+* @param[out] image            A handle of image
+*
+* @return @c 0 on success,
+*               otherwise a negative error value
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_OUT_OF_MEMORY Out of memory
+*
+* @see image_util_destroy_image()
+* @see image_util_get_image()
+* @see image_util_clone_image()
+*/
+int image_util_create_image_from_media_packet(media_packet_h media_packet, image_util_image_h *image);
+
+/**
 * @brief Clones an image handle.
 * @since_tizen 5.5
 *
index 50b25f2..36e0821 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-image-util
 Summary:    A Image Utility library in Tizen Native API
-Version:    0.4.3
+Version:    0.4.4
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 0ea1c4c..2eca6bc 100644 (file)
@@ -465,6 +465,11 @@ int image_util_create_image(unsigned int width, unsigned int height, image_util_
        return _image_error_capi(ret);
 }
 
+int image_util_create_image_from_media_packet(media_packet_h media_packet, image_util_image_h *image)
+{
+       return _image_util_packet_to_image(media_packet, image);
+}
+
 int image_util_clone_image(image_util_image_h src, image_util_image_h *dst)
 {
        int ret = IMAGE_UTIL_ERROR_NONE;
index 53171a5..21c93f3 100644 (file)
@@ -494,6 +494,238 @@ ERROR:
        return IMAGE_UTIL_ERROR_INVALID_OPERATION;
 }
 
+static int __get_video_info_from_packet(media_packet_h packet, int *width, int *height, mm_util_color_format_e *color_format, uint32_t *plane_num)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+       media_format_h fmt = NULL;
+       media_format_mimetype_e mimetype = 0;
+
+       ret = media_packet_get_format(packet, &fmt);
+       image_util_retvm_if((ret != MEDIA_PACKET_ERROR_NONE), IMAGE_UTIL_ERROR_INVALID_PARAMETER,
+                       "media_packet_get_format failed (%d)", ret);
+
+       ret = media_format_get_video_info(fmt, &mimetype, width, height, NULL, NULL);
+       media_format_unref(fmt);
+       if (ret != MEDIA_FORMAT_ERROR_NONE) {
+               image_util_error("media_packet_get_format failed (%d)", ret);
+               return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
+       }
+
+       ret = media_packet_get_number_of_video_planes(packet, plane_num);
+       if (ret != MEDIA_PACKET_ERROR_NONE) {
+               image_util_error("media_packet_get_number_of_video_plances failed (%d)", ret);
+               return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
+       }
+
+       *color_format = __mimetype_to_image_format(mimetype);
+
+       image_util_debug("width: %d, hiehgt: %d, color_format: %d, plane_num: %u", *width, *height, *color_format, *plane_num);
+
+       return IMAGE_UTIL_ERROR_NONE;
+}
+
+static int __get_video_plane_from_packet(media_packet_h packet, int plane_index, int *stride_width, int *stride_height, void **data_ptr)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+
+       if (stride_width) {
+               ret = media_packet_get_video_stride_width(packet, plane_index, stride_width);
+               if (ret != MEDIA_PACKET_ERROR_NONE) {
+                       image_util_error("media_packet_get_video_stride_width failed (%d)", ret);
+                       return ret;
+               }
+       }
+
+       if (stride_height) {
+               ret = media_packet_get_video_stride_height(packet, plane_index, stride_height);
+               if (ret != MEDIA_PACKET_ERROR_NONE) {
+                       image_util_error("media_packet_get_video_stride_height failed (%d)", ret);
+                       return ret;
+               }
+       }
+
+       if (data_ptr) {
+               ret = media_packet_get_video_plane_data_ptr(packet, plane_index, data_ptr);
+               if (ret != MEDIA_PACKET_ERROR_NONE) {
+                       image_util_error("media_packet_get_video_plane_data_ptr failed (%d)", ret);
+                       return ret;
+               }
+       }
+
+       image_util_debug("stride_width: %d, stride_height: %d, data_ptr: %p",
+               stride_width ? *stride_width : 0, stride_height ? *stride_height : 0,
+               data_ptr ? *data_ptr : NULL);
+
+       return MEDIA_PACKET_ERROR_NONE;
+}
+
+static int __get_video_data_from_420p(media_packet_h packet, uint32_t plane_num, int width, int height, void **data, size_t *size)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+       int i = 0;
+       int stride_width = 0;
+       int uv_width = width / 2, uv_height = height / 2;
+       void *src_ptr = NULL;
+       size_t dst_size = (width * height * 3) >> 1;
+       void *dst_data = NULL;
+       void *dst_ptr = NULL;
+
+       image_util_retvm_if(plane_num != 3, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid plane_num");
+       image_util_retvm_if(width <= 0, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid width");
+       image_util_retvm_if(height <= 0, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid height");
+       image_util_retvm_if(!data, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid data");
+       image_util_retvm_if(size == 0, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid size");
+
+       image_util_debug("width: %d, height: %d, size: %zu", width, height, dst_size);
+
+       dst_data = g_malloc0(dst_size);
+       dst_ptr = dst_data;
+
+       // y data
+       ret = __get_video_plane_from_packet(packet, 0, &stride_width, NULL, &src_ptr);
+       if (ret != MEDIA_PACKET_ERROR_NONE) {
+               image_util_error("__get_videodst_data_from_packet failed (%d)", ret);
+               goto ERROR;
+       }
+
+       for (i = 0; i < height; i++) {
+               memcpy(dst_ptr, src_ptr, width);
+               dst_ptr += width;
+               src_ptr += stride_width;
+       }
+
+       // u data
+       ret = __get_video_plane_from_packet(packet, 1, &stride_width, NULL, &src_ptr);
+       if (ret != MEDIA_PACKET_ERROR_NONE) {
+               image_util_error("__get_videodst_data_from_packet failed (%d)", ret);
+               goto ERROR;
+       }
+
+       for (i = 0; i < uv_height; i++) {
+               memcpy(dst_ptr, src_ptr, uv_width);
+               dst_ptr += uv_width;
+               src_ptr += stride_width;
+       }
+
+       // v data
+       ret = __get_video_plane_from_packet(packet, 2, &stride_width, NULL, &src_ptr);
+       if (ret != MEDIA_PACKET_ERROR_NONE) {
+               image_util_error("__get_videodst_data_from_packet failed (%d)", ret);
+               goto ERROR;
+       }
+
+       for (i = 0; i < uv_height; i++) {
+               memcpy(dst_ptr, src_ptr, uv_width);
+               dst_ptr += uv_width;
+               src_ptr += stride_width;
+       }
+
+       *data = dst_data;
+       *size = dst_size;
+
+       return IMAGE_UTIL_ERROR_NONE;
+
+ERROR:
+       g_free(dst_data);
+       return IMAGE_UTIL_ERROR_INVALID_OPERATION;
+}
+
+static int __get_video_data_from_420sp(media_packet_h packet, uint32_t plane_num, int width, int height, void **data, size_t *size)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+       int i = 0;
+       int stride_width = 0;
+       int uv_height = height / 2;
+       void *src_ptr = NULL;
+       size_t dst_size = (width * height * 3) >> 1;
+       void *dst_data = NULL;
+       void *dst_ptr = NULL;
+
+       image_util_retvm_if(plane_num != 2, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid plane_num");
+       image_util_retvm_if(width <= 0, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid width");
+       image_util_retvm_if(height <= 0, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid height");
+       image_util_retvm_if(!data, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid data");
+       image_util_retvm_if(size == 0, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid size");
+
+       image_util_debug("width: %d, height: %d, size: %zu", width, height, dst_size);
+
+       dst_data = g_malloc0(dst_size);
+       dst_ptr = dst_data;
+
+       // y data
+       ret = __get_video_plane_from_packet(packet, 0, &stride_width, NULL, &src_ptr);
+       if (ret != MEDIA_PACKET_ERROR_NONE) {
+               image_util_error("__get_video_data_from_packet failed (%d)", ret);
+               goto ERROR;
+       }
+
+       for (i = 0; i < height; i++) {
+               memcpy(dst_ptr, src_ptr, width);
+               dst_ptr += width;
+               src_ptr += stride_width;
+       }
+
+       // uv data
+       ret = __get_video_plane_from_packet(packet, 1, &stride_width, NULL, &src_ptr);
+       if (ret != MEDIA_PACKET_ERROR_NONE) {
+               image_util_error("__get_video_data_from_packet failed (%d)", ret);
+               goto ERROR;
+       }
+
+       for (i = 0; i < uv_height; i++) {
+               memcpy(dst_ptr, src_ptr, width);
+               dst_ptr += width;
+               src_ptr += stride_width;
+       }
+
+       *data = dst_data;
+       *size = dst_size;
+
+       return IMAGE_UTIL_ERROR_NONE;
+
+ERROR:
+       g_free(dst_data);
+       return IMAGE_UTIL_ERROR_INVALID_OPERATION;
+}
+
+static int __get_video_data_from_packet(media_packet_h packet, uint32_t plane_num, void **data, size_t *size)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+       unsigned int i = 0;
+       int stride_width = 0, stride_height = 0;
+       void *src_ptr = NULL;
+       size_t src_size = 0;
+       size_t dst_size = 0;
+       void *dst_data = NULL;
+
+       image_util_retvm_if(plane_num == 0, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid plane_num");
+       image_util_retvm_if(!data, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid data");
+       image_util_retvm_if(size == 0, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid size");
+
+       for (i = 0; i < plane_num; i++) {
+               ret = __get_video_plane_from_packet(packet, i, &stride_width, &stride_height, &src_ptr);
+               if (ret != MEDIA_PACKET_ERROR_NONE) {
+                       image_util_error("__get_video_data_from_packet failed (%d)", ret);
+                       goto ERROR;
+               }
+
+               src_size = (size_t)(stride_width) * stride_height;
+               dst_data = g_realloc(dst_data, dst_size + src_size);
+
+               memcpy(dst_data + dst_size, src_ptr, src_size);
+               dst_size += src_size;
+       }
+
+       *data = dst_data;
+       *size = dst_size;
+
+       return IMAGE_UTIL_ERROR_NONE;
+
+ERROR:
+       g_free(dst_data);
+       return IMAGE_UTIL_ERROR_INVALID_OPERATION;
+}
+
 int _image_util_image_to_packet(image_util_image_h image, media_packet_h *packet)
 {
        int ret = IMAGE_UTIL_ERROR_NONE;
@@ -535,15 +767,10 @@ int _image_util_image_to_packet(image_util_image_h image, media_packet_h *packet
 int _image_util_packet_to_image(media_packet_h packet, image_util_image_h *image)
 {
        int ret = IMAGE_UTIL_ERROR_NONE;
-       media_format_mimetype_e mimetype = 0;
        int width = 0, height = 0;
-       media_format_h fmt = NULL;
-       unsigned int i = 0;
+       mm_util_color_format_e color_format;
        uint32_t plane_num = 0;
-       int stride_width = 0, stride_height = 0;
-       void *plane_ptr = NULL;
-       size_t plane_size = 0;
-       void *ptr = NULL;
+       void *data = NULL;
        size_t size = 0;
 
        image_util_fenter();
@@ -551,68 +778,45 @@ int _image_util_packet_to_image(media_packet_h packet, image_util_image_h *image
        image_util_retvm_if(!packet, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid packet");
        image_util_retvm_if(!image, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid image");
 
-       ret = media_packet_get_format(packet, &fmt);
-       image_util_retvm_if((ret != MEDIA_PACKET_ERROR_NONE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "media_packet_get_format failed (%d)", ret);
-
-       ret = media_format_get_video_info(fmt, &mimetype, &width, &height, NULL, NULL);
-       if (ret != MEDIA_FORMAT_ERROR_NONE) {
-               image_util_error("media_packet_get_format failed (%d)", ret);
-               media_format_unref(fmt);
-               return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
+       ret = __get_video_info_from_packet(packet, &width, &height, &color_format, &plane_num);
+       if (ret != IMAGE_UTIL_ERROR_NONE) {
+               image_util_error("__get_video_info_from_packet failed (%d)", ret);
+               return ret;
        }
-       media_format_unref(fmt);
 
-       ret = media_packet_get_number_of_video_planes(packet, &plane_num);
-       if (ret != MEDIA_PACKET_ERROR_NONE) {
-               image_util_error("media_packet_get_number_of_video_plances failed (%d)", ret);
-               goto ERROR;
+       if (width <= 0 || height <= 0 || color_format == MM_UTIL_COLOR_NUM) {
+               image_util_error("invalid image width: %d height: %d color_format: %d", width, height, color_format);
+               return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
        }
 
-       image_util_debug("plane_num: %u", plane_num);
-
-       for (i = 0; i < plane_num; i++) {
-               ret = media_packet_get_video_stride_width(packet, i, &stride_width);
-               if (ret != MEDIA_PACKET_ERROR_NONE) {
-                       image_util_error("media_packet_get_video_stride_width failed (%d)", ret);
-                       goto ERROR;
+       if ((color_format == MM_UTIL_COLOR_YUV420 || color_format == MM_UTIL_COLOR_I420) && (plane_num == 3)) {
+               ret = __get_video_data_from_420p(packet, plane_num, width, height, &data, &size);
+               if (ret != IMAGE_UTIL_ERROR_NONE) {
+                       image_util_error("__get_video_data_from_i420 failed (%d)", ret);
+                       return ret;
                }
-
-               ret = media_packet_get_video_stride_height(packet, i, &stride_height);
-               if (ret != MEDIA_PACKET_ERROR_NONE) {
-                       image_util_error("media_packet_get_video_stride_height failed (%d)", ret);
-                       goto ERROR;
+       } else if ((color_format == MM_UTIL_COLOR_NV12) && (plane_num == 2)) {
+               ret = __get_video_data_from_420sp(packet, plane_num, width, height, &data, &size);
+               if (ret != IMAGE_UTIL_ERROR_NONE) {
+                       image_util_error("__get_video_data_from_nv12 failed (%d)", ret);
+                       return ret;
                }
-
-               plane_size = (size_t)(stride_width) * stride_height;
-
-               ret = media_packet_get_video_plane_data_ptr(packet, i, &plane_ptr);
-               if (ret != MEDIA_PACKET_ERROR_NONE) {
-                       image_util_error("media_packet_get_video_plane_data_ptr failed (%d)", ret);
-                       goto ERROR;
+       } else {
+               ret = __get_video_data_from_packet(packet, plane_num, &data, &size);
+               if (ret != IMAGE_UTIL_ERROR_NONE) {
+                       image_util_error("__get_video_data_from_packet failed (%d)", ret);
+                       return ret;
                }
-
-               image_util_debug("stride_width: %d, stride_height: %d, plane_ptr: %p, plane_size: %zu",
-                               stride_width, stride_height, plane_ptr,plane_size);
-
-               ptr = g_realloc(ptr, size + plane_size);
-
-               memcpy(ptr + size, plane_ptr, plane_size);
-               size += plane_size;
        }
 
-       image_util_debug("[Fotmat: %u] W x H : %d x %d buffer(size) : %p(%zu)", mimetype, width, height, ptr, size);
+       image_util_debug("w: %d h: %d format: %u buffer: %p size: %zu", width, height, color_format, data, size);
 
-       ret = mm_image_create_image(width, height, __mimetype_to_image_format(mimetype), ptr, size, image);
-       g_free(ptr);
-       image_util_retvm_if((ret != IMAGE_UTIL_ERROR_NONE), ret, "mm_image_create_image failed (%d)", ret);
+       ret = mm_image_create_image2((unsigned int)(width), (unsigned int)(height), color_format, data, size, image);
+       image_util_retvm_if((ret != IMAGE_UTIL_ERROR_NONE), ret, "mm_image_create_image2 failed (%d)", ret);
 
        image_util_fleave();
 
        return IMAGE_UTIL_ERROR_NONE;
-
-ERROR:
-       g_free(ptr);
-       return IMAGE_UTIL_ERROR_INVALID_OPERATION;
 }
 
 int _check_colorspace(image_util_type_e image_type, image_util_colorspace_e colorspace)