mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
Improved seeking in pull mode. Some refactoring and small fixes
This commit is contained in:
parent
9e2dc060a4
commit
5d1abdbe2c
2 changed files with 127 additions and 56 deletions
|
@ -53,7 +53,8 @@
|
|||
#define MAX_DVD_AUDIO_STREAMS 8
|
||||
#define MAX_DVD_SUBPICTURE_STREAMS 32
|
||||
#define BLOCK_SZ 4096
|
||||
#define SCAN_SZ 80
|
||||
#define SCAN_SCR_SZ 12
|
||||
#define SCAN_PTS_SZ 80
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -202,6 +203,11 @@ static gboolean gst_flups_demux_src_query (GstPad * pad, GstQuery * query);
|
|||
static GstStateChangeReturn gst_flups_demux_change_state (GstElement * element,
|
||||
GstStateChange transition);
|
||||
|
||||
static inline gboolean gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux,
|
||||
guint64 * pos, SCAN_MODE mode, guint64 * rts);
|
||||
static inline gboolean gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux,
|
||||
guint64 * pos, SCAN_MODE mode, guint64 * rts);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
|
||||
/*static guint gst_flups_demux_signals[LAST_SIGNAL] = { 0 };*/
|
||||
|
@ -547,9 +553,10 @@ gst_flups_demux_send_data (GstFluPSDemux * demux, GstFluPSStream * stream,
|
|||
/* caps */
|
||||
gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
|
||||
GST_BUFFER_TIMESTAMP (buf) = timestamp;
|
||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||
gst_segment_set_last_stop (&demux->src_segment, GST_FORMAT_TIME, timestamp);
|
||||
}
|
||||
|
||||
/* update position in the segment */
|
||||
gst_segment_set_last_stop (&demux->src_segment, GST_FORMAT_TIME,
|
||||
MPEGTIME_TO_GSTTIME (demux->current_scr));
|
||||
|
||||
/* Set the buffer discont flag, and clear discont state on the stream */
|
||||
if (stream->discont) {
|
||||
|
@ -929,6 +936,47 @@ not_supported:
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
gst_flups_demux_do_seek (GstFluPSDemux * demux, GstSegment * seeksegment)
|
||||
{
|
||||
gboolean found;
|
||||
guint64 fscr, offset;
|
||||
guint64 scr =
|
||||
MIN (demux->last_scr, GSTTIME_TO_MPEGTIME (seeksegment->last_stop));
|
||||
guint64 scr_rate_n = demux->last_scr_offset - demux->first_scr_offset;
|
||||
guint64 scr_rate_d = demux->last_scr - demux->first_scr;
|
||||
|
||||
#if POST_10_10
|
||||
GST_INFO_OBJECT (demux, "sink segment configured %" GST_SEGMENT_FORMAT,
|
||||
&demux->sink_segment);
|
||||
#endif
|
||||
|
||||
offset = MIN (gst_util_uint64_scale (scr, scr_rate_n, scr_rate_d),
|
||||
demux->sink_segment.stop);
|
||||
|
||||
gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &demux->first_scr);
|
||||
|
||||
found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr);
|
||||
if (!found) {
|
||||
found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr);
|
||||
}
|
||||
|
||||
while (found && fscr < scr) {
|
||||
offset++;
|
||||
found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr);
|
||||
}
|
||||
|
||||
while (found && fscr > scr) {
|
||||
offset--;
|
||||
found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr);
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (demux, "doing seek at offset %" G_GUINT64_FORMAT
|
||||
" SRC: %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
|
||||
offset, fscr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (fscr)));
|
||||
gst_segment_set_last_stop (&demux->sink_segment, GST_FORMAT_BYTES, offset);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_flups_demux_handle_seek_pull (GstFluPSDemux * demux, GstEvent * event)
|
||||
{
|
||||
|
@ -947,6 +995,9 @@ gst_flups_demux_handle_seek_pull (GstFluPSDemux * demux, GstEvent * event)
|
|||
if (format != GST_FORMAT_TIME)
|
||||
goto wrong_format;
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "Seek requested start %" GST_TIME_FORMAT " stop %"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
|
||||
|
||||
/* We need to convert to byte based seek and we need a scr_rate for that. */
|
||||
if (demux->scr_rate_n == G_MAXUINT64 || demux->scr_rate_d == G_MAXUINT64)
|
||||
goto no_scr_rate;
|
||||
|
@ -984,33 +1035,29 @@ gst_flups_demux_handle_seek_pull (GstFluPSDemux * demux, GstEvent * event)
|
|||
gst_segment_set_seek (&seeksegment, rate, format, flags,
|
||||
start_type, start, stop_type, stop, &update);
|
||||
|
||||
#if POST_10_10
|
||||
GST_DEBUG_OBJECT (demux, "seek segment configured %" GST_SEGMENT_FORMAT,
|
||||
&seeksegment);
|
||||
#endif
|
||||
|
||||
if (flush || seeksegment.last_stop != demux->src_segment.last_stop) {
|
||||
/* Do the actual seeking */
|
||||
#if POST_10_10
|
||||
GST_INFO_OBJECT (demux, "sink segment configured %" GST_SEGMENT_FORMAT,
|
||||
&demux->sink_segment);
|
||||
#endif
|
||||
gst_segment_set_last_stop (&demux->sink_segment, GST_FORMAT_BYTES,
|
||||
MIN (GSTTIME_TO_BYTES (seeksegment.last_stop),
|
||||
demux->sink_segment.stop));
|
||||
#if POST_10_10
|
||||
GST_INFO_OBJECT (demux, "sink segment configured %" GST_SEGMENT_FORMAT,
|
||||
&demux->sink_segment);
|
||||
#endif
|
||||
gst_flups_demux_do_seek (demux, &seeksegment);
|
||||
}
|
||||
|
||||
/* check the limits */
|
||||
if (seeksegment.start < first_pts)
|
||||
seeksegment.start = first_pts;
|
||||
|
||||
if (seeksegment.last_stop < first_pts)
|
||||
seeksegment.last_stop = first_pts;
|
||||
if (seeksegment.rate > 0.0) {
|
||||
if (seeksegment.start < first_pts - demux->base_time) {
|
||||
seeksegment.start = first_pts - demux->base_time;
|
||||
seeksegment.last_stop = seeksegment.start;
|
||||
}
|
||||
}
|
||||
|
||||
/* update the rate in our src segment */
|
||||
demux->sink_segment.rate = rate;
|
||||
|
||||
#if POST_10_10
|
||||
GST_DEBUG_OBJECT (demux, "seek segment configured %" GST_SEGMENT_FORMAT,
|
||||
GST_DEBUG_OBJECT (demux, "seek segment adjusted %" GST_SEGMENT_FORMAT,
|
||||
&seeksegment);
|
||||
#endif
|
||||
|
||||
|
@ -1287,7 +1334,7 @@ gst_flups_demux_parse_pack_start (GstFluPSDemux * demux)
|
|||
|
||||
scr_ext = (scr2 & 0x03fe0000) >> 17;
|
||||
/* We keep the offset of this scr */
|
||||
demux->last_scr_offset = demux->adapter_offset + 12;
|
||||
demux->cur_scr_offset = demux->adapter_offset + 12;
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "SCR: 0x%08llx SCRE: 0x%08x", scr, scr_ext);
|
||||
|
||||
|
@ -1330,7 +1377,7 @@ gst_flups_demux_parse_pack_start (GstFluPSDemux * demux)
|
|||
scr |= ((guint64) scr2 & 0xfe000000) >> 25;
|
||||
|
||||
/* We keep the offset of this scr */
|
||||
demux->last_scr_offset = demux->adapter_offset + 8;
|
||||
demux->cur_scr_offset = demux->adapter_offset + 8;
|
||||
|
||||
/* marker:1==1 ! mux_rate:22 ! marker:1==1 */
|
||||
new_rate = (scr2 & 0x007ffffe) >> 1;
|
||||
|
@ -1351,14 +1398,14 @@ gst_flups_demux_parse_pack_start (GstFluPSDemux * demux)
|
|||
/* keep the first src in order to calculate delta time */
|
||||
if (demux->first_scr == G_MAXUINT64) {
|
||||
demux->first_scr = scr;
|
||||
demux->first_scr_offset = demux->last_scr_offset;
|
||||
demux->first_scr_offset = demux->cur_scr_offset;
|
||||
demux->base_time = MPEGTIME_TO_GSTTIME (demux->first_scr);
|
||||
/* at begin consider the new_rate as the scr rate, bytes/clock ticks */
|
||||
scr_rate_n = new_rate;
|
||||
scr_rate_d = CLOCK_FREQ;
|
||||
} else if (demux->first_scr_offset != demux->last_scr_offset) {
|
||||
} else if (demux->first_scr_offset != demux->cur_scr_offset) {
|
||||
/* estimate byte rate related to the SCR */
|
||||
scr_rate_n = demux->last_scr_offset - demux->first_scr_offset;
|
||||
scr_rate_n = demux->cur_scr_offset - demux->first_scr_offset;
|
||||
scr_rate_d = scr_adjusted - demux->first_scr;
|
||||
} else {
|
||||
scr_rate_n = demux->scr_rate_n;
|
||||
|
@ -1370,7 +1417,7 @@ gst_flups_demux_parse_pack_start (GstFluPSDemux * demux)
|
|||
" at %" G_GUINT64_FORMAT ", scr rate: %" G_GUINT64_FORMAT
|
||||
"/%" G_GUINT64_FORMAT "(%f)",
|
||||
((demux->sink_segment.rate >= 0.0) ? "forward" : "backward"),
|
||||
scr, demux->last_scr_offset,
|
||||
scr, demux->cur_scr_offset,
|
||||
demux->first_scr, demux->first_scr_offset,
|
||||
scr_rate_n, scr_rate_d, (float) scr_rate_n / scr_rate_d);
|
||||
|
||||
|
@ -2103,7 +2150,7 @@ beach:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline gboolean
|
||||
gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos,
|
||||
SCAN_MODE mode, guint64 * rts)
|
||||
{
|
||||
|
@ -2112,31 +2159,40 @@ gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos,
|
|||
guint64 offset = *pos;
|
||||
gboolean found = FALSE;
|
||||
guint64 ts = 0;
|
||||
guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ);
|
||||
guint cursor, to_read = BLOCK_SZ;
|
||||
|
||||
/* read some data */
|
||||
ret = gst_pad_pull_range (demux->sinkpad, offset, BLOCK_SZ, &buffer);
|
||||
offset += BLOCK_SZ - SCAN_SZ + 1;
|
||||
do {
|
||||
if (offset + scan_sz > demux->sink_segment.stop)
|
||||
return FALSE;
|
||||
|
||||
if (offset + to_read > demux->sink_segment.stop)
|
||||
to_read = demux->sink_segment.stop - offset;
|
||||
|
||||
/* read some data */
|
||||
ret = gst_pad_pull_range (demux->sinkpad, offset, to_read, &buffer);
|
||||
const guint8 *data = GST_BUFFER_DATA (buffer);
|
||||
do {
|
||||
const guint end_scan = GST_BUFFER_SIZE (buffer) - scan_sz;
|
||||
/* scan the block */
|
||||
for (cursor = 0; !found && cursor <= end_scan; cursor++) {
|
||||
found = gst_flups_demux_scan_ts (demux, data++, mode, &ts);
|
||||
} while (!found && data < (GST_BUFFER_DATA (buffer) + BLOCK_SZ - SCAN_SZ));
|
||||
}
|
||||
|
||||
/* done with the buffer, unref it */
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
if (found) {
|
||||
*rts = ts;
|
||||
*pos = offset - 1;
|
||||
break;
|
||||
*pos = offset + cursor - 1;
|
||||
} else {
|
||||
offset += cursor;
|
||||
}
|
||||
} while (!found && offset < demux->sink_segment.stop);
|
||||
|
||||
ret = gst_pad_pull_range (demux->sinkpad, offset, BLOCK_SZ, &buffer);
|
||||
offset += BLOCK_SZ;
|
||||
} while (offset < (demux->sink_segment.stop * 0.10));
|
||||
return found;
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline gboolean
|
||||
gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos,
|
||||
SCAN_MODE mode, guint64 * rts)
|
||||
{
|
||||
|
@ -2145,28 +2201,39 @@ gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos,
|
|||
guint64 offset = *pos;
|
||||
gboolean found = FALSE;
|
||||
guint64 ts = 0;
|
||||
guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ);
|
||||
guint cursor, to_read = BLOCK_SZ;
|
||||
|
||||
/* read some data */
|
||||
ret = gst_pad_pull_range (demux->sinkpad, offset, BLOCK_SZ, &buffer);
|
||||
offset -= (BLOCK_SZ - SCAN_SZ + 1);
|
||||
do {
|
||||
const guint8 *data = GST_BUFFER_DATA (buffer) + BLOCK_SZ - SCAN_SZ;
|
||||
do {
|
||||
if (offset < scan_sz - 1)
|
||||
return FALSE;
|
||||
|
||||
if (offset > BLOCK_SZ)
|
||||
offset -= BLOCK_SZ;
|
||||
else {
|
||||
to_read = offset + 1;
|
||||
offset = 0;
|
||||
}
|
||||
/* read some data */
|
||||
ret = gst_pad_pull_range (demux->sinkpad, offset, to_read, &buffer);
|
||||
const guint start_scan = GST_BUFFER_SIZE (buffer) - scan_sz;
|
||||
const guint8 *data = GST_BUFFER_DATA (buffer) + start_scan;
|
||||
/* scan the block */
|
||||
for (cursor = (start_scan + 1); !found && cursor > 0; cursor--) {
|
||||
found = gst_flups_demux_scan_ts (demux, data--, mode, &ts);
|
||||
} while (!found && data > GST_BUFFER_DATA (buffer));
|
||||
}
|
||||
|
||||
/* done with the buffer, unref it */
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
if (found) {
|
||||
*rts = ts;
|
||||
*pos = offset + 1;
|
||||
break;
|
||||
*pos = offset + cursor;
|
||||
}
|
||||
|
||||
ret = gst_pad_pull_range (demux->sinkpad, offset, BLOCK_SZ, &buffer);
|
||||
offset -= BLOCK_SZ;
|
||||
} while (offset > (demux->sink_segment.stop * 0.90));
|
||||
} while (!found && offset > 0);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
|
@ -2206,13 +2273,15 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux)
|
|||
GST_DEBUG_OBJECT (demux, "First SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
|
||||
" in packet starting at %" G_GUINT64_FORMAT,
|
||||
demux->first_scr, GST_TIME_ARGS (demux->base_time), offset);
|
||||
demux->first_scr_offset = offset;
|
||||
/* scan for last SCR in the stream */
|
||||
offset = demux->sink_segment.stop - BLOCK_SZ;
|
||||
offset = demux->sink_segment.stop;
|
||||
gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &demux->last_scr);
|
||||
GST_DEBUG_OBJECT (demux, "Last SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
|
||||
" in packet starting at %" G_GUINT64_FORMAT,
|
||||
demux->last_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_scr)),
|
||||
offset);
|
||||
demux->last_scr_offset = offset;
|
||||
/* scan for first PTS in the stream */
|
||||
offset = demux->sink_segment.start;
|
||||
gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_PTS, &demux->first_pts);
|
||||
|
@ -2221,20 +2290,21 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux)
|
|||
demux->first_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_pts)),
|
||||
offset);
|
||||
/* scan for last PTS in the stream */
|
||||
offset = demux->sink_segment.stop - BLOCK_SZ;
|
||||
offset = demux->sink_segment.stop;
|
||||
gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_PTS, &demux->last_pts);
|
||||
GST_DEBUG_OBJECT (demux, "Last PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
|
||||
" in packet starting at %" G_GUINT64_FORMAT,
|
||||
demux->last_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_pts)),
|
||||
offset);
|
||||
|
||||
if (G_LIKELY (demux->first_pts != G_MAXUINT64 &&
|
||||
demux->last_pts != G_MAXUINT64)) {
|
||||
if (G_LIKELY (demux->first_scr != G_MAXUINT64 &&
|
||||
demux->last_scr != G_MAXUINT64)) {
|
||||
/* update the src segment */
|
||||
demux->src_segment.start = MPEGTIME_TO_GSTTIME (demux->first_pts);
|
||||
demux->src_segment.start =
|
||||
MPEGTIME_TO_GSTTIME (demux->first_scr) - demux->base_time;
|
||||
demux->src_segment.stop = -1;
|
||||
gst_segment_set_duration (&demux->src_segment, GST_FORMAT_TIME,
|
||||
MPEGTIME_TO_GSTTIME (demux->last_pts - demux->first_pts));
|
||||
MPEGTIME_TO_GSTTIME (demux->last_scr - demux->first_scr));
|
||||
gst_segment_set_last_stop (&demux->src_segment, GST_FORMAT_TIME,
|
||||
demux->src_segment.start);
|
||||
}
|
||||
|
|
|
@ -117,6 +117,7 @@ struct _GstFluPSDemux
|
|||
guint64 scr_rate_d;
|
||||
guint64 first_scr_offset;
|
||||
guint64 last_scr_offset;
|
||||
guint64 cur_scr_offset;
|
||||
|
||||
guint64 first_pts;
|
||||
guint64 last_pts;
|
||||
|
|
Loading…
Reference in a new issue