Add new internal API to enable extra video convert element 49/309349/1 accepted/tizen/unified/20240412.141439 accepted/tizen/unified/x/20240415.014042
authorJeongmo Yang <jm80.yang@samsung.com>
Wed, 13 Mar 2024 06:15:50 +0000 (15:15 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Tue, 9 Apr 2024 05:48:13 +0000 (14:48 +0900)
[Version] 0.6.44
[Issue Type] New feature

Change-Id: If3f76f120d6c709892bf217fddfff7d59da7080f
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
CMakeLists.txt
include/media_codec_internal.h
include/media_codec_port.h
include/media_codec_port_gst.h
packaging/capi-media-codec.spec
src/media_codec_internal.c
src/media_codec_port.c
src/media_codec_port_gst.c

index 3734ece..c42c0b9 100644 (file)
@@ -53,8 +53,8 @@ INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR})
 INSTALL(
         DIRECTORY ${INC_DIR}/ DESTINATION include/media
         FILES_MATCHING
-        PATTERN "media_codec_*.h" EXCLUDE
-        PATTERN "${INC_DIR}/*.h"
+        PATTERN "${INC_DIR}/media_codec.h"
+        PATTERN "${INC_DIR}/media_codec_internal.h"
         )
 
 SET(PC_NAME ${fw_name})
