X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fdecmpeg2.c;h=83c36f6980e05dd80d5ff5a8e4ed661186dbd40e;hb=f9341345b37e0738a140423297c222a7e40eddab;hp=03f6656b6a138239dfdbf3f2676beb99f39ac7f0;hpb=a6ecdb87d945458af1f5bff7b4fb0557c411bd95;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/decmpeg2.c b/libhb/decmpeg2.c index 03f6656b..83c36f69 100644 --- a/libhb/decmpeg2.c +++ b/libhb/decmpeg2.c @@ -1,11 +1,11 @@ /* $Id: decmpeg2.c,v 1.12 2005/03/03 16:30:42 titer Exp $ This file is part of the HandBrake source code. - Homepage: . + Homepage: . It may be used under the terms of the GNU General Public License. */ #include "hb.h" - +#include "hbffmpeg.h" #include "mpeg2dec/mpeg2.h" /* Cadence tracking */ @@ -25,15 +25,13 @@ #define BTB_PROG 64 #define TB_PROG 128 #define TBT_PROG 256 -int cadence[12]; -int flag = 0; +static int cadence[12]; +static int flag = 0; /********************************************************************** * hb_libmpeg2_t - ********************************************************************** - * A convenient libmpeg wrapper, used both here and in scan.c *********************************************************************/ -struct hb_libmpeg2_s +typedef struct hb_libmpeg2_s { mpeg2dec_t * libmpeg2; const mpeg2_info_t * info; @@ -41,20 +39,20 @@ struct hb_libmpeg2_s int width; int height; int rate; - int aspect_ratio; + double aspect_ratio; int got_iframe; /* set when we get our first iframe */ int look_for_iframe; /* need an iframe to add chap break */ int look_for_break; /* need gop start to add chap break */ uint32_t nframes; /* number of frames we've decoded */ int64_t last_pts; -}; +} hb_libmpeg2_t; /********************************************************************** * hb_libmpeg2_init ********************************************************************** * *********************************************************************/ -hb_libmpeg2_t * hb_libmpeg2_init() +static hb_libmpeg2_t * hb_libmpeg2_init() { hb_libmpeg2_t * m = calloc( sizeof( hb_libmpeg2_t ), 1 ); @@ -65,17 +63,75 @@ hb_libmpeg2_t * hb_libmpeg2_init() return m; } +static hb_buffer_t *hb_copy_frame( hb_job_t *job, int width, int height, + uint8_t* y, uint8_t *u, uint8_t *v ) +{ + int dst_w = width, dst_h = height; + if ( job ) + { + dst_w = job->title->width; + dst_h = job->title->height; + } + int dst_wh = dst_w * dst_h; + hb_buffer_t *buf = hb_video_buffer_init( dst_w, dst_h ); + + if ( dst_w != width || dst_h != height ) + { + // we're encoding and the frame dimensions don't match the title dimensions - + // rescale & matte Y, U, V into our output buf. + AVPicture in, out; + avpicture_alloc(&in, PIX_FMT_YUV420P, width, height ); + avpicture_alloc(&out, PIX_FMT_YUV420P, dst_w, dst_h ); + + int src_wh = width * height; + memcpy( in.data[0], y, src_wh ); + memcpy( in.data[1], u, src_wh >> 2 ); + memcpy( in.data[2], v, src_wh >> 2 ); + struct SwsContext *context = sws_getContext( width, height, PIX_FMT_YUV420P, + dst_w, dst_h, PIX_FMT_YUV420P, + SWS_LANCZOS|SWS_ACCURATE_RND, + NULL, NULL, NULL ); + sws_scale( context, in.data, in.linesize, 0, height, out.data, out.linesize ); + sws_freeContext( context ); + + u_int8_t *data = buf->data; + memcpy( data, out.data[0], dst_wh ); + data += dst_wh; + // U & V planes are 1/4 the size of Y plane. + dst_wh >>= 2; + memcpy( data, out.data[1], dst_wh ); + data += dst_wh; + memcpy( data, out.data[2], dst_wh ); + + avpicture_free( &out ); + avpicture_free( &in ); + } + else + { + // we're scanning or the frame dimensions match the title's dimensions + // so we can do a straight copy. + u_int8_t *data = buf->data; + memcpy( data, y, dst_wh ); + data += dst_wh; + // U & V planes are 1/4 the size of Y plane. + dst_wh >>= 2; + memcpy( data, u, dst_wh ); + data += dst_wh; + memcpy( data, v, dst_wh ); + } + return buf; +} + /********************************************************************** * hb_libmpeg2_decode ********************************************************************** * *********************************************************************/ -int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es, +static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es, hb_list_t * list_raw ) { mpeg2_state_t state; hb_buffer_t * buf; - uint8_t * data; if ( buf_es->size ) { @@ -111,13 +167,10 @@ int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es, * it keeps the pixel width & height that would cause * the storage width & height to come out in the correct * aspect ratio. Convert these back to aspect ratio. - * We do the calc in floating point to get the rounding right. - * We round in the second decimal digit because we scale - * the (integer) aspect by 9 to preserve the 1st digit. */ double ar_numer = m->width * m->info->sequence->pixel_width; double ar_denom = m->height * m->info->sequence->pixel_height; - m->aspect_ratio = ( ar_numer / ar_denom + .05 ) * HB_ASPECT_BASE; + m->aspect_ratio = ar_numer / ar_denom; } } } @@ -140,29 +193,18 @@ int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es, if( m->got_iframe ) { - buf = hb_buffer_init( m->width * m->height * 3 / 2 ); - data = buf->data; - + buf = hb_copy_frame( m->job, m->info->sequence->width, + m->info->sequence->height, + m->info->display_fbuf->buf[0], + m->info->display_fbuf->buf[1], + m->info->display_fbuf->buf[2] ); buf->sequence = buf_es->sequence; - memcpy( data, m->info->display_fbuf->buf[0], - m->width * m->height ); - data += m->width * m->height; - memcpy( data, m->info->display_fbuf->buf[1], - m->width * m->height / 4 ); - data += m->width * m->height / 4; - memcpy( data, m->info->display_fbuf->buf[2], - m->width * m->height / 4 ); - if( m->info->display_picture->flags & PIC_FLAG_TAGS ) { buf->start = ( (uint64_t) m->info->display_picture->tag << 32 ) | ( (uint64_t) m->info->display_picture->tag2 ); - /* - * Add back in again to track PTS of MPEG2 frames - * hb_log("MPEG2: Normal buf->start = %lld", buf->start); - */ } else if( m->last_pts > -1 ) { @@ -196,6 +238,14 @@ int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es, } hb_log( "mpeg2: \"%s\" (%d) at frame %u time %lld", chap_name, buf->new_chap, m->nframes, buf->start ); + } else if ( m->nframes == 0 && m->job && + hb_list_item( m->job->title->list_chapter, + m->job->chapter_start - 1 ) ) + { + hb_chapter_t * c = hb_list_item( m->job->title->list_chapter, + m->job->chapter_start - 1 ); + hb_log( "mpeg2: \"%s\" (%d) at frame %u time %lld", c->title, + m->job->chapter_start, m->nframes, buf->start ); } ++m->nframes; @@ -300,45 +350,11 @@ int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es, } /********************************************************************** - * hb_libmpeg2_info - ********************************************************************** - * - *********************************************************************/ -void hb_libmpeg2_info( hb_libmpeg2_t * m, int * width, int * height, - int * rate, int *aspect_ratio ) -{ - *width = m->width; - *height = m->height; - if (m->info->display_fbuf) - { - if( (m->info->display_picture->flags & PROGRESSIVE) && (m->height == 480) ) - { - /* The frame is progressive and it's NTSC DVD height, so change its FPS to 23.976. - This might not be correct for the title. It's really just for scan.c's benefit. - Scan.c will reset the fps to 29.97, until a simple majority of the preview - frames report at 23.976. - */ - //hb_log("Detecting NTSC Progressive Frame"); - m->rate = 1126125; - } - } - *rate = m->rate; - *aspect_ratio = m->aspect_ratio; -} - -int hb_libmpeg2_clear_aspect_ratio( hb_libmpeg2_t * m ) -{ - int ar = m->aspect_ratio; - m->aspect_ratio = 0; - return ar; -} - -/********************************************************************** * hb_libmpeg2_close ********************************************************************** * *********************************************************************/ -void hb_libmpeg2_close( hb_libmpeg2_t ** _m ) +static void hb_libmpeg2_close( hb_libmpeg2_t ** _m ) { hb_libmpeg2_t * m = *_m; @@ -364,7 +380,7 @@ struct hb_work_private_s ********************************************************************** * *********************************************************************/ -int decmpeg2Init( hb_work_object_t * w, hb_job_t * job ) +static int decmpeg2Init( hb_work_object_t * w, hb_job_t * job ) { hb_work_private_t * pv; @@ -384,11 +400,12 @@ int decmpeg2Init( hb_work_object_t * w, hb_job_t * job ) ********************************************************************** * *********************************************************************/ -int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in, +static int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_buffer_t ** buf_out ) { hb_work_private_t * pv = w->private_data; hb_buffer_t * buf, * last = NULL; + int status = HB_WORK_OK; // The reader found a chapter break, consume it completely, and remove it from the // stream. We need to shift it. @@ -405,6 +422,7 @@ int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in, { hb_list_add( pv->list, *buf_in ); *buf_in = NULL; + status = HB_WORK_DONE; } *buf_out = NULL; @@ -423,7 +441,7 @@ int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in, } } - return HB_WORK_OK; + return status; } /********************************************************************** @@ -431,21 +449,59 @@ int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in, ********************************************************************** * *********************************************************************/ -void decmpeg2Close( hb_work_object_t * w ) +static void decmpeg2Close( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; - hb_log( "mpeg2 done: %d frames", pv->libmpeg2->nframes ); + + // don't log during scan + if ( pv->libmpeg2->job ) + { + hb_log( "mpeg2 done: %d frames", pv->libmpeg2->nframes ); + } hb_list_close( &pv->list ); hb_libmpeg2_close( &pv->libmpeg2 ); free( pv ); } +static int decmpeg2Info( hb_work_object_t *w, hb_work_info_t *info ) +{ + hb_work_private_t *pv = w->private_data; + + memset( info, 0, sizeof(*info) ); + + if ( pv && pv->libmpeg2 && pv->libmpeg2->info && pv->libmpeg2->info->sequence ) + { + hb_libmpeg2_t *m = pv->libmpeg2; + + info->width = m->width; + info->height = m->height; + info->pixel_aspect_width = m->info->sequence->pixel_width; + info->pixel_aspect_height = m->info->sequence->pixel_height; + info->aspect = m->aspect_ratio; + + // if the frame is progressive & NTSC DVD height report it as 23.976 FPS + // so that scan can autodetect NTSC film + info->rate = 27000000; + info->rate_base = ( m->info->display_fbuf && m->info->display_picture && + (m->info->display_picture->flags & PROGRESSIVE) && + (m->height == 480 ) ) ? 1126125 : m->rate; + + info->bitrate = m->info->sequence->byte_rate * 8; + info->profile = m->info->sequence->profile_level_id >> 4; + info->level = m->info->sequence->profile_level_id & 0xf; + info->name = "mpeg2"; + return 1; + } + return 0; +} + hb_work_object_t hb_decmpeg2 = { WORK_DECMPEG2, "MPEG-2 decoder (libmpeg2)", decmpeg2Init, decmpeg2Work, - decmpeg2Close + decmpeg2Close, + decmpeg2Info };