mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-28 20:05:38 +00:00
gst/typefind/gsttypefindfunctions.c: Consolidate and re-work our mpeg system stream detection to probe more packets a...
Original commit message from CVS: * gst/typefind/gsttypefindfunctions.c: (mpeg_sys_is_valid_pack), (mpeg_sys_is_valid_pes), (mpeg_sys_is_valid_sys), (mpeg_sys_type_find), (mpeg_ts_type_find), (mpeg4_video_type_find), (mpeg_video_type_find), (mpeg_video_stream_type_find), (plugin_init): Consolidate and re-work our mpeg system stream detection to probe more packets and produce a higher confidence result. Fixes a regression caused by lowering the typefind probability last year - related to bug #397810. Remove the redundant MPEG-1 specific typefind function, as the new one detects both MPEG-1 & MPEG-2 happily. Also cleanup the MPEG elementary and MPEG-TS detection functions a little. Tested against my media test directory, with some improvements and no regressions.
This commit is contained in:
parent
56f01bc0cb
commit
1e2c327792
3 changed files with 273 additions and 208 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
|||
2007-05-11 Jan Schmidt <thaytan@mad.scientist.com>
|
||||
|
||||
* gst/typefind/gsttypefindfunctions.c: (mpeg_sys_is_valid_pack),
|
||||
(mpeg_sys_is_valid_pes), (mpeg_sys_is_valid_sys),
|
||||
(mpeg_sys_type_find), (mpeg_ts_type_find), (mpeg4_video_type_find),
|
||||
(mpeg_video_type_find), (mpeg_video_stream_type_find),
|
||||
(plugin_init):
|
||||
|
||||
Consolidate and re-work our mpeg system stream detection to probe
|
||||
more packets and produce a higher confidence result. Fixes a
|
||||
regression caused by lowering the typefind probability last year
|
||||
- related to bug #397810. Remove the redundant MPEG-1 specific
|
||||
typefind function, as the new one detects both MPEG-1 & MPEG-2
|
||||
happily.
|
||||
|
||||
Also cleanup the MPEG elementary and MPEG-TS detection functions a
|
||||
little.
|
||||
|
||||
Tested against my media test directory, with some improvements and
|
||||
no regressions.
|
||||
|
||||
2007-05-10 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/playback/gstplaybasebin.c: (fill_buffer), (check_queue),
|
||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
|||
Subproject commit 1b4fb5836a9e290fe13895643d41e0166de8a94c
|
||||
Subproject commit b5971d76ccd216c27e095c02c3a369a9d05cb36d
|
|
@ -1094,219 +1094,259 @@ static GstStaticCaps mpeg_sys_caps = GST_STATIC_CAPS ("video/mpeg, "
|
|||
(((guint8 *)(data))[1] == 0x00) && \
|
||||
(((guint8 *)(data))[2] == 0x01))
|
||||
|
||||
#define IS_MPEG_PACK_CODE(b) ((b) == 0xBA)
|
||||
#define IS_MPEG_SYS_CODE(b) ((b) == 0xBB)
|
||||
#define IS_MPEG_PACK_HEADER(data) (IS_MPEG_HEADER (data) && \
|
||||
(((guint8 *)(data))[3] == 0xBA))
|
||||
|
||||
#define IS_MPEG_SYSTEM_HEADER(data) (IS_MPEG_HEADER (data) && \
|
||||
(((guint8 *)(data))[3] == 0xBB))
|
||||
#define IS_MPEG_PACKET_HEADER(data) (IS_MPEG_HEADER (data) && \
|
||||
((((guint8 *)(data))[3] & 0x80) == 0x80))
|
||||
IS_MPEG_PACK_CODE (((guint8 *)(data))[3]))
|
||||
|
||||
#define IS_MPEG_PES_CODE(b) (((b) & 0xF0) == 0xE0 || ((b) & 0xF0) == 0xC0 || \
|
||||
(b) >= 0xBD)
|
||||
#define IS_MPEG_PES_HEADER(data) (IS_MPEG_HEADER (data) && \
|
||||
((((guint8 *)(data))[3] == 0xE0) || \
|
||||
(((guint8 *)(data))[3] == 0xC0) || \
|
||||
(((guint8 *)(data))[3] == 0xBD)))
|
||||
IS_MPEG_PES_CODE (((guint8 *)(data))[3]))
|
||||
|
||||
#define MPEG2_MAX_PROBE_LENGTH 4096 /* 4kB (random value) */
|
||||
#define MPEG2_MAX_PROBE_LENGTH (32 * 1024) /* 32kB should be 16 packs of the
|
||||
* most common 2kB pack size, but HD
|
||||
* streams might be bigger. */
|
||||
|
||||
static void
|
||||
mpeg2_sys_type_find (GstTypeFind * tf, gpointer unused)
|
||||
#define MPEG2_MIN_SYS_HEADERS 2
|
||||
#define MPEG2_MAX_SYS_HEADERS 5
|
||||
|
||||
static gboolean
|
||||
mpeg_sys_is_valid_pack (GstTypeFind * tf, guint8 * data, guint len,
|
||||
guint * pack_size)
|
||||
{
|
||||
guint8 *data, *data0;
|
||||
gint mpegversion, len;
|
||||
/* Check the pack header @ offset for validity, assuming that the 4 byte header
|
||||
* itself has already been checked. */
|
||||
guint8 stuff_len;
|
||||
|
||||
len = MPEG2_MAX_PROBE_LENGTH * 2;
|
||||
do {
|
||||
len = len / 2;
|
||||
data = gst_type_find_peek (tf, 0, 5 + len);
|
||||
} while (data == NULL && len >= 32);
|
||||
if (len < 12)
|
||||
return FALSE;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
/* Check marker bits */
|
||||
if ((data[4] & 0xC4) == 0x44) {
|
||||
/* MPEG-2 PACK */
|
||||
if (len < 14)
|
||||
return FALSE;
|
||||
|
||||
data0 = data;
|
||||
while (len > 0) {
|
||||
if (IS_MPEG_PACK_HEADER (data)) {
|
||||
if ((data[4] & 0xC0) == 0x40) {
|
||||
/* type 2 */
|
||||
mpegversion = 2;
|
||||
goto suggest;
|
||||
} else if ((data[4] & 0xF0) == 0x20) {
|
||||
mpegversion = 1;
|
||||
goto suggest;
|
||||
}
|
||||
} else if (IS_MPEG_PES_HEADER (data)) {
|
||||
/* PES stream */
|
||||
mpegversion = 2;
|
||||
goto suggest;
|
||||
if ((data[6] & 0x04) != 0x04 ||
|
||||
(data[8] & 0x04) != 0x04 ||
|
||||
(data[9] & 0x01) != 0x01 || (data[12] & 0x03) != 0x03)
|
||||
return FALSE;
|
||||
|
||||
stuff_len = data[13] & 0x07;
|
||||
|
||||
/* Check the following header bytes, if we can */
|
||||
if ((14 + stuff_len + 4) <= len) {
|
||||
if (!IS_MPEG_HEADER (data + 14 + stuff_len))
|
||||
return FALSE;
|
||||
}
|
||||
++data;
|
||||
--len;
|
||||
}
|
||||
return;
|
||||
suggest:
|
||||
{
|
||||
GstCaps *caps = gst_caps_copy (MPEG_SYS_CAPS);
|
||||
if (pack_size)
|
||||
*pack_size = 14 + stuff_len;
|
||||
return TRUE;
|
||||
} else if ((data[4] & 0xF1) == 0x21) {
|
||||
/* MPEG-1 PACK */
|
||||
if ((data[6] & 0x01) != 0x01 ||
|
||||
(data[8] & 0x01) != 0x01 ||
|
||||
(data[9] & 0x80) != 0x80 || (data[11] & 0x01) != 0x01)
|
||||
return FALSE;
|
||||
|
||||
gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
|
||||
G_TYPE_INT, mpegversion, NULL);
|
||||
/* lower probability if the marker isn't right at the start */
|
||||
if (data0 == data)
|
||||
gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, caps);
|
||||
else
|
||||
gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE - 10, caps);
|
||||
gst_caps_unref (caps);
|
||||
/* Check the following header bytes, if we can */
|
||||
if ((12 + 4) <= len) {
|
||||
if (!IS_MPEG_HEADER (data + 12))
|
||||
return FALSE;
|
||||
}
|
||||
if (pack_size)
|
||||
*pack_size = 12;
|
||||
return TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
/* ATTENTION: ugly return value:
|
||||
* 0 - invalid data
|
||||
* 1 - not enough data
|
||||
* anything else - size until next package
|
||||
*/
|
||||
static guint
|
||||
mpeg1_parse_header (GstTypeFind * tf, guint64 offset)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mpeg_sys_is_valid_pes (GstTypeFind * tf, guint8 * data, guint len,
|
||||
guint * pack_size)
|
||||
{
|
||||
guint8 *data = gst_type_find_peek (tf, offset, 4);
|
||||
guint size;
|
||||
guint pes_packet_len;
|
||||
|
||||
if (!data) {
|
||||
GST_LOG ("couldn't get MPEG header bytes");
|
||||
return 1;
|
||||
/* Check the PES header at the given position, assuming the header code itself
|
||||
* was already checked */
|
||||
if (len < 6)
|
||||
return FALSE;
|
||||
|
||||
/* For MPEG Program streams, unbounded PES is not allowed, so we must have a
|
||||
* valid length present */
|
||||
pes_packet_len = GST_READ_UINT16_BE (data + 4);
|
||||
if (pes_packet_len == 0)
|
||||
return FALSE;
|
||||
|
||||
/* Check the following header, if we can */
|
||||
if (6 + pes_packet_len + 4 <= len) {
|
||||
if (!IS_MPEG_HEADER (data + 6 + pes_packet_len))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (data[0] != 0 || data[1] != 0 || data[2] != 1) {
|
||||
GST_LOG ("no sync");
|
||||
return 0;
|
||||
}
|
||||
offset += 4;
|
||||
if (pack_size)
|
||||
*pack_size = 6 + pes_packet_len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_LOG ("sync %02x", data[3]);
|
||||
static gboolean
|
||||
mpeg_sys_is_valid_sys (GstTypeFind * tf, guint8 * data, guint len,
|
||||
guint * pack_size)
|
||||
{
|
||||
guint sys_hdr_len;
|
||||
|
||||
switch (data[3]) {
|
||||
case 0xBA: /* pack header */
|
||||
data = gst_type_find_peek (tf, offset, 8);
|
||||
if (!data) {
|
||||
GST_LOG ("couldn't get MPEG pack header bytes");
|
||||
return 1;
|
||||
}
|
||||
size = 12;
|
||||
/* check marker bits */
|
||||
if ((data[0] & 0xF1) != 0x21 ||
|
||||
(data[2] & 0x01) != 0x01 ||
|
||||
(data[4] & 0x01) != 0x01 ||
|
||||
(data[5] & 0x80) != 0x80 || (data[7] & 0x01) != 0x01) {
|
||||
GST_LOG ("wrong marker bits");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
/* Check the System header at the given position, assuming the header code itself
|
||||
* was already checked */
|
||||
if (len < 6)
|
||||
return FALSE;
|
||||
sys_hdr_len = GST_READ_UINT16_BE (data + 4);
|
||||
if (sys_hdr_len < 6)
|
||||
return FALSE;
|
||||
|
||||
case 0xB9: /* ISO end code */
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
case 0xBB: /* system header */
|
||||
data = gst_type_find_peek (tf, offset, 2);
|
||||
if (!data) {
|
||||
GST_LOG ("couldn't get MPEG pack header bytes");
|
||||
return 1;
|
||||
}
|
||||
size = GST_READ_UINT16_BE (data) + 6;
|
||||
offset += 2;
|
||||
data = gst_type_find_peek (tf, offset, size - 6);
|
||||
if (!data) {
|
||||
GST_LOG ("couldn't get MPEG pack header bytes");
|
||||
return 1;
|
||||
}
|
||||
/* check marker bits */
|
||||
if ((data[0] & 0x80) != 0x80 ||
|
||||
(data[2] & 0x01) != 0x01 || (data[4] & 0x20) != 0x20) {
|
||||
GST_LOG ("wrong marker bits");
|
||||
return 0;
|
||||
}
|
||||
/* check stream marker bits */
|
||||
for (offset = 6; offset < (size - 6); offset += 3) {
|
||||
if (data[offset] <= 0xBB || (data[offset + 1] & 0xC0) != 0xC0) {
|
||||
GST_LOG ("wrong marker bits");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (data[3] < 0xB9)
|
||||
return 0;
|
||||
data = gst_type_find_peek (tf, offset, 2);
|
||||
if (!data) {
|
||||
GST_LOG ("couldn't get MPEG pack header bytes");
|
||||
return 1;
|
||||
}
|
||||
size = GST_READ_UINT16_BE (data) + 6;
|
||||
/* FIXME: we could check PTS/DTS marker bits here... (bit overkill) */
|
||||
break;
|
||||
/* Check the following header, if we can */
|
||||
if (6 + sys_hdr_len + 4 <= len) {
|
||||
if (!IS_MPEG_HEADER (data + 6 + sys_hdr_len))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return size;
|
||||
if (pack_size)
|
||||
*pack_size = 6 + sys_hdr_len;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* calculation of possibility to identify random data as mpeg systemstream:
|
||||
* bits that must match in header detection: 32 (or more)
|
||||
* chance that random data is identifed: 1/2^32
|
||||
* chance that GST_MPEG_TYPEFIND_TRY_HEADERS headers are identified:
|
||||
* 1/2^(32*GST_MPEG_TYPEFIND_TRY_HEADERS)
|
||||
* chance that this happens in GST_MPEG_TYPEFIND_TRY_SYNC bytes:
|
||||
* 1-(1+1/2^(32*GST_MPEG_TYPEFIND_TRY_HEADERS)^GST_MPEG_TYPEFIND_TRY_SYNC)
|
||||
* chance that MPEG2_MIN_PACK_HEADERS headers are identified:
|
||||
* 1/2^(32*MPEG2_MIN_PACK_HEADERS)
|
||||
* chance that this happens in MPEG2_MAX_PROBE_LENGTH bytes:
|
||||
* 1-(1+1/2^(32*MPEG2_MIN_PACK_HEADERS)^MPEG2_MAX_PROBE_LENGTH)
|
||||
* for current values:
|
||||
* 1-(1+1/2^(32*4)^101024)
|
||||
* = <some_number>
|
||||
* 1-(1+1/2^(32*4)^101024)
|
||||
* = <some_number>
|
||||
* Since we also check marker bits and pes packet lengths, this probability is a
|
||||
* very coarse upper bound.
|
||||
*/
|
||||
#define GST_MPEG_TYPEFIND_TRY_HEADERS 4
|
||||
#define GST_MPEG_TYPEFIND_TRY_SYNC (100 * 1024) /* 100kB */
|
||||
#define GST_MPEG_TYPEFIND_SYNC_SIZE 2048
|
||||
static void
|
||||
mpeg1_sys_type_find (GstTypeFind * tf, gpointer unused)
|
||||
mpeg_sys_type_find (GstTypeFind * tf, gpointer unused)
|
||||
{
|
||||
guint8 *data = NULL;
|
||||
guint size = 0;
|
||||
guint64 skipped = 0;
|
||||
GstCaps *caps;
|
||||
guint8 *data, *data0, *first_sync, *end;
|
||||
gint mpegversion = 0;
|
||||
guint pack_headers = 0;
|
||||
guint pes_headers = 0;
|
||||
guint pack_size;
|
||||
guint since_last_sync = 0;
|
||||
guint32 sync_word = 0xffffffff;
|
||||
|
||||
while (skipped < GST_MPEG_TYPEFIND_TRY_SYNC) {
|
||||
if (size < 4) {
|
||||
data = gst_type_find_peek (tf, skipped, GST_MPEG_TYPEFIND_SYNC_SIZE);
|
||||
if (!data)
|
||||
break;
|
||||
size = GST_MPEG_TYPEFIND_SYNC_SIZE;
|
||||
}
|
||||
if (IS_MPEG_PACK_HEADER (data)) {
|
||||
/* found packet start code */
|
||||
guint found = 0;
|
||||
guint packet_size = 0;
|
||||
guint64 offset = skipped;
|
||||
G_STMT_START {
|
||||
gint len;
|
||||
|
||||
while (found < GST_MPEG_TYPEFIND_TRY_HEADERS) {
|
||||
packet_size = mpeg1_parse_header (tf, offset);
|
||||
if (packet_size <= 1)
|
||||
break;
|
||||
offset += packet_size;
|
||||
found++;
|
||||
}
|
||||
g_assert (found <= GST_MPEG_TYPEFIND_TRY_HEADERS);
|
||||
if (found == GST_MPEG_TYPEFIND_TRY_HEADERS || packet_size == 1) {
|
||||
GST_LOG ("suggesting mpeg1 system steeam");
|
||||
caps = gst_caps_copy (MPEG_SYS_CAPS);
|
||||
gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
|
||||
G_TYPE_INT, 1, NULL);
|
||||
gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 1, caps);
|
||||
gst_caps_unref (caps);
|
||||
return;
|
||||
}
|
||||
}
|
||||
data++;
|
||||
skipped++;
|
||||
size--;
|
||||
len = MPEG2_MAX_PROBE_LENGTH;
|
||||
do {
|
||||
len = len / 2;
|
||||
data = gst_type_find_peek (tf, 0, 5 + len);
|
||||
} while (data == NULL && len >= 32);
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
end = data + len;
|
||||
}
|
||||
}
|
||||
G_STMT_END;
|
||||
|
||||
data0 = data;
|
||||
first_sync = NULL;
|
||||
|
||||
while (data < end) {
|
||||
sync_word <<= 8;
|
||||
if (sync_word == 0x00000100) {
|
||||
/* Found potential sync word */
|
||||
if (first_sync == NULL)
|
||||
first_sync = data - 3;
|
||||
|
||||
if (since_last_sync > 4) {
|
||||
/* If more than 4 bytes since the last sync word, reset our counters,
|
||||
* as we're only interested in counting contiguous packets */
|
||||
pes_headers = pack_headers = 0;
|
||||
}
|
||||
pack_size = 0;
|
||||
|
||||
if (IS_MPEG_PACK_CODE (data[0])) {
|
||||
if ((data[1] & 0xC0) == 0x40) {
|
||||
/* MPEG-2 */
|
||||
mpegversion = 2;
|
||||
} else if ((data[1] & 0xF0) == 0x20) {
|
||||
mpegversion = 1;
|
||||
}
|
||||
if (mpegversion != 0 &&
|
||||
mpeg_sys_is_valid_pack (tf, data - 3, end - data + 3, &pack_size)) {
|
||||
pack_headers++;
|
||||
}
|
||||
} else if (IS_MPEG_PES_CODE (data[0])) {
|
||||
/* PES stream */
|
||||
if (mpeg_sys_is_valid_pes (tf, data - 3, end - data + 3, &pack_size)) {
|
||||
pes_headers++;
|
||||
if (mpegversion == 0)
|
||||
mpegversion = 2;
|
||||
}
|
||||
} else if (IS_MPEG_SYS_CODE (data[0])) {
|
||||
if (mpeg_sys_is_valid_sys (tf, data - 3, end - data + 3, &pack_size)) {
|
||||
pack_headers++;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found a packet with a known size, skip the bytes in it and loop
|
||||
* around to check the next packet. */
|
||||
if (pack_size != 0) {
|
||||
data += pack_size - 3;
|
||||
sync_word = 0xffffffff;
|
||||
since_last_sync = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sync_word |= data[0];
|
||||
since_last_sync++;
|
||||
data++;
|
||||
|
||||
/* If we have found MAX headers, and *some* were pes headers (pack headers
|
||||
* are optional in an mpeg system stream) then return our high-probability
|
||||
* result */
|
||||
if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MAX_SYS_HEADERS)
|
||||
goto suggest;
|
||||
}
|
||||
|
||||
/* If we at least saw MIN headers, and *some* were pes headers (pack headers
|
||||
* are optional in an mpeg system stream) then return a lower-probability
|
||||
* result */
|
||||
if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MIN_SYS_HEADERS)
|
||||
goto suggest;
|
||||
|
||||
return;
|
||||
suggest:
|
||||
{
|
||||
GstCaps *caps = gst_caps_copy (MPEG_SYS_CAPS);
|
||||
guint prob;
|
||||
|
||||
prob = GST_TYPE_FIND_POSSIBLE + (10 * (pack_headers + pes_headers));
|
||||
prob = MIN (prob, GST_TYPE_FIND_MAXIMUM);
|
||||
|
||||
/* lower probability if the first packet wasn't right at the start */
|
||||
if (data0 != first_sync && prob >= 10)
|
||||
prob -= 10;
|
||||
|
||||
GST_LOG ("Suggesting MPEG %d system stream, %d packs, %d pes, prob %u%%\n",
|
||||
mpegversion, pack_headers, pes_headers, prob);
|
||||
|
||||
gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
|
||||
G_TYPE_INT, mpegversion, NULL);
|
||||
gst_type_find_suggest (tf, prob, caps);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
};
|
||||
|
||||
/** video/mpegts Transport Stream **/
|
||||
static GstStaticCaps mpegts_caps = GST_STATIC_CAPS ("video/mpegts, "
|
||||
|
@ -1315,13 +1355,14 @@ static GstStaticCaps mpegts_caps = GST_STATIC_CAPS ("video/mpegts, "
|
|||
|
||||
#define GST_MPEGTS_TYPEFIND_MIN_HEADERS 4
|
||||
#define GST_MPEGTS_TYPEFIND_MAX_HEADERS 10
|
||||
#define GST_MPEGTS_MAX_PACKET_SIZE 204
|
||||
#define GST_MPEGTS_MAX_PACKET_SIZE 208
|
||||
#define GST_MPEGTS_TYPEFIND_SYNC_SIZE \
|
||||
(GST_MPEGTS_TYPEFIND_MIN_HEADERS * GST_MPEGTS_MAX_PACKET_SIZE)
|
||||
#define GST_MPEGTS_TYPEFIND_MAX_SYNC \
|
||||
(GST_MPEGTS_TYPEFIND_MAX_HEADERS * GST_MPEGTS_MAX_PACKET_SIZE)
|
||||
|
||||
#define MPEGTS_HDR_SIZE 4
|
||||
/* Check for sync byte, error_indicator == 0 and packet has payload */
|
||||
#define IS_MPEGTS_HEADER(data) (((data)[0] == 0x47) && \
|
||||
(((data)[1] & 0x80) == 0x00) && \
|
||||
(((data)[3] & 0x10) == 0x10))
|
||||
|
@ -1389,8 +1430,7 @@ mpeg_ts_type_find (GstTypeFind * tf, gpointer unused)
|
|||
/* found at least 4 headers. 10 headers = MAXIMUM probability.
|
||||
* Arbitrarily, I assigned 10% probability for each header we
|
||||
* found, 40% -> 100% */
|
||||
|
||||
probability = 10 * MIN (found, 10);
|
||||
probability = MIN (10 * found, GST_TYPE_FIND_MAXIMUM);
|
||||
|
||||
gst_type_find_suggest (tf, probability, caps);
|
||||
gst_caps_unref (caps);
|
||||
|
@ -1424,7 +1464,7 @@ mpeg4_video_type_find (GstTypeFind * tf, gpointer unused)
|
|||
|
||||
while (TRUE) {
|
||||
data = gst_type_find_peek (tf, offset, 4);
|
||||
if (data && data[0] == 0 && data[1] == 0 && data[2] == 1) {
|
||||
if (data && IS_MPEG_HEADER (data)) {
|
||||
int sc = data[3];
|
||||
|
||||
if (sc == 0xB0) /* visual_object_sequence_start_code */
|
||||
|
@ -1468,7 +1508,7 @@ mpeg_video_type_find (GstTypeFind * tf, gpointer unused)
|
|||
|
||||
gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
|
||||
G_TYPE_INT, 1, NULL);
|
||||
gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 1, caps);
|
||||
gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, caps);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
}
|
||||
|
@ -1514,25 +1554,33 @@ mpeg_video_stream_type_find (GstTypeFind * tf, gpointer unused)
|
|||
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)
|
||||
if (IS_MPEG_HEADER (data)) {
|
||||
/* An MPEG PACK header indicates that this isn't an elementary stream */
|
||||
if (IS_MPEG_PACK_CODE (data[3])) {
|
||||
if (mpeg_sys_is_valid_pack (tf, data, size, NULL))
|
||||
break;
|
||||
}
|
||||
/* else, we should now see an image */
|
||||
|
||||
/* are we a sequence (0xB3) or GOP (0xB8) header? */
|
||||
if (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) {
|
||||
if (IS_MPEG_HEADER (data) && data[4] == 0x0) {
|
||||
size -= 8;
|
||||
data += 8;
|
||||
skipped += 8;
|
||||
|
@ -1542,10 +1590,8 @@ mpeg_video_stream_type_find (GstTypeFind * tf, gpointer unused)
|
|||
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)) {
|
||||
if ((IS_MPEG_HEADER (data) && data[3] == 0x1) ||
|
||||
(IS_MPEG_HEADER (data + 1) && data[4] == 0x1)) {
|
||||
size -= 4;
|
||||
data += 4;
|
||||
skipped += 4;
|
||||
|
@ -2823,15 +2869,13 @@ plugin_init (GstPlugin * plugin)
|
|||
mp3_exts, MP3_CAPS, NULL, NULL);
|
||||
TYPE_FIND_REGISTER (plugin, "audio/x-ac3", GST_RANK_PRIMARY, ac3_type_find,
|
||||
ac3_exts, AC3_CAPS, NULL, NULL);
|
||||
TYPE_FIND_REGISTER (plugin, "video/mpeg1", GST_RANK_PRIMARY,
|
||||
mpeg1_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL);
|
||||
TYPE_FIND_REGISTER (plugin, "video/mpeg2", GST_RANK_SECONDARY,
|
||||
mpeg2_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL);
|
||||
TYPE_FIND_REGISTER (plugin, "video/mpeg-sys", GST_RANK_PRIMARY,
|
||||
mpeg_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL);
|
||||
TYPE_FIND_REGISTER (plugin, "video/mpegts", GST_RANK_PRIMARY,
|
||||
mpeg_ts_type_find, mpeg_ts_exts, MPEGTS_CAPS, NULL, NULL);
|
||||
TYPE_FIND_REGISTER (plugin, "application/ogg", GST_RANK_PRIMARY,
|
||||
ogganx_type_find, ogg_exts, OGGANX_CAPS, NULL, NULL);
|
||||
TYPE_FIND_REGISTER (plugin, "video/mpeg", GST_RANK_SECONDARY,
|
||||
TYPE_FIND_REGISTER (plugin, "video/mpeg,elementary", GST_RANK_SECONDARY,
|
||||
mpeg_video_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL, NULL);
|
||||
TYPE_FIND_REGISTER (plugin, "video/mpeg-stream", GST_RANK_MARGINAL,
|
||||
mpeg_video_stream_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL,
|
||||
|
|
Loading…
Reference in a new issue