diff options
author | Dave Robillard <dave@drobilla.net> | 2009-05-26 19:11:45 -0400 |
---|---|---|
committer | Dave Robillard <dave@drobilla.net> | 2009-05-26 19:11:45 -0400 |
commit | 0b46abe9aec9d8903430f49fe17f92dd8b0ba00e (patch) | |
tree | 5b4d6d8b85c0b002d4d503e75d6edc6772fcce85 /gst/mpegdemux | |
parent | e9f9ffa0e5ca0844a499a106963888176b6a7372 (diff) | |
parent | b75a26657febaf86c4137b4d41c068926325e316 (diff) | |
download | gst-plugins-bad-0b46abe9aec9d8903430f49fe17f92dd8b0ba00e.tar.gz gst-plugins-bad-0b46abe9aec9d8903430f49fe17f92dd8b0ba00e.tar.bz2 gst-plugins-bad-0b46abe9aec9d8903430f49fe17f92dd8b0ba00e.zip |
Merge branch 'fdo' into lv2
Diffstat (limited to 'gst/mpegdemux')
-rw-r--r-- | gst/mpegdemux/gstmpegdefs.h | 2 | ||||
-rw-r--r-- | gst/mpegdemux/gstmpegdemux.c | 134 | ||||
-rw-r--r-- | gst/mpegdemux/gstmpegdemux.h | 5 | ||||
-rw-r--r-- | gst/mpegdemux/gstmpegtsdemux.c | 28 | ||||
-rw-r--r-- | gst/mpegdemux/gstmpegtsdemux.h | 1 | ||||
-rw-r--r-- | gst/mpegdemux/gstpesfilter.h | 2 |
6 files changed, 158 insertions, 14 deletions
diff --git a/gst/mpegdemux/gstmpegdefs.h b/gst/mpegdemux/gstmpegdefs.h index d63667d8..7ad1e25c 100644 --- a/gst/mpegdemux/gstmpegdefs.h +++ b/gst/mpegdemux/gstmpegdefs.h @@ -173,6 +173,8 @@ #define ST_HDV_PRIVATE_A0 0xa0 #define ST_HDV_PRIVATE_A1 0xa1 #define ST_PS_DVD_SUBPICTURE 0xff +/* Blu-ray PGS subpictures */ +#define ST_BD_PGS_SUBPICTURE 0x90 /* Un-official time-code stream */ #define ST_PS_TIMECODE 0xd2 diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index 439bb563..ce1d0978 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -39,6 +39,7 @@ * Fluendo, S.L. All Rights Reserved. * * Contributor(s): Wim Taymans <wim@fluendo.com> + * Jan Schmidt <thaytan@noraisin.net> */ #ifdef HAVE_CONFIG_H @@ -56,6 +57,9 @@ #define SCAN_SCR_SZ 12 #define SCAN_PTS_SZ 80 +#define SEGMENT_THRESHOLD (300*GST_MSECOND) +#define VIDEO_SEGMENT_THRESHOLD (500*GST_MSECOND) + typedef enum { SCAN_SCR, @@ -177,6 +181,13 @@ static GstStaticPadTemplate audio_template = "audio/x-private1-ac3;" "audio/x-private1-dts;" "audio/ac3") ); +static GstStaticPadTemplate subpicture_template = +GST_STATIC_PAD_TEMPLATE ("subpicture_%02x", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("video/x-dvd-subpicture") + ); + static GstStaticPadTemplate private_template = GST_STATIC_PAD_TEMPLATE ("private_%d", GST_PAD_SRC, @@ -209,6 +220,10 @@ static inline gboolean gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, static inline gboolean gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos, SCAN_MODE mode, guint64 * rts); +static void gst_flups_demux_send_segment_updates (GstFluPSDemux * demux, + GstClockTime new_time); +static void gst_flups_demux_clear_times (GstFluPSDemux * demux); + static GstElementClass *parent_class = NULL; /*static guint gst_flups_demux_signals[LAST_SIGNAL] = { 0 };*/ @@ -250,10 +265,14 @@ gst_flups_demux_base_init (GstFluPSDemuxClass * klass) klass->sink_template = gst_static_pad_template_get (&sink_template); klass->video_template = gst_static_pad_template_get (&video_template); klass->audio_template = gst_static_pad_template_get (&audio_template); + klass->subpicture_template = + gst_static_pad_template_get (&subpicture_template); klass->private_template = gst_static_pad_template_get (&private_template); gst_element_class_add_pad_template (element_class, klass->video_template); gst_element_class_add_pad_template (element_class, klass->audio_template); + gst_element_class_add_pad_template (element_class, + klass->subpicture_template); gst_element_class_add_pad_template (element_class, klass->private_template); gst_element_class_add_pad_template (element_class, klass->sink_template); @@ -340,6 +359,7 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) gchar *name; GstFluPSDemuxClass *klass = GST_FLUPS_DEMUX_GET_CLASS (demux); GstCaps *caps; + GstClockTime threshold = SEGMENT_THRESHOLD; name = NULL; template = NULL; @@ -368,6 +388,7 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, mpeg_version, "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); + threshold = VIDEO_SEGMENT_THRESHOLD; break; } case ST_AUDIO_MPEG1: @@ -387,6 +408,7 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) template = klass->video_template; name = g_strdup_printf ("video_%02x", id); caps = gst_caps_new_simple ("video/x-h264", NULL); + threshold = VIDEO_SEGMENT_THRESHOLD; break; case ST_PS_AUDIO_AC3: template = klass->audio_template; @@ -404,6 +426,9 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) caps = gst_caps_new_simple ("audio/x-private1-lpcm", NULL); break; case ST_PS_DVD_SUBPICTURE: + template = klass->subpicture_template; + name = g_strdup_printf ("subpicture_%02x", id); + caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL); break; case ST_GST_AUDIO_RAWA52: template = klass->audio_template; @@ -424,6 +449,7 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) stream->notlinked = FALSE; stream->type = stream_type; stream->pad = gst_pad_new_from_template (template, name); + stream->segment_thresh = threshold; gst_pad_set_event_function (stream->pad, GST_DEBUG_FUNCPTR (gst_flups_demux_src_event)); gst_pad_set_query_function (stream->pad, @@ -559,6 +585,20 @@ gst_flups_demux_send_data (GstFluPSDemux * demux, GstFluPSStream * stream, GST_TIME_ARGS (demux->src_segment.last_stop), GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->current_scr))); + if (demux->src_segment.last_stop != GST_CLOCK_TIME_NONE) { + GstClockTime new_time = demux->base_time + demux->src_segment.last_stop; + + if (stream->last_ts == GST_CLOCK_TIME_NONE || stream->last_ts < new_time) { +#if 0 + g_print ("last_ts update on pad %s to time %" GST_TIME_FORMAT "\n", + GST_PAD_NAME (stream->pad), GST_TIME_ARGS (cur_scr_time)); +#endif + stream->last_ts = new_time; + } + + gst_flups_demux_send_segment_updates (demux, new_time); + } + /* Set the buffer discont flag, and clear discont state on the stream */ if (stream->discont) { GST_DEBUG_OBJECT (demux, "marking discont buffer"); @@ -731,12 +771,76 @@ gst_flups_demux_flush (GstFluPSDemux * demux) gst_adapter_clear (demux->adapter); gst_adapter_clear (demux->rev_adapter); gst_pes_filter_drain (&demux->filter); + gst_flups_demux_clear_times (demux); demux->adapter_offset = G_MAXUINT64; demux->current_scr = G_MAXUINT64; demux->bytes_since_scr = 0; } static void +gst_flups_demux_clear_times (GstFluPSDemux * demux) +{ + gint id; + + /* Clear the last ts for all streams */ + for (id = 0; id < GST_FLUPS_DEMUX_MAX_STREAMS; id++) { + GstFluPSStream *stream = demux->streams[id]; + + if (stream) { + stream->last_seg_start = stream->last_ts = GST_CLOCK_TIME_NONE; + } + } +} + +static void +gst_flups_demux_send_segment_updates (GstFluPSDemux * demux, + GstClockTime new_time) +{ + /* Advance all lagging streams by sending a segment update */ + gint id; + GstEvent *event = NULL; + + /* FIXME: Handle reverse playback */ + + if (new_time > demux->src_segment.stop) + return; + + for (id = 0; id < GST_FLUPS_DEMUX_MAX_STREAMS; id++) { + GstFluPSStream *stream = demux->streams[id]; + + if (stream) { + if (stream->last_ts == GST_CLOCK_TIME_NONE || + stream->last_ts < demux->src_segment.start) + stream->last_ts = demux->src_segment.start; + if (stream->last_ts + stream->segment_thresh < new_time) { +#if 0 + g_print ("Segment update to pad %s time %" GST_TIME_FORMAT " stop now %" + GST_TIME_FORMAT "\n", GST_PAD_NAME (stream->pad), + GST_TIME_ARGS (new_time), GST_TIME_ARGS (demux->src_segment.stop)); +#endif + GST_DEBUG_OBJECT (demux, + "Segment update to pad %s time %" GST_TIME_FORMAT, + GST_PAD_NAME (stream->pad), GST_TIME_ARGS (new_time)); + if (event == NULL) { + event = gst_event_new_new_segment_full (TRUE, + demux->src_segment.rate, demux->src_segment.applied_rate, + GST_FORMAT_TIME, new_time, + demux->src_segment.stop, + demux->src_segment.time + (new_time - demux->src_segment.start)); + } + gst_event_ref (event); + gst_pad_push_event (stream->pad, event); + stream->last_seg_start = stream->last_ts = new_time; + stream->need_segment = FALSE; + } + } + } + + if (event) + gst_event_unref (event); +} + +static void gst_flups_demux_close_segment (GstFluPSDemux * demux) { gint id; @@ -747,6 +851,10 @@ gst_flups_demux_close_segment (GstFluPSDemux * demux) &demux->src_segment); #endif + /* FIXME: Need to send a different segment-close to each pad where the + * last_seg_start != clock_time_none, as that indicates a sparse-stream + * event was sent there */ + /* Close the current segment for a linear playback */ if (demux->src_segment.rate >= 0) { /* for forward playback, we played from start to last_stop */ @@ -1306,7 +1414,7 @@ gst_flups_demux_reset_psm (GstFluPSDemux * demux) FILL_TYPE (0x40, 0x7f, -1); FILL_TYPE (0x80, 0x87, ST_PS_AUDIO_AC3); FILL_TYPE (0x88, 0x9f, ST_PS_AUDIO_DTS); - FILL_TYPE (0xa0, 0xbf, ST_PS_AUDIO_LPCM); + FILL_TYPE (0xa0, 0xaf, ST_PS_AUDIO_LPCM); FILL_TYPE (0xbd, 0xbd, -1); FILL_TYPE (0xc0, 0xdf, ST_AUDIO_MPEG1); FILL_TYPE (0xe0, 0xef, ST_GST_VIDEO_MPEG1_OR_2); @@ -1839,18 +1947,26 @@ gst_flups_demux_data_cb (GstPESFilter * filter, gboolean first, } if (G_LIKELY (stream_type == -1)) { - /* new id */ + /* new id is in the first byte */ id = data[offset++]; - /* Number of audio frames in this packet */ - nframes = data[offset++]; - - GST_DEBUG_OBJECT (demux, "private type 0x%02x, %d frames", id, - nframes); - - datalen -= 2; + datalen--; /* and remap */ stream_type = demux->psm[id]; + + /* Now, if it's a subpicture stream - no more, otherwise + * take the first byte too, since it's the frame count in audio + * streams and our backwards compat convention is to strip it off */ + if (stream_type != ST_PS_DVD_SUBPICTURE) { + /* Number of audio frames in this packet */ + nframes = data[offset++]; + datalen--; + GST_DEBUG_OBJECT (demux, "private type 0x%02x, %d frames", id, + nframes); + } else { + GST_DEBUG_OBJECT (demux, "private type 0x%02x, stream type %d", id, + stream_type); + } } } if (stream_type == -1) diff --git a/gst/mpegdemux/gstmpegdemux.h b/gst/mpegdemux/gstmpegdemux.h index ef175f76..29b3d5e5 100644 --- a/gst/mpegdemux/gstmpegdemux.h +++ b/gst/mpegdemux/gstmpegdemux.h @@ -86,6 +86,10 @@ struct _GstFluPSStream gint type; gint size_bound; + GstClockTime segment_thresh; + GstClockTime last_seg_start; + GstClockTime last_ts; + gboolean discont; gboolean notlinked; gboolean need_segment; @@ -149,6 +153,7 @@ struct _GstFluPSDemuxClass GstPadTemplate *sink_template; GstPadTemplate *video_template; GstPadTemplate *audio_template; + GstPadTemplate *subpicture_template; GstPadTemplate *private_template; }; diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index cd64a295..ef0de2c8 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -157,6 +157,10 @@ enum "audio/x-dts" \ ) +/* Can also use the subpicture pads for text subtitles? */ +#define SUBPICTURE_CAPS \ + GST_STATIC_CAPS ("subpicture/x-pgs; video/x-dvd-subpicture") + static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, @@ -175,6 +179,12 @@ GST_STATIC_PAD_TEMPLATE ("audio_%04x", GST_PAD_SOMETIMES, AUDIO_CAPS); +static GstStaticPadTemplate subpicture_template = +GST_STATIC_PAD_TEMPLATE ("subpicture_%04x", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + SUBPICTURE_CAPS); + static GstStaticPadTemplate private_template = GST_STATIC_PAD_TEMPLATE ("private_%04x", GST_PAD_SRC, @@ -250,10 +260,14 @@ gst_mpegts_demux_base_init (GstMpegTSDemuxClass * klass) klass->sink_template = gst_static_pad_template_get (&sink_template); klass->video_template = gst_static_pad_template_get (&video_template); klass->audio_template = gst_static_pad_template_get (&audio_template); + klass->subpicture_template = + gst_static_pad_template_get (&subpicture_template); klass->private_template = gst_static_pad_template_get (&private_template); gst_element_class_add_pad_template (element_class, klass->video_template); gst_element_class_add_pad_template (element_class, klass->audio_template); + gst_element_class_add_pad_template (element_class, + klass->subpicture_template); gst_element_class_add_pad_template (element_class, klass->private_template); gst_element_class_add_pad_template (element_class, klass->sink_template); @@ -675,6 +689,14 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, caps = gst_caps_new_simple ("audio/x-lpcm", NULL); break; case ST_PS_DVD_SUBPICTURE: + template = klass->subpicture_template; + name = g_strdup_printf ("subpicture_%04x", stream->PID); + caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL); + break; + case ST_BD_PGS_SUBPICTURE: + template = klass->subpicture_template; + name = g_strdup_printf ("subpicture_%04x", stream->PID); + caps = gst_caps_new_simple ("subpicture/x-pgs", NULL); break; default: break; @@ -992,8 +1014,8 @@ gst_mpegts_demux_data_cb (GstPESFilter * filter, gboolean first, goto unknown_type; GST_DEBUG_OBJECT (demux, - "New stream 0x%04x of type %d with caps %" GST_PTR_FORMAT, stream->PID, - stream->stream_type, GST_PAD_CAPS (stream->pad)); + "New stream 0x%04x of type 0x%02x with caps %" GST_PTR_FORMAT, + stream->PID, stream->stream_type, GST_PAD_CAPS (stream->pad)); srcpad = stream->pad; @@ -1017,7 +1039,7 @@ gst_mpegts_demux_data_cb (GstPESFilter * filter, gboolean first, unknown_type: { GST_DEBUG_OBJECT (demux, "got unknown stream id 0x%02x, type 0x%02x", - filter->id, filter->type); + filter->id, stream->stream_type); gst_buffer_unref (buffer); return gst_mpegts_demux_combine_flows (demux, stream, GST_FLOW_NOT_LINKED); } diff --git a/gst/mpegdemux/gstmpegtsdemux.h b/gst/mpegdemux/gstmpegtsdemux.h index dad2b023..fde68926 100644 --- a/gst/mpegdemux/gstmpegtsdemux.h +++ b/gst/mpegdemux/gstmpegtsdemux.h @@ -228,6 +228,7 @@ struct _GstMpegTSDemuxClass { GstPadTemplate * sink_template; GstPadTemplate * video_template; GstPadTemplate * audio_template; + GstPadTemplate * subpicture_template; GstPadTemplate * private_template; }; diff --git a/gst/mpegdemux/gstpesfilter.h b/gst/mpegdemux/gstpesfilter.h index b35d8746..ccc8461d 100644 --- a/gst/mpegdemux/gstpesfilter.h +++ b/gst/mpegdemux/gstpesfilter.h @@ -84,8 +84,6 @@ struct _GstPESFilter { gboolean unbounded_packet; guint16 length; - guint8 type; - gint64 pts; gint64 dts; }; |