summaryrefslogtreecommitdiff
path: root/ext/ffmpeg/gstffmpegdemux.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ffmpeg/gstffmpegdemux.c')
-rw-r--r--ext/ffmpeg/gstffmpegdemux.c81
1 files changed, 66 insertions, 15 deletions
diff --git a/ext/ffmpeg/gstffmpegdemux.c b/ext/ffmpeg/gstffmpegdemux.c
index c5feb3f..6912de3 100644
--- a/ext/ffmpeg/gstffmpegdemux.c
+++ b/ext/ffmpeg/gstffmpegdemux.c
@@ -56,6 +56,8 @@ struct _GstFFStream
gboolean discont;
gboolean eos;
GstFlowReturn last_flow;
+
+ GstTagList *tags; /* stream tags */
};
struct _GstFFMpegDemux
@@ -90,6 +92,9 @@ struct _GstFFMpegDemux
/* cached seek in READY */
GstEvent *seek_event;
+ /* cached upstream events */
+ GList *cached_events;
+
/* push mode data */
GstFFMpegPipe ffpipe;
GstTask *task;
@@ -325,8 +330,11 @@ gst_ffmpegdemux_close (GstFFMpegDemux * demux)
GstFFStream *stream;
stream = demux->streams[n];
- if (stream && stream->pad) {
- gst_element_remove_pad (GST_ELEMENT (demux), stream->pad);
+ if (stream) {
+ if (stream->pad)
+ gst_element_remove_pad (GST_ELEMENT (demux), stream->pad);
+ if (stream->tags)
+ gst_tag_list_free (stream->tags);
g_free (stream);
}
demux->streams[n] = NULL;
@@ -958,6 +966,7 @@ gst_ffmpegdemux_get_stream (GstFFMpegDemux * demux, AVStream * avstream)
stream->avstream = avstream;
stream->last_ts = GST_CLOCK_TIME_NONE;
stream->last_flow = GST_FLOW_OK;
+ stream->tags = NULL;
switch (ctx->codec_type) {
case CODEC_TYPE_VIDEO:
@@ -1019,12 +1028,11 @@ gst_ffmpegdemux_get_stream (GstFFMpegDemux * demux, AVStream * avstream)
/* metadata */
if ((codec = gst_ffmpeg_get_codecid_longname (ctx->codec_id))) {
- GstTagList *list = gst_tag_list_new ();
+ stream->tags = gst_tag_list_new ();
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
+ gst_tag_list_add (stream->tags, GST_TAG_MERGE_REPLACE,
(ctx->codec_type == CODEC_TYPE_VIDEO) ?
GST_TAG_VIDEO_CODEC : GST_TAG_AUDIO_CODEC, codec, NULL);
- gst_element_found_tags_for_pad (GST_ELEMENT (demux), pad, list);
}
return stream;
@@ -1124,9 +1132,10 @@ gst_ffmpegdemux_open (GstFFMpegDemux * demux)
GstFFMpegDemuxClass *oclass =
(GstFFMpegDemuxClass *) G_OBJECT_GET_CLASS (demux);
gchar *location;
- gint res, n_streams;
+ gint res, n_streams, i;
GstTagList *tags;
GstEvent *event;
+ GList *cached_events;
/* to be sure... */
gst_ffmpegdemux_close (demux);
@@ -1156,8 +1165,8 @@ gst_ffmpegdemux_open (GstFFMpegDemux * demux)
/* open_input_file() automatically reads the header. We can now map each
* created AVStream to a GstPad to make GStreamer handle it. */
- for (res = 0; res < n_streams; res++) {
- gst_ffmpegdemux_get_stream (demux, demux->context->streams[res]);
+ for (i = 0; i < n_streams; i++) {
+ gst_ffmpegdemux_get_stream (demux, demux->context->streams[i]);
}
gst_element_no_more_pads (GST_ELEMENT (demux));
@@ -1183,6 +1192,8 @@ gst_ffmpegdemux_open (GstFFMpegDemux * demux)
demux->opened = TRUE;
event = demux->seek_event;
demux->seek_event = NULL;
+ cached_events = demux->cached_events;
+ demux->cached_events = NULL;
GST_OBJECT_UNLOCK (demux);
if (event) {
@@ -1195,13 +1206,35 @@ gst_ffmpegdemux_open (GstFFMpegDemux * demux)
demux->segment.start, demux->segment.stop, demux->segment.time));
}
- /* grab the tags */
+ while (cached_events) {
+ event = cached_events->data;
+ GST_INFO_OBJECT (demux, "pushing cached %s event: %" GST_PTR_FORMAT,
+ GST_EVENT_TYPE_NAME (event), event->structure);
+ gst_ffmpegdemux_push_event (demux, event);
+ cached_events = g_list_delete_link (cached_events, cached_events);
+ }
+
+ /* grab the global tags */
tags = gst_ffmpegdemux_read_tags (demux);
if (tags) {
+ GST_INFO_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, tags);
gst_element_post_message (GST_ELEMENT (demux),
gst_message_new_tag (GST_OBJECT (demux), tags));
}
+ /* now handle the stream tags */
+ for (i = 0; i < n_streams; i++) {
+ GstFFStream *stream;
+
+ stream = gst_ffmpegdemux_get_stream (demux, demux->context->streams[i]);
+ if (stream->tags != NULL && stream->pad != NULL) {
+ GST_INFO_OBJECT (stream->pad, "stream tags: %" GST_PTR_FORMAT,
+ stream->tags);
+ gst_element_found_tags_for_pad (GST_ELEMENT (demux), stream->pad,
+ gst_tag_list_copy (stream->tags));
+ }
+ }
+
return TRUE;
/* ERRORS */
@@ -1517,7 +1550,8 @@ gst_ffmpegdemux_sink_event (GstPad * sinkpad, GstEvent * event)
demux = (GstFFMpegDemux *) (GST_PAD_PARENT (sinkpad));
ffpipe = &(demux->ffpipe);
- GST_DEBUG_OBJECT (demux, "event %s", GST_EVENT_TYPE_NAME (event));
+ GST_LOG_OBJECT (demux, "%s event: %" GST_PTR_FORMAT,
+ GST_EVENT_TYPE_NAME (event), event->structure);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
@@ -1539,6 +1573,11 @@ gst_ffmpegdemux_sink_event (GstPad * sinkpad, GstEvent * event)
/* forward event */
gst_pad_event_default (sinkpad, event);
+ GST_OBJECT_LOCK (demux);
+ g_list_foreach (demux->cached_events, (GFunc) gst_mini_object_unref,
+ NULL);
+ g_list_free (demux->cached_events);
+ GST_OBJECT_UNLOCK (demux);
GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
gst_adapter_clear (ffpipe->adapter);
ffpipe->srcresult = GST_FLOW_OK;
@@ -1565,11 +1604,19 @@ gst_ffmpegdemux_sink_event (GstPad * sinkpad, GstEvent * event)
*
* If the demuxer isn't opened, push straight away, since we'll
* be waiting against a cond that will never be signalled. */
- if (GST_EVENT_IS_SERIALIZED (event) && demux->opened) {
- GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
- while (!ffpipe->needed)
- GST_FFMPEG_PIPE_WAIT (ffpipe);
- GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
+ if (GST_EVENT_IS_SERIALIZED (event)) {
+ if (demux->opened) {
+ GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
+ while (!ffpipe->needed)
+ GST_FFMPEG_PIPE_WAIT (ffpipe);
+ GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
+ } else {
+ /* queue events and send them later (esp. tag events) */
+ GST_OBJECT_LOCK (demux);
+ demux->cached_events = g_list_append (demux->cached_events, event);
+ GST_OBJECT_UNLOCK (demux);
+ goto done;
+ }
}
break;
}
@@ -1760,6 +1807,10 @@ gst_ffmpegdemux_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_PAUSED_TO_READY:
gst_ffmpegdemux_close (demux);
gst_adapter_clear (demux->ffpipe.adapter);
+ g_list_foreach (demux->cached_events, (GFunc) gst_mini_object_unref,
+ NULL);
+ g_list_free (demux->cached_events);
+ demux->cached_events = NULL;
break;
default:
break;