summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2012-03-31 15:03:16 +0000
committerjstebbins <[email protected]>2012-03-31 15:03:16 +0000
commit57e4d1bcc1a8040562b2d248742ff74b34ca846a (patch)
treeb24bf501c52a127e61bffc77c1246d0055ea0aee /libhb
parentf8f1631a89c587600d6bfd82a01583afdde9f744 (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.c2
-rw-r--r--libhb/fifo.c138
-rw-r--r--libhb/internal.h123
-rw-r--r--libhb/rendersub.c2
-rw-r--r--libhb/vfr.c4
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;