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 {
__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;
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;
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);
}
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);
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;
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;
}
}
+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
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);