diff options
author | John Stebbins <[email protected]> | 2016-05-24 14:12:07 -0700 |
---|---|---|
committer | John Stebbins <[email protected]> | 2016-05-24 14:12:07 -0700 |
commit | e8c37c88b864f515aacda7a1a8fbcda9ed6b8bad (patch) | |
tree | 96b423f89f5a78af0a64db32d64b9dae50c63f67 /libhb/deccc608sub.c | |
parent | 76595a4b2131536eb3e498b161944057e882d038 (diff) |
sync: correct timestamp discontinuities in sync instead of reader (#192)
* sync: correct timestamp discontinuities in sync instead of reader
This patch passes discontinuity information through the pipeline till it
reaches sync.c. The timestamps are passed through the pipeline as read
and unmodified to sync.c (instead of attempting to correct
discontinuities in reader). In sync, when we see a discontinuity,
we know where the next timestamp should be based on the timestamp
and duration of the previous buffer (before the discontinuity). So
we calculate an "SCR" offset based on the timestamp after the
discontinuity and what we calculate it should be.
The old discontinuity handling code was broken due to the following.
The MPEG STD timing model relies heavily on the decoder having an STC
that is phase lock looped to the PCRs in the stream. When decoding a
broadcast stream, the decoder can count on the time measure between PCRs
using the STC to match to a high degree of accuracy.
I.e. STC - lastSTC == PCR - lastPCR. When a discontinuity occurs, the
decoder calculates a new PCR offset = PCR - STC. I.e. the offset is the
new PCR value minus what it would have been if there had been no
discontinuity.
The above does not work without a reliable STC, which we do not have.
We have been attempting to approximate one by avereraging the duration
of received packets and extrapolating an "STC" based on the last PTS and
the average packet duration. But this is highly variable and
unreliable.
* decavcodec: fix data type of next_pts
It needs to be double so that partial ticks are not lost
* deccc608sub: clarify comment
* sync: allow queueing more audio
Audio is small, and there is often a significant amount of audio in the
stream before the first video frame.
* sync: improve handling of damaged streams
When data is missing, the audio decoder was extrapolating timestamps
from the last pts before the error caused by the missing data which
caused sync issues.
Also, missing data can cause the video decoder to output a frame out of
order with the wrong scr sequence. Drop such frames.
Diffstat (limited to 'libhb/deccc608sub.c')
-rw-r--r-- | libhb/deccc608sub.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/libhb/deccc608sub.c b/libhb/deccc608sub.c index 8ac6642da..03c544f20 100644 --- a/libhb/deccc608sub.c +++ b/libhb/deccc608sub.c @@ -135,6 +135,7 @@ static int general_608_init (struct s_write *wb) hb_buffer_list_clear(&wb->list); wb->last_pts = 0; + wb->last_scr_sequence = 0; return 0; } @@ -944,6 +945,7 @@ static int write_cc_buffer_as_ssa(struct eia608_screen *data, buffer->s.frametype = HB_FRAME_SUBTITLE; buffer->s.start = ms_start; buffer->s.stop = AV_NOPTS_VALUE; + buffer->s.scr_sequence = wb->data608->current_visible_scr_sequence; sprintf((char*)buffer->data, "%d,,Default,,0,0,0,,", ++wb->line); len = strlen((char*)buffer->data); memcpy(buffer->data + len, wb->enc_buffer, wb->enc_buffer_used); @@ -958,6 +960,7 @@ static int write_cc_buffer_as_ssa(struct eia608_screen *data, buffer->s.flags = HB_BUF_FLAG_EOS; buffer->s.start = ms_start; buffer->s.stop = ms_start; + buffer->s.scr_sequence = wb->data608->current_visible_scr_sequence; hb_buffer_list_append(&wb->list, buffer); wb->clear_sub_needed = 0; } @@ -1232,10 +1235,12 @@ static void handle_command(unsigned char c1, const unsigned char c2, case COM_RESUMECAPTIONLOADING: wb->data608->mode=MODE_POPUP; wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; break; case COM_RESUMETEXTDISPLAY: wb->data608->mode=MODE_TEXT; wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; break; case COM_ROLLUP2: if (wb->data608->rollup_base_row + 1 < 2) @@ -1260,6 +1265,7 @@ static void handle_command(unsigned char c1, const unsigned char c2, wb->rollup_cr = 1; } wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; wb->data608->mode=MODE_ROLLUP_2; erase_memory (wb, 0); wb->data608->cursor_column = 0; @@ -1287,6 +1293,7 @@ static void handle_command(unsigned char c1, const unsigned char c2, wb->rollup_cr = 1; } wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; wb->data608->mode=MODE_ROLLUP_3; erase_memory (wb, 0); wb->data608->cursor_column = 0; @@ -1314,6 +1321,7 @@ static void handle_command(unsigned char c1, const unsigned char c2, wb->rollup_cr = 1; } wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; wb->data608->mode = MODE_ROLLUP_4; wb->data608->cursor_column = 0; wb->data608->cursor_row = wb->data608->rollup_base_row; @@ -1328,6 +1336,7 @@ static void handle_command(unsigned char c1, const unsigned char c2, { wb->rollup_cr = 0; wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; break; } if (write_cc_buffer(wb)) @@ -1335,6 +1344,7 @@ static void handle_command(unsigned char c1, const unsigned char c2, roll_up(wb); wb->data608->cursor_column = 0; wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; break; case COM_ERASENONDISPLAYEDMEMORY: erase_memory (wb,0); @@ -1353,6 +1363,7 @@ static void handle_command(unsigned char c1, const unsigned char c2, // the last pts is the time to remove the previously // displayed CC from the display wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; // Write "clear" subtitle if necessary struct eia608_screen *data; @@ -1367,6 +1378,7 @@ static void handle_command(unsigned char c1, const unsigned char c2, { swap_visible_buffer(wb); wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; } if (write_cc_buffer(wb)) wb->data608->screenfuls_counter++; @@ -1732,6 +1744,7 @@ static void process608(const unsigned char *data, int length, // write a buffer now write_cc_buffer(wb); wb->data608->current_visible_start_ms = wb->last_pts; + wb->data608->current_visible_scr_sequence = wb->last_scr_sequence; } } } @@ -1811,6 +1824,7 @@ static int decccWork( hb_work_object_t * w, hb_buffer_t ** buf_in, } pv->cc608->last_pts = in->s.start; + pv->cc608->last_scr_sequence = in->s.scr_sequence; process608(in->data, in->size, pv->cc608); /* |