From: Sangchul Lee Date: Mon, 10 May 2021 01:01:40 +0000 (+0900) Subject: webrtc_test: Revise media packet source test X-Git-Tag: submit/tizen/20210729.023123~27 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ae5752c5f6f450dc985d9a7f3ecf2040b7bd158d;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_test: Revise media packet source test In case of the test using H264 format, infinite loop is applied to the h264 source pipeline by using seek 0 and modifying pts/dts values of the media packet. A bus watch message handler is also added to detect EOS situation. [Version] 0.2.33 [Issue Type] Improvement Change-Id: I55d285905baf4de19803d5e569a401cb0512d9b2 Signed-off-by: Sangchul Lee --- diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index 6df9b698..fb9cd976 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -1,6 +1,6 @@ Name: capi-media-webrtc Summary: A WebRTC library in Tizen Native API -Version: 0.2.32 +Version: 0.2.33 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/test/webrtc_test.c b/test/webrtc_test.c index e46deaff..a2297f88 100644 --- a/test/webrtc_test.c +++ b/test/webrtc_test.c @@ -146,12 +146,15 @@ typedef struct { GstElement *src; GstElement *sink; GstElement *demux; + GstBus *bus; + guint bus_watcher; gulong handoff_signal_id; gulong pad_added_signal_id; bool is_overflowed; bool is_stop_requested; GCond cond; GMutex mutex; + bool got_eos; } media_packet_source_s; typedef struct _connection_s { @@ -368,6 +371,14 @@ static void __release_packet_source(int conn_idx, unsigned int source_idx) __disconnect_signal((GObject *)packet_source->demux, packet_source->pad_added_signal_id); packet_source->pad_added_signal_id = 0; } + if (packet_source->bus_watcher > 0) { + gst_bus_remove_watch(packet_source->bus); + packet_source->bus_watcher = 0; + } + if (packet_source->bus) { + gst_object_unref(packet_source->bus); + packet_source->bus = NULL; + } g_clear_object(&packet_source->src_pipeline); packet_source->src_pipeline = NULL; @@ -1865,6 +1876,10 @@ static media_packet_h __make_media_packet(media_packet_source_s *packet_source, media_packet_h packet = NULL; guchar *data_ptr; gsize size; + static GstClockTime base_pts = 0; + static GstClockTime base_dts = 0; + static GstClockTime last_pts = 0; + static GstClockTime last_dts = 0; GstClockTime pts; GstClockTime dts; GstClockTime duration; @@ -1881,6 +1896,12 @@ static media_packet_h __make_media_packet(media_packet_source_s *packet_source, return NULL; } + if (packet_source->got_eos) { + base_pts = last_pts; + base_dts = last_dts; + packet_source->got_eos = false; + } + if (set_buffer_as_external_memory) { gst_buffer_ref(buffer); @@ -1899,10 +1920,15 @@ static media_packet_h __make_media_packet(media_packet_source_s *packet_source, } gst_buffer_unmap(buffer, &buff_info); - ret |= media_packet_set_pts(packet, GST_BUFFER_PTS(buffer)); - ret |= media_packet_set_dts(packet, GST_BUFFER_DTS(buffer)); + last_pts = pts = base_pts + GST_BUFFER_PTS(buffer); + last_dts = dts = base_dts + GST_BUFFER_DTS(buffer); + ret |= media_packet_set_pts(packet, last_pts); + ret |= media_packet_set_dts(packet, last_dts); ret |= media_packet_set_duration(packet, GST_BUFFER_DURATION(buffer)); + g_print("buffer[%p], size[%u], pts[%llu], dts[%llu], duration[%llu]\n", + buffer, gst_buffer_get_size(buffer), last_pts, last_dts, GST_BUFFER_DURATION(buffer)); + /* FIXME: We put the gstbuffer to extra field of media packet. It does not guarantee the validity of the gstbuffer * after destroying this media packet. Currently, the gstbuffer must be used before destroying the packet. */ ret |= media_packet_set_extra(packet, (void *)buffer); @@ -1924,18 +1950,18 @@ static media_packet_h __make_media_packet(media_packet_source_s *packet_source, gst_buffer_ref(buffer); size = gst_buffer_get_size(buffer); - pts = GST_BUFFER_PTS(buffer); - dts = GST_BUFFER_DTS(buffer); + last_pts = pts = base_pts + GST_BUFFER_PTS(buffer); + last_dts = dts = base_dts + GST_BUFFER_DTS(buffer); duration = GST_BUFFER_DURATION(buffer); - g_print("buffer[%p], size[%u], pts[%llu], dts[%llu], duration[%llu]\n", buffer, size, pts, dts, duration); + g_print("buffer[%p], size[%u], pts[%llu], dts[%llu], duration[%llu]\n", buffer, size, last_pts, last_dts, duration); - ret = media_packet_set_pts(packet, pts); + ret = media_packet_set_pts(packet, last_pts); if (ret != MEDIA_PACKET_ERROR_NONE) { g_printerr("failed to media_packet_set_pts()\n"); goto error; } - ret = media_packet_set_dts(packet, dts); + ret = media_packet_set_dts(packet, last_dts); if (ret != MEDIA_PACKET_ERROR_NONE) { g_printerr("failed to media_packet_set_dts()\n"); goto error; @@ -2139,7 +2165,7 @@ static void __stream_handoff_cb(GstElement *object, GstBuffer *buffer, GstPad *p g_free(caps_str); gst_caps_unref(caps); - packet = __make_media_packet(packet_source, buffer, USE_GSTBUFFER_WITHOUT_COPY); + packet = __make_media_packet(packet_source, buffer, false); if (!packet) { g_printerr("failed to __make_media_packet()\n"); return; @@ -2315,6 +2341,66 @@ static void __demux_pad_added_cb(GstElement *object, GstPad *pad, gpointer data) } } +static gboolean __bus_watch_cb(GstBus *bus, GstMessage *message, gpointer user_data) +{ + media_packet_source_s *packet_source = (media_packet_source_s *)user_data; + GError *err = NULL; + GstState gst_state_old = GST_STATE_VOID_PENDING; + GstState gst_state_new = GST_STATE_VOID_PENDING; + GstState gst_state_pending = GST_STATE_VOID_PENDING; + + if (message == NULL) { + g_print("message is null\n"); + return TRUE; + } + if (packet_source == NULL) { + g_printerr("packet_source is NULL\n"); + return FALSE; + } + if (packet_source->src_pipeline == NULL) { + g_printerr("src_pipeline is NULL\n"); + return FALSE; + } + + switch (GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_ERROR: + gst_message_parse_error(message, &err, NULL); + + g_printerr("Error[from %s]: message[%s], code[%d]\n", + GST_OBJECT_NAME(GST_OBJECT_CAST(GST_ELEMENT(GST_MESSAGE_SRC(message)))), err->message, err->code); + + g_error_free(err); + break; + + case GST_MESSAGE_STATE_CHANGED: + if (GST_MESSAGE_SRC(message) != GST_OBJECT(packet_source->src_pipeline)) + return TRUE; + + gst_message_parse_state_changed(message, &gst_state_old, &gst_state_new, &gst_state_pending); + g_print("GST_MESSAGE_STATE_CHANGED: Old[GST_STATE_%s] New[GST_STATE_%s] Pending[GST_STATE_%s]\n", + gst_element_state_get_name(gst_state_old), gst_element_state_get_name(gst_state_new), gst_element_state_get_name(gst_state_pending)); + + break; + + case GST_MESSAGE_EOS: + g_print("GST_MESSAGE_EOS end-of-stream\n"); + packet_source->got_eos = true; + /* loop it again */ + gst_element_seek(packet_source->src_pipeline, + 1.0, + GST_FORMAT_TIME, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, + GST_SEEK_TYPE_SET, 0, + GST_SEEK_TYPE_NONE, 0); + break; + + default: + break; + } + + return TRUE; +} + #ifdef TIZEN_TV #define TEST_640_480_VIDEO_MP4_PATH "/opt/usr/home/owner/share/media/1.mp4" #else @@ -2367,9 +2453,27 @@ static GstElement* __build_h264_format_pipeline(media_packet_source_s *packet_so if (packet_source->handoff_signal_id == 0) goto error; + if (!(packet_source->bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)))) { + g_printerr("failed to gst_pipeline_get_bus()\n"); + goto error; + } + + if ((packet_source->bus_watcher = gst_bus_add_watch(packet_source->bus, (GstBusFunc) __bus_watch_cb, packet_source)) == 0) { + g_printerr("failed to gst_bus_add_watch()\n"); + goto error; + } + return pipeline; error: + if (packet_source->bus_watcher > 0) { + gst_bus_remove_watch(packet_source->bus); + packet_source->bus_watcher = 0; + } + if (packet_source->bus) { + gst_object_unref(packet_source->bus); + packet_source->bus = NULL; + } gst_object_unref(pipeline); if (packet_source->pad_added_signal_id > 0) { __disconnect_signal((GObject *)packet_source->demux, packet_source->pad_added_signal_id);