mpegtsdemux: added autodetect of packet size and removed m2ts mode property

This commit is contained in:
Josep Torra 2009-09-04 12:30:18 +02:00
parent e7f883a272
commit 659e90f8f6
2 changed files with 35 additions and 39 deletions

View file

@ -103,7 +103,6 @@ enum
PROP_PROGRAM_NUMBER, PROP_PROGRAM_NUMBER,
PROP_PAT_INFO, PROP_PAT_INFO,
PROP_PMT_INFO, PROP_PMT_INFO,
PROP_M2TS
}; };
#define GSTTIME_TO_BYTES(time) \ #define GSTTIME_TO_BYTES(time) \
@ -307,11 +306,6 @@ gst_mpegts_demux_class_init (GstMpegTSDemuxClass * klass)
"about the currently selected program and its streams", "about the currently selected program and its streams",
MPEGTS_TYPE_PMT_INFO, G_PARAM_READABLE)); MPEGTS_TYPE_PMT_INFO, G_PARAM_READABLE));
g_object_class_install_property (gobject_class, PROP_M2TS,
g_param_spec_boolean ("m2ts_mode", "M2TS(192 bytes) Mode",
"Defines if the input is normal TS ie .ts(188 bytes)"
"or Blue-Ray Format ie .m2ts(192 bytes).", FALSE, G_PARAM_READWRITE));
gstelement_class->change_state = gst_mpegts_demux_change_state; gstelement_class->change_state = gst_mpegts_demux_change_state;
gstelement_class->provide_clock = gst_mpegts_demux_provide_clock; gstelement_class->provide_clock = gst_mpegts_demux_provide_clock;
} }
@ -333,8 +327,6 @@ gst_mpegts_demux_init (GstMpegTSDemux * demux)
demux->nb_elementary_pids = 0; demux->nb_elementary_pids = 0;
demux->check_crc = DEFAULT_PROP_CHECK_CRC; demux->check_crc = DEFAULT_PROP_CHECK_CRC;
demux->program_number = DEFAULT_PROP_PROGRAM_NUMBER; demux->program_number = DEFAULT_PROP_PROGRAM_NUMBER;
demux->packetsize = MPEGTS_NORMAL_TS_PACKETSIZE;
demux->m2ts_mode = FALSE;
demux->sync_lut = NULL; demux->sync_lut = NULL;
demux->sync_lut_len = 0; demux->sync_lut_len = 0;
demux->bitrate = -1; demux->bitrate = -1;
@ -487,34 +479,18 @@ static gboolean
gst_mpegts_demux_sink_setcaps (GstPad * pad, GstCaps * caps) gst_mpegts_demux_sink_setcaps (GstPad * pad, GstCaps * caps)
{ {
GstMpegTSDemux *demux = GST_MPEGTS_DEMUX (gst_pad_get_parent (pad)); GstMpegTSDemux *demux = GST_MPEGTS_DEMUX (gst_pad_get_parent (pad));
gboolean ret = FALSE;
GstStructure *structure = NULL; GstStructure *structure = NULL;
gint expected_packetsize =
(demux->m2ts_mode ? MPEGTS_M2TS_TS_PACKETSIZE :
MPEGTS_NORMAL_TS_PACKETSIZE);
gint packetsize = expected_packetsize;
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
GST_DEBUG_OBJECT (demux, "setcaps called with %" GST_PTR_FORMAT, caps); GST_DEBUG_OBJECT (demux, "setcaps called with %" GST_PTR_FORMAT, caps);
if (!gst_structure_get_int (structure, "packetsize", &packetsize)) { if (!gst_structure_get_int (structure, "packetsize", &demux->packetsize)) {
GST_DEBUG_OBJECT (demux, "packetsize parameter not found in sink caps"); GST_DEBUG_OBJECT (demux, "packetsize parameter not found in sink caps");
} }
if (packetsize < expected_packetsize) {
GST_WARNING_OBJECT (demux, "packetsize = %" G_GINT32_FORMAT "is less then"
"expected packetsize of %d bytes", packetsize, expected_packetsize);
goto beach;
}
/* here we my have a correct value for packet size */
demux->packetsize = packetsize;
ret = TRUE;
beach:
gst_object_unref (demux); gst_object_unref (demux);
return ret; return TRUE;
} }
static FORCE_INLINE guint32 static FORCE_INLINE guint32
@ -2901,6 +2877,26 @@ is_mpegts_sync (const guint8 * in_data, const guint8 * end_data,
return ret; return ret;
} }
static inline void
gst_mpegts_demux_detect_packet_size (GstMpegTSDemux * demux, guint len)
{
guint i, packetsize;
for (i = 1; i < len; i++) {
packetsize = demux->sync_lut[i] - demux->sync_lut[i - 1];
if (packetsize == MPEGTS_NORMAL_TS_PACKETSIZE ||
packetsize == MPEGTS_M2TS_TS_PACKETSIZE ||
packetsize == MPEGTS_DVB_ASI_TS_PACKETSIZE ||
packetsize == MPEGTS_ATSC_TS_PACKETSIZE)
goto done;
else
packetsize = 0;
}
done:
demux->packetsize = (packetsize ? packetsize : MPEGTS_NORMAL_TS_PACKETSIZE);
GST_DEBUG_OBJECT (demux, "packet_size set to %d bytes", demux->packetsize);
}
static FORCE_INLINE guint static FORCE_INLINE guint
gst_mpegts_demux_sync_scan (GstMpegTSDemux * demux, const guint8 * in_data, gst_mpegts_demux_sync_scan (GstMpegTSDemux * demux, const guint8 * in_data,
@ -2909,10 +2905,12 @@ gst_mpegts_demux_sync_scan (GstMpegTSDemux * demux, const guint8 * in_data,
guint sync_count = 0; guint sync_count = 0;
const guint8 *end_scan = in_data + size - demux->packetsize; const guint8 *end_scan = in_data + size - demux->packetsize;
guint8 *ptr_data = (guint8 *) in_data; guint8 *ptr_data = (guint8 *) in_data;
guint packetsize =
(demux->packetsize ? demux->packetsize : MPEGTS_NORMAL_TS_PACKETSIZE);
/* Check if the LUT table is big enough */ /* Check if the LUT table is big enough */
if (G_UNLIKELY (demux->sync_lut_len < (size / MPEGTS_NORMAL_TS_PACKETSIZE))) { if (G_UNLIKELY (demux->sync_lut_len < (size / packetsize))) {
demux->sync_lut_len = size / MPEGTS_NORMAL_TS_PACKETSIZE; demux->sync_lut_len = size / packetsize;
if (demux->sync_lut) if (demux->sync_lut)
g_free (demux->sync_lut); g_free (demux->sync_lut);
demux->sync_lut = g_new0 (guint8 *, demux->sync_lut_len); demux->sync_lut = g_new0 (guint8 *, demux->sync_lut_len);
@ -2922,22 +2920,24 @@ gst_mpegts_demux_sync_scan (GstMpegTSDemux * demux, const guint8 * in_data,
while (ptr_data <= end_scan && sync_count < demux->sync_lut_len) { while (ptr_data <= end_scan && sync_count < demux->sync_lut_len) {
/* if sync code is found try to store it in the LUT */ /* if sync code is found try to store it in the LUT */
guint chance = is_mpegts_sync (ptr_data, end_scan, demux->packetsize); guint chance = is_mpegts_sync (ptr_data, end_scan, packetsize);
if (G_LIKELY (chance > 50)) { if (G_LIKELY (chance > 50)) {
/* skip paketsize bytes and try find next */ /* skip paketsize bytes and try find next */
guint8 *next_sync = ptr_data + demux->packetsize; guint8 *next_sync = ptr_data + packetsize;
if (next_sync < end_scan) { if (next_sync < end_scan) {
demux->sync_lut[sync_count] = ptr_data; demux->sync_lut[sync_count] = ptr_data;
sync_count++; sync_count++;
ptr_data += demux->packetsize; ptr_data += packetsize;
} else } else
goto done; goto done;
} else { } else {
ptr_data++; ptr_data++;
} }
} }
done: done:
if (G_UNLIKELY (!demux->packetsize))
gst_mpegts_demux_detect_packet_size (demux, sync_count);
*flush = ptr_data - in_data; *flush = ptr_data - in_data;
return sync_count; return sync_count;
@ -3147,9 +3147,6 @@ gst_mpegts_demux_set_property (GObject * object, guint prop_id,
case PROP_PROGRAM_NUMBER: case PROP_PROGRAM_NUMBER:
demux->program_number = g_value_get_int (value); demux->program_number = g_value_get_int (value);
break; break;
case PROP_M2TS:
demux->m2ts_mode = g_value_get_boolean (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -3200,9 +3197,6 @@ gst_mpegts_demux_get_property (GObject * object, guint prop_id,
} }
break; break;
} }
case PROP_M2TS:
g_value_set_boolean (value, demux->m2ts_mode);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;

View file

@ -59,6 +59,8 @@ G_BEGIN_DECLS
#define MPEGTS_MAX_PID 0x1fff #define MPEGTS_MAX_PID 0x1fff
#define MPEGTS_NORMAL_TS_PACKETSIZE 188 #define MPEGTS_NORMAL_TS_PACKETSIZE 188
#define MPEGTS_M2TS_TS_PACKETSIZE 192 #define MPEGTS_M2TS_TS_PACKETSIZE 192
#define MPEGTS_DVB_ASI_TS_PACKETSIZE 204
#define MPEGTS_ATSC_TS_PACKETSIZE 208
#define IS_MPEGTS_SYNC(data) (((data)[0] == 0x47) && \ #define IS_MPEGTS_SYNC(data) (((data)[0] == 0x47) && \
(((data)[1] & 0x80) == 0x00) && \ (((data)[1] & 0x80) == 0x00) && \
@ -200,7 +202,7 @@ struct _GstMpegTSDemux {
/* indicates that we need to close our pad group, because we've added /* indicates that we need to close our pad group, because we've added
* at least one pad */ * at least one pad */
gboolean need_no_more_pads; gboolean need_no_more_pads;
guint16 packetsize; gint packetsize;
gboolean m2ts_mode; gboolean m2ts_mode;
/* clocking */ /* clocking */
GstClock * clock; GstClock * clock;