index 87eac43..aa96597 100644 (file)
@@ -45,6 +45,8 @@ extern "C" {
  */
 int mediacodec_foreach_supported_codec_static(mediacodec_supported_codec_cb callback, void *user_data);
 
+int mediacodec_enable_extra_video_converter(mediacodec_h mediacodec, gboolean enable, const char *converter_name, int crop_x, int crop_y, int crop_w, int crop_h);
+
 /**
  * @}
  */
index d13531c..fede8d2 100644 (file)
@@ -179,6 +179,15 @@ typedef struct mc_video_port_definition_t {
        gint framerate;
 } mc_video_port_definition_t;
 
+typedef struct mc_extra_converter_t {
+       gboolean enable;
+       gchar *name;
+       gint crop_x;
+       gint crop_y;
+       gint crop_w;
+       gint crop_h;
+} mc_extra_converter_t;
+
 /* Codec Private data */
 struct _mc_handle_t {
        int state;                                  /**<  mc current state */
@@ -209,6 +218,8 @@ struct _mc_handle_t {
        int num_supported_encoder;
 
        mc_ini_t *ini;
+
+       mc_extra_converter_t extra_converter;
 };
 
 /*===========================================================================================
@@ -260,6 +271,8 @@ int mc_unset_eos_cb(MMHandleType mediacodec);
 int mc_set_buffer_status_cb(MMHandleType mediacodec, mediacodec_buffer_status_cb callback, void* user_data);
 int mc_unset_buffer_status_cb(MMHandleType mediacodec);
 
+int mc_enable_extra_video_converter(MMHandleType mediacodec, gboolean enable, const char *converter_name, int crop_x, int crop_y, int crop_w, int crop_h);
+
 int _mediacodec_foreach_supported_codec(mediacodec_supported_codec_cb callback, void* user_data);
 
 void _mc_create_codec_map_from_ini(mc_handle_t *mc_handle, mc_codec_spec_t *spec_emul);
index 3f63bc2..c095ada 100644 (file)
@@ -148,6 +148,8 @@ struct _mc_gst_core_t {
        void* user_data[_MEDIACODEC_EVENT_TYPE_NUM];
 
        GstVideoInfo *video_info;
+
+       mc_extra_converter_t *extra_converter;
 };
 
 struct _GstMCBuffer {
@@ -170,6 +172,8 @@ mc_ret_e mc_gst_flush_buffers(mc_handle_t *mc_handle);
 
 mc_ret_e mc_gst_get_packet_pool(mc_handle_t *mc_handle, media_packet_pool_h *packet_pool);
 
+mc_ret_e mc_gst_set_property_array_int(GstElement *element, const gchar *property_name, gint *array, guint array_length);
+
 #ifdef __cplusplus
 }
 #endif
index c41bb7b..bed5b52 100644 (file)
@@ -4,7 +4,7 @@
 
 Name:       capi-media-codec
 Summary:    A Media Codec library in Tizen Native API
-Version:    0.6.43
+Version:    0.6.44
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index bdf24a5..66af04d 100644 (file)
@@ -1,6 +1,7 @@
 #include <dlog.h>
 #include <media_codec.h>
 #include <media_codec_port.h>
+#include <media_codec_port_gst.h>
 #include <media_codec_ini.h>
 #include <media_codec_spec_emul.h>
 #include <media_codec_internal.h>
@@ -108,3 +109,17 @@ int mediacodec_foreach_supported_codec_static(mediacodec_supported_codec_cb call
 ERROR:
        return MEDIACODEC_ERROR_INVALID_PARAMETER;
 }
+
+int mediacodec_enable_extra_video_converter(mediacodec_h mediacodec, gboolean enable, const char *converter_name, int crop_x, int crop_y, int crop_w, int crop_h)
+{
+       MEDIACODEC_INSTANCE_CHECK(mediacodec);
+       mediacodec_s *handle = (mediacodec_s *)mediacodec;
+       MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
+
+       int ret = mc_enable_extra_video_converter(handle->mc_handle, enable, converter_name, crop_x, crop_y, crop_w, crop_h);
+
+       if (ret != MEDIACODEC_ERROR_NONE)
+               return __convert_error_code_internal(ret, (char *)__FUNCTION__);
+       else
+               return MEDIACODEC_ERROR_NONE;
+}
index 34c0d7f..b736853 100644 (file)
@@ -107,12 +107,13 @@ int mc_destroy(MMHandleType mediacodec)
 
        mc_handle->is_prepared = false;
 
-       /* free mediacodec structure */
-       if (mc_handle) {
-               g_free((void *)mc_handle);
-               mc_handle = NULL;
+       if (mc_handle->extra_converter.name) {
+               g_free(mc_handle->extra_converter.name);
+               mc_handle->extra_converter.name = NULL;
        }
 
+       g_free((void *)mc_handle);
+
        return ret;
 }
 
@@ -793,6 +794,43 @@ int mc_unset_buffer_status_cb(MMHandleType mediacodec)
        return MC_ERROR_NONE;
 }
 
+int mc_enable_extra_video_converter(MMHandleType mediacodec, gboolean enable, const char *converter_name, int crop_x, int crop_y, int crop_w, int crop_h)
+{
+       mc_handle_t *mc_handle = (mc_handle_t *) mediacodec;
+
+       if (!mc_handle) {
+               LOGE("fail invaild param\n");
+               return MC_INVALID_ARG;
+       }
+
+       if (enable && !converter_name) {
+               LOGE("It's enabled, but converter name is NULL");
+               return MC_INVALID_ARG;
+       }
+
+       LOGI("enable: %d", enable);
+       mc_handle->extra_converter.enable = enable;
+
+       if (enable) {
+               if (mc_handle->extra_converter.name) {
+                       LOGI("free converter name old[%s]", mc_handle->extra_converter.name);
+                       g_free(mc_handle->extra_converter.name);
+                       mc_handle->extra_converter.name = NULL;
+               }
+
+               LOGI("element name: %s", converter_name);
+               mc_handle->extra_converter.name = g_strdup(converter_name);
+
+               LOGI("crop[%d,%d,%dx%d]", crop_x, crop_y, crop_w, crop_h);
+               mc_handle->extra_converter.crop_x = crop_x;
+               mc_handle->extra_converter.crop_y = crop_y;
+               mc_handle->extra_converter.crop_w = crop_w;
+               mc_handle->extra_converter.crop_h = crop_h;
+       }
+
+       return MC_ERROR_NONE;
+}
+
 int _mediacodec_foreach_supported_codec(mediacodec_supported_codec_cb callback, void *user_data)
 {
        int i;
index 74fd638..e2954ec 100644 (file)
@@ -185,6 +185,7 @@ static int(*adec_wma_vtable[])() = {&__mc_fill_input_buffer_with_packet,
 static int(*aenc_opus_vtable[])() =  {&__mc_fill_input_buffer_with_packet,                  /* Opus Encoder Vtable */
                                                        &__mc_fill_aenc_packet_with_output_buffer};
 
+#define MEDIACODEC_CROP_ARRAY_LENGTH 4
 #define MEDIACODEC_ELEMENT_SET_STATE(x_element, x_state)                                          \
        do {                                                                                            \
                LOGD("setting state [%s:%d] to [%s]\n", #x_state, x_state, GST_ELEMENT_NAME(x_element)); \
@@ -1147,6 +1148,8 @@ static gboolean _mc_gst_video_info_check_and_new(mc_gst_core_t *core, GstMCBuffe
 {
        int i = 0;
        gchar *caps_str = NULL;
+       tbm_surface_h surface = NULL;
+       tbm_surface_info_s sinfo = {0, };
 
        if (!core || !mcbuffer) {
                LOGE("NULL core[%p] or mcbuffer[%p]", core, mcbuffer);
@@ -1166,9 +1169,19 @@ static gboolean _mc_gst_video_info_check_and_new(mc_gst_core_t *core, GstMCBuffe
                        return FALSE;
                }
 
-               for (i = 0 ; i < GST_VIDEO_INFO_N_PLANES(core->video_info) ; i++) {
-                       GST_VIDEO_INFO_PLANE_OFFSET(core->video_info, i) = 0;
-                       media_packet_get_video_stride_width(mcbuffer->packet, i, &GST_VIDEO_INFO_PLANE_STRIDE(core->video_info, i));
+               if (media_packet_get_tbm_surface(mcbuffer->packet, &surface) != MEDIA_PACKET_ERROR_NONE) {
+                       LOGE("get surface failed");
+                       return FALSE;
+               }
+
+               if (tbm_surface_get_info(surface, &sinfo) != TBM_SURFACE_ERROR_NONE) {
+                       LOGE("get surface info failed");
+                       return FALSE;
+               }
+
+               for (i = 0 ; i < sinfo.num_planes ; i++) {
+                       GST_VIDEO_INFO_PLANE_OFFSET(core->video_info, i) = sinfo.planes[i].offset;
+                       GST_VIDEO_INFO_PLANE_STRIDE(core->video_info, i) = sinfo.planes[i].stride;
 
                        LOGI("[%d] offset[%zu], stride[%d]", i,
                                GST_VIDEO_INFO_PLANE_OFFSET(core->video_info, i),
@@ -1877,6 +1890,7 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle)
        new_core->codec_id = id;
        new_core->codec_type = &codec_map[i].type;
        new_core->mc_caps_new = video ? &_mc_gst_vid_caps_new : &_mc_gst_aud_caps_new;
+       new_core->extra_converter = &mc_handle->extra_converter;
 
        new_core->bufmgr = tbm_bufmgr_init(new_core->drm_fd);
        if (new_core->bufmgr == NULL) {
@@ -2202,6 +2216,97 @@ ERROR:
        return FALSE;
 }
 
+static GstElement *__mc_gst_extra_converter_new(mc_extra_converter_t *extra_converter)
+{
+       GstElement *element = NULL;
+       gint array[MEDIACODEC_CROP_ARRAY_LENGTH] = {0, };
+
+       if (!extra_converter) {
+               LOGE("NULL extra converter");
+               return NULL;
+       }
+
+       LOGI("extra converter[%s]", extra_converter->name);
+
+       element = gst_element_factory_make(extra_converter->name, NULL);
+       if (!element) {
+               LOGE("create element[%s] failed", extra_converter->name);
+               return NULL;
+       }
+
+       array[0] = extra_converter->crop_x;
+       array[1] = extra_converter->crop_y;
+       array[2] = extra_converter->crop_w;
+       array[3] = extra_converter->crop_h;
+
+       if (mc_gst_set_property_array_int(element,
+               "crop", array, MEDIACODEC_CROP_ARRAY_LENGTH) != MC_ERROR_NONE) {
+               gst_object_unref(element);
+               return NULL;
+       }
+
+       LOGI("set crop to extra converter[%d,%d,%dx%d]",
+               array[0], array[1], array[2], array[3] );
+
+       return element;
+}
+
+
+#ifdef TIZEN_FEATURE_ENABLE_DUMP_SOURCE
+static GstPadProbeReturn __dump_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
+{
+       static int count = 0;
+       int i = 0;
+       const gchar *dump_path = (const gchar *)u_data;
+       GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
+       GstMemory *memory = NULL;
+       FILE *fp = NULL;
+       tbm_surface_h surface = NULL;
+       tbm_surface_info_s sinfo = {0, };
+
+       if (!dump_path) {
+               LOGW("NULL path");
+               return GST_PAD_PROBE_OK;
+       }
+
+       if (count++ > 10) {
+               LOGW("[%s] SKIP DUMP", dump_path);
+               return GST_PAD_PROBE_OK;
+       }
+
+       memory = gst_buffer_peek_memory(buffer, 0);
+
+       if (!gst_is_tizen_memory(memory)) {
+               LOGW("Not tizen memory");
+               return GST_PAD_PROBE_OK;
+       }
+
+       surface = gst_tizen_memory_get_surface(memory);
+       if (!surface) {
+               LOGW("No surface");
+               return GST_PAD_PROBE_OK;
+       }
+
+       fp = fopen(dump_path, "a");
+       if (!fp) {
+               LOGW("file open failed[%s]", dump_path);
+               return GST_PAD_PROBE_OK;
+       }
+
+       tbm_surface_get_info(surface, &sinfo);
+
+       for (i = 0 ; i < sinfo.num_planes ; i++) {
+               LOGI("[dump:%s] write plane[%d] size[%u]", dump_path, i, sinfo.planes[i].size);
+               fwrite(sinfo.planes[i].ptr, 1, sinfo.planes[i].size, fp);
+       }
+
+       fclose(fp);
+
+       return GST_PAD_PROBE_OK;
+}
+#endif /* TIZEN_FEATURE_ENABLE_DUMP_SOURCE */
+
+
 mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name)
 {
        int i = 0;
@@ -2243,31 +2348,22 @@ mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name)
 
                if (!core->video && core->encoder) {
                        core->audioconvert = gst_element_factory_make("audioconvert", NULL);
-
                        if (!core->audioconvert) {
                                LOGE("audioconvert can't create");
                                goto ERROR;
                        }
 
                        core->audioresample = gst_element_factory_make("audioresample", NULL);
-
                        if (!core->audioresample) {
                                LOGE("audioresample can't create");
                                goto ERROR;
                        }
                }
 
-               if (core->video && core->encoder) {
-                       core->videoconvert = gst_element_factory_make("videoconvert", NULL);
-
+               if (core->video && core->encoder && core->extra_converter->enable) {
+                       core->videoconvert = __mc_gst_extra_converter_new(core->extra_converter);
                        if (!core->videoconvert) {
-                               LOGE("videoconvert can't create");
-                               goto ERROR;
-                       }
-
-                       core->videoscale = gst_element_factory_make("videoscale", NULL);
-                       if (!core->videoscale) {
-                               LOGE("videoscale can't create");
+                               LOGE("create[%s] failed", core->extra_converter->name);
                                goto ERROR;
                        }
                }
@@ -2296,12 +2392,22 @@ mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name)
                                goto ERROR;
                        }
                } else if (core->video && core->encoder) {
-                       gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL);
+                       if (core->extra_converter->enable) {
+                               gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->videoconvert, core->codec, core->fakesink, NULL);
 
-                       /* link elements */
-                       if (!(gst_element_link_many(core->appsrc, core->codec, core->fakesink, NULL))) {
-                               LOGE("gst_element_link_many is failed");
-                               goto ERROR;
+                               /* link elements */
+                               if (!(gst_element_link_many(core->appsrc, core->videoconvert, core->codec, core->fakesink, NULL))) {
+                                       LOGE("gst_element_link_many is failed");
+                                       goto ERROR;
+                               }
+                       } else {
+                               gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL);
+
+                               /* link elements */
+                               if (!(gst_element_link_many(core->appsrc, core->codec, core->fakesink, NULL))) {
+                                       LOGE("gst_element_link_many is failed");
+                                       goto ERROR;
+                               }
                        }
                } else {
                        gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL);
@@ -2313,6 +2419,26 @@ mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name)
                        }
                }
 
+#ifdef TIZEN_FEATURE_ENABLE_DUMP_SOURCE
+               {
+                       GstPad *pad = NULL;
+
+                       pad = gst_element_get_static_pad(core->videoconvert, "sink");
+                       if (pad) {
+                               gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, __dump_probe, "/tmp/input.dump", NULL);
+                               gst_object_unref(pad);
+                               pad = NULL;
+                       }
+
+                       pad = gst_element_get_static_pad(core->videoconvert, "src");
+                       if (pad) {
+                               gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, __dump_probe, "/tmp/output.dump", NULL);
+                               gst_object_unref(pad);
+                               pad = NULL;
+                       }
+               }
+#endif /* TIZEN_FEATURE_ENABLE_DUMP_SOURCE */
+
                /* connect signals, bus watcher */
                bus = gst_pipeline_get_bus(GST_PIPELINE(core->pipeline));
                core->bus_watch_id = gst_bus_add_watch(bus, __mc_gst_bus_callback, core);
