webrtc_test: Revise media packet source test 39/258039/6
authorSangchul Lee <sc11.lee@samsung.com>
Mon, 10 May 2021 01:01:40 +0000 (10:01 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 7 Jul 2021 09:24:08 +0000 (18:24 +0900)
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 <sc11.lee@samsung.com>
packaging/capi-media-webrtc.spec
test/webrtc_test.c

index 6df9b6989ef71143546916229c07b1e0dcd7b568..fb9cd97694d2e6cd4c6b2652019ccc654be78d3c 100644 (file)
@@ -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
index e46deaff7de232c07b6e1c7cf90e668cbd267189..a2297f885db2e24335adf54e3409d97808d9c1f4 100644 (file)
@@ -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);