diff options
author | jstebbins <[email protected]> | 2012-03-31 15:03:16 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2012-03-31 15:03:16 +0000 |
commit | 57e4d1bcc1a8040562b2d248742ff74b34ca846a (patch) | |
tree | b24bf501c52a127e61bffc77c1246d0055ea0aee /libhb | |
parent | f8f1631a89c587600d6bfd82a01583afdde9f744 (diff) |
libhb: fix cfr encoding
when frames are duplicated, the frame was not copied properly and resulted
in divide by 0 later when the frame is processed.
This fix is a bit larger than the minimum size necessary to fix the problem.
I took the oportunity to clean up some buffer initialization and copy
operations.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4563 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/decvobsub.c | 2 | ||||
-rw-r--r-- | libhb/fifo.c | 138 | ||||
-rw-r--r-- | libhb/internal.h | 123 | ||||
-rw-r--r-- | libhb/rendersub.c | 2 | ||||
-rw-r--r-- | libhb/vfr.c | 4 |
5 files changed, 148 insertions, 121 deletions
diff --git a/libhb/decvobsub.c b/libhb/decvobsub.c index 2160d59e2..b633e7804 100644 --- a/libhb/decvobsub.c +++ b/libhb/decvobsub.c @@ -543,7 +543,7 @@ static hb_buffer_t * CropSubtitle( hb_work_object_t * w, uint8_t * raw ) realwidth = crop[3] - crop[2] + 1; realheight = crop[1] - crop[0] + 1; - buf = hb_pic_buffer_init( PIX_FMT_YUVA420P, realwidth, realheight ); + buf = hb_frame_buffer_init( PIX_FMT_YUVA420P, realwidth, realheight ); buf->s.start = pv->pts_start; buf->s.stop = pv->pts_stop; buf->s.type = SUBTITLE_BUF; diff --git a/libhb/fifo.c b/libhb/fifo.c index 391fc39c6..1a89d6a1d 100644 --- a/libhb/fifo.c +++ b/libhb/fifo.c @@ -363,6 +363,144 @@ void hb_buffer_reduce( hb_buffer_t * b, int size ) } } +hb_buffer_t * hb_buffer_copy( const hb_buffer_t * src ) +{ + hb_buffer_t * buf; + + if ( src == NULL ) + return NULL; + + buf = hb_buffer_init( src->size ); + if ( buf ) + { + memcpy( buf->data, src->data, src->size ); + buf->s = src->s; + buf->f = src->f; + if ( buf->s.type == FRAME_BUF ) + hb_buffer_init_planes( buf ); + } + + return buf; +} + +static void hb_buffer_init_planes_internal( hb_buffer_t * b, uint8_t * has_plane ) +{ + uint8_t * plane = b->data; + int p; + + for( p = 0; p < 4; p++ ) + { + if ( has_plane[p] ) + { + b->plane[p].data = plane; + b->plane[p].stride = hb_image_stride( b->f.fmt, b->f.width, p ); + b->plane[p].height = hb_image_height( b->f.fmt, b->f.height, p ); + b->plane[p].width = hb_image_width( b->f.fmt, b->f.width, p ); + b->plane[p].size = hb_image_stride( b->f.fmt, b->f.width, p ) * + hb_image_height( b->f.fmt, b->f.height, p ); + plane += b->plane[p].size; + } + } +} + +void hb_buffer_init_planes( hb_buffer_t * b ) +{ + const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[b->f.fmt]; + int p; + + uint8_t has_plane[4] = {0,}; + + for( p = 0; p < 4; p++ ) + { + has_plane[desc->comp[p].plane] = 1; + } + hb_buffer_init_planes_internal( b, has_plane ); +} + +// this routine gets a buffer for an uncompressed picture +// with pixel format pix_fmt and dimensions width x height. +hb_buffer_t * hb_frame_buffer_init( int pix_fmt, int width, int height ) +{ + const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; + hb_buffer_t * buf; + int p; + uint8_t has_plane[4] = {0,}; + + for( p = 0; p < 4; p++ ) + { + has_plane[desc->comp[p].plane] = 1; + } + + int size = 0; + for( p = 0; p < 4; p++ ) + { + if ( has_plane[p] ) + { + size += hb_image_stride( pix_fmt, width, p ) * + hb_image_height( pix_fmt, height, p ); + } + } + + buf = hb_buffer_init( size ); + if( buf == NULL ) + return NULL; + + buf->s.type = FRAME_BUF; + buf->f.width = width; + buf->f.height = height; + buf->f.fmt = pix_fmt; + + hb_buffer_init_planes_internal( buf, has_plane ); + return buf; +} + +// this routine reallocs a buffer for an uncompressed YUV420 video frame +// with dimensions width x height. +void hb_video_buffer_realloc( hb_buffer_t * buf, int width, int height ) +{ + const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[buf->f.fmt]; + int p; + uint8_t has_plane[4] = {0,}; + + for( p = 0; p < 4; p++ ) + { + has_plane[desc->comp[p].plane] = 1; + } + + int size = 0; + for( p = 0; p < 4; p++ ) + { + if ( has_plane[p] ) + { + size += hb_image_stride( buf->f.fmt, width, p ) * + hb_image_height( buf->f.fmt, height, p ); + } + } + + hb_buffer_realloc(buf, size ); + + buf->f.width = width; + buf->f.height = height; + + hb_buffer_init_planes_internal( buf, has_plane ); +} + +// this routine 'moves' data from src to dst by interchanging 'data', +// 'size' & 'alloc' between them and copying the rest of the fields +// from src to dst. +void hb_buffer_swap_copy( hb_buffer_t *src, hb_buffer_t *dst ) +{ + uint8_t *data = dst->data; + int size = dst->size; + int alloc = dst->alloc; + + *dst = *src; + + src->data = data; + src->size = size; + src->alloc = alloc; +} + // Frees the specified buffer list. void hb_buffer_close( hb_buffer_t ** _b ) { diff --git a/libhb/internal.h b/libhb/internal.h index fa391bc6d..0ae63924a 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -69,7 +69,7 @@ struct hb_buffer_s struct settings { - enum { AUDIO_BUF, VIDEO_BUF, SUBTITLE_BUF, OTHER_BUF } type; + enum { AUDIO_BUF, VIDEO_BUF, SUBTITLE_BUF, FRAME_BUF, OTHER_BUF } type; int id; // ID of the track that the packet comes from int64_t start; // start time of frame @@ -128,11 +128,14 @@ void hb_buffer_pool_init( void ); void hb_buffer_pool_free( void ); hb_buffer_t * hb_buffer_init( int size ); +hb_buffer_t * hb_frame_buffer_init( int pix_fmt, int w, int h); +void hb_buffer_init_planes( hb_buffer_t * b ); void hb_buffer_realloc( hb_buffer_t *, int size ); +void hb_video_buffer_realloc( hb_buffer_t * b, int w, int h ); void hb_buffer_reduce( hb_buffer_t * b, int size ); void hb_buffer_close( hb_buffer_t ** ); -void hb_buffer_copy_settings( hb_buffer_t * dst, - const hb_buffer_t * src ); +hb_buffer_t * hb_buffer_copy( const hb_buffer_t * src ); +void hb_buffer_swap_copy( hb_buffer_t *src, hb_buffer_t *dst ); void hb_buffer_move_subs( hb_buffer_t * dst, hb_buffer_t * src ); hb_fifo_t * hb_fifo_init( int capacity, int thresh ); @@ -189,123 +192,11 @@ static inline int hb_image_height( int pix_fmt, int height, int plane ) return height; } -// this routine gets a buffer for an uncompressed picture -// with pixel format pix_fmt and dimensions width x height. -static inline hb_buffer_t * hb_pic_buffer_init( int pix_fmt, int width, int height ) -{ - const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; - - hb_buffer_t * buf; - int p; - uint8_t has_plane[4] = {0,}; - - for( p = 0; p < 4; p++ ) - { - has_plane[desc->comp[p].plane] = 1; - } - - int size = 0; - for( p = 0; p < 4; p++ ) - { - if( has_plane[p] ) - { - size += hb_image_stride( pix_fmt, width, p ) * - hb_image_height( pix_fmt, height, p ); - } - } - - buf = hb_buffer_init( size ); - if( buf == NULL ) - return NULL; - - buf->s.type = VIDEO_BUF; - buf->f.width = width; - buf->f.height = height; - buf->f.fmt = pix_fmt; - - uint8_t * plane = buf->data; - for( p = 0; p < 4; p++ ) - { - if ( has_plane[p] ) - { - buf->plane[p].data = plane; - buf->plane[p].stride = hb_image_stride( pix_fmt, width, p ); - buf->plane[p].height = hb_image_height( pix_fmt, height, p ); - buf->plane[p].width = hb_image_width( pix_fmt, width, p ); - buf->plane[p].size = hb_image_stride( pix_fmt, width, p ) * - hb_image_height( pix_fmt, height, p ); - plane += buf->plane[p].size; - } - } - return buf; -} - // this routine gets a buffer for an uncompressed YUV420 video frame // with dimensions width x height. static inline hb_buffer_t * hb_video_buffer_init( int width, int height ) { - return hb_pic_buffer_init( PIX_FMT_YUV420P, width, height ); -} - -// this routine reallocs a buffer for an uncompressed YUV420 video frame -// with dimensions width x height. -static inline void hb_video_buffer_realloc( hb_buffer_t * buf, int width, int height ) -{ - const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[buf->f.fmt]; - int p; - - uint8_t has_plane[4] = {0,}; - - for( p = 0; p < 4; p++ ) - { - has_plane[desc->comp[p].plane] = 1; - } - - int size = 0; - for( p = 0; p < 4; p++ ) - { - if( has_plane[p] ) - { - size += hb_image_stride( buf->f.fmt, width, p ) * - hb_image_height( buf->f.fmt, height, p ); - } - } - - hb_buffer_realloc(buf, size ); - - buf->f.width = width; - buf->f.height = height; - - uint8_t * plane = buf->data; - for( p = 0; p < 4; p++ ) - { - if( has_plane[p] ) - { - buf->plane[p].data = plane; - buf->plane[p].stride = hb_image_stride( buf->f.fmt, width, p ); - buf->plane[p].height = hb_image_height( buf->f.fmt, height, p ); - buf->plane[p].width = hb_image_width( buf->f.fmt, width, p ); - buf->plane[p].size = hb_image_stride( buf->f.fmt, width, p ) * - hb_image_height( buf->f.fmt, height, p ); - plane += buf->plane[p].size; - } - } -} - -// this routine 'moves' data from src to dst by interchanging 'data', -// 'size' & 'alloc' between them and copying the rest of the fields -// from src to dst. -static inline void hb_buffer_swap_copy( hb_buffer_t *src, hb_buffer_t *dst ) -{ - uint8_t *data = dst->data; - int size = dst->size; - int alloc = dst->alloc; - - *dst = *src; - - src->data = data; - src->size = size; - src->alloc = alloc; + return hb_frame_buffer_init( PIX_FMT_YUV420P, width, height ); } /*********************************************************************** diff --git a/libhb/rendersub.c b/libhb/rendersub.c index 26a3ec06d..e10177fc9 100644 --- a/libhb/rendersub.c +++ b/libhb/rendersub.c @@ -358,7 +358,7 @@ static hb_buffer_t * RenderSSAFrame( ASS_Image * frame ) unsigned frameV = (yuv >> 8 ) & 0xff; unsigned frameU = (yuv >> 0 ) & 0xff; - sub = hb_pic_buffer_init( PIX_FMT_YUVA420P, frame->w, frame->h ); + sub = hb_frame_buffer_init( PIX_FMT_YUVA420P, frame->w, frame->h ); if( sub == NULL ) return NULL; diff --git a/libhb/vfr.c b/libhb/vfr.c index fb12393b9..7ea308124 100644 --- a/libhb/vfr.c +++ b/libhb/vfr.c @@ -277,9 +277,7 @@ static void adjust_frame_rate( hb_filter_private_t *pv, hb_buffer_t **buf_out ) 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_init( out->size ); - memcpy( dup->data, out->data, out->size ); - dup->s = out->s; + hb_buffer_t *dup = hb_buffer_copy( out ); dup->s.new_chap = 0; dup->s.start = cfr_stop; cfr_stop += pv->frame_rate; |