]> granicus.if.org Git - handbrake/commitdiff
Correct chroma size for raw video frames - width & height need to be rounded up if...
authorvan <vanj.hb@gmail.com>
Sat, 8 Nov 2008 06:50:15 +0000 (06:50 +0000)
committervan <vanj.hb@gmail.com>
Sat, 8 Nov 2008 06:50:15 +0000 (06:50 +0000)
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1905 b64f7644-9d1e-0410-96f1-a4d463321fa5

13 files changed:
libhb/deblock.c
libhb/decavcodec.c
libhb/decmpeg2.c
libhb/decomb.c
libhb/deinterlace.c
libhb/denoise.c
libhb/detelecine.c
libhb/encavcodec.c
libhb/enctheora.c
libhb/encx264.c
libhb/encxvid.c
libhb/internal.h
libhb/render.c

index dbc669031937ccff4b85e193e194d98ff023c908..f549fbbb5485551070ebe5df1ed137d1511d2510 100644 (file)
@@ -405,8 +405,7 @@ hb_filter_private_t * hb_deblock_init( int pix_fmt,
 
     pv->pp7_src = (uint8_t*)malloc( pv->pp7_temp_stride*(h+8)*sizeof(uint8_t) );
 
-    int buf_size = 3 * width * height / 2;
-    pv->buf_out = hb_buffer_init( buf_size );
+    pv->buf_out = hb_video_buffer_init( width, height );
 
     return pv;
 }
index e215aef9fd715ce33251a0508edef4a2c2155e00..81ea4996b456b123d099a158347229c7bfdfaba8 100644 (file)
@@ -426,7 +426,7 @@ static hb_buffer_t *copy_frame( hb_work_private_t *pv, AVFrame *frame )
         w =  pv->job->title->width;
         h =  pv->job->title->height;
     }
