diff --git a/ChangeLog b/ChangeLog index b0e496569b..eb6cbf4174 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2004-01-25 Ronald Bultje + + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_info): + Additional pad usability check. + * gst/mpeg1videoparse/gstmp1videoparse.c: (gst_mp1videoparse_init), + (mp1videoparse_find_next_gop), (gst_mp1videoparse_time_code), + (gst_mp1videoparse_real_chain): + Fix MPEG video stream parsing. The original plugin had several + issues, including not timestamping streams where the source was + not timestamped (this happens with PTS values in mpeg system + streams, but MPEG video is also a valid stream on its own so + that needs timestamps too). We use the display time code for that + for now. Also, if one incoming buffer contains multiple valid + frames, we push them all on correctly now, including proper EOS + handling. Lastly, several potential segfaults were fixed, and we + properly sync on new sequence/gop headers to include them in next, + not previous frames (since they're header for the next frame, not + the previous). Also see #119206. + * gst/mpegaudioparse/gstmpegaudioparse.c: (gst_mp3parse_chain), + (bpf_from_header): + Move caps setting so we only do it after finding several valid + MPEG-1 fraes sequentially, not right after the first one (which + might be coincidental). + * gst/typefind/gsttypefindfunctions.c: (mpeg1_sys_type_find), + (mpeg_video_type_find), (mpeg_video_stream_type_find), + (plugin_init): + Add unsynced MPEG video stream typefinding, and change some + probability values so we detect streams rightly. The idea is as + follows: I can have an unsynced system stream which contains + video. In the current code, I would randomly get a type for either + system or video stream type found, because the probabilities are + being calculated rather randomly. I now use fixed values, so we + always prefer system stream if that was found (and that is how it + should be). If no system stream was found, we can still identity the stream as video-only. + 2004-01-23 Benjamin Otte * gst/avi/gstavidemux.c: (gst_avi_demux_stream_avih), diff --git a/gst-libs/gst/riff/riff-read.c b/gst-libs/gst/riff/riff-read.c index 1ebeb28b72..870f778222 100644 --- a/gst-libs/gst/riff/riff-read.c +++ b/gst-libs/gst/riff/riff-read.c @@ -815,7 +815,7 @@ gst_riff_read_info (GstRiffRead *riff) /* let the world know about this wonderful thing */ for (padlist = gst_element_get_pad_list (element); padlist != NULL; padlist = padlist->next) { - if (GST_PAD_IS_SRC (padlist->data)) { + if (GST_PAD_IS_SRC (padlist->data) && GST_PAD_IS_USABLE(padlist->data)) { gst_event_ref (event); gst_pad_push (GST_PAD (padlist->data), GST_DATA (event)); } diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index 6183e6b520..df67cec6ca 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -569,17 +569,10 @@ mpeg1_sys_type_find (GstTypeFind *tf, gpointer unused) g_assert (found <= GST_MPEG_TYPEFIND_TRY_HEADERS); if (found == GST_MPEG_TYPEFIND_TRY_HEADERS || packet_size == 1) { - guint probability = found * GST_TYPE_FIND_MAXIMUM * - (GST_MPEG_TYPEFIND_TRY_SYNC - skipped) / - GST_MPEG_TYPEFIND_TRY_HEADERS / GST_MPEG_TYPEFIND_TRY_SYNC; - - if (probability < GST_TYPE_FIND_MINIMUM) - probability = GST_TYPE_FIND_MINIMUM; - g_assert (probability <= GST_TYPE_FIND_MAXIMUM); caps = MPEG_SYS_CAPS; gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion", G_TYPE_INT, 1, 0); - gst_type_find_suggest (tf, probability, caps); + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 1, caps); return; } } @@ -603,7 +596,96 @@ mpeg_video_type_find (GstTypeFind *tf, gpointer unused) data = gst_type_find_peek (tf, 0, 8); if (data && memcmp(data, sequence_header, 4)==0){ - gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MPEG_VIDEO_CAPS); + GstCaps *caps = MPEG_VIDEO_CAPS; + gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion", + G_TYPE_INT, 1, 0); + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 1, caps); + } +} + +/* + * Idea is the same as MPEG system stream typefinding: We check each + * byte of the stream to see if - from that point on - the stream + * matches a predefined set of marker bits as defined in the MPEG + * video specs. + * + * I'm sure someone will do a chance calculation here too. + */ + +#define GST_MPEGVID_TYPEFIND_TRY_PICTURES 6 +#define GST_MPEGVID_TYPEFIND_TRY_SYNC (100 * 1024) /* 100 kB */ +#define GST_MPEGVID_TYPEFIND_SYNC_SIZE 2048 + +static void +mpeg_video_stream_type_find (GstTypeFind *tf, gpointer unused) +{ + gint size = 0, found = 0; + guint64 skipped = 0; + guint8 *data = NULL; + + while (1) { + if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES) { + GstCaps *caps = MPEG_VIDEO_CAPS; + gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion", + G_TYPE_INT, 1, 0); + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 2, caps); + return; + } + + if (skipped > GST_MPEGVID_TYPEFIND_TRY_SYNC) + break; + + if (size < 4) { + data = gst_type_find_peek (tf, skipped, GST_MPEGVID_TYPEFIND_SYNC_SIZE); + if (!data) + break; + size = GST_MPEGVID_TYPEFIND_SYNC_SIZE; + } + + /* are we a sequence (0xB3) or GOP (0xB8) header? */ + if (data[0] == 0x0 && data[1] == 0x0 && data[2] == 0x1 && + (data[3] == 0xB3 || data[3] == 0xB8)) { + size -= 8; + data += 8; + skipped += 8; + if (data[3] == 0xB3) + continue; + else if (size < 4) { + data = gst_type_find_peek (tf, skipped, GST_MPEGVID_TYPEFIND_SYNC_SIZE); + size = GST_MPEGVID_TYPEFIND_SYNC_SIZE; + if (!data) + break; + } + /* else, we should now see an image */ + } + + /* image header (and, when found, slice header) */ + if (data[0] == 0x0 && data[1] == 0x0 && + data[2] == 0x1 && data[4] == 0x0) { + size -= 8; + data += 8; + skipped += 8; + if (size < 5) { + data = gst_type_find_peek (tf, skipped, GST_MPEGVID_TYPEFIND_SYNC_SIZE); + size = GST_MPEGVID_TYPEFIND_SYNC_SIZE; + if (!data) + break; + } + if ((data[0] == 0x0 && data[1] == 0x0 && + data[2] == 0x1 && data[3] == 0x1) || + (data[1] == 0x0 && data[2] == 0x0 && + data[3] == 0x1 && data[4] == 0x1)) { + size -= 4; + data += 4; + skipped += 4; + found += 1; + continue; + } + } + + size--; + data++; + skipped++; } } @@ -1141,6 +1223,8 @@ plugin_init (GstPlugin *plugin) ogg_exts, "OggS", 4, GST_TYPE_FIND_MAXIMUM); TYPE_FIND_REGISTER (plugin, "video/mpeg", GST_RANK_SECONDARY, mpeg_video_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL); + TYPE_FIND_REGISTER (plugin, "video/mpeg", GST_RANK_MARGINAL, + mpeg_video_stream_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL); TYPE_FIND_REGISTER (plugin, "video/quicktime", GST_RANK_SECONDARY, qt_type_find, qt_exts, QT_CAPS, NULL); TYPE_FIND_REGISTER_START_WITH (plugin, "application/vnd.rn-realmedia", GST_RANK_SECONDARY,