It may be used under the terms of the GNU General Public License. */
#include "hb.h"
-
-#include "ffmpeg/avcodec.h"
+#include "hbffmpeg.h"
struct hb_work_private_s
{
{
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;
"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;
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;
- if( job->pixel_ratio )
+ if( job->anamorphic.mode )
{
- context->sample_aspect_ratio.num = job->pixel_aspect_width;
- context->sample_aspect_ratio.den = job->pixel_aspect_height;
+ context->sample_aspect_ratio.num = job->anamorphic.par_width;
+ context->sample_aspect_ratio.den = job->anamorphic.par_height;
hb_log( "encavcodec: encoding with stored aspect %d/%d",
- job->pixel_aspect_width, job->pixel_aspect_height );
+ job->anamorphic.par_width, job->anamorphic.par_height );
}
if( job->mux & ( HB_MUX_MP4 | HB_MUX_PSP ) )
}
}
- if( avcodec_open( context, codec ) )
+ if( hb_avcodec_open( context, codec ) )
{
hb_log( "hb_work_encavcodec_init: avcodec_open failed" );
}
if( pv->context )
{
- hb_log( "encavcodec: closing libavcodec" );
+ hb_deep_log( 2, "encavcodec: closing libavcodec" );
avcodec_flush_buffers( pv->context );
- avcodec_close( pv->context );
+ hb_avcodec_close( pv->context );
}
if( pv->file )
{
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;
}
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 );
+ 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;