typefind: Hold off making suggestions too early for MPEG based formats

By suggesting possible detection too early, it's possible that
the wrong format is detected. Hold off making suggestions until one
of the following conditions is met:
* Probability > GST_TYPE_FIND_LIKELY
* At least MPEG_MIN_PROBE_LENGTH bytes have been examined
* EOS, in which case the best guess wins

Fixes #628
This commit is contained in:
Thomas Bluemel 2019-06-26 15:53:11 -06:00 committed by Thomas Bluemel
parent 8f125fb4d9
commit 36319169d0

View file

@ -2159,12 +2159,27 @@ static GstStaticCaps mpeg_sys_caps = GST_STATIC_CAPS ("video/mpeg, "
#define IS_MPEG_PES_HEADER(data) (IS_MPEG_HEADER (data) && \
IS_MPEG_PES_CODE (((guint8 *)(data))[3]))
#define MPEG_MIN_PROBE_LENGTH (4 * 1024) /* Examine at least 4kB of data to
* give the various MPEG formats enough
* data to avoid mis-detections. */
#define MPEG2_MAX_PROBE_LENGTH (128 * 1024) /* 128kB should be 64 packs of the
* most common 2kB pack size. */
#define MPEG2_MIN_SYS_HEADERS 2
#define MPEG2_MAX_SYS_HEADERS 5
static gboolean
mpeg_should_suggest (GstTypeFind * tf, GstTypeFindProbability prob, guint size)
{
/* only suggest if we probed at least a certain amount of data, if
* we have a high confindence, or when we reached eos. This gives
* various MPEG based formats a better chance of correctly identifying
* the data. */
return prob > GST_TYPE_FIND_LIKELY || size >= MPEG_MIN_PROBE_LENGTH ||
gst_type_find_is_eos (tf);
}
static gboolean
mpeg_sys_is_valid_pack (GstTypeFind * tf, const guint8 * data, guint len,
guint * pack_size)
@ -2407,6 +2422,9 @@ suggest:
if (data0 != first_sync && prob >= 10)
prob -= 10;
if (!mpeg_should_suggest (tf, prob, end - data0))
return;
GST_LOG ("Suggesting MPEG %d system stream, %d packs, %d pes, prob %u%%",
mpegversion, pack_headers, pes_headers, prob);
@ -2505,6 +2523,9 @@ mpeg_ts_type_find (GstTypeFind * tf, gpointer unused)
* found, 40% -> 100% */
probability = MIN (10 * found, GST_TYPE_FIND_MAXIMUM);
if (!mpeg_should_suggest (tf, probability, size))
return;
gst_type_find_suggest_simple (tf, probability, "video/mpegts",
"systemstream", G_TYPE_BOOLEAN, TRUE,
"packetsize", G_TYPE_INT, pack_sizes[p], NULL);
@ -2664,7 +2685,8 @@ mpeg4_video_type_find (GstTypeFind * tf, gpointer unused)
else if (seen_vos && seen_vol)
probability = GST_TYPE_FIND_POSSIBLE - 20;
gst_type_find_suggest (tf, probability, MPEG4_VIDEO_CAPS);
if (mpeg_should_suggest (tf, probability, c.size))
gst_type_find_suggest (tf, probability, MPEG4_VIDEO_CAPS);
}
}
@ -2807,7 +2829,8 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
GST_LOG ("good:%d, bad:%d, pps:%d, sps:%d, idr:%d ssps:%d", good, bad,
seen_pps, seen_sps, seen_idr, seen_ssps);
if (seen_sps && seen_pps && seen_idr && good >= 10 && bad < 4) {
if (seen_sps && seen_pps && seen_idr && good >= 10 && bad < 4
&& mpeg_should_suggest (tf, GST_TYPE_FIND_LIKELY, c.size)) {
gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H264_VIDEO_CAPS);
return;
}
@ -2820,7 +2843,8 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
GST_LOG ("good:%d, bad:%d, pps:%d, sps:%d, idr:%d ssps=%d", good, bad,
seen_pps, seen_sps, seen_idr, seen_ssps);
if (good >= 2 && bad == 0) {
if (good >= 2 && bad == 0
&& mpeg_should_suggest (tf, GST_TYPE_FIND_POSSIBLE, c.size)) {
gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, H264_VIDEO_CAPS);
}
}
@ -2900,7 +2924,8 @@ h265_video_type_find (GstTypeFind * tf, gpointer unused)
GST_LOG ("good:%d, bad:%d, pps:%d, sps:%d, vps:%d, irap:%d", good, bad,
seen_pps, seen_sps, seen_vps, seen_irap);
if (seen_sps && seen_pps && seen_irap && good >= 10 && bad < 4) {
if (seen_sps && seen_pps && seen_irap && good >= 10 && bad < 4
&& mpeg_should_suggest (tf, GST_TYPE_FIND_LIKELY, c.size)) {
gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H265_VIDEO_CAPS);
return;
}
@ -2913,7 +2938,8 @@ h265_video_type_find (GstTypeFind * tf, gpointer unused)
GST_LOG ("good:%d, bad:%d, pps:%d, sps:%d, vps:%d, irap:%d", good, bad,
seen_pps, seen_sps, seen_vps, seen_irap);
if (good >= 2 && bad == 0) {
if (good >= 2 && bad == 0
&& mpeg_should_suggest (tf, GST_TYPE_FIND_POSSIBLE, c.size)) {
gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, H265_VIDEO_CAPS);
}
}
@ -3020,9 +3046,11 @@ mpeg_video_stream_type_find (GstTypeFind * tf, gpointer unused)
else if (seen_seq)
probability = GST_TYPE_FIND_POSSIBLE - 20;
gst_type_find_suggest_simple (tf, probability, "video/mpeg",
"systemstream", G_TYPE_BOOLEAN, FALSE,
"mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, FALSE, NULL);
if (mpeg_should_suggest (tf, probability, c.size)) {
gst_type_find_suggest_simple (tf, probability, "video/mpeg",
"systemstream", G_TYPE_BOOLEAN, FALSE,
"mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, FALSE, NULL);
}
}
}