-    hb_buffer_t *buf = hb_buffer_init( w * h * 3 / 2 );
+    hb_buffer_t *buf = hb_video_buffer_init( w, h );
     uint8_t *dst = buf->data;
 
     if ( context->pix_fmt != PIX_FMT_YUV420P || w != context->width ||
@@ -449,7 +449,7 @@ static hb_buffer_t *copy_frame( hb_work_private_t *pv, AVFrame *frame )
     else
     {
         dst = copy_plane( dst, frame->data[0], w, frame->linesize[0], h );
-        w >>= 1; h >>= 1;
+        w = (w + 1) >> 1; h = (h + 1) >> 1;
         dst = copy_plane( dst, frame->data[1], w, frame->linesize[1], h );
         dst = copy_plane( dst, frame->data[2], w, frame->linesize[2], h );
     }
index e0387dd64717e623c7103c7458e33d83edc25346..eae00919cfad0f113a50e309516642ce0a7104dc 100644 (file)
@@ -75,7 +75,7 @@ static hb_buffer_t *hb_copy_frame( hb_job_t *job, int width, int height,
         dst_h = job->title->height;
     }
     int dst_wh = dst_w * dst_h;
-    hb_buffer_t *buf  = hb_buffer_init( dst_wh + ( dst_wh >> 1 ) );
+    hb_buffer_t *buf  = hb_video_buffer_init( dst_w, dst_h );
 
     if ( dst_w != width || dst_h != height )
     {
index e83f0d5a6923c6b6b00b8eb1ad90004615e003d9..2194f56335ebcf0668d6834ce7a4bb1d267a76b0 100644 (file)
@@ -1113,9 +1113,8 @@ hb_filter_private_t * hb_decomb_init( int pix_fmt,
     pv->width[1]  = pv->width[2]  = width >> 1;
     pv->height[1] = pv->height[2] = height >> 1;
 
-    int buf_size = 3 * width * height / 2;
-    pv->buf_out[0] = hb_buffer_init( buf_size );
-    pv->buf_out[1] = hb_buffer_init( buf_size );
+    pv->buf_out[0] = hb_video_buffer_init( width, height );
+    pv->buf_out[1] = hb_video_buffer_init( width, height );
     pv->buf_settings = hb_buffer_init( 0 );
 
     pv->yadif_deinterlaced_frames = 0;
index 9e4c33eb4551531cc4448f60fdb1e02070ea43a5..b6b10fe43d279b09c44856f9219083d19e6ae928 100644 (file)
@@ -531,9 +531,8 @@ hb_filter_private_t * hb_deinterlace_init( int pix_fmt,
     pv->width[1]  = pv->width[2]  = width >> 1;
     pv->height[1] = pv->height[2] = height >> 1;
 
-    int buf_size = 3 * width * height / 2;
-    pv->buf_out[0] = hb_buffer_init( buf_size );
-    pv->buf_out[1] = hb_buffer_init( buf_size );
+    pv->buf_out[0] = hb_video_buffer_init( width, height );
+    pv->buf_out[1] = hb_video_buffer_init( width, height );
     pv->buf_settings = hb_buffer_init( 0 );
 
     pv->yadif_ready    = 0;
index 6d335fcdcf62951ee9f19a6168538f43e88b2f77..39139124e5f8ff74075958d41a6b292bfb059dd0 100644 (file)
@@ -368,8 +368,7 @@ hb_filter_private_t * hb_denoise_init( int pix_fmt,
     hqdn3d_precalc_coef( pv->hqdn3d_coef[2], spatial_chroma );
     hqdn3d_precalc_coef( pv->hqdn3d_coef[3], temporal_chroma );
 
-    int buf_size = 3 * width * height / 2;
-    pv->buf_out = hb_buffer_init( buf_size );
+    pv->buf_out = hb_video_buffer_init( width, height );
 
     return pv;
 }
index d3757cb69a97754b76dc1b1d2fcde54b28d2b2cb..92d279d6fb015141943cedbc19b5036685b94447 100644 (file)
@@ -829,8 +829,7 @@ hb_filter_private_t * hb_detelecine_init( int pix_fmt,
     pv->width[1]  = pv->width[2] = width >> 1;
     pv->height[1] = pv->height[2] = height >> 1;
 
-    int buf_size = 3 * width * height / 2;
-    pv->buf_out = hb_buffer_init( buf_size );
+    pv->buf_out = hb_video_buffer_init( width, height );
 
     struct pullup_context * ctx;
     pv->pullup_ctx = ctx = pullup_alloc_context();
index d3decd7d1e89beaf6f9d1fce196a1ada753373f4..d22d30d3de02cabca76e2d2aecdf47e35515c575 100644 (file)
@@ -237,7 +237,7 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
     frame->quality = pv->context->global_quality;
 
     /* Should be way too large */
-    buf = hb_buffer_init( 3 * job->width * job->height / 2 );
+    buf = hb_video_buffer_init( job->width, job->height );
     buf->size = avcodec_encode_video( pv->context, buf->data, buf->alloc,
                                       frame );
     buf->start = in->start;
index 274887f9ffe22796663119aba4999e52cbc91856..c2df9d9a677766db97dd4026b0e86fa65f95acd2 100644 (file)
@@ -142,13 +142,13 @@ int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
     yuv.y_height = job->height;
     yuv.y_stride = job->width;
 
-    yuv.uv_width = job->width / 2;
-    yuv.uv_height = job->height / 2;
-    yuv.uv_stride = job->width / 2;
+    yuv.uv_width = (job->width + 1) / 2;
+    yuv.uv_height = (job->height + 1) / 2;
+    yuv.uv_stride = yuv.uv_width;
 
     yuv.y = in->data;
     yuv.u = in->data + job->width * job->height;
-    yuv.v = in->data + job->width * job->height * 5/4;
+    yuv.v = in->data + yuv.uv_width * yuv.uv_height;
 
     theora_encode_YUVin(&pv->theora, &yuv);
 
index e2d90cd313730d5b8dbf4f4d237195de6e769641..97de03e8ed3889b6411b1fe98822a3ac26412200 100644 (file)
@@ -312,6 +312,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job )
     x264_picture_alloc( &pv->pic_in, X264_CSP_I420,
                         job->width, job->height );
 
+    pv->pic_in.img.i_stride[2] = pv->pic_in.img.i_stride[1] = ( ( job->width + 1 ) >> 1 );
     pv->x264_allocated_pic = pv->pic_in.img.plane[0];
 
     if (job->areBframes)
@@ -391,7 +392,7 @@ static hb_buffer_t *nal_encode( hb_work_object_t *w, x264_picture_t *pic_out,
     hb_job_t *job = pv->job;
 
     /* Should be way too large */
-    buf = hb_buffer_init( 3 * job->width * job->height / 2 );
+    buf = hb_video_buffer_init( job->width, job->height );
     buf->size = 0;
     buf->frametype = 0;
 
@@ -505,17 +506,18 @@ static hb_buffer_t *x264_encode( hb_work_object_t *w, hb_buffer_t *in )
     /* Point x264 at our current buffers Y(UV) data.  */
     pv->pic_in.img.plane[0] = in->data;
 
+    int uvsize = ( (job->width + 1) >> 1 ) * ( (job->height + 1) >> 1 );
     if( job->grayscale )
     {
         /* XXX x264 has currently no option for grayscale encoding */
-        memset( pv->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );
-        memset( pv->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );
+        memset( pv->pic_in.img.plane[1], 0x80, uvsize );
+        memset( pv->pic_in.img.plane[2], 0x80, uvsize );
     }
     else
     {
         /* Point x264 at our buffers (Y)UV data */
         pv->pic_in.img.plane[1] = in->data + job->width * job->height;
-        pv->pic_in.img.plane[2] = in->data + 5 * job->width * job->height / 4;
+        pv->pic_in.img.plane[2] = pv->pic_in.img.plane[1] + uvsize;
     }
     if( in->new_chap && job->chapter_markers )
     {
index 18961dc28eed3f28a13f2934d6674bb36e85c570..cb4ca01fee97ce2e233109244923fe197c349ea2 100644 (file)
@@ -158,7 +158,7 @@ int encxvidWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
     }
 
     /* Should be way too large */
-    buf = hb_buffer_init( 3 * job->width * job->height / 2 );
+    buf = hb_video_buffer_init( job->width, job->height );
     buf->start = in->start;
     buf->stop  = in->stop;
 
index a8f5edfd9e581b94d8bac39245b7e26e232fd4c7..3ae1dad79bb24d85b6e15b8f181172339fdd6a0d 100644 (file)
@@ -96,6 +96,21 @@ void          hb_fifo_push( hb_fifo_t *, hb_buffer_t * );
 void          hb_fifo_push_head( hb_fifo_t *, hb_buffer_t * );
 void          hb_fifo_close( hb_fifo_t ** );
 
+// 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 )
+{
+    // Y requires w x h bytes. U & V each require (w+1)/2 x
+    // (h+1)/2 bytes (the "+1" is to round up). We shift rather
+    // than divide by 2 since the compiler can't know these ints
+    // are positive so it generates very expensive integer divides
+    // if we do "/2". The code here matches the calculation for
+    // PIX_FMT_YUV420P in ffmpeg's avpicture_fill() which is required
+    // for most of HB's filters to work right.
+    return hb_buffer_init( width * height + ( ( width+1 ) >> 1 ) *
+                           ( ( height+1 ) >> 1 ) * 2 );
+}
+
 /***********************************************************************
  * Threads: update.c, scan.c, work.c, reader.c, muxcommon.c
  **********************************************************************/
index 7900ba2ae26984dfeb88704ecf6941e5a2ec5eda..5ca6a4c8de480ffd3d1d9e254d1808c6e524f1d1 100644 (file)
@@ -55,13 +55,13 @@ hb_work_object_t hb_render =
  */
 static uint8_t *getU(uint8_t *data, int width, int height, int x, int y)
 {
-    return(&data[(((y/2) * (width/2)) + (x/2)) + (width*height)]);
+    return(&data[(y>>1) * ((width+1)>>1) + (x>>1) + width*height]);
 }
 
 static uint8_t *getV(uint8_t *data, int width, int height, int x, int y)
 {
-    return(&data[(((y/2) * (width/2)) + (x/2)) + (width*height) +
-                 (width*height)/4]);
+    int w2 = (width+1) >> 1, h2 = (height+1) >> 1;
+    return(&data[(y>>1) * w2 + (x>>1) + width*height + w2*h2]);
 }
 
 static void ApplySub( hb_job_t * job, hb_buffer_t * buf,
@@ -248,7 +248,7 @@ int renderWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
     }
 
     /* Setup render buffer */
-    hb_buffer_t * buf_render = hb_buffer_init( 3 * job->width * job->height / 2 );
+    hb_buffer_t * buf_render = hb_video_buffer_init( job->width, job->height );
 
     /* Apply filters */
     if( job->filters )