summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libhb/common.c182
-rw-r--r--libhb/common.h19
-rw-r--r--libhb/decavcodec.c137
-rw-r--r--libhb/deccc608sub.c47
-rw-r--r--libhb/deccc608sub.h1
-rw-r--r--libhb/declpcm.c25
-rw-r--r--libhb/decomb.c33
-rw-r--r--libhb/decpgssub.c90
-rw-r--r--libhb/decssasub.c34
-rw-r--r--libhb/deinterlace.c74
-rw-r--r--libhb/demuxmpeg.c16
-rw-r--r--libhb/enc_qsv.c95
-rw-r--r--libhb/encavcodec.c96
-rw-r--r--libhb/encavcodecaudio.c37
-rw-r--r--libhb/enclame.c32
-rw-r--r--libhb/encvorbis.c15
-rw-r--r--libhb/encx264.c27
-rw-r--r--libhb/encx265.c28
-rw-r--r--libhb/internal.h8
-rw-r--r--libhb/nlmeans.c52
-rw-r--r--libhb/qsv_filter.c115
-rw-r--r--libhb/qsv_filter.h1
-rw-r--r--libhb/qsv_filter_pp.h2
-rw-r--r--libhb/reader.c25
-rw-r--r--libhb/scan.c47
-rw-r--r--libhb/stream.c75
-rw-r--r--libhb/sync.c125
-rw-r--r--libhb/vfr.c464
28 files changed, 872 insertions, 1030 deletions
diff --git a/libhb/common.c b/libhb/common.c
index 6877e31a6..c03fb2807 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -2567,6 +2567,188 @@ void hb_limit_rational64( int64_t *x, int64_t *y, int64_t num, int64_t den, int6
}
/**********************************************************************
+ * hb_buffer_list implementation
+ *********************************************************************/
+void hb_buffer_list_append(hb_buffer_list_t *list, hb_buffer_t *buf)
+{
+ int count = 1;
+ hb_buffer_t *end = buf;
+
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ // Input buffer may be a list of buffers, find the end.
+ while (end != NULL && end->next != NULL)
+ {
+ end = end->next;
+ count++;
+ }
+ if (list->tail == NULL)
+ {
+ list->head = buf;
+ list->tail = end;
+ }
+ else
+ {
+ list->tail->next = buf;
+ list->tail = end;
+ }
+ list->count += count;
+}
+
+void hb_buffer_list_prepend(hb_buffer_list_t *list, hb_buffer_t *buf)
+{
+ int count = 1;
+ hb_buffer_t *end = buf;
+
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ // Input buffer may be a list of buffers, find the end.
+ while (end != NULL && end->next != NULL)
+ {
+ end = end->next;
+ count++;
+ }
+ if (list->tail == NULL)
+ {
+ list->head = buf;
+ list->tail = end;
+ }
+ else
+ {
+ end->next = list->head;
+ list->head = buf;
+ }
+ list->count += count;
+}
+
+hb_buffer_t* hb_buffer_list_rem_head(hb_buffer_list_t *list)
+{
+ if (list == NULL)
+ {
+ return NULL;
+ }
+ hb_buffer_t *head = list->head;
+ if (list->head != NULL)
+ {
+ if (list->head == list->tail)
+ {
+ list->tail = NULL;
+ }
+ list->head = list->head->next;
+ list->count--;
+ }
+ if (head != NULL)
+ {
+ head->next = NULL;
+ }
+ return head;
+}
+
+hb_buffer_t* hb_buffer_list_rem_tail(hb_buffer_list_t *list)
+{
+ if (list == NULL)
+ {
+ return NULL;
+ }
+ hb_buffer_t *tail = list->tail;
+
+ if (list->head == list->tail)
+ {
+ list->head = list->tail = NULL;
+ list->count = 0;
+ }
+ else if (list->tail != NULL)
+ {
+ hb_buffer_t *end = list->head;
+ while (end != NULL && end->next != list->tail)
+ {
+ end = end->next;
+ }
+ end->next = NULL;
+ list->tail = end;
+ list->count--;
+ }
+ if (tail != NULL)
+ {
+ tail->next = NULL;
+ }
+ return tail;
+}
+
+hb_buffer_t* hb_buffer_list_head(hb_buffer_list_t *list)
+{
+ if (list == NULL)
+ {
+ return NULL;
+ }
+ return list->head;
+}
+
+hb_buffer_t* hb_buffer_list_tail(hb_buffer_list_t *list)
+{
+ if (list == NULL)
+ {
+ return NULL;
+ }
+ return list->tail;
+}
+
+hb_buffer_t* hb_buffer_list_set(hb_buffer_list_t *list, hb_buffer_t *buf)
+{
+ int count = 0;
+
+ if (list == NULL)
+ {
+ return NULL;
+ }
+
+ hb_buffer_t *head = list->head;
+ hb_buffer_t *end = buf;
+ if (end != NULL)
+ {
+ count++;
+ while (end->next != NULL)
+ {
+ end = end->next;
+ count++;
+ }
+ }
+ list->head = buf;
+ list->tail = end;
+ list->count = count;
+ return head;
+}
+
+hb_buffer_t* hb_buffer_list_clear(hb_buffer_list_t *list)
+{
+ if (list == NULL)
+ {
+ return NULL;
+ }
+ hb_buffer_t *head = list->head;
+ list->head = list->tail = NULL;
+ list->count = 0;
+ return head;
+}
+
+void hb_buffer_list_close(hb_buffer_list_t *list)
+{
+ hb_buffer_t *buf = hb_buffer_list_clear(list);
+ hb_buffer_close(&buf);
+}
+
+int hb_buffer_list_count(hb_buffer_list_t *list)
+{
+ return list->count;
+}
+
+/**********************************************************************
* hb_list implementation
**********************************************************************
* Basic and slow, but enough for what we need
diff --git a/libhb/common.h b/libhb/common.h
index a928eb484..b540de9de 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -75,6 +75,7 @@
typedef struct hb_handle_s hb_handle_t;
typedef struct hb_hwd_s hb_hwd_t;
typedef struct hb_list_s hb_list_t;
+typedef struct hb_buffer_list_s hb_buffer_list_t;
typedef struct hb_rate_s hb_rate_t;
typedef struct hb_dither_s hb_dither_t;
typedef struct hb_mixdown_s hb_mixdown_t;
@@ -130,6 +131,24 @@ typedef enum
#include "libavcodec/qsv.h"
#endif
+struct hb_buffer_list_s
+{
+ hb_buffer_t *head;
+ hb_buffer_t *tail;
+ int count;
+};
+
+void hb_buffer_list_append(hb_buffer_list_t *list, hb_buffer_t *buf);
+void hb_buffer_list_prepend(hb_buffer_list_t *list, hb_buffer_t *buf);
+hb_buffer_t* hb_buffer_list_head(hb_buffer_list_t *list);
+hb_buffer_t* hb_buffer_list_rem_head(hb_buffer_list_t *list);
+hb_buffer_t* hb_buffer_list_tail(hb_buffer_list_t *list);
+hb_buffer_t* hb_buffer_list_rem_tail(hb_buffer_list_t *list);
+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);
+
hb_list_t * hb_list_init();
int hb_list_count( const hb_list_t * );
void hb_list_add( hb_list_t *, void * );
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index ae9806f95..474d672d2 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -81,58 +81,58 @@ typedef struct {
struct hb_work_private_s
{
- hb_job_t *job;
- hb_title_t *title;
- AVCodecContext *context;
- AVCodecParserContext *parser;
- AVFrame *frame;
- hb_buffer_t *palette;
- int threads;
- int video_codec_opened;
- hb_list_t *list;
- double duration; // frame duration (for video)
- double field_duration; // field duration (for video)
- int frame_duration_set; // Indicates valid timing was found in stream
- double pts_next; // next pts we expect to generate
- int64_t chap_time; // time of next chap mark (if new_chap != 0)
- int new_chap; // output chapter mark pending
- uint32_t nframes;
- uint32_t ndrops;
- uint32_t decode_errors;
- int64_t prev_pts;
- int brokenTS; // video stream may contain packed b-frames
- hb_buffer_t* delayq[HEAP_SIZE];
- int queue_primed;
- pts_heap_t pts_heap;
- void* buffer;
- struct SwsContext *sws_context; // if we have to rescale or convert color space
- int sws_width;
- int sws_height;
- int sws_pix_fmt;
- int cadence[12];
- int wait_for_keyframe;
+ hb_job_t * job;
+ hb_title_t * title;
+ AVCodecContext * context;
+ AVCodecParserContext * parser;
+ AVFrame * frame;
+ hb_buffer_t * palette;
+ int threads;
+ int video_codec_opened;
+ hb_buffer_list_t list;
+ double duration; // frame duration (for video)
+ double field_duration; // field duration (for video)
+ int frame_duration_set; // Indicates valid timing was found in stream
+ double pts_next; // next pts we expect to generate
+ int64_t chap_time; // time of next chap mark (if new_chap != 0)
+ int new_chap; // output chapter mark pending
+ uint32_t nframes;
+ uint32_t ndrops;
+ uint32_t decode_errors;
+ int64_t prev_pts;
+ int brokenTS; // video stream may contain packed b-frames
+ hb_buffer_t* delayq[HEAP_SIZE];
+ int queue_primed;
+ pts_heap_t pts_heap;
+ void* buffer;
+ struct SwsContext * sws_context; // if we have to rescale or convert color space
+ int sws_width;
+ int sws_height;
+ int sws_pix_fmt;
+ int cadence[12];
+ int wait_for_keyframe;
#ifdef USE_HWD
- hb_va_dxva2_t *dxva2;
- uint8_t *dst_frame;
- hb_oclscale_t *opencl_scale;
+ hb_va_dxva2_t * dxva2;
+ uint8_t * dst_frame;
+ hb_oclscale_t * opencl_scale;
#endif
- hb_audio_resample_t *resample;
+ hb_audio_resample_t * resample;
#ifdef USE_QSV
// QSV-specific settings
struct
{
- int decode;
- av_qsv_config config;
- const char *codec_name;
+ int decode;
+ av_qsv_config config;
+ const char * codec_name;
#define USE_QSV_PTS_WORKAROUND // work around out-of-order output timestamps
#ifdef USE_QSV_PTS_WORKAROUND
- hb_list_t *pts_list;
+ hb_list_t * pts_list;
#endif
} qsv;
#endif
- hb_list_t * list_subtitle;
+ hb_list_t * list_subtitle;
};
#ifdef USE_QSV_PTS_WORKAROUND
@@ -188,7 +188,6 @@ static int64_t hb_av_pop_next_pts(hb_list_t *list)
#endif
static void decodeAudio( hb_audio_t * audio, hb_work_private_t *pv, uint8_t *data, int size, int64_t pts );
-static hb_buffer_t *link_buf_list( hb_work_private_t *pv );
static int64_t heap_pop( pts_heap_t *heap )
@@ -267,7 +266,7 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job )
pv->title = job->title;
else
pv->title = w->title;
- pv->list = hb_list_init();
+ hb_buffer_list_clear(&pv->list);
codec = avcodec_find_decoder(w->codec_param);
pv->context = avcodec_alloc_context3(codec);
@@ -431,8 +430,7 @@ static void closePrivData( hb_work_private_t ** ppv )
if ( pv )
{
flushDelayQueue( pv );
- hb_buffer_t *buf = link_buf_list( pv );
- hb_buffer_close( &buf );
+ hb_buffer_list_close(&pv->list);
if ( pv->job && pv->context && pv->context->codec )
{
@@ -471,10 +469,6 @@ static void closePrivData( hb_work_private_t ** ppv )
av_freep( &pv->context->extradata );
av_freep( &pv->context );
}
- if ( pv->list )
- {
- hb_list_empty( &pv->list );
- }
hb_audio_resample_free(pv->resample);
#ifdef USE_HWD
@@ -576,7 +570,7 @@ static int decavcodecaWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
decodeAudio( w->audio, pv, pout, pout_len, cur );
}
}
- *buf_out = link_buf_list( pv );
+ *buf_out = hb_buffer_list_clear(&pv->list);
return HB_WORK_OK;
}
@@ -1032,10 +1026,10 @@ static void flushDelayQueue( hb_work_private_t *pv )
int slot = pv->queue_primed ? pv->nframes & (HEAP_SIZE-1) : 0;
// flush all the video packets left on our timestamp-reordering delay q
- while ( ( buf = pv->delayq[slot] ) != NULL )
+ while ((buf = pv->delayq[slot]) != NULL)
{
- buf->s.start = heap_pop( &pv->pts_heap );
- hb_list_add( pv->list, buf );
+ buf->s.start = heap_pop(&pv->pts_heap);
+ hb_buffer_list_append(&pv->list, buf);
pv->delayq[slot] = NULL;
slot = ( slot + 1 ) & (HEAP_SIZE-1);
}
@@ -1446,7 +1440,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
log_chapter( pv, pv->job->chapter_start, buf->s.start );
}
checkCadence( pv->cadence, flags, buf->s.start );
- hb_list_add( pv->list, buf );
+ hb_buffer_list_append(&pv->list, buf);
++pv->nframes;
return got_picture;
}
@@ -1490,7 +1484,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
log_chapter( pv, pv->job->chapter_start, buf->s.start );
}
checkCadence( pv->cadence, buf->s.flags, buf->s.start );
- hb_list_add( pv->list, buf );
+ hb_buffer_list_append(&pv->list, buf);
}
// add the new frame to the delayq & push its timestamp on the heap
@@ -1568,30 +1562,6 @@ static void decodeVideo( hb_work_object_t *w, uint8_t *data, int size, int seque
}
}
-/*
- * Removes all packets from 'pv->list', links them together into
- * a linked-list, and returns the first packet in the list.
- */
-static hb_buffer_t *link_buf_list( hb_work_private_t *pv )
-{
- hb_buffer_t *head = hb_list_item( pv->list, 0 );
-
- if ( head )
- {
- hb_list_rem( pv->list, head );
-
- hb_buffer_t *last = head, *buf;
-
- while ( ( buf = hb_list_item( pv->list, 0 ) ) != NULL )
- {
- hb_list_rem( pv->list, buf );
- last->next = buf;
- last = buf;
- }
- }
- return head;
-}
-
static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job )
{
@@ -1604,7 +1574,7 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job )
pv->title = job->title;
else
pv->title = w->title;
- pv->list = hb_list_init();
+ hb_buffer_list_clear(&pv->list);
#ifdef USE_QSV
if (hb_qsv_decode_is_enabled(job))
@@ -1819,8 +1789,8 @@ static int decavcodecvWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
{
decodeVideo(w, in->data, 0, 0, pts, dts, 0);
}
- hb_list_add( pv->list, in );
- *buf_out = link_buf_list( pv );
+ hb_buffer_list_append(&pv->list, in);
+ *buf_out = hb_buffer_list_clear(&pv->list);
return HB_WORK_DONE;
}
@@ -1919,7 +1889,7 @@ static int decavcodecvWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
}
decodeVideo( w, in->data, in->size, in->sequence, pts, dts, in->s.frametype );
hb_buffer_close( &in );
- *buf_out = link_buf_list( pv );
+ *buf_out = hb_buffer_list_clear(&pv->list);
return HB_WORK_OK;
}
@@ -2157,8 +2127,7 @@ static void decavcodecvFlush( hb_work_object_t *w )
if (pv->context != NULL && pv->context->codec != NULL)
{
flushDelayQueue( pv );
- hb_buffer_t *buf = link_buf_list( pv );
- hb_buffer_close( &buf );
+ hb_buffer_list_close(&pv->list);
if ( pv->title->opaque_priv == NULL )
{
pv->video_codec_opened = 0;
@@ -2293,7 +2262,7 @@ static void decodeAudio(hb_audio_t *audio, hb_work_private_t *pv, uint8_t *data,
out->s.duration = duration;
out->s.stop = duration + pv->pts_next;
pv->pts_next = duration + pv->pts_next;
- hb_list_add(pv->list, out);
+ hb_buffer_list_append(&pv->list, out);
}
}
}
diff --git a/libhb/deccc608sub.c b/libhb/deccc608sub.c
index 3b3f95393..bb36410fd 100644
--- a/libhb/deccc608sub.c
+++ b/libhb/deccc608sub.c
@@ -141,8 +141,7 @@ static int general_608_init (struct s_write *wb)
wb->new_channel = 1;
wb->in_xds_mode = 0;
- wb->hb_buffer = NULL;
- wb->hb_last_buffer = NULL;
+ hb_buffer_list_clear(&wb->list);
wb->last_pts = 0;
return 0;
}
@@ -162,10 +161,7 @@ static void general_608_close (struct s_write *wb)
if( wb->subline ) {
free(wb->subline);
}
-
- if( wb->hb_buffer ) {
- hb_buffer_close( &wb->hb_buffer );
- }
+ hb_buffer_list_close(&wb->list);
}
@@ -959,15 +955,7 @@ static int write_cc_buffer_as_ssa(struct eia608_screen *data,
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);
- if (wb->hb_last_buffer)
- {
- wb->hb_last_buffer->next = buffer;
- }
- else
- {
- wb->hb_buffer = buffer;
- }
- wb->hb_last_buffer = buffer;
+ hb_buffer_list_append(&wb->list, buffer);
wrote_something=1;
wb->clear_sub_needed = 1;
}
@@ -978,15 +966,7 @@ static int write_cc_buffer_as_ssa(struct eia608_screen *data,
buffer->s.start = ms_start;
buffer->s.stop = ms_start;
buffer->data[0] = 0;
- if (wb->hb_last_buffer != NULL)
- {
- wb->hb_last_buffer->next = buffer;
- }
- else
- {
- wb->hb_buffer = buffer;
- }
- wb->hb_last_buffer = buffer;
+ hb_buffer_list_append(&wb->list, buffer);
wb->clear_sub_needed = 0;
}
if (debug_608)
@@ -1832,16 +1812,9 @@ static int decccWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
/*
* Grab any pending buffer and output them with the EOF on the end
*/
- if (pv->cc608->hb_last_buffer) {
- pv->cc608->hb_last_buffer->next = in;
- *buf_out = pv->cc608->hb_buffer;
- *buf_in = NULL;
- pv->cc608->hb_buffer = NULL;
- pv->cc608->hb_last_buffer = NULL;
- } else {
- *buf_out = in;
- *buf_in = NULL;
- }
+ *buf_in = NULL;
+ hb_buffer_list_append(&pv->cc608->list, in);
+ *buf_out = hb_buffer_list_clear(&pv->cc608->list);
return HB_WORK_DONE;
}
@@ -1851,11 +1824,7 @@ static int decccWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
/*
* If there is one waiting then pass it on
*/
- *buf_out = pv->cc608->hb_buffer;
-
- pv->cc608->hb_buffer = NULL;
- pv->cc608->hb_last_buffer = NULL;
-
+ *buf_out = hb_buffer_list_clear(&pv->cc608->list);
return HB_WORK_OK;
}
diff --git a/libhb/deccc608sub.h b/libhb/deccc608sub.h
index d01209f62..0fa8c26d7 100644
--- a/libhb/deccc608sub.h
+++ b/libhb/deccc608sub.h
@@ -85,6 +85,7 @@ struct s_write {
int new_sentence;
int new_channel;
int in_xds_mode;
+ hb_buffer_list_t list;
hb_buffer_t *hb_buffer;
hb_buffer_t *hb_last_buffer;
uint64_t last_pts;
diff --git a/libhb/declpcm.c b/libhb/declpcm.c
index c85c803e9..c7aa5343c 100644
--- a/libhb/declpcm.c
+++ b/libhb/declpcm.c
@@ -188,7 +188,9 @@ static int declpcmWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
hb_work_private_t * pv = w->private_data;
hb_buffer_t *in = *buf_in;
hb_buffer_t *buf = NULL;
+ hb_buffer_list_t list;
+ hb_buffer_list_clear(&list);
if (in->s.flags & HB_BUF_FLAG_EOF)
{
/* EOF on input stream - send it downstream & say that we're done */
@@ -199,13 +201,14 @@ static int declpcmWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
pv->sequence = in->sequence;
- /* if we have a frame to finish, add enough data from this buf to finish it */
- if ( pv->size )
+ // if we have a frame to finish, add enough data from this buf
+ // to finish it
+ if (pv->size)
{
- memcpy( pv->frame + pv->pos, in->data + 6, pv->size - pv->pos );
+ memcpy(pv->frame + pv->pos, in->data + 6, pv->size - pv->pos);
buf = Decode( w );
+ hb_buffer_list_append(&list, buf);
}
- *buf_out = buf;
/* save the (rest of) data from this buf in our frame buffer */
lpcmInfo( w, in );
@@ -213,18 +216,14 @@ static int declpcmWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
int amt = in->size - off;
pv->pos = amt;
memcpy( pv->frame, in->data + off, amt );
- if ( amt >= pv->size )
+ if (amt >= pv->size)
{
- if ( buf )
- {
- buf->next = Decode( w );
- }
- else
- {
- *buf_out = Decode( w );
- }
+ buf = Decode( w );
+ hb_buffer_list_append(&list, buf);
pv->size = 0;
}
+
+ *buf_out = hb_buffer_list_clear(&list);
return HB_WORK_OK;
}
diff --git a/libhb/decomb.c b/libhb/decomb.c
index b00d7ce27..3eaee3251 100644
--- a/libhb/decomb.c
+++ b/libhb/decomb.c
@@ -2545,8 +2545,9 @@ static int hb_decomb_work( hb_filter_object_t * filter,
{
hb_filter_private_t * pv = filter->private_data;
hb_buffer_t * in = *buf_in;
- hb_buffer_t * last = NULL, * out = NULL;
+ hb_buffer_list_t list;
+ hb_buffer_list_clear(&list);
if (in->s.flags & HB_BUF_FLAG_EOF)
{
*buf_out = in;
@@ -2625,22 +2626,15 @@ static int hb_decomb_work( hb_filter_object_t * filter,
pv->is_combed == 0 ||
frame == num_frames - 1)
{
- if ( out == NULL )
- {
- last = out = o_buf[idx];
- }
- else
- {
- last->next = o_buf[idx];
- last = last->next;
- }
- last->next = NULL;
+ /* Copy buffered settings to output buffer settings */
+ o_buf[idx]->s = pv->ref[1]->s;
+
+ o_buf[idx]->next = NULL;
+ hb_buffer_list_append(&list, o_buf[idx]);
// Indicate that buffer was consumed
o_buf[idx] = NULL;
- /* Copy buffered settings to output buffer settings */
- last->s = pv->ref[1]->s;
idx ^= 1;
if ((pv->mode & MODE_MASK) && pv->spatial_metric >= 0 )
@@ -2650,7 +2644,7 @@ static int hb_decomb_work( hb_filter_object_t * filter,
((pv->mode & MODE_MASK) && (pv->mode & MODE_GAMMA)) ||
pv->is_combed)
{
- apply_mask(pv, last);
+ apply_mask(pv, hb_buffer_list_tail(&list));
}
}
}
@@ -2662,13 +2656,14 @@ static int hb_decomb_work( hb_filter_object_t * filter,
the duration of the saved timestamps. */
if ((pv->mode & MODE_BOB) && pv->is_combed)
{
- out->s.stop -= (out->s.stop - out->s.start) / 2LL;
- last->s.start = out->s.stop;
- last->s.new_chap = 0;
+ hb_buffer_t *first = hb_buffer_list_head(&list);
+ hb_buffer_t *second = hb_buffer_list_tail(&list);
+ first->s.stop -= (first->s.stop - first->s.start) / 2LL;
+ second->s.start = first->s.stop;
+ second->s.new_chap = 0;
}
- *buf_out = out;
-
+ *buf_out = hb_buffer_list_clear(&list);
return HB_FILTER_OK;
}
diff --git a/libhb/decpgssub.c b/libhb/decpgssub.c
index 9b0bd4212..46990102a 100644
--- a/libhb/decpgssub.c
+++ b/libhb/decpgssub.c
@@ -18,15 +18,13 @@ struct hb_work_private_s
// packet until we have processed several packets. So we cache
// all the packets we see until libav returns a subtitle with
// the information we need.
- hb_buffer_t * list_pass_buffer;
- hb_buffer_t * last_pass_buffer;
+ hb_buffer_list_t list_pass;
// It is possible for multiple subtitles to be enncapsulated in
// one packet. This won't happen for PGS subs, but may for other
// types of subtitles. Since I plan to generalize this code to handle
// other than PGS, we will need to keep a list of all subtitles seen
// while parsing an input packet.
- hb_buffer_t * list_buffer;
- hb_buffer_t * last_buffer;
+ hb_buffer_list_t list;
// XXX: we may occasionally see subtitles with broken timestamps
// while this should really get fixed elsewhere,
// dropping subtitles should be avoided as much as possible
@@ -50,6 +48,8 @@ static int decsubInit( hb_work_object_t * w, hb_job_t * job )
pv = calloc( 1, sizeof( hb_work_private_t ) );
w->private_data = pv;
+ hb_buffer_list_clear(&pv->list);
+ hb_buffer_list_clear(&pv->list_pass);
pv->discard_subtitle = 1;
pv->seen_forced_sub = 0;
pv->last_pts = 0;
@@ -168,18 +168,10 @@ static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
if (in->s.flags & HB_BUF_FLAG_EOF)
{
/* EOF on input stream - send it downstream & say that we're done */
- if ( pv->list_buffer == NULL )
- {
- pv->list_buffer = pv->last_buffer = in;
- }
- else
- {
- pv->last_buffer->next = in;
- }
*buf_in = NULL;
- *buf_out = pv->list_buffer;
- pv->list_buffer = NULL;
+ hb_buffer_list_append(&pv->list, in);
+ *buf_out = hb_buffer_list_clear(&pv->list);
return HB_WORK_DONE;
}
@@ -189,15 +181,8 @@ static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
{
// Append to buffer list. It will be sent to fifo after we determine
// if this is a packet we need.
- if ( pv->list_pass_buffer == NULL )
- {
- pv->list_pass_buffer = pv->last_pass_buffer = in;
- }
- else
- {
- pv->last_pass_buffer->next = in;
- pv->last_pass_buffer = in;
- }
+ hb_buffer_list_append(&pv->list_pass, in);
+
// We are keeping the buffer, so prevent the filter loop from
// deleting it.
*buf_in = NULL;
@@ -286,7 +271,7 @@ static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
//
// If passthru, create an empty subtitle.
// Also, flag an empty subtitle for subtitle RENDER.
- make_empty_pgs(pv->list_pass_buffer);
+ make_empty_pgs(hb_buffer_list_head(&pv->list_pass));
clear_subtitle = 1;
}
// is the subtitle forced?
@@ -340,15 +325,17 @@ static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
if ( w->subtitle->config.dest == PASSTHRUSUB &&
hb_subtitle_can_pass( PGSSUB, pv->job->mux ) )
{
- /* PGS subtitles are spread across multiple packets (1 per segment).
- * In the MKV container, all segments are found in the same packet
- * (this is expected by some devices, such as the WD TV Live).
- * So if there are multiple packets, merge them. */
- if (pv->list_pass_buffer->next == NULL)
+ /* PGS subtitles are spread across multiple packets,
+ * 1 per segment.
+ *
+ * In the MKV container, all segments are found in the same
+ * packet (this is expected by some devices, such as the
+ * WD TV Live). So if there are multiple packets,
+ * merge them. */
+ if (hb_buffer_list_count(&pv->list_pass) == 1)
{
// packets already merged (e.g. MKV sources)
- out = pv->list_pass_buffer;
- pv->list_pass_buffer = NULL;
+ out = hb_buffer_list_clear(&pv->list_pass);
}
else
{
@@ -356,7 +343,7 @@ static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
uint8_t * data;
hb_buffer_t * b;
- b = pv->list_pass_buffer;
+ b = hb_buffer_list_head(&pv->list_pass);
while (b != NULL)
{
size += b->size;
@@ -365,14 +352,14 @@ static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
out = hb_buffer_init( size );
data = out->data;
- b = pv->list_pass_buffer;
+ b = hb_buffer_list_head(&pv->list_pass);
while (b != NULL)
{
- memcpy( data, b->data, b->size );
+ memcpy(data, b->data, b->size);
data += b->size;
b = b->next;
}
- hb_buffer_close( &pv->list_pass_buffer );
+ hb_buffer_list_close(&pv->list_pass);
out->s = in->s;
out->sequence = in->sequence;
@@ -468,15 +455,7 @@ static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
alpha += out->plane[3].stride;
}
}
- if ( pv->list_buffer == NULL )
- {
- pv->list_buffer = pv->last_buffer = out;
- }
- else
- {
- pv->last_buffer->next = out;
- pv->last_buffer = out;
- }
+ hb_buffer_list_append(&pv->list, out);
out = NULL;
}
else
@@ -493,32 +472,19 @@ static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
out->f.height = 0;
}
}
- if ( pv->list_buffer == NULL )
- {
- pv->list_buffer = pv->last_buffer = out;
- }
- else
- {
- pv->last_buffer->next = out;
- }
- while (pv->last_buffer && pv->last_buffer->next)
- {
- pv->last_buffer = pv->last_buffer->next;
- }
+ hb_buffer_list_append(&pv->list, out);
}
- else if ( has_subtitle )
+ else if (has_subtitle)
{
- hb_buffer_close( &pv->list_pass_buffer );
- pv->list_pass_buffer = NULL;
+ hb_buffer_list_close(&pv->list_pass);
}
- if ( has_subtitle )
+ if (has_subtitle)
{
avsubtitle_free(&subtitle);
}
} while (avp.size > 0);
- *buf_out = pv->list_buffer;
- pv->list_buffer = NULL;
+ *buf_out = hb_buffer_list_clear(&pv->list);
return HB_WORK_OK;
}
diff --git a/libhb/decssasub.c b/libhb/decssasub.c
index 4a974ac38..0f6ac042b 100644
--- a/libhb/decssasub.c
+++ b/libhb/decssasub.c
@@ -241,9 +241,10 @@ static hb_buffer_t *ssa_decode_packet( hb_work_object_t * w, hb_buffer_t *in )
hb_buffer_realloc(in, ++in->size);
in->data[in->size - 1] = '\0';
- hb_buffer_t *out_list = NULL;
- hb_buffer_t **nextPtr = &out_list;
+ hb_buffer_list_t list;
+ hb_buffer_t *buf;
+ hb_buffer_list_clear(&list);
const char *EOL = "\r\n";
char *curLine, *curLine_parserData;
for ( curLine = strtok_r( (char *) in->data, EOL, &curLine_parserData );
@@ -255,14 +256,9 @@ static hb_buffer_t *ssa_decode_packet( hb_work_object_t * w, hb_buffer_t *in )
continue;
// Decode an individual SSA line
- hb_buffer_t *out;
- out = ssa_decode_line_to_mkv_ssa(w, (uint8_t *)curLine, strlen(curLine), in->sequence);
- if ( out == NULL )
- continue;
-
- // Append 'out' to 'out_list'
- *nextPtr = out;
- nextPtr = &out->next;
+ buf = ssa_decode_line_to_mkv_ssa(w, (uint8_t *)curLine,
+ strlen(curLine), in->sequence);
+ hb_buffer_list_append(&list, buf);
}
// For point-to-point encoding, when the start time of the stream
@@ -279,21 +275,19 @@ static hb_buffer_t *ssa_decode_packet( hb_work_object_t * w, hb_buffer_t *in )
// such that first output packet's display time aligns with the
// input packet's display time. This should give the correct time
// when point-to-point encoding is in effect.
- if (out_list && out_list->s.start > in->s.start)
+ buf = hb_buffer_list_head(&list);
+ if (buf && buf->s.start > in->s.start)
{
- int64_t slip = out_list->s.start - in->s.start;
- hb_buffer_t *out;
-
- out = out_list;
- while (out)
+ int64_t slip = buf->s.start - in->s.start;
+ while (buf != NULL)
{
- out->s.start -= slip;
- out->s.stop -= slip;
- out = out->next;
+ buf->s.start -= slip;
+ buf->s.stop -= slip;
+ buf = buf->next;
}
}
- return out_list;
+ return hb_buffer_list_clear(&list);
}
/*
diff --git a/libhb/deinterlace.c b/libhb/deinterlace.c
index cd68a6070..a402a5253 100644
--- a/libhb/deinterlace.c
+++ b/libhb/deinterlace.c
@@ -390,7 +390,9 @@ static hb_buffer_t * deint_fast(hb_filter_private_t * pv, hb_buffer_t * in)
int ii;
hb_buffer_t *dst, *src;
+ hb_buffer_list_t list;
+ hb_buffer_list_clear(&list);
if (in != NULL)
{
dst = hb_frame_buffer_init(in->f.fmt, in->f.width, in->f.height);
@@ -409,42 +411,20 @@ static hb_buffer_t * deint_fast(hb_filter_private_t * pv, hb_buffer_t * in)
taskset_cycle( &pv->deint_taskset );
}
- hb_buffer_t *first = NULL, *last = NULL;
for (ii = 0; ii < pv->deint_nsegs; ii++)
{
src = pv->deint_arguments[ii].src;
dst = pv->deint_arguments[ii].dst;
pv->deint_arguments[ii].src = NULL;
pv->deint_arguments[ii].dst = NULL;
- if (first == NULL)
- {
- first = dst;
- }
- if (last != NULL)
- {
- last->next = dst;
- }
- last = dst;
+ hb_buffer_list_append(&list, dst);
dst->s = src->s;
hb_buffer_close(&src);
}
- if (in == NULL)
- {
- // Flushing final buffers. Append EOS marker buffer.
- dst = hb_buffer_eof_init();
- if (first == NULL)
- {
- first = dst;
- }
- else
- {
- last->next = dst;
- }
- }
pv->deint_nsegs = 0;
- return first;
+ return hb_buffer_list_clear(&list);
}
static int hb_deinterlace_init( hb_filter_object_t * filter,
@@ -580,30 +560,31 @@ static int hb_deinterlace_work( hb_filter_object_t * filter,
{
hb_filter_private_t * pv = filter->private_data;
hb_buffer_t * in = *buf_in;
- hb_buffer_t * last = NULL, * out = NULL;
+ hb_buffer_list_t list;
+ *buf_in = NULL;
+ hb_buffer_list_clear(&list);
if (in->s.flags & HB_BUF_FLAG_EOF)
{
- *buf_out = in;
- *buf_in = NULL;
if( !( pv->yadif_mode & MODE_YADIF_ENABLE ) )
{
// Flush final frames
- *buf_out = deint_fast(pv, NULL);
+ hb_buffer_list_append(&list, deint_fast(pv, NULL));
}
+ hb_buffer_list_append(&list, in);
+
+ *buf_out = hb_buffer_list_clear(&list);
return HB_FILTER_DONE;
}
- /* Use libavcodec deinterlace if yadif_mode < 0 */
+ /* Use fast deinterlace if yadif_mode < 0 */
if( !( pv->yadif_mode & MODE_YADIF_ENABLE ) )
{
- *buf_in = NULL;
*buf_out = deint_fast(pv, in);
return HB_FILTER_OK;
}
/* Store current frame in yadif cache */
- *buf_in = NULL;
yadif_store_ref(pv, in);
// yadif requires 3 buffers, prev, cur, and next. For the first
@@ -647,7 +628,8 @@ static int hb_deinterlace_work( hb_filter_object_t * filter,
if (o_buf[idx] == NULL)
{
- o_buf[idx] = hb_frame_buffer_init(in->f.fmt, in->f.width, in->f.height);
+ o_buf[idx] = hb_frame_buffer_init(in->f.fmt,
+ in->f.width, in->f.height);
}
yadif_filter(pv, o_buf[idx], parity, tff);
@@ -655,22 +637,13 @@ static int hb_deinterlace_work( hb_filter_object_t * filter,
// else, add only final frame
if (( pv->yadif_mode & MODE_YADIF_BOB ) || frame == num_frames - 1)
{
- if ( out == NULL )
- {
- last = out = o_buf[idx];
- }
- else
- {
- last->next = o_buf[idx];
- last = last->next;
- }
- last->next = NULL;
+ /* Copy buffered settings to output buffer settings */
+ o_buf[idx]->s = pv->yadif_ref[1]->s;
+ o_buf[idx]->next = NULL;
+ hb_buffer_list_append(&list, o_buf[idx]);
// Indicate that buffer was consumed
o_buf[idx] = NULL;
-
- /* Copy buffered settings to output buffer settings */
- last->s = pv->yadif_ref[1]->s;
idx ^= 1;
}
}
@@ -681,13 +654,14 @@ static int hb_deinterlace_work( hb_filter_object_t * filter,
* timestamps. */
if (pv->yadif_mode & MODE_YADIF_BOB)
{
- out->s.stop -= (out->s.stop - out->s.start) / 2LL;
- last->s.start = out->s.stop;
- last->s.new_chap = 0;
+ hb_buffer_t *first = hb_buffer_list_head(&list);
+ hb_buffer_t *second = hb_buffer_list_tail(&list);
+ first->s.stop -= (first->s.stop - first->s.start) / 2LL;
+ second->s.start = first->s.stop;
+ second->s.new_chap = 0;
}
- *buf_out = out;
-
+ *buf_out = hb_buffer_list_clear(&list);
return HB_FILTER_OK;
}
diff --git a/libhb/demuxmpeg.c b/libhb/demuxmpeg.c
index f370caf04..cbc1c3f98 100644
--- a/libhb/demuxmpeg.c
+++ b/libhb/demuxmpeg.c
@@ -71,7 +71,7 @@ static inline void restore_chap( hb_psdemux_t *state, hb_buffer_t *buf )
/* Basic MPEG demuxer */
-void hb_demux_dvd_ps( hb_buffer_t * buf, hb_list_t * list_es, hb_psdemux_t* state )
+void hb_demux_dvd_ps( hb_buffer_t * buf, hb_buffer_list_t * list_es, hb_psdemux_t* state )
{
hb_buffer_t * buf_es;
int pos = 0;
@@ -232,7 +232,7 @@ void hb_demux_dvd_ps( hb_buffer_t * buf, hb_list_t * list_es, hb_psdemux_t* stat
}
memcpy( buf_es->data, d + pos, pes_packet_end - pos );
- hb_list_add( list_es, buf_es );
+ hb_buffer_list_append(list_es, buf_es);
pos = pes_packet_end;
}
@@ -248,7 +248,7 @@ void hb_demux_dvd_ps( hb_buffer_t * buf, hb_list_t * list_es, hb_psdemux_t* stat
// stripped off and buf has all the info gleaned from them: id is set,
// start contains the pts (if any), renderOffset contains the dts (if any)
// and stop contains the pcr (if it changed).
-void hb_demux_mpeg(hb_buffer_t *buf, hb_list_t *list_es,
+void hb_demux_mpeg(hb_buffer_t *buf, hb_buffer_list_t *list_es,
hb_psdemux_t *state, int tolerance)
{
while ( buf )
@@ -342,19 +342,19 @@ void hb_demux_mpeg(hb_buffer_t *buf, hb_list_t *list_es,
hb_buffer_t *tmp = buf->next;
buf->next = NULL;
- hb_list_add( list_es, buf );
+ hb_buffer_list_append(list_es, buf);
buf = tmp;
}
}
-void hb_demux_ts(hb_buffer_t *buf, hb_list_t *list_es, hb_psdemux_t *state)
+void hb_demux_ts(hb_buffer_t *buf, hb_buffer_list_t *list_es, hb_psdemux_t *state)
{
// Distance between PCRs in TS is up to 100ms, but we have seen
// streams that exceed this, so allow up to 300ms.
hb_demux_mpeg(buf, list_es, state, 300);
}
-void hb_demux_ps(hb_buffer_t *buf, hb_list_t *list_es, hb_psdemux_t *state)
+void hb_demux_ps(hb_buffer_t *buf, hb_buffer_list_t *list_es, hb_psdemux_t *state)
{
// Distance between SCRs in PS is up to 700ms
hb_demux_mpeg(buf, list_es, state, 700);
@@ -363,7 +363,7 @@ void hb_demux_ps(hb_buffer_t *buf, hb_list_t *list_es, hb_psdemux_t *state)
// "null" demuxer (makes a copy of input buf & returns it in list)
// used when the reader for some format includes its own demuxer.
// for example, ffmpeg.
-void hb_demux_null( hb_buffer_t * buf, hb_list_t * list_es, hb_psdemux_t* state )
+void hb_demux_null( hb_buffer_t * buf, hb_buffer_list_t * list_es, hb_psdemux_t* state )
{
while ( buf )
{
@@ -388,7 +388,7 @@ void hb_demux_null( hb_buffer_t * buf, hb_list_t * list_es, hb_psdemux_t* state
hb_buffer_t *tmp = buf->next;
buf->next = NULL;
- hb_list_add( list_es, buf );
+ hb_buffer_list_append(list_es, buf);
buf = tmp;
}
}
diff --git a/libhb/enc_qsv.c b/libhb/enc_qsv.c
index 39ed16bef..4f99bbc95 100644
--- a/libhb/enc_qsv.c
+++ b/libhb/enc_qsv.c
@@ -67,44 +67,44 @@ hb_work_object_t hb_encqsv =
struct hb_work_private_s
{
- hb_job_t *job;
- uint32_t frames_in;
- uint32_t frames_out;
- int64_t last_start;
+ hb_job_t * job;
+ uint32_t frames_in;
+ uint32_t frames_out;
+ int64_t last_start;
- hb_qsv_param_t param;
- av_qsv_space enc_space;
- hb_qsv_info_t *qsv_info;
+ hb_qsv_param_t param;
+ av_qsv_space enc_space;
+ hb_qsv_info_t * qsv_info;
- hb_list_t *delayed_chapters;
- int64_t next_chapter_pts;
+ hb_list_t * delayed_chapters;
+ int64_t next_chapter_pts;
#define BFRM_DELAY_MAX 16
- uint32_t *init_delay;
- int bfrm_delay;
- int64_t init_pts[BFRM_DELAY_MAX + 1];
- hb_list_t *list_dts;
+ int * init_delay;
+ int bfrm_delay;
+ int64_t init_pts[BFRM_DELAY_MAX + 1];
+ hb_list_t * list_dts;
- int64_t frame_duration[FRAME_INFO_SIZE];
+ int64_t frame_duration[FRAME_INFO_SIZE];
- int async_depth;
- int max_async_depth;
+ int async_depth;
+ int max_async_depth;
// if encode-only, system memory used
- int is_sys_mem;
- mfxSession mfx_session;
- struct SwsContext *sws_context_to_nv12;
+ int is_sys_mem;
+ mfxSession mfx_session;
+ struct SwsContext * sws_context_to_nv12;
// whether to expect input from VPP or from QSV decode
- int is_vpp_present;
+ int is_vpp_present;
// whether the encoder is initialized
- int init_done;
+ int init_done;
- hb_list_t *delayed_processing;
- hb_list_t *encoded_frames;
+ hb_list_t * delayed_processing;
+ hb_buffer_list_t encoded_frames;
- hb_list_t *loaded_plugins;
+ hb_list_t * loaded_plugins;
};
// used in delayed_chapters list
@@ -680,8 +680,8 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
pv->is_sys_mem = hb_qsv_decode_is_enabled(job) == 0;
pv->qsv_info = hb_qsv_info_get(job->vcodec);
pv->delayed_processing = hb_list_init();
- pv->encoded_frames = hb_list_init();
pv->last_start = INT64_MIN;
+ hb_buffer_list_clear(&pv->encoded_frames);
pv->next_chapter_pts = AV_NOPTS_VALUE;
pv->delayed_chapters = hb_list_init();
@@ -984,7 +984,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
}
else
{
- hb_error("encqsvInit: invalid rate control (%d, %d)",
+ hb_error("encqsvInit: invalid rate control (%f, %d)",
job->vquality, job->vbitrate);
return -1;
}
@@ -1514,16 +1514,7 @@ void encqsvClose(hb_work_object_t *w)
}
hb_list_close(&pv->delayed_chapters);
}
- if (pv->encoded_frames != NULL)
- {
- hb_buffer_t *item;
- while ((item = hb_list_item(pv->encoded_frames, 0)) != NULL)
- {
- hb_list_rem(pv->encoded_frames, item);
- hb_buffer_close(&item);
- }
- hb_list_close(&pv->encoded_frames);
- }
+ hb_buffer_list_close(&pv->encoded_frames);
}
free(pv);
@@ -1677,7 +1668,7 @@ static void compute_init_delay(hb_work_private_t *pv, mfxBitstream *bs)
}
/* This can come in handy */
- hb_deep_log(2, "compute_init_delay: %"PRId64" (%d frames)", pv->init_delay[0], pv->bfrm_delay);
+ hb_deep_log(2, "compute_init_delay: %d (%d frames)", pv->init_delay[0], pv->bfrm_delay);
/* The delay only needs to be set once. */
pv->init_delay = NULL;
@@ -1781,7 +1772,7 @@ static void qsv_bitstream_slurp(hb_work_private_t *pv, mfxBitstream *bs)
restore_chapter(pv, buf);
}
- hb_list_add(pv->encoded_frames, buf);
+ hb_buffer_list_append(&pv->encoded_frames, buf);
pv->frames_out++;
return;
@@ -1923,28 +1914,6 @@ static int qsv_enc_work(hb_work_private_t *pv,
return 0;
}
-static hb_buffer_t* link_buffer_list(hb_list_t *list)
-{
- hb_buffer_t *buf, *prev = NULL, *out = NULL;
-
- while ((buf = hb_list_item(list, 0)) != NULL)
- {
- hb_list_rem(list, buf);
-
- if (prev == NULL)
- {
- prev = out = buf;
- }
- else
- {
- prev->next = buf;
- prev = buf;
- }
- }
-
- return out;
-}
-
int encqsvWork(hb_work_object_t *w, hb_buffer_t **buf_in, hb_buffer_t **buf_out)
{
hb_work_private_t *pv = w->private_data;
@@ -1968,8 +1937,8 @@ int encqsvWork(hb_work_object_t *w, hb_buffer_t **buf_in, hb_buffer_t **buf_out)
if (in->s.flags & HB_BUF_FLAG_EOF)
{
qsv_enc_work(pv, NULL, NULL);
- hb_list_add(pv->encoded_frames, in);
- *buf_out = link_buffer_list(pv->encoded_frames);
+ hb_buffer_list_append(&pv->encoded_frames, in);
+ *buf_out = hb_buffer_list_clear(&pv->encoded_frames);
*buf_in = NULL; // don't let 'work_loop' close this buffer
return HB_WORK_DONE;
}
@@ -2091,7 +2060,7 @@ int encqsvWork(hb_work_object_t *w, hb_buffer_t **buf_in, hb_buffer_t **buf_out)
goto fail;
}
- *buf_out = link_buffer_list(pv->encoded_frames);
+ *buf_out = hb_buffer_list_clear(&pv->encoded_frames);
return HB_WORK_OK;
fail:
diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c
index 5063e43f1..134dbcc6b 100644
--- a/libhb/encavcodec.c
+++ b/libhb/encavcodec.c
@@ -32,8 +32,7 @@ struct hb_work_private_s
int frameno_in;
int frameno_out;
- hb_buffer_t * delay_head;
- hb_buffer_t * delay_tail;
+ hb_buffer_list_t delay_list;
int64_t dts_delay;
@@ -66,6 +65,8 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job )
w->private_data = pv;
pv->job = job;
+ hb_buffer_list_clear(&pv->delay_list);
+
int clock_min, clock_max, clock;
hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);
@@ -435,27 +436,20 @@ static uint8_t convert_pict_type( int pict_type, char pkt_flag_key, uint16_t* sf
// This is similar to how x264 generates DTS
static hb_buffer_t * process_delay_list( hb_work_private_t * pv, hb_buffer_t * buf )
{
- if ( pv->job->areBframes )
+ if (pv->job->areBframes)
{
// Has dts_delay been set yet?
- if ( pv->frameno_in <= pv->job->areBframes )
+ hb_buffer_list_append(&pv->delay_list, buf);
+ if (pv->frameno_in <= pv->job->areBframes)
{
// dts_delay not yet set. queue up buffers till it is set.
- if ( pv->delay_tail == NULL )
- {
- pv->delay_head = pv->delay_tail = buf;
- }
- else
- {
- pv->delay_tail->next = buf;
- pv->delay_tail = buf;
- }
return NULL;
}
// We have dts_delay. Apply it to any queued buffers renderOffset
// and return all queued buffers.
- if ( pv->delay_tail == NULL && buf != NULL )
+ buf = hb_buffer_list_head(&pv->delay_list);
+ while (buf != NULL)
{
// Use the cached frame info to get the start time of Nth frame
// Note that start Nth frame != start time this buffer since the
@@ -467,40 +461,16 @@ static hb_buffer_t * process_delay_list( hb_work_private_t * pv, hb_buffer_t * b
}
else
{
- buf->s.renderOffset =
- get_frame_start(pv, pv->frameno_out - pv->job->areBframes);
- }
- pv->frameno_out++;
- return buf;
- }
- else
- {
- pv->delay_tail->next = buf;
- buf = pv->delay_head;
- while ( buf )
- {
- // Use the cached frame info to get the start time of Nth frame
- // Note that start Nth frame != start time this buffer since the
- // output buffers have rearranged start times.
- if (pv->frameno_out < pv->job->areBframes)
- {
- int64_t start = get_frame_start( pv, pv->frameno_out );
- buf->s.renderOffset = start - pv->dts_delay;
- }
- else
- {
- buf->s.renderOffset = get_frame_start(pv,
+ buf->s.renderOffset = get_frame_start(pv,
pv->frameno_out - pv->job->areBframes);
- }
- buf = buf->next;
- pv->frameno_out++;
}
- buf = pv->delay_head;
- pv->delay_head = pv->delay_tail = NULL;
- return buf;
+ buf = buf->next;
+ pv->frameno_out++;
}
+ buf = hb_buffer_list_clear(&pv->delay_list);
+ return buf;
}
- else if ( buf )
+ else if (buf != NULL)
{
buf->s.renderOffset = buf->s.start;
return buf;
@@ -520,12 +490,15 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
hb_job_t * job = pv->job;
AVFrame * frame;
hb_buffer_t * in = *buf_in, * buf;
+ hb_buffer_list_t list;
char final_flushing_call = !!(in->s.flags & HB_BUF_FLAG_EOF);
- if ( final_flushing_call )
+
+ hb_buffer_list_clear(&list);
+ if (final_flushing_call)
{
- //make a flushing call to encode for codecs that can encode out of order
/* EOF on input - send it downstream & say we're done */
- *buf_in = NULL;
+ // make a flushing call to encode for codecs that can encode
+ // out of order
frame = NULL;
}
else
@@ -560,9 +533,6 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
AVPacket pkt;
int got_packet;
char still_flushing = final_flushing_call;
- hb_buffer_t* buf_head = NULL;
- hb_buffer_t* buf_last = NULL;
-
do
{
av_init_packet(&pkt);
@@ -588,15 +558,7 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
buf->s.frametype = convert_pict_type( pv->context->coded_frame->pict_type, pkt.flags & AV_PKT_FLAG_KEY, &buf->s.flags );
buf = process_delay_list( pv, buf );
- if (buf_head == NULL)
- {
- buf_head = buf;
- }
- else
- {
- buf_last->next = buf;
- }
- buf_last = buf;
+ hb_buffer_list_append(&list, buf);
}
/* Write stats */
if (job->pass_id == HB_PASS_ENCODE_1ST &&
@@ -605,27 +567,21 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
fprintf( pv->file, "%s", pv->context->stats_out );
}
} while (still_flushing);
- if (buf_last != NULL && final_flushing_call)
- {
- buf_last->next = in;
- buf = buf_head;
- }
- else if (final_flushing_call)
+
+ if (final_flushing_call)
{
- buf = in;
+ *buf_in = NULL;
+ hb_buffer_list_append(&list, in);
}
}
else
{
- buf = NULL;
-
hb_error( "encavcodec: codec context has uninitialized codec; skipping frame" );
}
av_frame_free( &frame );
- *buf_out = buf;
-
+ *buf_out = hb_buffer_list_clear(&list);
return final_flushing_call? HB_WORK_DONE : HB_WORK_OK;
}
diff --git a/libhb/encavcodecaudio.c b/libhb/encavcodecaudio.c
index 2f302b348..ed4997e1e 100644
--- a/libhb/encavcodecaudio.c
+++ b/libhb/encavcodecaudio.c
@@ -426,26 +426,19 @@ static hb_buffer_t* Encode(hb_work_object_t *w)
static hb_buffer_t * Flush( hb_work_object_t * w )
{
- hb_buffer_t *first, *buf, *last;
+ hb_buffer_list_t list;
+ hb_buffer_t *buf;
- first = last = buf = Encode( w );
- while( buf )
+ hb_buffer_list_clear(&list);
+ buf = Encode( w );
+ while (buf != NULL)
{
- last = buf;
- buf->next = Encode( w );
- buf = buf->next;
+ hb_buffer_list_append(&list, buf);
+ buf = Encode( w );
}
- if( last )
- {
- last->next = hb_buffer_eof_init();
- }
- else
- {
- first = hb_buffer_eof_init();
- }
-
- return first;
+ hb_buffer_list_append(&list, hb_buffer_eof_init());
+ return hb_buffer_list_clear(&list);
}
/***********************************************************************
@@ -458,6 +451,7 @@ static int encavcodecaWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
{
hb_work_private_t * pv = w->private_data;
hb_buffer_t * in = *buf_in, * buf;
+ hb_buffer_list_t list;
if (in->s.flags & HB_BUF_FLAG_EOF)
{
@@ -475,14 +469,15 @@ static int encavcodecaWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
hb_list_add( pv->list, in );
*buf_in = NULL;
- *buf_out = buf = Encode( w );
-
- while ( buf )
+ hb_buffer_list_clear(&list);
+ buf = Encode( w );
+ while (buf != NULL)
{
- buf->next = Encode( w );
- buf = buf->next;
+ hb_buffer_list_append(&list, buf);
+ buf = Encode( w );
}
+ *buf_out = hb_buffer_list_clear(&list);
return HB_WORK_OK;
}
diff --git a/libhb/enclame.c b/libhb/enclame.c
index 0efe21906..9ba7c5d87 100644
--- a/libhb/enclame.c
+++ b/libhb/enclame.c
@@ -185,7 +185,10 @@ int enclameWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
hb_audio_t * audio = w->audio;
hb_buffer_t * in = *buf_in;
hb_buffer_t * buf;
+ hb_buffer_list_t list;
+ *buf_in = NULL;
+ hb_buffer_list_clear(&list);
if (in->s.flags & HB_BUF_FLAG_EOF)
{
/* EOF on input - send it downstream & say we're done */
@@ -202,35 +205,24 @@ int enclameWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
{
hb_buffer_close( &buf );
}
-
- // Add the flushed data
- *buf_out = buf;
-
+ hb_buffer_list_append(&list, buf);
// Add the eof
- if ( buf )
- {
- buf->next = in;
- }
- else
- {
- *buf_out = in;
- }
+ hb_buffer_list_append(&list, in);
- *buf_in = NULL;
+ *buf_out = hb_buffer_list_clear(&list);
return HB_WORK_DONE;
}
- hb_list_add( pv->list, *buf_in );
- *buf_in = NULL;
-
- *buf_out = buf = Encode( w );
+ hb_list_add(pv->list, in);
- while( buf )
+ buf = Encode( w );
+ while (buf)
{
- buf->next = Encode( w );
- buf = buf->next;
+ hb_buffer_list_append(&list, buf);
+ buf = Encode( w );
}
+ *buf_out = hb_buffer_list_clear(&list);
return HB_WORK_OK;
}
diff --git a/libhb/encvorbis.c b/libhb/encvorbis.c
index c4ff206e1..ad5b690bc 100644
--- a/libhb/encvorbis.c
+++ b/libhb/encvorbis.c
@@ -258,23 +258,26 @@ int encvorbisWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
hb_work_private_t * pv = w->private_data;
hb_buffer_t * in = *buf_in;
hb_buffer_t * buf;
+ hb_buffer_list_t list;
*buf_in = NULL;
+ hb_buffer_list_clear(&list);
if (in->s.flags & HB_BUF_FLAG_EOF)
{
/* EOF on input - send it downstream & say we're done */
*buf_out = in;
- return HB_WORK_DONE;
+ return HB_WORK_DONE;
}
- hb_list_add( pv->list, in );
+ hb_list_add(pv->list, in);
- *buf_out = buf = Encode( w );
- while( buf )
+ buf = Encode( w );
+ while (buf)
{
- buf->next = Encode( w );
- buf = buf->next;
+ hb_buffer_list_append(&list, buf);
+ buf = Encode( w );
}
+ *buf_out = hb_buffer_list_clear(&list);
return HB_WORK_OK;
}
diff --git a/libhb/encx264.c b/libhb/encx264.c
index 24e838357..2580f2ee9 100644
--- a/libhb/encx264.c
+++ b/libhb/encx264.c
@@ -53,8 +53,6 @@ struct hb_work_private_s
x264_picture_t pic_in;
uint8_t * grey_data;
- uint32_t frames_in;
- uint32_t frames_out;
int64_t last_stop; // Debugging - stop time of previous input frame
hb_list_t *delayed_chapters;
@@ -669,8 +667,11 @@ int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
x264_picture_t pic_out;
int i_nal;
x264_nal_t *nal;
- hb_buffer_t *last_buf = NULL;
+ hb_buffer_list_t list;
+ hb_buffer_list_clear(&list);
+
+ // flush delayed frames
while ( x264_encoder_delayed_frames( pv->x264 ) )
{
x264_encoder_encode( pv->x264, &nal, &i_nal, NULL, &pic_out );
@@ -680,29 +681,17 @@ int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
break;
hb_buffer_t *buf = nal_encode( w, &pic_out, i_nal, nal );
- if ( buf )
- {
- ++pv->frames_out;
- if ( last_buf == NULL )
- *buf_out = buf;
- else
- last_buf->next = buf;
- last_buf = buf;
- }
+ hb_buffer_list_append(&list, buf);
}
- // Flushed everything - add the eof to the end of the chain.
- if ( last_buf == NULL )
- *buf_out = in;
- else
- last_buf->next = in;
+ // add the EOF to the end of the chain
+ hb_buffer_list_append(&list, in);
+ *buf_out = hb_buffer_list_clear(&list);
*buf_in = NULL;
return HB_WORK_DONE;
}
// Not EOF - encode the packet & wrap it in a NAL
- ++pv->frames_in;
- ++pv->frames_out;
*buf_out = x264_encode( w, in );
return HB_WORK_OK;
}
diff --git a/libhb/encx265.c b/libhb/encx265.c
index ad9f5ff86..d9c15637d 100644
--- a/libhb/encx265.c
+++ b/libhb/encx265.c
@@ -538,36 +538,20 @@ int encx265Work(hb_work_object_t *w, hb_buffer_t **buf_in, hb_buffer_t **buf_out
uint32_t nnal;
x265_nal *nal;
x265_picture pic_out;
- hb_buffer_t *last_buf = NULL;
+ hb_buffer_list_t list;
+
+ hb_buffer_list_clear(&list);
// flush delayed frames
while (x265_encoder_encode(pv->x265, &nal, &nnal, NULL, &pic_out) > 0)
{
hb_buffer_t *buf = nal_encode(w, &pic_out, nal, nnal);
- if (buf != NULL)
- {
- if (last_buf == NULL)
- {
- *buf_out = buf;
- }
- else
- {
- last_buf->next = buf;
- }
- last_buf = buf;
- }
+ hb_buffer_list_append(&list, buf);
}
-
// add the EOF to the end of the chain
- if (last_buf == NULL)
- {
- *buf_out = in;
- }
- else
- {
- last_buf->next = in;
- }
+ hb_buffer_list_append(&list, in);
+ *buf_out = hb_buffer_list_clear(&list);
*buf_in = NULL;
return HB_WORK_DONE;
}
diff --git a/libhb/internal.h b/libhb/internal.h
index bcecc5040..ab444ace8 100644
--- a/libhb/internal.h
+++ b/libhb/internal.h
@@ -292,11 +292,11 @@ typedef struct {
int new_chap;
} hb_psdemux_t;
-typedef void (*hb_muxer_t)(hb_buffer_t *, hb_list_t *, hb_psdemux_t*);
+typedef void (*hb_muxer_t)(hb_buffer_t *, hb_buffer_list_t *, hb_psdemux_t*);
-void hb_demux_ps( hb_buffer_t * ps_buf, hb_list_t * es_list, hb_psdemux_t * );
-void hb_demux_ts( hb_buffer_t * ps_buf, hb_list_t * es_list, hb_psdemux_t * );
-void hb_demux_null( hb_buffer_t * ps_buf, hb_list_t * es_list, hb_psdemux_t * );
+void hb_demux_ps(hb_buffer_t * ps_buf, hb_buffer_list_t * es_list, hb_psdemux_t *);
+void hb_demux_ts(hb_buffer_t * ps_buf, hb_buffer_list_t * es_list, hb_psdemux_t *);
+void hb_demux_null(hb_buffer_t * ps_buf, hb_buffer_list_t * es_list, hb_psdemux_t *);
extern const hb_muxer_t hb_demux[];
diff --git a/libhb/nlmeans.c b/libhb/nlmeans.c
index a306c8f4a..295aad863 100644
--- a/libhb/nlmeans.c
+++ b/libhb/nlmeans.c
@@ -1070,26 +1070,20 @@ static hb_buffer_t * nlmeans_filter(hb_filter_private_t *pv)
pv->next_frame -= pv->thread_count;
// Collect results from taskset
- hb_buffer_t *last = NULL, *out = NULL;
+ hb_buffer_list_t list;
+ hb_buffer_list_clear(&list);
for (int t = 0; t < pv->thread_count; t++)
{
- if (out == NULL)
- {
- out = last = pv->thread_data[t]->out;
- }
- else
- {
- last->next = pv->thread_data[t]->out;
- last = pv->thread_data[t]->out;
- }
+ hb_buffer_list_append(&list, pv->thread_data[t]->out);
}
- return out;
+ return hb_buffer_list_clear(&list);
}
static hb_buffer_t * nlmeans_filter_flush(hb_filter_private_t *pv)
{
- hb_buffer_t *out = NULL, *last = NULL;
+ hb_buffer_list_t list;
+ hb_buffer_list_clear(&list);
for (int f = 0; f < pv->next_frame; f++)
{
Frame *frame = &pv->frame[f];
@@ -1140,17 +1134,9 @@ static hb_buffer_t * nlmeans_filter_flush(hb_filter_private_t *pv)
pv->diff_max[c]);
}
buf->s = frame->s;
- if (out == NULL)
- {
- out = last = buf;
- }
- else
- {
- last->next = buf;
- last = buf;
- }
+ hb_buffer_list_append(&list, buf);
}
- return out;
+ return hb_buffer_list_clear(&list);
}
static int nlmeans_work(hb_filter_object_t *filter,
@@ -1162,21 +1148,17 @@ static int nlmeans_work(hb_filter_object_t *filter,
if (in->s.flags & HB_BUF_FLAG_EOF)
{
- hb_buffer_t *last;
+ hb_buffer_list_t list;
+ hb_buffer_t *buf;
+
// Flush buffered frames
- last = *buf_out = nlmeans_filter_flush(pv);
+ buf = nlmeans_filter_flush(pv);
+ hb_buffer_list_set(&list, buf);
+
+ // And terminate the buffer list with a EOF buffer
+ hb_buffer_list_append(&list, in);
+ *buf_out = hb_buffer_list_clear(&list);
- // And terminate the buffer list with a null buffer
- if (last != NULL)
- {
- while (last->next != NULL)
- last = last->next;
- last->next = in;
- }
- else
- {
- *buf_out = in;
- }
*buf_in = NULL;
return HB_FILTER_DONE;
}
diff --git a/libhb/qsv_filter.c b/libhb/qsv_filter.c
index 87e10ee28..33a324cf8 100644
--- a/libhb/qsv_filter.c
+++ b/libhb/qsv_filter.c
@@ -35,29 +35,29 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct hb_filter_private_s
{
- hb_job_t *job;
- hb_list_t *list;
-
- int width_in;
- int height_in;
- int pix_fmt;
- int pix_fmt_out;
- int width_out;
- int height_out;
- int crop[4];
- int deinterlace;
- int is_frc_used;
+ hb_job_t * job;
+ hb_buffer_list_t list;
+
+ int width_in;
+ int height_in;
+ int pix_fmt;
+ int pix_fmt_out;
+ int width_out;
+ int height_out;
+ int crop[4];
+ int deinterlace;
+ int is_frc_used;
// set during init, used to configure input surfaces' "area of interest"
- mfxU16 CropX;
- mfxU16 CropY;
- mfxU16 CropH;
- mfxU16 CropW;
+ mfxU16 CropX;
+ mfxU16 CropY;
+ mfxU16 CropH;
+ mfxU16 CropW;
- av_qsv_space *vpp_space;
+ av_qsv_space * vpp_space;
// FRC param(s)
- mfxExtVPPFrameRateConversion frc_config;
+ mfxExtVPPFrameRateConversion frc_config;
};
static int hb_qsv_filter_init( hb_filter_object_t * filter,
@@ -339,7 +339,7 @@ static int hb_qsv_filter_init( hb_filter_object_t * filter,
filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) );
hb_filter_private_t * pv = filter->private_data;
- pv->list = hb_list_init();
+ hb_buffer_list_clear(&pv->list);
// list of init params provided at work.c:~700
pv->width_in = init->geometry.width;
pv->height_in = init->geometry.height;
@@ -451,7 +451,7 @@ static void hb_qsv_filter_close( hb_filter_object_t * filter )
// closing the commong stuff
av_qsv_context_clean(qsv);
}
- hb_list_close(&pv->list);
+ hb_buffer_list_close(&pv->list);
free( pv );
filter->private_data = NULL;
}
@@ -598,7 +598,8 @@ static int hb_qsv_filter_work( hb_filter_object_t * filter,
return HB_FILTER_OK;
}
- while(1){
+ while(1)
+ {
int ret = filter_init(qsv,pv);
if(ret >= 2)
av_qsv_sleep(1);
@@ -610,68 +611,54 @@ static int hb_qsv_filter_work( hb_filter_object_t * filter,
if (in->s.flags & HB_BUF_FLAG_EOF)
{
- while(1){
+ while(1)
+ {
sts = process_frame(in->qsv_details.qsv_atom, qsv, pv);
if(sts)
- hb_list_add(pv->list,in);
+ hb_buffer_list_append(&pv->list, in);
else
break;
}
- hb_list_add( pv->list, in );
- *buf_out = link_buf_list( pv );
+ hb_buffer_list_append(&pv->list, in);
+ *buf_out = hb_buffer_list_clear(&pv->list);
return HB_FILTER_DONE;
}
sts = process_frame(in->qsv_details.qsv_atom, qsv, pv);
- if(sts){
- hb_list_add(pv->list,in);
+ if(sts)
+ {
+ hb_buffer_list_append(&pv->list, in);
}
- if( hb_list_count(pv->list) ){
- *buf_out = hb_list_item(pv->list,0);
- out = *buf_out;
- if(pv->is_frc_used && out)
+ out = *buf_out = hb_buffer_list_rem_head(&pv->list);
+ if (pv->is_frc_used && out != NULL)
+ {
+ if (out->qsv_details.qsv_atom)
{
- if(out->qsv_details.qsv_atom){
- av_qsv_stage* stage = av_qsv_get_last_stage( out->qsv_details.qsv_atom );
- mfxFrameSurface1 *work_surface = stage->out.p_surface;
-
- av_qsv_wait_on_sync( qsv,stage );
-
- av_qsv_space *qsv_vpp = pv->vpp_space;
- int64_t duration = ((double)qsv_vpp->m_mfxVideoParam.vpp.Out.FrameRateExtD/(double)qsv_vpp->m_mfxVideoParam.vpp.Out.FrameRateExtN ) * 90000.;
- out->s.start = work_surface->Data.TimeStamp;
- out->s.stop = work_surface->Data.TimeStamp + duration;
- }
+ av_qsv_stage* stage;
+ mfxFrameSurface1 *work_surface;
+ int64_t duration;
+ av_qsv_space *qsv_vpp;
+
+ stage = av_qsv_get_last_stage(out->qsv_details.qsv_atom);
+ work_surface = stage->out.p_surface;
+
+ av_qsv_wait_on_sync( qsv,stage );
+
+ qsv_vpp = pv->vpp_space;
+ duration =
+ ((double)qsv_vpp->m_mfxVideoParam.vpp.Out.FrameRateExtD /
+ (double)qsv_vpp->m_mfxVideoParam.vpp.Out.FrameRateExtN ) *
+ 90000.;
+ out->s.start = work_surface->Data.TimeStamp;
+ out->s.stop = work_surface->Data.TimeStamp + duration;
}
- hb_list_rem(pv->list,*buf_out);
}
- else
- *buf_out = NULL;
return HB_FILTER_OK;
}
-// see devavcode.c
-hb_buffer_t *link_buf_list( hb_filter_private_t *pv )
-{
- hb_buffer_t *head = hb_list_item( pv->list, 0 );
-
- if ( head )
- {
- hb_list_rem( pv->list, head );
- hb_buffer_t *last = head, *buf;
- while ( ( buf = hb_list_item( pv->list, 0 ) ) != NULL )
- {
- hb_list_rem( pv->list, buf );
- last->next = buf;
- last = buf;
- }
- }
- return head;
-}
-
#endif // USE_QSV
diff --git a/libhb/qsv_filter.h b/libhb/qsv_filter.h
index e55a85cdf..6c456edf1 100644
--- a/libhb/qsv_filter.h
+++ b/libhb/qsv_filter.h
@@ -29,7 +29,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef QSV_FILTER_H
#define QSV_FILTER_H
-hb_buffer_t *link_buf_list( hb_filter_private_t *pv );
void qsv_filter_close( av_qsv_context* qsv, AV_QSV_STAGE_TYPE vpp_type );
#endif // QSV_FILTER_H
diff --git a/libhb/qsv_filter_pp.h b/libhb/qsv_filter_pp.h
index e70370321..8a72ad5b2 100644
--- a/libhb/qsv_filter_pp.h
+++ b/libhb/qsv_filter_pp.h
@@ -31,8 +31,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "msdk/mfxplugin.h"
-extern hb_buffer_t *link_buf_list( hb_filter_private_t *pv );
-
struct qsv_filter_task_s;
typedef struct{
diff --git a/libhb/reader.c b/libhb/reader.c
index 9c742e6fd..dda2a2e71 100644
--- a/libhb/reader.c
+++ b/libhb/reader.c
@@ -366,15 +366,15 @@ static void new_scr_offset( hb_work_private_t *r, hb_buffer_t *buf )
**********************************************************************/
void ReadLoop( void * _w )
{
- hb_work_object_t * w = _w;
+ hb_work_object_t * w = _w;
hb_work_private_t * r = w->private_data;
- hb_fifo_t ** fifos;
- hb_buffer_t * buf = NULL;
- hb_list_t * list;
- int n;
- int chapter = -1;
- int chapter_end = r->job->chapter_end;
- uint8_t done = 0;
+ hb_fifo_t ** fifos;
+ hb_buffer_t * buf = NULL;
+ hb_buffer_list_t list;
+ int n;
+ int chapter = -1;
+ int chapter_end = r->job->chapter_end;
+ uint8_t done = 0;
if (r->bd)
{
@@ -489,7 +489,7 @@ void ReadLoop( void * _w )
hb_stream_seek_chapter( r->stream, start );
}
- list = hb_list_init();
+ hb_buffer_list_clear(&list);
while(!*r->die && !r->job->done && !done)
{
@@ -537,11 +537,10 @@ void ReadLoop( void * _w )
}
}
- (hb_demux[r->title->demuxer])( buf, list, &r->demux );
+ (hb_demux[r->title->demuxer])(buf, &list, &r->demux);
- while( ( buf = hb_list_item( list, 0 ) ) )
+ while ((buf = hb_buffer_list_rem_head(&list)) != NULL)
{
- hb_list_rem( list, buf );
fifos = GetFifoForId( r, buf->s.id );
if (fifos && r->stream && r->start_found == 2 )
@@ -752,7 +751,7 @@ void ReadLoop( void * _w )
}
}
- hb_list_empty( &list );
+ hb_buffer_list_close(&list);
hb_log( "reader: done. %d scr changes", r->demux.scr_changes );
}
diff --git a/libhb/scan.c b/libhb/scan.c
index 56a256f8b..2280644ba 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -516,21 +516,23 @@ static int is_close_to( int val, int target, int thresh )
**********************************************************************/
static int DecodePreviews( hb_scan_t * data, hb_title_t * title, int flush )
{
- int i, npreviews = 0, abort = 0;
- hb_buffer_t * buf, * buf_es;
- hb_list_t * list_es;
- int progressive_count = 0;
- int pulldown_count = 0;
- int doubled_frame_count = 0;
- int interlaced_preview_count = 0;
- int frame_wait = 0;
- int cc_wait = 10;
- int frames;
- hb_stream_t * stream = NULL;
- info_list_t * info_list = calloc( data->preview_count+1, sizeof(*info_list) );
+ int i, npreviews = 0, abort = 0;
+ hb_buffer_t * buf, * buf_es;
+ hb_buffer_list_t list_es;
+ int progressive_count = 0;
+ int pulldown_count = 0;
+ int doubled_frame_count = 0;
+ int interlaced_preview_count = 0;
+ int frame_wait = 0;
+ int cc_wait = 10;
+ int frames;
+ hb_stream_t * stream = NULL;
+ info_list_t * info_list;
+
+ info_list = calloc(data->preview_count+1, sizeof(*info_list));
crop_record_t *crops = crop_record_init( data->preview_count );
- list_es = hb_list_init();
+ hb_buffer_list_clear(&list_es);
if( data->batch )
{
@@ -712,11 +714,10 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title, int flush )
total_read += buf->size;
packets++;
- (hb_demux[title->demuxer])(buf, list_es, 0 );
+ (hb_demux[title->demuxer])(buf, &list_es, 0 );
- while( ( buf_es = hb_list_item( list_es, 0 ) ) )
+ while ((buf_es = hb_buffer_list_rem_head(&list_es)) != NULL)
{
- hb_list_rem( list_es, buf_es );
if( buf_es->s.id == title->video_id && vid_buf == NULL )
{
vid_decoder->work( vid_decoder, &buf_es, &vid_buf );
@@ -802,11 +803,7 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title, int flush )
progressive_count++;
}
- while( ( buf_es = hb_list_item( list_es, 0 ) ) )
- {
- hb_list_rem( list_es, buf_es );
- hb_buffer_close( &buf_es );
- }
+ hb_buffer_list_close(&list_es);
/* Check preview for interlacing artifacts */
if( hb_detect_comb( vid_buf, 10, 30, 9, 10, 30, 9 ) )
@@ -1061,12 +1058,8 @@ skip_preview:
crop_record_free( crops );
free( info_list );
- while( ( buf_es = hb_list_item( list_es, 0 ) ) )
- {
- hb_list_rem( list_es, buf_es );
- hb_buffer_close( &buf_es );
- }
- hb_list_close( &list_es );
+ hb_buffer_list_close(&list_es);
+
if (data->bd)
hb_bd_stop( data->bd );
if (data->dvd)
diff --git a/libhb/stream.c b/libhb/stream.c
index 76fb96fc9..1d5f0f446 100644
--- a/libhb/stream.c
+++ b/libhb/stream.c
@@ -4468,8 +4468,10 @@ static int stream_kind_to_buf_type(int kind)
static hb_buffer_t * generate_output_data(hb_stream_t *stream, int curstream)
{
- hb_buffer_t *buf = NULL, *first = NULL;
+ hb_buffer_list_t list;
+ hb_buffer_t *buf = NULL;
+ hb_buffer_list_clear(&list);
hb_ts_stream_t * ts_stream = &stream->ts.list[curstream];
hb_buffer_t * b = ts_stream->buf;
if (!ts_stream->pes_info_valid)
@@ -4534,16 +4536,8 @@ static hb_buffer_t * generate_output_data(hb_stream_t *stream, int curstream)
// we want the whole TS stream including all substreams.
// DTS-HD is an example of this.
- if (first == NULL)
- {
- first = buf = hb_buffer_init(es_size);
- }
- else
- {
- hb_buffer_t *tmp = hb_buffer_init(es_size);
- buf->next = tmp;
- buf = tmp;
- }
+ buf = hb_buffer_init(es_size);
+ hb_buffer_list_append(&list, buf);
buf->s.id = get_id(pes_stream);
buf->s.type = stream_kind_to_buf_type(pes_stream->stream_kind);
@@ -4579,7 +4573,7 @@ static hb_buffer_t * generate_output_data(hb_stream_t *stream, int curstream)
}
b->size = 0;
ts_stream->packet_offset = 0;
- return first;
+ return hb_buffer_list_clear(&list);
}
static void hb_ts_stream_append_pkt(hb_stream_t *stream, int idx,
@@ -4604,18 +4598,17 @@ static void hb_ts_stream_append_pkt(hb_stream_t *stream, int idx,
static hb_buffer_t * flush_ts_streams( hb_stream_t *stream )
{
- hb_buffer_t *out, **last;
+ hb_buffer_list_t list;
+ hb_buffer_t *buf;
int ii;
- last = &out;
+ hb_buffer_list_clear(&list);
for (ii = 0; ii < stream->ts.count; ii++)
{
- *last = generate_output_data(stream, ii);
- // generate_output_data can generate 0 or multiple output buffers
- while (*last != NULL)
- last = &(*last)->next;
+ buf = generate_output_data(stream, ii);
+ hb_buffer_list_append(&list, buf);
}
- return out;
+ return hb_buffer_list_clear(&list);
}
/***********************************************************************
@@ -4632,10 +4625,10 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
*/
int video_index = ts_index_of_video(stream);
int curstream;
- hb_buffer_t *out = NULL;
- hb_buffer_t **last;
+ hb_buffer_t *buf = NULL;
+ hb_buffer_list_t list;
- last = &out;
+ hb_buffer_list_clear(&list);
if (chapter > 0)
{
@@ -4686,10 +4679,8 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
if (discontinuity)
{
// If there is a discontinuity, flush all data
- *last = flush_ts_streams(stream);
- // flush_ts_streams can generate 0 or multiple output buffers
- while (*last != NULL)
- last = &(*last)->next;
+ buf = flush_ts_streams(stream);
+ hb_buffer_list_append(&list, buf);
}
if (adapt_len > 0)
{
@@ -4710,10 +4701,8 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
// When we get a new pcr, we flush all data that was
// referenced to the last pcr. This makes it easier
// for reader to resolve pcr discontinuities.
- *last = flush_ts_streams(stream);
- // flush_ts_streams can generate 0 or multiple output buffers
- while (*last != NULL)
- last = &(*last)->next;
+ buf = flush_ts_streams(stream);
+ hb_buffer_list_append(&list, buf);
int64_t pcr;
pcr = ((uint64_t)pkt[ 6] << (33 - 8) ) |
@@ -4734,7 +4723,7 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
// the video stream DTS for the PCR.
if (!stream->ts.found_pcr && (stream->ts_flags & TS_HAS_PCR))
{
- return out;
+ return hb_buffer_list_clear(&list);
}
// Get continuity
@@ -4771,7 +4760,7 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
// a PCR when one is needed). The only thing that can
// change in the dup is the PCR which we grabbed above
// so ignore the rest.
- return out;
+ return hb_buffer_list_clear(&list);
}
}
if ( !start && (ts_stream->continuity != -1) &&
@@ -4782,7 +4771,7 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
(int)continuity,
(ts_stream->continuity + 1) & 0xf );
ts_stream->continuity = continuity;
- return out;
+ return hb_buffer_list_clear(&list);
}
ts_stream->continuity = continuity;
@@ -4811,7 +4800,7 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
// I ran across a poorly mastered BD that does not properly pad
// the adaptation field and causes parsing errors below if we
// do not exit early here.
- return out;
+ return hb_buffer_list_clear(&list);
}
/* If we get here the packet is valid - process its data */
@@ -4825,10 +4814,8 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
// we have to ship the old packet before updating the pcr
// since the packet we've been accumulating is referenced
// to the old pcr.
- *last = generate_output_data(stream, curstream);
- // generate_output_data can generate 0 or multiple output buffers
- while (*last != NULL)
- last = &(*last)->next;
+ buf = generate_output_data(stream, curstream);
+ hb_buffer_list_append(&list, buf);
ts_stream->pes_info_valid = 0;
ts_stream->packet_len = 0;
}
@@ -4839,7 +4826,7 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
{
ts_err( stream, curstream, "missing start code" );
ts_stream->skipbad = 1;
- return out;
+ return hb_buffer_list_clear(&list);
}
// If we were skipping a bad packet, start fresh on this new PES packet
@@ -4857,7 +4844,7 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
// a DTS or PTS.
if (stream->ts.last_timestamp < 0 && (pes[7] >> 6) == 0)
{
- return out;
+ return hb_buffer_list_clear(&list);
}
if ((pes[7] >> 6) != 0)
{
@@ -4903,12 +4890,10 @@ hb_buffer_t * hb_ts_decode_pkt( hb_stream_t *stream, const uint8_t * pkt,
ts_stream->pes_info.packet_len > 0 &&
ts_stream->packet_len >= ts_stream->pes_info.packet_len + 6)
{
- // generate_output_data can generate 0 or multiple output buffers
- *last = generate_output_data(stream, curstream);
- while (*last != NULL)
- last = &(*last)->next;
+ buf = generate_output_data(stream, curstream);
+ hb_buffer_list_append(&list, buf);
}
- return out;
+ return hb_buffer_list_clear(&list);
}
static hb_buffer_t * hb_ts_stream_decode( hb_stream_t *stream )
diff --git a/libhb/sync.c b/libhb/sync.c
index 688e1cd53..d3cb4cbde 100644
--- a/libhb/sync.c
+++ b/libhb/sync.c
@@ -60,10 +60,9 @@ typedef struct
typedef struct
{
- int link;
- int merge;
- hb_buffer_t * list_current;
- hb_buffer_t * last;
+ int link;
+ int merge;
+ hb_buffer_list_t list_current;
} subtitle_sanitizer_t;
typedef struct
@@ -218,17 +217,17 @@ hb_work_object_t * hb_sync_init( hb_job_t * job )
return ret;
}
-static void InitSubtitle( hb_job_t * job, hb_sync_video_t * sync, int i )
+static void InitSubtitle( hb_job_t * job, hb_sync_video_t * sync, int ii )
{
hb_subtitle_t * subtitle;
- subtitle = hb_list_item( job->list_subtitle, i );
+ subtitle = hb_list_item( job->list_subtitle, ii );
if (subtitle->format == TEXTSUB &&
subtitle->config.dest == PASSTHRUSUB &&
(job->mux & HB_MUX_MASK_MP4))
{
// Merge overlapping subtitles since mpv tx3g does not support them
- sync->subtitle_sanitizer[i].merge = 1;
+ sync->subtitle_sanitizer[ii].merge = 1;
}
// PGS subtitles don't need to be linked because there are explicit
// "clear" subtitle packets that indicate the end time of the
@@ -237,13 +236,14 @@ static void InitSubtitle( hb_job_t * job, hb_sync_video_t * sync, int i )
subtitle->source != PGSSUB)
{
// Fill in stop time when it is missing
- sync->subtitle_sanitizer[i].link = 1;
+ sync->subtitle_sanitizer[ii].link = 1;
}
+ hb_buffer_list_clear(&sync->subtitle_sanitizer[ii].list_current);
}
static void CloseSubtitle(hb_sync_video_t * sync, int ii)
{
- hb_buffer_close(&sync->subtitle_sanitizer[ii].list_current);
+ hb_buffer_list_close(&sync->subtitle_sanitizer[ii].list_current);
}
/***********************************************************************
@@ -345,82 +345,70 @@ static hb_buffer_t * merge_ssa(hb_buffer_t *a, hb_buffer_t *b)
static hb_buffer_t * mergeSubtitles(subtitle_sanitizer_t *sanitizer, int end)
{
- hb_buffer_t *a, *b, *buf, *out = NULL, *last = NULL;
+ hb_buffer_t *a, *b, *buf;
+ hb_buffer_list_t list;
+
+ hb_buffer_list_clear(&list);
do
{
- a = sanitizer->list_current;
- b = a != NULL ? a->next : NULL;
+ a = hb_buffer_list_head(&sanitizer->list_current);
+ if (a == NULL)
+ {
+ break;
+ }
+ b = a->next;
buf = NULL;
- if (a != NULL && b == NULL && end)
+ if (b == NULL && end)
{
- sanitizer->list_current = a->next;
- if (sanitizer->list_current == NULL)
- sanitizer->last = NULL;
- a->next = NULL;
- buf = a;
+ buf = hb_buffer_list_rem_head(&sanitizer->list_current);
}
- else if (a != NULL && a->s.stop != AV_NOPTS_VALUE)
+ else if (a->s.stop != AV_NOPTS_VALUE)
{
if (!sanitizer->merge)
{
- sanitizer->list_current = a->next;
- if (sanitizer->list_current == NULL)
- sanitizer->last = NULL;
- a->next = NULL;
- buf = a;
+ buf = hb_buffer_list_rem_head(&sanitizer->list_current);
}
else if (b != NULL && a->s.stop > b->s.start)
{
// Overlap
if (ABS(a->s.start - b->s.start) <= 18000)
{
+ if (b->s.stop == AV_NOPTS_VALUE && !end)
+ {
+ // To evaluate overlaps, we need the stop times
+ // for a and b
+ break;
+ }
+ a = hb_buffer_list_rem_head(&sanitizer->list_current);
+
// subtitles start within 1/5 second of eachother, merge
- if (a->s.stop > b->s.stop)
+ if (a->s.stop > b->s.stop && b->s.stop != AV_NOPTS_VALUE)
{
// a continues after b, reorder the list and swap
- hb_buffer_t *tmp = a;
- a->next = b->next;
- b->next = a;
- if (sanitizer->last == b)
- {
- sanitizer->last = a;
- }
- a = b;
- b = tmp;
- sanitizer->list_current = a;
+ b = a;
+ a = hb_buffer_list_rem_head(&sanitizer->list_current);
+ hb_buffer_list_prepend(&sanitizer->list_current, b);
}
- a->next = NULL;
b->s.start = a->s.stop;
buf = merge_ssa(a, b);
hb_buffer_close(&a);
a = buf;
- buf = NULL;
- sanitizer->list_current = a;
if (b->s.stop != AV_NOPTS_VALUE &&
ABS(b->s.stop - b->s.start) <= 18000)
{
// b and a completely overlap, remove b
- a->next = b->next;
- b->next = NULL;
- if (sanitizer->last == b)
- {
- sanitizer->last = a;
- }
+ b = hb_buffer_list_rem_head(&sanitizer->list_current);
hb_buffer_close(&b);
}
- else
- {
- a->next = b;
- }
}
else
{
- // a starts before b, output copy of a and
+ // a starts before b, output copy of a and update a start
buf = hb_buffer_dup(a);
buf->s.stop = b->s.start;
a->s.start = b->s.start;
@@ -428,11 +416,8 @@ static hb_buffer_t * mergeSubtitles(subtitle_sanitizer_t *sanitizer, int end)
}
else if (b != NULL && a->s.stop <= b->s.start)
{
- sanitizer->list_current = a->next;
- if (sanitizer->list_current == NULL)
- sanitizer->last = NULL;
- a->next = NULL;
- buf = a;
+ // a starts and ends before b
+ buf = hb_buffer_list_rem_head(&sanitizer->list_current);
}
}
@@ -442,19 +427,11 @@ static hb_buffer_t * mergeSubtitles(subtitle_sanitizer_t *sanitizer, int end)
buf->s.duration = buf->s.stop - buf->s.start;
else
buf->s.duration = AV_NOPTS_VALUE;
- if (last == NULL)
- {
- out = last = buf;
- }
- else
- {
- last->next = buf;
- last = buf;
- }
+ hb_buffer_list_append(&list, buf);
}
- } while (buf != NULL);
+ } while (hb_buffer_list_count(&list) >= 2 || end);
- return out;
+ return hb_buffer_list_clear(&list);
}
static hb_buffer_t * sanitizeSubtitle(
@@ -496,9 +473,10 @@ static hb_buffer_t * sanitizeSubtitle(
if (sub->s.renderOffset != AV_NOPTS_VALUE)
sub->s.renderOffset -= pv->common->video_pts_slip;
- if (sanitizer->last != NULL && sanitizer->last->s.stop == AV_NOPTS_VALUE)
+ hb_buffer_t *last = hb_buffer_list_tail(&sanitizer->list_current);
+ if (last != NULL && last->s.stop == AV_NOPTS_VALUE)
{
- sanitizer->last->s.stop = sub->s.start;
+ last->s.stop = sub->s.start;
}
if (sub->s.start == sub->s.stop)
@@ -507,18 +485,7 @@ static hb_buffer_t * sanitizeSubtitle(
// of subtitles is not encoded in the stream
hb_buffer_close(&sub);
}
- if (sub != NULL)
- {
- if (sanitizer->last == NULL)
- {
- sanitizer->list_current = sanitizer->last = sub;
- }
- else
- {
- sanitizer->last->next = sub;
- sanitizer->last = sub;
- }
- }
+ hb_buffer_list_append(&sanitizer->list_current, sub);
return mergeSubtitles(sanitizer, 0);
}
diff --git a/libhb/vfr.c b/libhb/vfr.c
index 8f62c9241..92c46f4ed 100644
--- a/libhb/vfr.c
+++ b/libhb/vfr.c
@@ -6,7 +6,7 @@
It may be used under the terms of the GNU General Public License v2.
For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
*/
-
+
#include "hb.h"
struct hb_filter_private_s
@@ -73,17 +73,6 @@ static void build_gamma_lut( hb_filter_private_t * pv )
}
}
-// insert buffer 'succ' after buffer chain element 'pred'.
-// caller must guarantee that 'pred' and 'succ' are non-null.
-static hb_buffer_t *insert_buffer_in_chain(
- hb_buffer_t *pred,
- hb_buffer_t *succ )
-{
- succ->next = pred->next;
- pred->next = succ;
- return succ;
-}
-
#define DUP_THRESH_SSE 5.0
// Compute ths sum of squared errors for a 16x16 block
@@ -150,151 +139,156 @@ static float motion_metric( hb_filter_private_t * pv, hb_buffer_t * a, hb_buffer
// times are left alone.
//
-static void adjust_frame_rate( hb_filter_private_t *pv, hb_buffer_t **buf_out )
+static void adjust_frame_rate( hb_filter_private_t *pv, hb_buffer_list_t *list )
{
- hb_buffer_t *out = *buf_out;
+ hb_buffer_t *out = hb_buffer_list_tail(list);
- if ( out && out->size > 0 )
+ if (out == NULL || out->size <= 0 )
{
- if ( pv->cfr == 0 )
- {
- ++pv->count_frames;
- pv->out_last_stop = out->s.stop;
- return;
- }
+ return;
+ }
+
+ if ( pv->cfr == 0 )
+ {
+ ++pv->count_frames;
+ pv->out_last_stop = out->s.stop;
+ return;
+ }
+
+ // compute where this frame would stop if the frame rate were constant
+ // (this is our target stopping time for CFR and earliest possible
+ // stopping time for PFR).
+ double cfr_stop = pv->frame_rate * ( pv->count_frames + 1 );
- // compute where this frame would stop if the frame rate were constant
- // (this is our target stopping time for CFR and earliest possible
- // stopping time for PFR).
- double cfr_stop = pv->frame_rate * ( pv->count_frames + 1 );
+ hb_buffer_t * next = hb_fifo_see( pv->delay_queue );
- hb_buffer_t * next = hb_fifo_see( pv->delay_queue );
+ float next_metric = 0;
+ if( next )
+ next_metric = motion_metric( pv, out, next );
+
+ if( pv->out_last_stop >= out->s.stop )
+ {
+ ++pv->drops;
+ hb_buffer_list_rem_tail(list);
+ hb_buffer_close(&out);
- float next_metric = 0;
- if( next )
- next_metric = motion_metric( pv, out, next );
+ pv->frame_metric = next_metric;
+ if( next_metric > pv->max_metric )
+ pv->max_metric = next_metric;
- if( pv->out_last_stop >= out->s.stop )
+ return;
+ }
+
+ if( out->s.start <= pv->out_last_stop &&
+ out->s.stop > pv->out_last_stop &&
+ next && next->s.stop < cfr_stop )
+ {
+ // This frame starts before the end of the last output
+ // frame and ends after the end of the last output
+ // frame (i.e. it straddles it). Also the next frame
+ // ends before the end of the next output frame. If the
+ // next frame is not a duplicate, and we haven't seen
+ // a changed frame since the last output frame,
+ // then drop this frame.
+ //
+ // This causes us to sync to the pattern of progressive
+ // 23.976 fps content that has been upsampled to
+ // progressive 59.94 fps.
+ if( pv->out_metric > pv->max_metric &&
+ next_metric > pv->max_metric )
{
+ // Pattern: N R R N
+ // o c n
+ // N == new frame
+ // R == repeat frame
+ // o == last output frame
+ // c == current frame
+ // n == next frame
+ // We haven't seen a frame change since the last output
+ // frame and the next frame changes. Use the next frame,
+ // drop this one.
++pv->drops;
- hb_buffer_close( buf_out );
-
pv->frame_metric = next_metric;
- if( next_metric > pv->max_metric )
- pv->max_metric = next_metric;
-
+ pv->max_metric = next_metric;
+ pv->sync_parity = 1;
+ hb_buffer_list_rem_tail(list);
+ hb_buffer_close(&out);
return;
}
-
- if( out->s.start <= pv->out_last_stop &&
- out->s.stop > pv->out_last_stop &&
- next && next->s.stop < cfr_stop )
+ else if( pv->sync_parity &&
+ pv->out_metric < pv->max_metric &&
+ pv->max_metric > pv->frame_metric &&
+ pv->frame_metric < next_metric )
{
- // This frame starts before the end of the last output
- // frame and ends after the end of the last output
- // frame (i.e. it straddles it). Also the next frame
- // ends before the end of the next output frame. If the
- // next frame is not a duplicate, and we haven't seen
- // a changed frame since the last output frame,
- // then drop this frame.
- //
- // This causes us to sync to the pattern of progressive
- // 23.976 fps content that has been upsampled to
- // progressive 59.94 fps.
- if( pv->out_metric > pv->max_metric &&
- next_metric > pv->max_metric )
- {
- // Pattern: N R R N
- // o c n
- // N == new frame
- // R == repeat frame
- // o == last output frame
- // c == current frame
- // n == next frame
- // We haven't seen a frame change since the last output
- // frame and the next frame changes. Use the next frame,
- // drop this one.
- ++pv->drops;
- pv->frame_metric = next_metric;
- pv->max_metric = next_metric;
- pv->sync_parity = 1;
- hb_buffer_close( buf_out );
- return;
- }
- else if( pv->sync_parity &&
- pv->out_metric < pv->max_metric &&
- pv->max_metric > pv->frame_metric &&
- pv->frame_metric < next_metric )
- {
- // Pattern: R N R N
- // o c n
- // N == new frame
- // R == repeat frame
- // o == last output frame
- // c == current frame
- // n == next frame
- // If we see this pattern, we must not use the next
- // frame when straddling the current frame.
- pv->sync_parity = 0;
- }
- else if( pv->sync_parity )
- {
- // The pattern is indeterminate. Continue dropping
- // frames on the same schedule
- ++pv->drops;
- pv->frame_metric = next_metric;
- pv->max_metric = next_metric;
- pv->sync_parity = 1;
- hb_buffer_close( buf_out );
- return;
- }
-
+ // Pattern: R N R N
+ // o c n
+ // N == new frame
+ // R == repeat frame
+ // o == last output frame
+ // c == current frame
+ // n == next frame
+ // If we see this pattern, we must not use the next
+ // frame when straddling the current frame.
+ pv->sync_parity = 0;
+ }
+ else if( pv->sync_parity )
+ {
+ // The pattern is indeterminate. Continue dropping
+ // frames on the same schedule
+ ++pv->drops;
+ pv->frame_metric = next_metric;
+ pv->max_metric = next_metric;
+ pv->sync_parity = 1;
+ hb_buffer_list_rem_tail(list);
+ hb_buffer_close(&out);
+ return;
}
- // this frame has to start where the last one stopped.
- out->s.start = pv->out_last_stop;
+ }
- pv->out_metric = pv->frame_metric;
- pv->frame_metric = next_metric;
- pv->max_metric = next_metric;
+ // this frame has to start where the last one stopped.
+ out->s.start = pv->out_last_stop;
- // at this point we know that this frame doesn't push the average
- // rate over the limit so we just pass it on for PFR. For CFR we're
- // going to return it (with its start & stop times modified) and
- // we may have to dup it.
- ++pv->count_frames;
- if ( pv->cfr > 1 )
+ pv->out_metric = pv->frame_metric;
+ pv->frame_metric = next_metric;
+ pv->max_metric = next_metric;
+
+ // at this point we know that this frame doesn't push the average
+ // rate over the limit so we just pass it on for PFR. For CFR we're
+ // going to return it (with its start & stop times modified) and
+ // we may have to dup it.
+ ++pv->count_frames;
+ if ( pv->cfr > 1 )
+ {
+ // PFR - we're going to keep the frame but may need to
+ // adjust it's stop time to meet the average rate constraint.
+ if ( out->s.stop <= cfr_stop )
{
- // PFR - we're going to keep the frame but may need to
- // adjust it's stop time to meet the average rate constraint.
- if ( out->s.stop <= cfr_stop )
- {
- out->s.stop = cfr_stop;
- }
- pv->out_last_stop = out->s.stop;
+ out->s.stop = cfr_stop;
}
- else
+ pv->out_last_stop = out->s.stop;
+ }
+ else
+ {
+ // we're doing CFR so we have to either trim some time from a
+ // buffer that ends too far in the future or, if the buffer is
+ // two or more frame times long, split it into multiple pieces,
+ // each of which is a frame time long.
+ double excess_dur = (double)out->s.stop - cfr_stop;
+ out->s.stop = cfr_stop;
+ pv->out_last_stop = out->s.stop;
+ for ( ; excess_dur >= pv->frame_rate; excess_dur -= pv->frame_rate )
{
- // we're doing CFR so we have to either trim some time from a
- // buffer that ends too far in the future or, if the buffer is
- // two or more frame times long, split it into multiple pieces,
- // each of which is a frame time long.
- double excess_dur = (double)out->s.stop - cfr_stop;
- out->s.stop = cfr_stop;
- pv->out_last_stop = out->s.stop;
- for ( ; excess_dur >= pv->frame_rate; excess_dur -= pv->frame_rate )
- {
- /* next frame too far ahead - dup current frame */
- hb_buffer_t *dup = hb_buffer_dup( out );
- dup->s.new_chap = 0;
- dup->s.start = cfr_stop;
- cfr_stop += pv->frame_rate;
- dup->s.stop = cfr_stop;
- pv->out_last_stop = dup->s.stop;
- out = insert_buffer_in_chain( out, dup );
- ++pv->dups;
- ++pv->count_frames;
- }
+ /* next frame too far ahead - dup current frame */
+ hb_buffer_t *dup = hb_buffer_dup( out );
+ dup->s.new_chap = 0;
+ dup->s.start = cfr_stop;
+ cfr_stop += pv->frame_rate;
+ dup->s.stop = cfr_stop;
+ pv->out_last_stop = dup->s.stop;
+ hb_buffer_list_append(list, dup);
+ ++pv->dups;
+ ++pv->count_frames;
}
}
}
@@ -386,17 +380,17 @@ static int hb_vfr_info( hb_filter_object_t * filter,
if ( pv->cfr == 0 )
{
/* Ensure we're using "Same as source" FPS */
- sprintf( info->human_readable_desc,
+ sprintf( info->human_readable_desc,
"frame rate: same as source (around %.3f fps)",
(float)pv->vrate.num / pv->vrate.den );
}
else if ( pv->cfr == 2 )
{
- // For PFR, we want the framerate based on the source's actual
- // framerate, unless it's higher than the specified peak framerate.
+ // For PFR, we want the framerate based on the source's actual
+ // framerate, unless it's higher than the specified peak framerate.
double source_fps = (double)pv->input_vrate.num / pv->input_vrate.den;
double peak_fps = (double)pv->vrate.num / pv->vrate.den;
- sprintf( info->human_readable_desc,
+ sprintf( info->human_readable_desc,
"frame rate: %.3f fps -> peak rate limited to %.3f fps",
source_fps , peak_fps );
}
@@ -405,7 +399,7 @@ static int hb_vfr_info( hb_filter_object_t * filter,
// Constant framerate. Signal the framerate we are using.
double source_fps = (double)pv->input_vrate.num / pv->input_vrate.den;
double constant_fps = (double)pv->vrate.num / pv->vrate.den;
- sprintf( info->human_readable_desc,
+ sprintf( info->human_readable_desc,
"frame rate: %.3f fps -> constant %.3f fps",
source_fps , constant_fps );
}
@@ -429,23 +423,23 @@ static void hb_vfr_close( hb_filter_object_t * filter )
if( pv->job )
{
hb_interjob_t * interjob = hb_interjob_get( pv->job->h );
-
- /* Preserve dropped frame count for more accurate
- * framerates in 2nd passes.
+
+ /* Preserve dropped frame count for more accurate
+ * framerates in 2nd passes.
*/
interjob->out_frame_count = pv->count_frames;
interjob->total_time = pv->out_last_stop;
}
- hb_log("render: lost time: %"PRId64" (%i frames)",
+ hb_log("render: lost time: %"PRId64" (%i frames)",
pv->total_lost_time, pv->dropped_frames);
- hb_log("render: gained time: %"PRId64" (%i frames) (%"PRId64" not accounted for)",
- pv->total_gained_time, pv->extended_frames,
+ hb_log("render: gained time: %"PRId64" (%i frames) (%"PRId64" not accounted for)",
+ pv->total_gained_time, pv->extended_frames,
pv->total_lost_time - pv->total_gained_time);
if (pv->dropped_frames)
{
- hb_log("render: average dropped frame duration: %"PRId64,
+ hb_log("render: average dropped frame duration: %"PRId64,
(pv->total_lost_time / pv->dropped_frames) );
}
@@ -464,26 +458,29 @@ static int hb_vfr_work( hb_filter_object_t * filter,
hb_buffer_t ** buf_out )
{
hb_filter_private_t * pv = filter->private_data;
- hb_buffer_t * in = *buf_in;
- hb_buffer_t * out = NULL;
+ hb_buffer_list_t list;
+ hb_buffer_t * in = *buf_in;
+ hb_buffer_t * out = NULL;
*buf_in = NULL;
*buf_out = NULL;
+ hb_buffer_list_clear(&list);
+
if (in->s.flags & HB_BUF_FLAG_EOF)
{
- hb_buffer_t *head = NULL, *tail = NULL, *next;
- int counter = 2;
+ hb_buffer_t * next;
+ int counter = 2;
/* If the input buffer is end of stream, send out an empty one
* to the next stage as well. To avoid losing the contents of
- * the delay queue connect the buffers in the delay queue in
+ * the delay queue connect the buffers in the delay queue in
* the correct order, and add the end of stream buffer to the
* end.
- */
- while( ( next = hb_fifo_get( pv->delay_queue ) ) != NULL )
+ */
+ while ((next = hb_fifo_get(pv->delay_queue)) != NULL)
{
-
+
/* We can't use the given time stamps. Previous frames
might already have been extended, throwing off the
raw values fed to render.c. Instead, their
@@ -492,34 +489,13 @@ static int hb_vfr_work( hb_filter_object_t * filter,
If it needed its duration extended to make up
lost time, it will have happened above. */
next->s.start = pv->last_start[counter];
- next->s.stop = pv->last_stop[counter--];
-
- adjust_frame_rate( pv, &next );
-
- if( next )
- {
- if( !head && !tail )
- {
- head = next;
- } else {
- tail->next = next;
- }
- // Move tail to the end of the list that
- // adjust_frame_rate could return
- while (next)
- {
- tail = next;
- next = next->next;
- }
- }
+ next->s.stop = pv->last_stop[counter--];
+
+ hb_buffer_list_append(&list, next);
+ adjust_frame_rate(pv, &list);
}
- if( tail )
- {
- tail->next = in;
- *buf_out = head;
- } else {
- *buf_out = in;
- }
+ hb_buffer_list_append(&list, in);
+ *buf_out = hb_buffer_list_clear(&list);
return HB_FILTER_DONE;
}
@@ -529,11 +505,11 @@ static int hb_vfr_work( hb_filter_object_t * filter,
{
/* We need to compensate for the time lost by dropping frame(s).
Spread its duration out in quarters, because usually dropped frames
- maintain a 1-out-of-5 pattern and this spreads it out amongst
+ maintain a 1-out-of-5 pattern and this spreads it out amongst
the remaining ones. Store these in the lost_time array, which
- has 4 slots in it. Because not every frame duration divides
- evenly by 4, and we can't lose the remainder, we have to go
- through an awkward process to preserve it in the 4th array index.
+ has 4 slots in it. Because not every frame duration divides
+ evenly by 4, and we can't lose the remainder, we have to go
+ through an awkward process to preserve it in the 4th array index.
*/
uint64_t temp_duration = in->s.start - pv->last_stop[0];
pv->lost_time[0] += (temp_duration / 4);
@@ -569,73 +545,73 @@ static int hb_vfr_work( hb_filter_object_t * filter,
hb_fifo_push( pv->delay_queue, in );
/*
- * Keep the last three frames in our queue, this ensures that we have
- * the last two always in there should we need to rewrite the
+ * Keep the last three frames in our queue, this ensures that we have
+ * the last two always in there should we need to rewrite the
* durations on them.
*/
- if( hb_fifo_size( pv->delay_queue ) >= 4 )
+ if (hb_fifo_size(pv->delay_queue) < 4)
{
- out = hb_fifo_get( pv->delay_queue );
+ *buf_out = NULL;
+ return HB_FILTER_OK;
}
- if( out )
+ out = hb_fifo_get(pv->delay_queue);
+ /* The current frame exists. That means it hasn't been dropped by a
+ * filter. We may edit its duration if needed.
+ */
+ if( pv->lost_time[3] > 0 )
{
- /* The current frame exists. That means it hasn't been dropped by a
- * filter. We may edit its duration if needed.
- */
- if( pv->lost_time[3] > 0 )
+ int time_shift = 0;
+
+ for( i = 3; i >= 0; i-- )
{
- int time_shift = 0;
-
- for( i = 3; i >= 0; i-- )
- {
- /*
- * A frame's been dropped earlier by VFR detelecine.
- * Gotta make up the lost time. This will also
- * slow down the video.
- * The dropped frame's has to be accounted for, so
- * divvy it up amongst the 4 frames left behind.
- * This is what the delay_queue is for;
- * telecined sequences start 2 frames before
- * the dropped frame, so to slow down the right
- * ones you need a 2 frame delay between
- * reading input and writing output.
- */
-
- /* We want to extend the outputted frame's duration by the value
- stored in the 4th slot of the lost_time array. Because we need
- to adjust all the values in the array so they're contiguous,
- extend the duration inside the array first, before applying
- it to the current frame buffer. */
- pv->last_start[i] += time_shift;
- pv->last_stop[i] += pv->lost_time[i] + time_shift;
-
- /* Log how much time has been added back in to the video. */
- pv->total_gained_time += pv->lost_time[i];
- time_shift += pv->lost_time[i];
-
- pv->lost_time[i] = 0;
-
- /* Log how many frames have had their durations extended. */
- pv->extended_frames++;
- }
+ /*
+ * A frame's been dropped earlier by VFR detelecine.
+ * Gotta make up the lost time. This will also
+ * slow down the video.
+ * The dropped frame's has to be accounted for, so
+ * divvy it up amongst the 4 frames left behind.
+ * This is what the delay_queue is for;
+ * telecined sequences start 2 frames before
+ * the dropped frame, so to slow down the right
+ * ones you need a 2 frame delay between
+ * reading input and writing output.
+ */
+
+ /* We want to extend the outputted frame's duration by the value
+ stored in the 4th slot of the lost_time array. Because we need
+ to adjust all the values in the array so they're contiguous,
+ extend the duration inside the array first, before applying
+ it to the current frame buffer. */
+ pv->last_start[i] += time_shift;
+ pv->last_stop[i] += pv->lost_time[i] + time_shift;
+
+ /* Log how much time has been added back in to the video. */
+ pv->total_gained_time += pv->lost_time[i];
+ time_shift += pv->lost_time[i];
+
+ pv->lost_time[i] = 0;
+
+ /* Log how many frames have had their durations extended. */
+ pv->extended_frames++;
}
-
- /* We can't use the given time stamps. Previous frames
- might already have been extended, throwing off the
- raw values fed to render.c. Instead, their
- stop and start times are stored in arrays.
- The 4th cached frame will be the to use.
- If it needed its duration extended to make up
- lost time, it will have happened above. */
- out->s.start = pv->last_start[3];
- out->s.stop = pv->last_stop[3];
-
- adjust_frame_rate( pv, &out );
}
- *buf_out = out;
+ /* We can't use the given time stamps. Previous frames
+ might already have been extended, throwing off the
+ raw values fed to render.c. Instead, their
+ stop and start times are stored in arrays.
+ The 4th cached frame will be the to use.
+ If it needed its duration extended to make up
+ lost time, it will have happened above. */
+ out->s.start = pv->last_start[3];
+ out->s.stop = pv->last_stop[3];
+
+ hb_buffer_list_append(&list, out);
+ adjust_frame_rate(pv, &list);
+
+ *buf_out = hb_buffer_list_clear(&list);
return HB_FILTER_OK;
}