From 1854d83049ab37c9d94dd563fe9a0a12b60c5cb2 Mon Sep 17 00:00:00 2001 From: Haesu Gwon Date: Thu, 2 Mar 2023 10:14:13 +0900 Subject: [PATCH] media_editor: Fix wrong fixed output resolution(HD) issue - 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 | 14 +++++ include/media_editor.h | 4 +- include/media_editor_private.h | 14 +++++ packaging/capi-media-editor.spec | 4 +- src/media_editor_clip.c | 100 ++++++++++++++++++++++++++++++- src/media_editor_private.c | 34 +++++++++++ 6 files changed, 165 insertions(+), 5 deletions(-) diff --git a/gtest/ut_clip.cpp b/gtest/ut_clip.cpp index 18f2889..aa3315e 100644 --- a/gtest/ut_clip.cpp +++ b/gtest/ut_clip.cpp @@ -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); diff --git a/include/media_editor.h b/include/media_editor.h index 25e396e..ed772f0 100644 --- a/include/media_editor.h +++ b/include/media_editor.h @@ -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 diff --git a/include/media_editor_private.h b/include/media_editor_private.h index 4eae115..518ccd3 100644 --- a/include/media_editor_private.h +++ b/include/media_editor_private.h @@ -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 */ diff --git a/packaging/capi-media-editor.spec b/packaging/capi-media-editor.spec index 02af3fe..39433e7 100644 --- a/packaging/capi-media-editor.spec +++ b/packaging/capi-media-editor.spec @@ -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 diff --git a/src/media_editor_clip.c b/src/media_editor_clip.c index 810aa4c..0bdec13 100644 --- a/src/media_editor_clip.c +++ b/src/media_editor_clip.c @@ -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; } diff --git a/src/media_editor_private.c b/src/media_editor_private.c index a7bedc7..fede624 100644 --- a/src/media_editor_private.c +++ b/src/media_editor_private.c @@ -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; +} -- 2.34.1