@@ -3653,3 +3779,36 @@ mc_ret_e mc_gst_get_packet_pool(mc_handle_t *mc_handle, media_packet_pool_h *pac
        *packet_pool = pool;
        return MC_ERROR_NONE;
 }
+
+mc_ret_e mc_gst_set_property_array_int(GstElement *element, const gchar *property_name, gint *array, guint array_length)
+{
+       guint i = 0;
+       GValue value = G_VALUE_INIT;
+       GValue tmp = G_VALUE_INIT;
+
+       if (!element || !property_name || !array) {
+               LOGE("NULL param[%p,%p,%p]", element, property_name, array);
+               return MC_PARAM_ERROR;
+       }
+
+       g_value_init(&value, GST_TYPE_ARRAY);
+       g_value_init(&tmp, G_TYPE_INT);
+
+       LOGI("set element[%s], property[%s], array_length[%d]",
+               GST_ELEMENT_NAME(element), property_name, array_length);
+
+       gst_value_array_init(&value, array_length);
+
+       for (i = 0 ; i < array_length ; i++) {
+               LOGI("    array[%u] %d", i, array[i]);
+               g_value_set_int(&tmp, array[i]);
+               gst_value_array_append_value(&value, &tmp);
+       }
+
+       g_object_set_property(G_OBJECT(element), property_name, &value);
+
+       g_value_unset(&tmp);
+       g_value_unset(&value);
+
+       return MC_ERROR_NONE;
+}