X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;ds=sidebyside;f=libhb%2Fencavcodec.c;h=d102548b06b0ad664fe491143aad6744144c0d1a;hb=17860fcc4da9def330562abe8cc09a564d38387e;hp=dca246d2586fe39906b44938a93c755fc0abf13a;hpb=2707a4c05f84b3846e4e77ca4e9850cc61ffca10;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c index dca246d2..d102548b 100644 --- a/libhb/encavcodec.c +++ b/libhb/encavcodec.c @@ -6,7 +6,7 @@ #include "hb.h" -#include "ffmpeg/avcodec.h" +#include "libavcodec/avcodec.h" struct hb_work_private_s { @@ -32,6 +32,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) { AVCodec * codec; AVCodecContext * context; + int rate_num, rate_den; hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) ); w->private_data = pv; @@ -45,7 +46,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) "failed" ); } context = avcodec_alloc_context(); - if( job->vquality < 0.0 || job->vquality > 1.0 ) + if( job->vquality < 0.0 ) { /* Rate control */ context->bit_rate = 1000 * job->vbitrate; @@ -54,14 +55,55 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) else { /* Constant quantizer */ - context->qmin = 31 - job->vquality * 30; - context->qmax = context->qmin; + // These settings produce better image quality than + // what was previously used + context->flags |= CODEC_FLAG_QSCALE; + if (job->vquality < 1.0) + { + float vquality; + vquality = 31 - job->vquality * 31; + // A value of 0 has undefined behavior + // and ffmpeg qp has integral increments + if (vquality < 1.0) + vquality = 1.0; + context->global_quality = FF_QP2LAMBDA * vquality + 0.5; + } + else + { + context->global_quality = FF_QP2LAMBDA * job->vquality + 0.5; + } + context->mb_decision = 1; hb_log( "encavcodec: encoding at constant quantizer %d", - context->qmin ); + context->global_quality ); } context->width = job->width; context->height = job->height; - context->time_base = (AVRational) { job->vrate_base, job->vrate }; + rate_num = job->vrate_base; + rate_den = job->vrate; + if (rate_den == 27000000) + { + int ii; + for (ii = 0; ii < hb_video_rates_count; ii++) + { + if (abs(rate_num - hb_video_rates[ii].rate) < 10) + { + rate_num = hb_video_rates[ii].rate; + break; + } + } + } + hb_reduce(&rate_num, &rate_den, rate_num, rate_den); + if ((rate_num & ~0xFFFF) || (rate_den & ~0xFFFF)) + { + hb_log( "encavcodec: truncating framerate %d / %d", + rate_num, rate_den ); + } + while ((rate_num & ~0xFFFF) || (rate_den & ~0xFFFF)) + { + rate_num >>= 1; + rate_den >>= 1; + } + context->time_base = (AVRational) { rate_num, rate_den }; context->gop_size = 10 * job->vrate / job->vrate_base; context->pix_fmt = PIX_FMT_YUV420P; @@ -175,9 +217,11 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in, AVFrame * frame; hb_buffer_t * in = *buf_in, * buf; - if(!in->data) + if ( in->size <= 0 ) { - *buf_out = NULL; + /* EOF on input - send it downstream & say we're done */ + *buf_out = in; + *buf_in = NULL; return HB_WORK_DONE; } @@ -188,6 +232,9 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in, frame->linesize[0] = job->width; frame->linesize[1] = job->width / 2; frame->linesize[2] = job->width / 2; + // For constant quality, setting the quality in AVCodecContext + // doesn't do the trick. It must be set in the AVFrame. + frame->quality = pv->context->global_quality; /* Should be way too large */ buf = hb_buffer_init( 3 * job->width * job->height / 2 );