diff options
-rw-r--r-- | libhb/common.c | 21 | ||||
-rw-r--r-- | libhb/common.h | 2 | ||||
-rw-r--r-- | libhb/internal.h | 1 | ||||
-rw-r--r-- | libhb/reader.c | 80 | ||||
-rw-r--r-- | libhb/stream.c | 4 |
5 files changed, 107 insertions, 1 deletions
diff --git a/libhb/common.c b/libhb/common.c index 3e91635be..5f40b217d 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -2592,6 +2592,7 @@ void hb_limit_rational64( int64_t *x, int64_t *y, int64_t num, int64_t den, int6 void hb_buffer_list_append(hb_buffer_list_t *list, hb_buffer_t *buf) { int count = 1; + int size = 0; hb_buffer_t *end = buf; if (buf == NULL) @@ -2600,8 +2601,10 @@ void hb_buffer_list_append(hb_buffer_list_t *list, hb_buffer_t *buf) } // Input buffer may be a list of buffers, find the end. + size += buf->size; while (end != NULL && end->next != NULL) { + size += end->size; end = end->next; count++; } @@ -2616,11 +2619,13 @@ void hb_buffer_list_append(hb_buffer_list_t *list, hb_buffer_t *buf) list->tail = end; } list->count += count; + list->size += size; } void hb_buffer_list_prepend(hb_buffer_list_t *list, hb_buffer_t *buf) { int count = 1; + int size = 0; hb_buffer_t *end = buf; if (buf == NULL) @@ -2629,8 +2634,10 @@ void hb_buffer_list_prepend(hb_buffer_list_t *list, hb_buffer_t *buf) } // Input buffer may be a list of buffers, find the end. + size += buf->size; while (end != NULL && end->next != NULL) { + size += end->size; end = end->next; count++; } @@ -2645,6 +2652,7 @@ void hb_buffer_list_prepend(hb_buffer_list_t *list, hb_buffer_t *buf) list->head = buf; } list->count += count; + list->size += size; } hb_buffer_t* hb_buffer_list_rem_head(hb_buffer_list_t *list) @@ -2662,6 +2670,7 @@ hb_buffer_t* hb_buffer_list_rem_head(hb_buffer_list_t *list) } list->head = list->head->next; list->count--; + list->size -= head->size; } if (head != NULL) { @@ -2682,6 +2691,7 @@ hb_buffer_t* hb_buffer_list_rem_tail(hb_buffer_list_t *list) { list->head = list->tail = NULL; list->count = 0; + list->size = 0; } else if (list->tail != NULL) { @@ -2693,6 +2703,7 @@ hb_buffer_t* hb_buffer_list_rem_tail(hb_buffer_list_t *list) end->next = NULL; list->tail = end; list->count--; + list->size -= tail->size; } if (tail != NULL) { @@ -2722,6 +2733,7 @@ hb_buffer_t* hb_buffer_list_tail(hb_buffer_list_t *list) hb_buffer_t* hb_buffer_list_set(hb_buffer_list_t *list, hb_buffer_t *buf) { int count = 0; + int size = 0; if (list == NULL) { @@ -2733,15 +2745,18 @@ hb_buffer_t* hb_buffer_list_set(hb_buffer_list_t *list, hb_buffer_t *buf) if (end != NULL) { count++; + size += end->size; while (end->next != NULL) { end = end->next; count++; + size += end->size; } } list->head = buf; list->tail = end; list->count = count; + list->size = size; return head; } @@ -2754,6 +2769,7 @@ hb_buffer_t* hb_buffer_list_clear(hb_buffer_list_t *list) hb_buffer_t *head = list->head; list->head = list->tail = NULL; list->count = 0; + list->size = 0; return head; } @@ -2768,6 +2784,11 @@ int hb_buffer_list_count(hb_buffer_list_t *list) return list->count; } +int hb_buffer_list_size(hb_buffer_list_t *list) +{ + return list->size; +} + /********************************************************************** * hb_list implementation ********************************************************************** diff --git a/libhb/common.h b/libhb/common.h index 92d911320..d38e4fce5 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -144,6 +144,7 @@ struct hb_buffer_list_s hb_buffer_t *head; hb_buffer_t *tail; int count; + int size; }; void hb_buffer_list_append(hb_buffer_list_t *list, hb_buffer_t *buf); @@ -156,6 +157,7 @@ hb_buffer_t* hb_buffer_list_clear(hb_buffer_list_t *list); hb_buffer_t* hb_buffer_list_set(hb_buffer_list_t *list, hb_buffer_t *buf); void hb_buffer_list_close(hb_buffer_list_t *list); int hb_buffer_list_count(hb_buffer_list_t *list); +int hb_buffer_list_size(hb_buffer_list_t *list); hb_list_t * hb_list_init(); int hb_list_count( const hb_list_t * ); diff --git a/libhb/internal.h b/libhb/internal.h index 79a01dd9b..d4014dca0 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -71,6 +71,7 @@ struct hb_buffer_settings_s int64_t stop; // stop time of frame int64_t renderOffset; // DTS used by b-frame offsets in muxmp4 int64_t pcr; + int split; uint8_t discontinuity; int new_chap; // Video packets: if non-zero, is the index of the chapter whose boundary was crossed diff --git a/libhb/reader.c b/libhb/reader.c index 0c6f6d853..d58271b56 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -36,6 +36,12 @@ typedef struct int valid; // Stream timing is not valid until next scr. } stream_timing_t; +typedef struct +{ + int id; + hb_buffer_list_t list; +} buffer_splice_list_t; + struct hb_work_private_s { hb_handle_t * h; @@ -63,6 +69,9 @@ struct hb_work_private_s uint64_t st_first; uint64_t duration; hb_fifo_t * fifos[100]; + + buffer_splice_list_t * splice_list; + int splice_list_size; }; /*********************************************************************** @@ -70,6 +79,7 @@ struct hb_work_private_s **********************************************************************/ static hb_fifo_t ** GetFifoForId( hb_work_private_t * r, int id ); static void UpdateState( hb_work_private_t * r, int64_t start); +static hb_buffer_list_t * get_splice_list(hb_work_private_t * r, int id); /*********************************************************************** * reader_init @@ -250,6 +260,28 @@ static int reader_init( hb_work_object_t * w, hb_job_t * job ) } } + // Count number of splice lists needed for merging buffers + // that have been split + int count = 1; // 1 for video + count += hb_list_count( job->list_subtitle ); + count += hb_list_count( job->list_audio ); + r->splice_list_size = count; + r->splice_list = calloc(count, sizeof(buffer_splice_list_t)); + + // Initialize stream id's of splice lists + int ii, jj = 0; + r->splice_list[jj++].id = r->title->video_id; + for (ii = 0; ii < hb_list_count(job->list_subtitle); ii++) + { + hb_subtitle_t * subtitle = hb_list_item(job->list_subtitle, ii); + r->splice_list[jj++].id = subtitle->id; + } + for (ii = 0; ii < hb_list_count(job->list_audio); ii++) + { + hb_audio_t * audio = hb_list_item(job->list_audio, ii); + r->splice_list[jj++].id = audio->id; + } + // The stream needs to be open before starting the reader thead // to prevent a race with decoders that may share information // with the reader. Specifically avcodec needs this. @@ -290,8 +322,41 @@ static void reader_close( hb_work_object_t * w ) free( r ); } -static void push_buf( const hb_work_private_t *r, hb_fifo_t *fifo, hb_buffer_t *buf ) +static void push_buf( hb_work_private_t *r, hb_fifo_t *fifo, hb_buffer_t *buf ) { + // Handle buffers that were split across a PCR discontinuity. + // Rejoin them into a single buffer. + hb_buffer_list_t * list = get_splice_list(r, buf->s.id); + if (list != NULL) + { + hb_buffer_list_append(list, buf); + if (buf->s.split) + { + return; + } + + int count = hb_buffer_list_count(list); + if (count > 1) + { + int size = hb_buffer_list_size(list); + hb_buffer_t * b = hb_buffer_init(size); + buf = hb_buffer_list_head(list); + b->s = buf->s; + + int pos = 0; + while ((buf = hb_buffer_list_rem_head(list)) != NULL) + { + memcpy(b->data + pos, buf->data, buf->size); + pos += buf->size; + hb_buffer_close(&buf); + } + buf = b; + } + else + { + buf = hb_buffer_list_clear(list); + } + } while ( !*r->die && !r->job->done ) { if ( hb_fifo_full_wait( fifo ) ) @@ -853,3 +918,16 @@ static hb_fifo_t ** GetFifoForId( hb_work_private_t * r, int id ) return NULL; } +static hb_buffer_list_t * get_splice_list(hb_work_private_t * r, int id) +{ + int ii; + + for (ii = 0; ii < r->splice_list_size; ii++) + { + if (r->splice_list[ii].id == id) + { + return &r->splice_list[ii].list; + } + } + return NULL; +} diff --git a/libhb/stream.c b/libhb/stream.c index 3ddba0256..caa998a07 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -4537,6 +4537,10 @@ static hb_buffer_t * generate_output_data(hb_stream_t *stream, int curstream) // DTS-HD is an example of this. buf = hb_buffer_init(es_size); + if (ts_stream->packet_len < ts_stream->pes_info.packet_len + 6) + { + buf->s.split = 1; + } hb_buffer_list_append(&list, buf); buf->s.id = get_id(pes_stream); |