From: Zaheer Abbas Merali Date: Thu, 16 Oct 2008 16:37:33 +0000 (+0000) Subject: gst/mpegdemux/gstmpegtsdemux.*: Properly handle some resync cases in the optimised... X-Git-Tag: 1.19.3~507^2~19938 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e758c7dc2390c57d605288f236e126f4f272bc9a;p=platform%2Fupstream%2Fgstreamer.git 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. --- diff --git a/ChangeLog b/ChangeLog index 57448a2..4b00469 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2008-10-16 Zaheer Abbas Merali + + 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 * sys/acmenc/Makefile.am: Remove incorrect use of DIRECTSOUND_LDFLAGS diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 6ac0503..1aa2f38 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -1046,7 +1046,7 @@ gst_fluts_demux_get_stream_for_PID (GstFluTSDemux * demux, guint16 PID) stream->PAT.version_number = -1; stream->PMT_pid = FLUTS_MAX_PID + 1; stream->flags |= FLUTS_STREAM_FLAG_STREAM_TYPE_UNKNOWN; - + stream->pes_buffer_in_sync = FALSE; switch (PID) { /* check for fixed mapping */ case PID_PROGRAM_ASSOCIATION_TABLE: @@ -1959,6 +1959,8 @@ gst_fluts_stream_pes_buffer_flush (GstFluTSStream * stream) if (stream->pes_buffer) { GST_BUFFER_SIZE (stream->pes_buffer) = stream->pes_buffer_used; 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; } return ret; @@ -1981,6 +1983,8 @@ gst_fluts_stream_pes_buffer_push (GstFluTSStream * stream, stream->pes_buffer_size <<= 1; ret = gst_fluts_stream_pes_buffer_flush (stream); + if (ret == GST_FLOW_LOST_SYNC) + goto done; } 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); #endif stream->pes_buffer_used += in_size; - +done: return ret; } @@ -2011,13 +2015,32 @@ gst_fluts_demux_pes_buffer_flush (GstFluTSDemux * demux) for (i = 0; i < FLUTS_MAX_PID + 1; i++) { GstFluTSStream *stream = demux->streams[i]; if (stream && stream->pad) { - ret = gst_fluts_stream_pes_buffer_flush (stream); - if (G_UNLIKELY (ret == GST_FLOW_OK)) - goto done; + gst_fluts_stream_pes_buffer_flush (stream); + stream->pes_buffer_in_sync = FALSE; } } + 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; } @@ -2207,7 +2230,7 @@ gst_fluts_demux_parse_stream (GstFluTSDemux * demux, GstFluTSStream * stream, "bytes of %u bytes in the PES buffer", PID, stream->pes_buffer_used, stream->pes_buffer_size); /* 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); /* Resize the buffer to half if no overflow detected and * 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", stream->pes_buffer_size); } - if (ret == GST_FLOW_LOST_SYNC) - goto done; + /* mark the stream not in sync to give a chance on PES filter to + * detect lost sync */ + stream->pes_buffer_in_sync = FALSE; stream->pes_buffer_overflow = FALSE; } GST_LOG_OBJECT (demux, "Elementary packet of size %u for PID 0x%04x", datalen, PID); if (datalen > 0) { - ret = gst_fluts_stream_pes_buffer_push (stream, data, datalen); + 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); + /* 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; } else { 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) { /* if sync code is found try to store it in the LUT */ if (G_LIKELY (IS_MPEGTS_SYNC (ptr_data))) { - demux->sync_lut[sync_count] = ptr_data; - sync_count++; /* skip paketsize bytes and try find next */ - ptr_data += demux->packetsize; + guint8 *next_sync = ptr_data + demux->packetsize; + if (next_sync < end_scan) { + demux->sync_lut[sync_count] = ptr_data; + sync_count++; + ptr_data += demux->packetsize; + } else + goto done; + } else { ptr_data++; } } - +done: *flush = ptr_data - in_data; return sync_count; @@ -2453,9 +2499,11 @@ gst_fluts_demux_chain (GstPad * pad, GstBuffer * buffer) gint i; 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); - + } /* first push the new buffer into the adapter */ gst_adapter_push (demux->adapter, buffer); @@ -2473,19 +2521,24 @@ gst_fluts_demux_chain (GstPad * pad, GstBuffer * buffer) /* process all packets */ for (i = 0; i < sync_count; i++) { ret = gst_fluts_demux_parse_transport_packet (demux, demux->sync_lut[i]); + if (G_UNLIKELY (ret == GST_FLOW_LOST_SYNC)) { + flush = demux->sync_lut[i] - data + 1; + ret = GST_FLOW_OK; + continue; + } if (G_UNLIKELY (ret != GST_FLOW_OK)) { - if (ret == GST_FLOW_LOST_SYNC) { - ret = GST_FLOW_OK; - continue; - } flush = demux->sync_lut[i] - data + demux->packetsize; + flush = MIN (avail, flush); goto done; } } done: /* flush processed data */ - gst_adapter_flush (demux->adapter, flush); + if (flush) { + GST_DEBUG_OBJECT (demux, "flushing %d/%d", flush, avail); + gst_adapter_flush (demux->adapter, flush); + } gst_object_unref (demux); diff --git a/gst/mpegdemux/gstmpegtsdemux.h b/gst/mpegdemux/gstmpegtsdemux.h index d26aedc..4878290 100644 --- a/gst/mpegdemux/gstmpegtsdemux.h +++ b/gst/mpegdemux/gstmpegtsdemux.h @@ -164,6 +164,7 @@ struct _GstFluTSStream { guint32 pes_buffer_size; guint32 pes_buffer_used; gboolean pes_buffer_overflow; + gboolean pes_buffer_in_sync; GstPESFilter filter; GstPad * pad; GstFlowReturn last_ret;