media_editor: Fix wrong fixed output resolution(HD) issue 22/289122/10 accepted/tizen_8.0_unified accepted/tizen_unified_dev tizen_8.0 accepted/tizen/8.0/unified/20231005.092736 accepted/tizen/unified/20230830.170534 accepted/tizen/unified/dev/20240620.004108 tizen_8.0_m2_release
authorHaesu Gwon <haesu.gwon@samsung.com>
Thu, 2 Mar 2023 01:14:13 +0000 (10:14 +0900)
committerHaesu Gwon <haesu.gwon@samsung.com>
Tue, 29 Aug 2023 06:54:36 +0000 (15:54 +0900)
- GES set default output resolution(1280x720) in latest version,
  so we need to set proper resolution.

[Version] 0.0.19
[Issue Type] Bug fix

Change-Id: I3e01b4ac8c897fcafaff2d85e1af4978cfbeee18

gtest/ut_clip.cpp
include/media_editor.h
include/media_editor_private.h
packaging/capi-media-editor.spec
src/media_editor_clip.c
src/media_editor_private.c

index 18f2889..aa3315e 100644 (file)
@@ -95,6 +95,20 @@ public:
     const unsigned int duration = 100;
 };
 
+TEST_F(MediaeditorClipTest, DISABLED_clip_add_to_end_time)
+{
+    int ret = mediaeditor_add_clip(GetHandle(), GetMp4Path(1).c_str(), layer_id, -1, 3000, 2000, &clip_id);
+    ASSERT_EQ(ret, MEDIAEDITOR_ERROR_NONE);
+
+    ret = mediaeditor_add_clip(GetHandle(), GetMp4Path(2).c_str(), layer_id, -1, 1000, 0, &clip_id);
+    ASSERT_EQ(ret, MEDIAEDITOR_ERROR_NONE);
+
+    ret = mediaeditor_start_render(GetHandle(), GetOutputPath().c_str(), RenderCompletedCb, GetHandle());
+    ASSERT_EQ(ret, MEDIAEDITOR_ERROR_NONE);
+
+    WaitForAsync();
+}
+
 TEST_F(MediaeditorClipTest, DISABLED_clip_add_move_remove)
 {
     int ret = mediaeditor_move_clip_layer(GetHandle(), clip_id, 0);
index 25e396e..ed772f0 100644 (file)
@@ -767,7 +767,7 @@ int mediaeditor_unset_layer_priority_changed_cb(mediaeditor_h editor);
  * @param[in] editor   The media editor handle
  * @param[in] path     The content location to add
  * @param[in] layer_id The layer ID to add clip
- * @param[in] start    The starting position of @a path clip which is placed in timeline (in milliseconds)\n
+ * @param[in] start    The start time of @a path clip which is placed in timeline (in milliseconds)\n
  *                     If this is less than 0, clip will be added to the end of layer. i.e. it will be set to layer's duration
  * @param[in] duration The duration that the clip is in effect for in the timeline (in milliseconds)\n
  *                     It should be lesser than or equal to clip's duration. If not, error will be occurred in runtime.\n
@@ -1146,7 +1146,7 @@ int mediaeditor_add_transition(mediaeditor_h editor, mediaeditor_transition_type
  * @param[in] editor     The media editor handle
  * @param[in] type       The effect type
  * @param[in] layer_id   The layer priority
- * @param[in] start      The starting position of effect which is placed in timeline (in milliseconds)
+ * @param[in] start      The start time of effect which is placed in timeline (in milliseconds)
  * @param[in] duration   The duration of effect (in milliseconds)
  * @param[out] effect_id The effect ID
  * @return @c 0 on success, otherwise a negative error value
index 4eae115..518ccd3 100644 (file)
@@ -144,6 +144,14 @@ do { \
     src = NULL; \
 } while (0)
 
+#define PRINT_CAPS(x_caps, x_prefix) \
+do { \
+       if (!(x_caps)) break; \
+       gchar *caps_str = gst_caps_to_string(x_caps); \
+       LOG_INFO("%s caps[%s]", x_prefix, caps_str); \
+       g_free(caps_str); \
+} while (0)
+
 #define GENERATE_DOT(x_mediaeditor, x_fmt, x_arg...) \
 do { \
     gchar *dot_name; \
@@ -282,6 +290,11 @@ typedef enum _idle_cb_type_e {
     IDLE_CB_TYPE_NUM
 } idle_cb_type_e;
 
+typedef enum _track_type_e {
+    TRACK_AUDIO,
+    TRACK_VIDEO
+} track_type_e;
+
 typedef struct _mediaeditor_s {
     GMutex mutex;
     GMutex event_src_mutex;
@@ -332,6 +345,7 @@ int _mediaeditor_start_preview(mediaeditor_s *editor);
 int _mediaeditor_stop_preview(mediaeditor_s *editor);
 int _check_privilege(const char *path, bool file_exist, int mode);
 int _check_feature(const char *feature);
+int _get_track(mediaeditor_s *editor, track_type_e track_type, GESTrack **track);
 
 #ifndef TIZEN_TV
 /* media_editor_resource */
index 02af3fe..39433e7 100644 (file)
@@ -1,7 +1,7 @@
 Name:       capi-media-editor
 Summary:    A Tizen Media Editor API
-Version:    0.0.18
-Release:    1
+Version:    0.0.19
+Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
 Source0:    %{name}-%{version}.tar.gz
index 810aa4c..0bdec13 100644 (file)
@@ -180,6 +180,81 @@ static GESGroup *__mediaeditor_find_group(GList *lists, unsigned int id)
     return group_data->group;
 }
 
+static int __init_track_resolution(GESTrack *track)
+{
+    GstCaps *caps = NULL;
+
+    caps = gst_caps_new_simple("video/x-raw",
+                               "width", G_TYPE_INT, 0,
+                               "height", G_TYPE_INT, 0,
+                               NULL);
+    RET_VAL_IF(caps == NULL, MEDIAEDITOR_ERROR_INVALID_OPERATION, "failed to create caps");
+
+    PRINT_CAPS(caps, "track_video");
+    ges_track_update_restriction_caps(track, caps);
+    gst_caps_unref(caps);
+
+    return MEDIAEDITOR_ERROR_NONE;
+}
+
+static int __update_track_resolution(mediaeditor_s *editor, int width, int height)
+{
+    GESTrack *video_track = NULL;
+    GstCaps *caps = NULL;
+    GstCaps *video_caps = NULL;
+    int track_width = 0;
+    int track_height = 0;
+
+    NULL_PARAM_CHECK(editor);
+
+    int ret = _get_track(editor, TRACK_VIDEO, &video_track);
+    RET_VAL_IF(ret != MEDIAEDITOR_ERROR_NONE, ret, "failed to get video track");
+
+    /* If first clip is added, we should initialize track resolution */
+    if (g_list_length(editor->clips) == 1)
+        __init_track_resolution(video_track);
+
+    caps = ges_track_get_restriction_caps(video_track);
+    RET_VAL_IF(caps == NULL, MEDIAEDITOR_ERROR_INVALID_OPERATION, "failed to get caps from video track");
+    PRINT_CAPS(caps, "video_track");
+
+    if (!gst_structure_get_int(gst_caps_get_structure(caps, 0), "width", &track_width) ||
+        !gst_structure_get_int(gst_caps_get_structure(caps, 0), "height", &track_height)) {
+        LOG_ERROR("no width/height information in video track or invalid type");
+        gst_caps_unref(caps);
+        return MEDIAEDITOR_ERROR_INVALID_OPERATION;
+    }
+    gst_caps_unref(caps);
+
+    if (track_width < width) {
+        video_caps = gst_caps_new_simple("video/x-raw",
+                                         "width", G_TYPE_INT, width,
+                                         NULL);
+        RET_VAL_IF(video_caps == NULL, MEDIAEDITOR_ERROR_INVALID_OPERATION, "failed to create video_caps");
+    }
+
+    if (track_height < height) {
+        if (video_caps == NULL) {
+            video_caps = gst_caps_new_simple("video/x-raw",
+                                             "height", G_TYPE_INT, height,
+                                             NULL);
+            RET_VAL_IF(video_caps == NULL, MEDIAEDITOR_ERROR_INVALID_OPERATION, "failed to create video_caps");
+        } else {
+            gst_caps_set_simple(video_caps, "height", G_TYPE_INT, height, NULL);
+        }
+    }
+
+    if (video_caps) {
+        PRINT_CAPS(video_caps, "track_video");
+        ges_track_update_restriction_caps(video_track, video_caps);
+    }
+
+    gst_caps_unref(video_caps);
+    gst_object_unref(video_track);
+
+    return MEDIAEDITOR_ERROR_NONE;
+}
+
 static bool __has_audio_track(GESClip *clip)
 {
     RET_VAL_IF(clip == NULL, false, "clip is NULL");
@@ -248,7 +323,7 @@ int _mediaeditor_add_clip(mediaeditor_s *editor, const char *path, unsigned int
         ret = _mediaeditor_get_layer_end_time(editor, layer_id, &end_time);
         RET_VAL_IF(ret != MEDIAEDITOR_ERROR_NONE, ret, "failed to get layer end time");
 
-        LOG_INFO("start point[%d] is changed to [%d]ms of layer_id[%d]", start, end_time, layer_id);
+        LOG_INFO("start time[%d] is changed to [%d]ms of layer_id[%d]", start, end_time, layer_id);
         start = end_time;
     }
 
@@ -285,6 +360,9 @@ int _mediaeditor_add_clip(mediaeditor_s *editor, const char *path, unsigned int
 
         ges_timeline_element_set_child_properties(GES_TIMELINE_ELEMENT(clip), "width", width, "height", height, NULL);
         ges_timeline_element_set_child_properties(GES_TIMELINE_ELEMENT(clip), "posx", 0, "posy", 0, NULL);
+
+        ret = __update_track_resolution(editor, width, height);
+        RET_VAL_IF(ret != MEDIAEDITOR_ERROR_NONE, ret, "failed to update track resolution");
     }
 
     return MEDIAEDITOR_ERROR_NONE;
@@ -313,6 +391,8 @@ int _mediaeditor_remove_clip(mediaeditor_s *editor, unsigned int clip_id)
 
     editor->clips = g_list_remove(editor->clips, clip_data);
 
+    //TODO: update resolution if rightmost or bottommost clip is removed.
+
     return MEDIAEDITOR_ERROR_NONE;
 }
 
@@ -552,8 +632,11 @@ int _mediaeditor_get_clip_resolution(mediaeditor_s *editor, unsigned int clip_id
 int _mediaeditor_set_clip_resolution(mediaeditor_s *editor, unsigned int clip_id,
   unsigned int width, unsigned int height)
 {
+    int ret = MEDIAEDITOR_ERROR_NONE;
     mediaeditor_clip_s *clip_data = NULL;
     GESClip *clip = NULL;
+    unsigned int pos_x = 0;
+    unsigned int pos_y = 0;
 
     NULL_PARAM_CHECK(editor);
     RET_VAL_IF(clip_id >= editor->clip_id, MEDIAEDITOR_ERROR_INVALID_PARAMETER, "invalid id");
@@ -567,6 +650,12 @@ int _mediaeditor_set_clip_resolution(mediaeditor_s *editor, unsigned int clip_id
 
     ges_timeline_element_set_child_properties(GES_TIMELINE_ELEMENT(clip), "width", width, "height", height, NULL);
 
+    ret = _mediaeditor_get_clip_position(editor, clip_id, &pos_x, &pos_y);
+    RET_VAL_IF(ret != MEDIAEDITOR_ERROR_NONE, ret, "failed to get clip position");
+
+    ret = __update_track_resolution(editor, (int)(pos_x + width), (int)(pos_y + height));
+    RET_VAL_IF(ret != MEDIAEDITOR_ERROR_NONE, ret, "failed to update track resolution");
+
     return MEDIAEDITOR_ERROR_NONE;
 }
 
@@ -590,7 +679,10 @@ int _mediaeditor_get_clip_position(mediaeditor_s *editor, unsigned int clip_id,
 int _mediaeditor_set_clip_position(mediaeditor_s *editor, unsigned int clip_id,
   unsigned int pos_x, unsigned int pos_y)
 {
+    int ret = MEDIAEDITOR_ERROR_NONE;
     GESClip *clip = NULL;
+    unsigned int width = 0;
+    unsigned int height = 0;
 
     NULL_PARAM_CHECK(editor);
     RET_VAL_IF(clip_id >= editor->clip_id, MEDIAEDITOR_ERROR_INVALID_PARAMETER, "invalid id");
@@ -601,6 +693,12 @@ int _mediaeditor_set_clip_position(mediaeditor_s *editor, unsigned int clip_id,
 
     ges_timeline_element_set_child_properties(GES_TIMELINE_ELEMENT(clip), "posx", pos_x, "posy", pos_y, NULL);
 
+    ret = _mediaeditor_get_clip_resolution(editor, clip_id, &width, &height);
+    RET_VAL_IF(ret != MEDIAEDITOR_ERROR_NONE, ret, "failed to get clip resolution");
+
+    ret = __update_track_resolution(editor, (int)(pos_x + width), (int)(pos_y + height));
+    RET_VAL_IF(ret != MEDIAEDITOR_ERROR_NONE, ret, "failed to update track resolution");
+
     return MEDIAEDITOR_ERROR_NONE;
 }
 
index a7bedc7..fede624 100644 (file)
@@ -753,3 +753,37 @@ int _check_feature(const char *feature)
 
     return MEDIAEDITOR_ERROR_NONE;
 }
+
+int _get_track(mediaeditor_s *editor, track_type_e track_type, GESTrack **track)
+{
+    GList *l = NULL;
+    GESTrack *track_tmp = NULL;
+
+    RET_VAL_IF(editor == NULL, MEDIAEDITOR_ERROR_INVALID_PARAMETER, "editor is null");
+    RET_VAL_IF(track == NULL, MEDIAEDITOR_ERROR_INVALID_PARAMETER, "track is null");
+
+    GList *tracks = ges_timeline_get_tracks(editor->gst.timeline);
+    RET_VAL_IF(tracks == NULL, MEDIAEDITOR_ERROR_INVALID_OPERATION, "failed to get track");
+
+    for (l = tracks; l; l = g_list_next(l)) {
+        track_tmp = GES_TRACK(l->data);
+
+        if ((track_type == TRACK_AUDIO) && GES_IS_AUDIO_TRACK(track_tmp)) {
+            *track = gst_object_ref(track_tmp);
+            break;
+        }
+        if ((track_type == TRACK_VIDEO) && GES_IS_VIDEO_TRACK(track_tmp)) {
+            *track = gst_object_ref(track_tmp);
+            break;
+        }
+    }
+
+    g_list_free_full(tracks, gst_object_unref);
+
+    if (*track == NULL) {
+        LOG_ERROR("There's no matched track");
+        return MEDIAEDITOR_ERROR_INVALID_OPERATION;
+    }
+
+    return MEDIAEDITOR_ERROR_NONE;
+}