summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libhb/common.c21
-rw-r--r--libhb/common.h2
-rw-r--r--libhb/internal.h1
-rw-r--r--libhb/reader.c80
-rw-r--r--libhb/stream.c4
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);