diff options
author | jstebbins <[email protected]> | 2012-06-25 07:56:49 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2012-06-25 07:56:49 +0000 |
commit | efbf9c29a90a8590080c98a53a67cb5e98cddb02 (patch) | |
tree | 2e2e1748ea3ce9ad24fe7ba8413b43ada2ec764b | |
parent | 7e1d3dc3448805803138cb4fe4ad1e1c8d6f1c85 (diff) |
libhb: fix deinterlace fast problem with sources that have <mod8 alignment
avpicture_deinterlace requires that both width and height of the input
be 8 pixel aligned. Video buffers already have padding to align horizontally
to 16 pixels, but they were not padded vertically. This adds vertical
padding.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4776 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r-- | libhb/decavcodec.c | 9 | ||||
-rw-r--r-- | libhb/decomb.c | 45 | ||||
-rw-r--r-- | libhb/deinterlace.c | 6 | ||||
-rw-r--r-- | libhb/detelecine.c | 19 | ||||
-rw-r--r-- | libhb/fifo.c | 13 | ||||
-rw-r--r-- | libhb/hb.c | 128 | ||||
-rw-r--r-- | libhb/hb.h | 1 | ||||
-rw-r--r-- | libhb/internal.h | 20 |
8 files changed, 155 insertions, 86 deletions
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index 8a236ca4a..875a94c67 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -578,13 +578,16 @@ static hb_buffer_t *copy_frame( hb_work_private_t *pv, AVFrame *frame ) { w = buf->plane[0].stride; h = buf->plane[0].height; - dst = copy_plane( dst, frame->data[0], w, frame->linesize[0], h ); + dst = buf->plane[0].data; + copy_plane( dst, frame->data[0], w, frame->linesize[0], h ); w = buf->plane[1].stride; h = buf->plane[1].height; - dst = copy_plane( dst, frame->data[1], w, frame->linesize[1], h ); + dst = buf->plane[1].data; + copy_plane( dst, frame->data[1], w, frame->linesize[1], h ); w = buf->plane[2].stride; h = buf->plane[2].height; - dst = copy_plane( dst, frame->data[2], w, frame->linesize[2], h ); + dst = buf->plane[2].data; + copy_plane( dst, frame->data[2], w, frame->linesize[2], h ); } return buf; } diff --git a/libhb/decomb.c b/libhb/decomb.c index 3ce36d23e..40bcb2a6c 100644 --- a/libhb/decomb.c +++ b/libhb/decomb.c @@ -133,6 +133,7 @@ typedef struct yadif_thread_arg_s { struct hb_filter_private_s { int width[3]; + int stride[3]; int height[3]; // Decomb parameters @@ -370,7 +371,7 @@ void apply_mask( hb_filter_private_t * pv ) apply_mask_line( srcp, mskp, pv->width[plane] ); } - srcp += pv->pic_out.linesize[plane]; + srcp += pv->stride[plane]; mskp += pv->ref_stride[plane]; } } @@ -394,6 +395,7 @@ static void store_ref( const uint8_t ** pic, uint8_t * ref = pv->ref[2][i]; int w = pv->width[i]; + int s = pv->stride[i]; int h = pv->height[i]; int ref_stride = pv->ref_stride[i]; @@ -401,7 +403,7 @@ static void store_ref( const uint8_t ** pic, for( y = 0; y < h; y++ ) { memcpy(ref, src, w); - src = (uint8_t*)src + w; + src = (uint8_t*)src + s; ref = (uint8_t*)ref + ref_stride; } } @@ -1618,7 +1620,7 @@ void yadif_decomb_filter_thread( void *thread_args_v ) int segment, segment_start, segment_stop; yadif_thread_arg_t *thread_args = thread_args_v; uint8_t **dst; - int parity, tff, y, w, h, penultimate, ultimate, ref_stride, is_combed; + int parity, tff, y, w, s, h, penultimate, ultimate, ref_stride, is_combed; pv = thread_args->pv; segment = thread_args->segment; @@ -1662,6 +1664,7 @@ void yadif_decomb_filter_thread( void *thread_args_v ) parity = yadif_work->parity; tff = yadif_work->tff; w = pv->width[plane]; + s = pv->stride[plane]; h = pv->height[plane]; penultimate = h - 2; ultimate = h - 1; @@ -1683,7 +1686,7 @@ void yadif_decomb_filter_thread( void *thread_args_v ) { /* This line gets blend filtered, not yadif filtered. */ uint8_t *cur = &pv->ref[1][plane][y*ref_stride]; - uint8_t *dst2 = &dst[plane][y*w]; + uint8_t *dst2 = &dst[plane][y*s]; /* These will be useful if we ever do temporal blending. */ // uint8_t *prev = &pv->ref[0][plane][y*ref_stride]; // uint8_t *next = &pv->ref[2][plane][y*ref_stride]; @@ -1694,7 +1697,7 @@ void yadif_decomb_filter_thread( void *thread_args_v ) { /* Just apply vertical cubic interpolation */ uint8_t *cur = &pv->ref[1][plane][y*ref_stride]; - uint8_t *dst2 = &dst[plane][y*w]; + uint8_t *dst2 = &dst[plane][y*s]; cubic_interpolate_line( dst2, cur, plane, y, pv ); } @@ -1712,7 +1715,7 @@ void yadif_decomb_filter_thread( void *thread_args_v ) uint8_t *prev = &pv->ref[0][plane][y*ref_stride]; uint8_t *cur = &pv->ref[1][plane][y*ref_stride]; uint8_t *next = &pv->ref[2][plane][y*ref_stride]; - uint8_t *dst2 = &dst[plane][y*w]; + uint8_t *dst2 = &dst[plane][y*s]; yadif_filter_line( dst2, prev, @@ -1726,35 +1729,35 @@ void yadif_decomb_filter_thread( void *thread_args_v ) else if( y == 0 ) { /* BFF, so y0 = y1 */ - memcpy( &dst[plane][y*w], + memcpy( &dst[plane][y*s], &pv->ref[1][plane][1*ref_stride], w * sizeof(uint8_t) ); } else if( y == 1 ) { /* TFF, so y1 = y0 */ - memcpy( &dst[plane][y*w], + memcpy( &dst[plane][y*s], &pv->ref[1][plane][0], w * sizeof(uint8_t) ); } else if( y == penultimate ) { /* BFF, so penultimate y = ultimate y */ - memcpy( &dst[plane][y*w], + memcpy( &dst[plane][y*s], &pv->ref[1][plane][ultimate*ref_stride], w * sizeof(uint8_t) ); } else if( y == ultimate ) { /* TFF, so ultimate y = penultimate y */ - memcpy( &dst[plane][y*w], + memcpy( &dst[plane][y*s], &pv->ref[1][plane][penultimate*ref_stride], w * sizeof(uint8_t) ); } } else { - memcpy( &dst[plane][y*w], + memcpy( &dst[plane][y*s], &pv->ref[1][plane][y*ref_stride], w * sizeof(uint8_t) ); } @@ -1838,13 +1841,14 @@ static void yadif_filter( uint8_t ** dst, uint8_t * dest = dst[i]; int w = pv->width[i]; + int s = pv->stride[i]; int ref_stride = pv->ref_stride[i]; int y; for( y = 0; y < pv->height[i]; y++ ) { memcpy(dest, ref, w); - dest += w; + dest += s; ref += ref_stride; } } @@ -1888,13 +1892,14 @@ static void yadif_filter( uint8_t ** dst, uint8_t * dest = dst[i]; int w = pv->width[i]; + int s = pv->stride[i]; int ref_stride = pv->ref_stride[i]; int y; for( y = 0; y < pv->height[i]; y++ ) { memcpy(dest, ref, w); - dest += w; + dest += s; ref += ref_stride; } } @@ -1913,9 +1918,11 @@ static int hb_decomb_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->width[0] = hb_image_stride( init->pix_fmt, init->width, 0 ); + pv->width[0] = hb_image_width( init->pix_fmt, init->width, 0 ); + pv->stride[0] = hb_image_stride( init->pix_fmt, init->width, 0 ); pv->height[0] = hb_image_height( init->pix_fmt, init->height, 0 ); - pv->width[1] = pv->width[2] = hb_image_stride( init->pix_fmt, init->width, 1 ); + pv->width[1] = pv->width[2] = hb_image_width( init->pix_fmt, init->width, 1 ); + pv->stride[1] = pv->stride[2] = hb_image_stride( init->pix_fmt, init->width, 1 ); pv->height[1] = pv->height[2] = hb_image_height( init->pix_fmt, init->height, 1 ); build_gamma_lut( pv ); @@ -2005,8 +2012,8 @@ static int hb_decomb_init( hb_filter_object_t * filter, for( i = 0; i < 3; i++ ) { int is_chroma = !!i; - int w = ((pv->width[0] + 31) & (~31))>>is_chroma; - int h = ((pv->height[0]+6+ 31) & (~31))>>is_chroma; + int w = ((init->width + 31) & (~31))>>is_chroma; + int h = ((init->height+6+ 31) & (~31))>>is_chroma; pv->mask[i] = calloc( 1, w*h*sizeof(uint8_t) ) + 3*w; pv->mask_filtered[i] = calloc( 1, w*h*sizeof(uint8_t) ) + 3*w; @@ -2016,7 +2023,7 @@ static int hb_decomb_init( hb_filter_object_t * filter, if( pv->mode & MODE_EEDI2 ) { /* Allocate half-height eedi2 buffers */ - int height = pv->height[0] / 2; + int height = init->height / 2; for( i = 0; i < 3; i++ ) { int is_chroma = !!i; @@ -2030,7 +2037,7 @@ static int hb_decomb_init( hb_filter_object_t * filter, } /* Allocate full-height eedi2 buffers */ - height = pv->height[0]; + height = init->height; for( i = 0; i < 3; i++ ) { int is_chroma = !!i; diff --git a/libhb/deinterlace.c b/libhb/deinterlace.c index e654817c3..ee410a1cf 100644 --- a/libhb/deinterlace.c +++ b/libhb/deinterlace.c @@ -536,8 +536,12 @@ static int hb_deinterlace_work( hb_filter_object_t * filter, { hb_avpicture_fill( &pic_out, pv->buf_out[0] ); + // avpicture_deinterlace requires 8 byte aligned width and height + // we have aligned all buffers to 16 byte width and height strides + // so use the image stride when deinterlacing avpicture_deinterlace( &pic_out, &pic_in, pv->buf_out[0]->f.fmt, - pv->buf_out[0]->f.width, pv->buf_out[0]->f.height ); + pv->buf_out[0]->plane[0].stride, + pv->buf_out[0]->plane[0].height_stride ); pv->buf_out[0]->s = in->s; hb_buffer_move_subs( pv->buf_out[0], in ); diff --git a/libhb/detelecine.c b/libhb/detelecine.c index 41b9838f0..96596487c 100644 --- a/libhb/detelecine.c +++ b/libhb/detelecine.c @@ -33,6 +33,7 @@ struct pullup_buffer { int lock[2]; unsigned char **planes; + int *size; }; struct pullup_field @@ -593,11 +594,13 @@ static void pullup_alloc_buffer( struct pullup_context * c, int i; if( b->planes ) return; b->planes = calloc( c->nplanes, sizeof(unsigned char *) ); + b->size = calloc( c->nplanes, sizeof(int) ); for ( i = 0; i < c->nplanes; i++ ) { - b->planes[i] = malloc(c->h[i]*c->stride[i]); + b->size[i] = c->h[i] * c->stride[i]; + b->planes[i] = malloc(b->size[i]); /* Deal with idiotic 128=0 for chroma: */ - memset( b->planes[i], c->background[i], c->h[i]*c->stride[i] ); + memset( b->planes[i], c->background[i], b->size[i] ); } } @@ -919,9 +922,9 @@ static int hb_detelecine_work( hb_filter_object_t * filter, } /* Copy input buffer into pullup buffer */ - memcpy( buf->planes[0], in->plane[0].data, in->plane[0].size ); - memcpy( buf->planes[1], in->plane[1].data, in->plane[1].size ); - memcpy( buf->planes[2], in->plane[2].data, in->plane[2].size ); + memcpy( buf->planes[0], in->plane[0].data, buf->size[0] ); + memcpy( buf->planes[1], in->plane[1].data, buf->size[1] ); + memcpy( buf->planes[2], in->plane[2].data, buf->size[2] ); /* Submit buffer fields based on buffer flags. Detelecine assumes BFF when the TFF flag isn't present. */ @@ -1011,9 +1014,9 @@ static int hb_detelecine_work( hb_filter_object_t * filter, out = hb_video_buffer_init( in->f.width, in->f.height ); /* Copy pullup frame buffer into output buffer */ - memcpy( out->plane[0].data, frame->buffer->planes[0], in->plane[0].size ); - memcpy( out->plane[1].data, frame->buffer->planes[1], in->plane[1].size ); - memcpy( out->plane[2].data, frame->buffer->planes[2], in->plane[2].size ); + memcpy( out->plane[0].data, frame->buffer->planes[0], frame->buffer->size[0] ); + memcpy( out->plane[1].data, frame->buffer->planes[1], frame->buffer->size[1] ); + memcpy( out->plane[2].data, frame->buffer->planes[2], frame->buffer->size[2] ); pullup_release_frame( frame ); diff --git a/libhb/fifo.c b/libhb/fifo.c index 4859c990a..13f361260 100644 --- a/libhb/fifo.c +++ b/libhb/fifo.c @@ -389,7 +389,7 @@ hb_buffer_t * hb_buffer_copy( const hb_buffer_t * src ) static void hb_buffer_init_planes_internal( hb_buffer_t * b, uint8_t * has_plane ) { uint8_t * plane = b->data; - int p; + int p, tot = 0; for( p = 0; p < 4; p++ ) { @@ -397,11 +397,12 @@ static void hb_buffer_init_planes_internal( hb_buffer_t * b, uint8_t * has_plane { 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].height_stride = hb_image_height_stride( 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 ); + b->plane[p].height = hb_image_height( b->f.fmt, b->f.height, p ); + b->plane[p].size = b->plane[p].stride * b->plane[p].height_stride; plane += b->plane[p].size; + tot += b->plane[p].size; } } } @@ -440,7 +441,7 @@ hb_buffer_t * hb_frame_buffer_init( int pix_fmt, int width, int height ) if ( has_plane[p] ) { size += hb_image_stride( pix_fmt, width, p ) * - hb_image_height( pix_fmt, height, p ); + hb_image_height_stride( pix_fmt, height, p ); } } @@ -476,7 +477,7 @@ void hb_video_buffer_realloc( hb_buffer_t * buf, int width, int height ) if ( has_plane[p] ) { size += hb_image_stride( buf->f.fmt, width, p ) * - hb_image_height( buf->f.fmt, height, p ); + hb_image_height_stride( buf->f.fmt, height, p ); } } diff --git a/libhb/hb.c b/libhb/hb.c index 32c07aa0b..0ad101aaf 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -141,8 +141,14 @@ int hb_avpicture_fill( AVPicture *pic, hb_buffer_t *buf ) for( ii = 0; ii < 4; ii++ ) pic->linesize[ii] = buf->plane[ii].stride; - ret = av_image_fill_pointers( pic->data, buf->f.fmt, buf->f.height, + ret = av_image_fill_pointers( pic->data, buf->f.fmt, + buf->plane[0].height_stride, buf->data, pic->linesize ); + if (ret != buf->size) + { + hb_error("Internal error hb_avpicture_fill expected %d, got %d", + buf->size, ret); + } return ret; } @@ -705,6 +711,50 @@ int hb_save_preview( hb_handle_t * h, int title, int preview, hb_buffer_t *buf ) return 0; } +hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, int preview ) +{ + FILE * file; + char filename[1024]; + + hb_title_t * title = hb_list_item( h->list_title, title_idx - 1); + if ( title == NULL ) + { + hb_error( "hb_read_preview: invalid title (%d)", title_idx ); + return NULL; + } + + hb_get_tempory_filename( h, filename, "%d_%d_%d", + hb_get_instance_id(h), title_idx, preview ); + + file = fopen( filename, "rb" ); + if( !file ) + { + hb_error( "hb_read_preview: fopen failed (%s)", filename ); + return NULL; + } + + hb_buffer_t * buf; + buf = hb_frame_buffer_init( PIX_FMT_YUV420P, title->width, title->height ); + + int pp, hh; + for( pp = 0; pp < 3; pp++ ) + { + uint8_t *data = buf->plane[pp].data; + int stride = buf->plane[pp].stride; + int w = buf->plane[pp].width; + int h = buf->plane[pp].height; + + for( hh = 0; hh < h; hh++ ) + { + fread( data, w, 1, file ); + data += stride; + } + } + fclose( file ); + + return buf; +} + /** * Create preview image of desired title a index of picture. * @param h Handle to hb_handle_t. @@ -717,53 +767,50 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, { hb_job_t * job = title->job; char filename[1024]; - FILE * file; - uint8_t * buf1, * buf2, * buf3, * buf4, * pen; + hb_buffer_t * in_buf, * deint_buf = NULL, * preview_buf; + uint8_t * pen; uint32_t swsflags; - AVPicture pic_in, pic_preview, pic_deint, pic_crop, pic_scale; + AVPicture pic_in, pic_preview, pic_deint, pic_crop; struct SwsContext * context; int i; - int deint_width = ((title->width + 7) >> 3) << 3; - int rgb_width = ((job->width + 7) >> 3) << 3; int preview_size; swsflags = SWS_LANCZOS | SWS_ACCURATE_RND; - buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) ); - buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, deint_width, title->height ) ); - buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, rgb_width, job->height ) ); - buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGB32, rgb_width, job->height ) ); - avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P, - title->width, title->height ); - avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P, - deint_width, title->height ); - avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P, - rgb_width, job->height ); - avpicture_fill( &pic_preview, buf4, PIX_FMT_RGB32, - rgb_width, job->height ); + preview_buf = hb_frame_buffer_init( PIX_FMT_RGB32, + job->width, job->height ); + hb_avpicture_fill( &pic_preview, preview_buf ); // Allocate the AVPicture frames and fill in memset( filename, 0, 1024 ); - hb_get_tempory_filename( h, filename, "%d_%d_%d", - h->id, title->index, picture ); - - file = fopen( filename, "rb" ); - if( !file ) + in_buf = hb_read_preview( h, title->index, picture ); + if ( in_buf == NULL ) { - hb_log( "hb_get_preview: fopen failed" ); return; } - fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file ); - fclose( file ); + hb_avpicture_fill( &pic_in, in_buf ); if( job->deinterlace ) { // Deinterlace and crop - avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height ); - av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] ); + // avpicture_deinterlace requires width & height that are 8 byte + // alligned. This means the left and bottom edges of the preview + // will not get deinterlaced or transfered into the output buffer + // by avpicture_deinterlace. So copy the original frame into + // the deinterlace buffer so we don't see uninitialized data in + // the resulting image. + deint_buf = hb_frame_buffer_init( PIX_FMT_YUV420P, + title->width, title->height ); + hb_avpicture_fill( &pic_deint, deint_buf ); + + avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, + in_buf->plane[0].stride, in_buf->plane[0].height_stride ); + + av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, + job->crop[0], job->crop[2] ); } else { @@ -775,27 +822,13 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, context = hb_sws_get_context(title->width - (job->crop[2] + job->crop[3]), title->height - (job->crop[0] + job->crop[1]), PIX_FMT_YUV420P, - job->width, job->height, PIX_FMT_YUV420P, + job->width, job->height, PIX_FMT_RGB32, swsflags); // Scale sws_scale(context, (const uint8_t* const *)pic_crop.data, pic_crop.linesize, 0, title->height - (job->crop[0] + job->crop[1]), - pic_scale.data, pic_scale.linesize); - - // Free context - sws_freeContext( context ); - - // Get preview context - context = hb_sws_get_context(rgb_width, job->height, PIX_FMT_YUV420P, - rgb_width, job->height, PIX_FMT_RGB32, - swsflags); - - // Create preview - sws_scale(context, - (const uint8_t* const *)pic_scale.data, pic_scale.linesize, - 0, job->height, pic_preview.data, pic_preview.linesize); // Free context @@ -805,15 +838,14 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, pen = buffer; for( i = 0; i < job->height; i++ ) { - memcpy( pen, buf4 + preview_size * i, 4 * job->width ); + memcpy( pen, pic_preview.data[0] + preview_size * i, 4 * job->width ); pen += 4 * job->width; } // Clean up - avpicture_free( &pic_preview ); - avpicture_free( &pic_scale ); - avpicture_free( &pic_deint ); - avpicture_free( &pic_in ); + hb_buffer_close( &in_buf ); + hb_buffer_close( &deint_buf ); + hb_buffer_close( &preview_buf ); } /** diff --git a/libhb/hb.h b/libhb/hb.h index 9f65dca93..a594d93fc 100644 --- a/libhb/hb.h +++ b/libhb/hb.h @@ -61,6 +61,7 @@ int hb_detect_comb( hb_buffer_t * buf, int width, int height, int color_equal, i int hb_save_preview( hb_handle_t * h, int title, int preview, hb_buffer_t *buf ); +hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, int preview ); void hb_get_preview_by_index( hb_handle_t *, int, int, uint8_t * ); void hb_get_preview( hb_handle_t *, hb_title_t *, int, uint8_t * ); diff --git a/libhb/internal.h b/libhb/internal.h index 36d8de4ef..577f6671e 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -110,6 +110,7 @@ struct hb_buffer_s int stride; int width; int height; + int height_stride; int size; } plane[4]; // 3 Color components + alpha @@ -166,7 +167,9 @@ static inline int hb_image_stride( int pix_fmt, int width, int plane ) int linesize = av_image_get_linesize( pix_fmt, width, plane ); // Make buffer SIMD friendly. - linesize = MULTIPLE_MOD_UP( linesize, 16 ); + // Decomb requires stride aligned to 32 bytes + // TODO: eliminate extra buffer copies in decomb + linesize = MULTIPLE_MOD_UP( linesize, 32 ); return linesize; } @@ -183,6 +186,21 @@ static inline int hb_image_width( int pix_fmt, int width, int plane ) return width; } +static inline int hb_image_height_stride( int pix_fmt, int height, int plane ) +{ + const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; + + // Decomb requires 6 extra lines and stride aligned to 32 bytes + // TODO: eliminate extra buffer copies in decomb + height = MULTIPLE_MOD_UP( height + 6, 32 ); + if ( plane == 1 || plane == 2 ) + { + height = height >> desc->log2_chroma_h; + } + + return height; +} + static inline int hb_image_height( int pix_fmt, int height, int plane ) { const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; |