OSDN Git Service

Jamfile - Fixes tab instead of 4 spaces.
[handbrake-jp/handbrake-jp-git.git] / libhb / encavcodec.c
index 85aa608..d102548 100644 (file)
@@ -1,12 +1,12 @@
 /* $Id: encavcodec.c,v 1.23 2005/10/13 23:47:06 titer Exp $
 
    This file is part of the HandBrake source code.
-   Homepage: <http://handbrake.m0k.org/>.
+   Homepage: <http://handbrake.fr/>.
    It may be used under the terms of the GNU General Public License. */
 
 #include "hb.h"
 
-#include "ffmpeg/avcodec.h"
+#include "libavcodec/avcodec.h"
 
 struct hb_work_private_s
 {
@@ -20,19 +20,20 @@ int  encavcodecWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
 void encavcodecClose( hb_work_object_t * );
 
 hb_work_object_t hb_encavcodec =
-{   
+{
     WORK_ENCAVCODEC,
     "MPEG-4 encoder (libavcodec)",
     encavcodecInit,
     encavcodecWork,
     encavcodecClose
-}; 
+};
 
 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;
 
@@ -70,7 +112,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job )
         context->sample_aspect_ratio.num = job->pixel_aspect_width;
         context->sample_aspect_ratio.den = job->pixel_aspect_height;
 
-        hb_log( "encavcodec: encoding with stored aspect %d/%d", 
+        hb_log( "encavcodec: encoding with stored aspect %d/%d",
                 job->pixel_aspect_width, job->pixel_aspect_height );
     }
 
@@ -135,7 +177,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job )
                 context->extradata_size );
 #endif
     }
-    
+
     return 0;
 }
 
@@ -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 );