gst/mpegdemux/gstmpegtsdemux.*: Properly handle some resync cases in the optimised buffering strategy.
Original commit message from CVS: Patch by: Josep Torra * gst/mpegdemux/gstmpegtsdemux.c: * gst/mpegdemux/gstmpegtsdemux.h: Properly handle some resync cases in the optimised buffering strategy.
This commit is contained in:
parent
4a7573c61a
commit
e758c7dc23
@ -1,3 +1,12 @@
|
|||||||
|
2008-10-16 Zaheer Abbas Merali <zaheerabbas at merali dot org>
|
||||||
|
|
||||||
|
Patch by: Josep Torra
|
||||||
|
|
||||||
|
* gst/mpegdemux/gstmpegtsdemux.c:
|
||||||
|
* gst/mpegdemux/gstmpegtsdemux.h:
|
||||||
|
Properly handle some resync cases in the optimised
|
||||||
|
buffering strategy.
|
||||||
|
|
||||||
2008-10-16 Michael Smith <msmith@songbirdnest.com>
|
2008-10-16 Michael Smith <msmith@songbirdnest.com>
|
||||||
* sys/acmenc/Makefile.am:
|
* sys/acmenc/Makefile.am:
|
||||||
Remove incorrect use of DIRECTSOUND_LDFLAGS
|
Remove incorrect use of DIRECTSOUND_LDFLAGS
|
||||||
|
@ -1046,7 +1046,7 @@ gst_fluts_demux_get_stream_for_PID (GstFluTSDemux * demux, guint16 PID)
|
|||||||
stream->PAT.version_number = -1;
|
stream->PAT.version_number = -1;
|
||||||
stream->PMT_pid = FLUTS_MAX_PID + 1;
|
stream->PMT_pid = FLUTS_MAX_PID + 1;
|
||||||
stream->flags |= FLUTS_STREAM_FLAG_STREAM_TYPE_UNKNOWN;
|
stream->flags |= FLUTS_STREAM_FLAG_STREAM_TYPE_UNKNOWN;
|
||||||
|
stream->pes_buffer_in_sync = FALSE;
|
||||||
switch (PID) {
|
switch (PID) {
|
||||||
/* check for fixed mapping */
|
/* check for fixed mapping */
|
||||||
case PID_PROGRAM_ASSOCIATION_TABLE:
|
case PID_PROGRAM_ASSOCIATION_TABLE:
|
||||||
@ -1959,6 +1959,8 @@ gst_fluts_stream_pes_buffer_flush (GstFluTSStream * stream)
|
|||||||
if (stream->pes_buffer) {
|
if (stream->pes_buffer) {
|
||||||
GST_BUFFER_SIZE (stream->pes_buffer) = stream->pes_buffer_used;
|
GST_BUFFER_SIZE (stream->pes_buffer) = stream->pes_buffer_used;
|
||||||
ret = gst_pes_filter_push (&stream->filter, stream->pes_buffer);
|
ret = gst_pes_filter_push (&stream->filter, stream->pes_buffer);
|
||||||
|
if (ret == GST_FLOW_LOST_SYNC)
|
||||||
|
stream->pes_buffer_in_sync = FALSE;
|
||||||
stream->pes_buffer = NULL;
|
stream->pes_buffer = NULL;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -1981,6 +1983,8 @@ gst_fluts_stream_pes_buffer_push (GstFluTSStream * stream,
|
|||||||
stream->pes_buffer_size <<= 1;
|
stream->pes_buffer_size <<= 1;
|
||||||
|
|
||||||
ret = gst_fluts_stream_pes_buffer_flush (stream);
|
ret = gst_fluts_stream_pes_buffer_flush (stream);
|
||||||
|
if (ret == GST_FLOW_LOST_SYNC)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G_UNLIKELY (!stream->pes_buffer)) {
|
if (G_UNLIKELY (!stream->pes_buffer)) {
|
||||||
@ -1998,7 +2002,7 @@ gst_fluts_stream_pes_buffer_push (GstFluTSStream * stream,
|
|||||||
memcpy (out_data, in_data, in_size);
|
memcpy (out_data, in_data, in_size);
|
||||||
#endif
|
#endif
|
||||||
stream->pes_buffer_used += in_size;
|
stream->pes_buffer_used += in_size;
|
||||||
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2011,13 +2015,32 @@ gst_fluts_demux_pes_buffer_flush (GstFluTSDemux * demux)
|
|||||||
for (i = 0; i < FLUTS_MAX_PID + 1; i++) {
|
for (i = 0; i < FLUTS_MAX_PID + 1; i++) {
|
||||||
GstFluTSStream *stream = demux->streams[i];
|
GstFluTSStream *stream = demux->streams[i];
|
||||||
if (stream && stream->pad) {
|
if (stream && stream->pad) {
|
||||||
ret = gst_fluts_stream_pes_buffer_flush (stream);
|
gst_fluts_stream_pes_buffer_flush (stream);
|
||||||
if (G_UNLIKELY (ret == GST_FLOW_OK))
|
stream->pes_buffer_in_sync = FALSE;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
static FORCE_INLINE GstFlowReturn
|
||||||
|
gst_fluts_demux_push_fragment (GstFluTSStream * stream,
|
||||||
|
const guint8 * in_data, guint in_size)
|
||||||
|
{
|
||||||
|
GstFlowReturn ret;
|
||||||
|
GstBuffer *es_buf = gst_buffer_new_and_alloc (in_size);
|
||||||
|
#ifdef USE_LIBOIL
|
||||||
|
oil_memcpy (GST_BUFFER_DATA (es_buf), in_data, in_size);
|
||||||
|
#else
|
||||||
|
memcpy (GST_BUFFER_DATA (es_buf), in_data, in_size);
|
||||||
|
#endif
|
||||||
|
ret = gst_pes_filter_push (&stream->filter, es_buf);
|
||||||
|
|
||||||
|
/* If PES filter return ok then PES fragment buffering
|
||||||
|
* can be enabled */
|
||||||
|
if (ret == GST_FLOW_OK)
|
||||||
|
stream->pes_buffer_in_sync = TRUE;
|
||||||
|
else if (ret == GST_FLOW_LOST_SYNC)
|
||||||
|
stream->pes_buffer_in_sync = FALSE;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2207,7 +2230,7 @@ gst_fluts_demux_parse_stream (GstFluTSDemux * demux, GstFluTSStream * stream,
|
|||||||
"bytes of %u bytes in the PES buffer",
|
"bytes of %u bytes in the PES buffer",
|
||||||
PID, stream->pes_buffer_used, stream->pes_buffer_size);
|
PID, stream->pes_buffer_used, stream->pes_buffer_size);
|
||||||
/* Flush buffered PES data */
|
/* Flush buffered PES data */
|
||||||
ret = gst_fluts_stream_pes_buffer_flush (stream);
|
gst_fluts_stream_pes_buffer_flush (stream);
|
||||||
gst_pes_filter_drain (&stream->filter);
|
gst_pes_filter_drain (&stream->filter);
|
||||||
/* Resize the buffer to half if no overflow detected and
|
/* Resize the buffer to half if no overflow detected and
|
||||||
* had been used less than half of it */
|
* had been used less than half of it */
|
||||||
@ -2219,15 +2242,33 @@ gst_fluts_demux_parse_stream (GstFluTSDemux * demux, GstFluTSStream * stream,
|
|||||||
GST_DEBUG_OBJECT (demux, "PES buffer size reduced to %u bytes",
|
GST_DEBUG_OBJECT (demux, "PES buffer size reduced to %u bytes",
|
||||||
stream->pes_buffer_size);
|
stream->pes_buffer_size);
|
||||||
}
|
}
|
||||||
if (ret == GST_FLOW_LOST_SYNC)
|
/* mark the stream not in sync to give a chance on PES filter to
|
||||||
goto done;
|
* detect lost sync */
|
||||||
|
stream->pes_buffer_in_sync = FALSE;
|
||||||
stream->pes_buffer_overflow = FALSE;
|
stream->pes_buffer_overflow = FALSE;
|
||||||
}
|
}
|
||||||
GST_LOG_OBJECT (demux, "Elementary packet of size %u for PID 0x%04x",
|
GST_LOG_OBJECT (demux, "Elementary packet of size %u for PID 0x%04x",
|
||||||
datalen, PID);
|
datalen, PID);
|
||||||
|
|
||||||
if (datalen > 0) {
|
if (datalen > 0) {
|
||||||
|
if (!stream->pes_buffer_in_sync) {
|
||||||
|
/* Push the first fragment to PES filter to have a chance to
|
||||||
|
* detect GST_FLOW_LOST_SYNC.
|
||||||
|
*/
|
||||||
|
GST_LOG_OBJECT (demux, "fragment directly pushed to PES filter");
|
||||||
|
ret = gst_fluts_demux_push_fragment (stream, data, datalen);
|
||||||
|
} else {
|
||||||
|
/* Otherwhise we buffer the PES fragment */
|
||||||
ret = gst_fluts_stream_pes_buffer_push (stream, data, datalen);
|
ret = gst_fluts_stream_pes_buffer_push (stream, data, datalen);
|
||||||
|
/* If sync is lost here is due a pes_buffer_flush and we can try
|
||||||
|
* to resync in the PES filter with the current fragment
|
||||||
|
*/
|
||||||
|
if (ret == GST_FLOW_LOST_SYNC) {
|
||||||
|
GST_LOG_OBJECT (demux, "resync, fragment pushed to PES filter");
|
||||||
|
ret = gst_fluts_demux_push_fragment (stream, data, datalen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING_OBJECT (demux, "overflow of datalen: %u so skipping",
|
GST_WARNING_OBJECT (demux, "overflow of datalen: %u so skipping",
|
||||||
@ -2428,15 +2469,20 @@ gst_fluts_demux_sync_scan (GstFluTSDemux * demux, const guint8 * in_data,
|
|||||||
while (ptr_data <= end_scan && sync_count < LENGHT_SYNC_LUT) {
|
while (ptr_data <= end_scan && sync_count < LENGHT_SYNC_LUT) {
|
||||||
/* if sync code is found try to store it in the LUT */
|
/* if sync code is found try to store it in the LUT */
|
||||||
if (G_LIKELY (IS_MPEGTS_SYNC (ptr_data))) {
|
if (G_LIKELY (IS_MPEGTS_SYNC (ptr_data))) {
|
||||||
|
/* skip paketsize bytes and try find next */
|
||||||
|
guint8 *next_sync = ptr_data + demux->packetsize;
|
||||||
|
if (next_sync < end_scan) {
|
||||||
demux->sync_lut[sync_count] = ptr_data;
|
demux->sync_lut[sync_count] = ptr_data;
|
||||||
sync_count++;
|
sync_count++;
|
||||||
/* skip paketsize bytes and try find next */
|
|
||||||
ptr_data += demux->packetsize;
|
ptr_data += demux->packetsize;
|
||||||
|
} else
|
||||||
|
goto done;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ptr_data++;
|
ptr_data++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
*flush = ptr_data - in_data;
|
*flush = ptr_data - in_data;
|
||||||
|
|
||||||
return sync_count;
|
return sync_count;
|
||||||
@ -2453,9 +2499,11 @@ gst_fluts_demux_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
gint i;
|
gint i;
|
||||||
guint sync_count;
|
guint sync_count;
|
||||||
|
|
||||||
if (GST_BUFFER_IS_DISCONT (buffer))
|
if (GST_BUFFER_IS_DISCONT (buffer)) {
|
||||||
|
/* Flush buffered PES data */
|
||||||
|
gst_fluts_demux_pes_buffer_flush (demux);
|
||||||
gst_adapter_clear (demux->adapter);
|
gst_adapter_clear (demux->adapter);
|
||||||
|
}
|
||||||
/* first push the new buffer into the adapter */
|
/* first push the new buffer into the adapter */
|
||||||
gst_adapter_push (demux->adapter, buffer);
|
gst_adapter_push (demux->adapter, buffer);
|
||||||
|
|
||||||
@ -2473,19 +2521,24 @@ gst_fluts_demux_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
/* process all packets */
|
/* process all packets */
|
||||||
for (i = 0; i < sync_count; i++) {
|
for (i = 0; i < sync_count; i++) {
|
||||||
ret = gst_fluts_demux_parse_transport_packet (demux, demux->sync_lut[i]);
|
ret = gst_fluts_demux_parse_transport_packet (demux, demux->sync_lut[i]);
|
||||||
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
|
if (G_UNLIKELY (ret == GST_FLOW_LOST_SYNC)) {
|
||||||
if (ret == GST_FLOW_LOST_SYNC) {
|
flush = demux->sync_lut[i] - data + 1;
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
|
||||||
flush = demux->sync_lut[i] - data + demux->packetsize;
|
flush = demux->sync_lut[i] - data + demux->packetsize;
|
||||||
|
flush = MIN (avail, flush);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* flush processed data */
|
/* flush processed data */
|
||||||
|
if (flush) {
|
||||||
|
GST_DEBUG_OBJECT (demux, "flushing %d/%d", flush, avail);
|
||||||
gst_adapter_flush (demux->adapter, flush);
|
gst_adapter_flush (demux->adapter, flush);
|
||||||
|
}
|
||||||
|
|
||||||
gst_object_unref (demux);
|
gst_object_unref (demux);
|
||||||
|
|
||||||
|
@ -164,6 +164,7 @@ struct _GstFluTSStream {
|
|||||||
guint32 pes_buffer_size;
|
guint32 pes_buffer_size;
|
||||||
guint32 pes_buffer_used;
|
guint32 pes_buffer_used;
|
||||||
gboolean pes_buffer_overflow;
|
gboolean pes_buffer_overflow;
|
||||||
|
gboolean pes_buffer_in_sync;
|
||||||
GstPESFilter filter;
|
GstPESFilter filter;
|
||||||
GstPad * pad;
|
GstPad * pad;
|
||||||
GstFlowReturn last_ret;
|
GstFlowReturn last_ret;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user