OSDN Git Service

Remove the transformation matrix, and use the width field of the tkhd atom to do...
[handbrake-jp/handbrake-jp-git.git] / libhb / encfaac.c
index a5b704f..2ba9ad4 100644 (file)
@@ -8,12 +8,9 @@
 
 #include "faac.h"
 
-struct hb_work_object_s
+struct hb_work_private_s
 {
-    HB_WORK_COMMON;
-
     hb_job_t   * job;
-    hb_audio_t * audio;
 
     faacEncHandle * faac;
     unsigned long   input_samples;
@@ -22,59 +19,102 @@ struct hb_work_object_s
 
     hb_list_t     * list;
     int64_t         pts;
+       
+       int             out_discrete_channels;
+
 };
 
-/***********************************************************************
- * Local prototypes
- **********************************************************************/
-static void Close( hb_work_object_t ** _w );
-static int  Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
-                  hb_buffer_t ** buf_out );
+int  encfaacInit( hb_work_object_t *, hb_job_t * );
+int  encfaacWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
+void encfaacClose( hb_work_object_t * );
+
+hb_work_object_t hb_encfaac =
+{
+    WORK_ENCFAAC,
+    "AAC encoder (libfaac)",
+    encfaacInit,
+    encfaacWork,
+    encfaacClose
+};
 
 /***********************************************************************
  * hb_work_encfaac_init
  ***********************************************************************
  *
  **********************************************************************/
-hb_work_object_t * hb_work_encfaac_init( hb_job_t * job, hb_audio_t * audio )
+int encfaacInit( hb_work_object_t * w, hb_job_t * job )
 {
-    hb_work_object_t * w = calloc( sizeof( hb_work_object_t ), 1 );
+    hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
     faacEncConfigurationPtr cfg;
-    w->name  = strdup( "AAC encoder (libfaac)" );
-    w->work  = Work;
-    w->close = Close;
+    uint8_t * bytes;
+    unsigned long length;
 
-    w->job   = job;
-    w->audio = audio;
+    w->private_data = pv;
 
-    w->faac = faacEncOpen( job->arate, 2, &w->input_samples,
-                           &w->output_bytes );
-    w->buf  = malloc( w->input_samples * sizeof( float ) );
+    pv->job   = job;
+
+       /* pass the number of channels used into the private work data */
+       pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown);
+
+    pv->faac = faacEncOpen( job->arate, pv->out_discrete_channels, &pv->input_samples,
+                           &pv->output_bytes );
+    pv->buf  = malloc( pv->input_samples * sizeof( float ) );
     
-    cfg                = faacEncGetCurrentConfiguration( w->faac );
+    cfg                = faacEncGetCurrentConfiguration( pv->faac );
     cfg->mpegVersion   = MPEG4;
     cfg->aacObjectType = LOW;
     cfg->allowMidside  = 1;
-    cfg->useLfe        = 0;
+       
+       if (pv->out_discrete_channels == 6) {
+               /* we are preserving 5.1 audio into 6-channel AAC,
+               so indicate that we have an lfe channel */
+               cfg->useLfe    = 1;
+       } else {
+               cfg->useLfe    = 0;
+       }
+
     cfg->useTns        = 0;
-    cfg->bitRate       = job->abitrate * 500; /* Per channel */
+    cfg->bitRate       = job->abitrate * 1000 / pv->out_discrete_channels; /* Per channel */
     cfg->bandWidth     = 0;
     cfg->outputFormat  = 0;
     cfg->inputFormat   =  FAAC_INPUT_FLOAT;
-    if( !faacEncSetConfiguration( w->faac, cfg ) )
+       
+       if (w->amixdown == HB_AMIXDOWN_6CH && w->source_acodec == HB_ACODEC_AC3)
+    {
+        /* we are preserving 5.1 AC-3 audio into 6-channel AAC, and need to
+        re-map the output of deca52 into our own mapping - the mapping
+        below is the default mapping expected by QuickTime */
+        /* DTS output from libdca is already in the right mapping for QuickTime */
+        /* This doesn't seem to be correct for VLC on Linux */
+        cfg->channel_map[0] = 2;
+        cfg->channel_map[1] = 1;
+        cfg->channel_map[2] = 3;
+        cfg->channel_map[3] = 4;
+        cfg->channel_map[4] = 5;
+        cfg->channel_map[5] = 0;
+       }
+       
+    if( !faacEncSetConfiguration( pv->faac, cfg ) )
     {
         hb_log( "faacEncSetConfiguration failed" );
+        *job->die = 1;
+        return 0;
     }
-    if( faacEncGetDecoderSpecificInfo( w->faac, &audio->config.faac.decinfo,
-                                       &audio->config.faac.size ) < 0 )
+
+    if( faacEncGetDecoderSpecificInfo( pv->faac, &bytes, &length ) < 0 )
     {
         hb_log( "faacEncGetDecoderSpecificInfo failed" );
+        *job->die = 1;
+        return 0;
     }
+    memcpy( w->config->aac.bytes, bytes, length );
+    w->config->aac.length = length;
+    free( bytes );
 
-    w->list = hb_list_init();
-    w->pts  = -1;
+    pv->list = hb_list_init();
+    pv->pts  = -1;
 
-    return w;
+    return 0;
 }
 
 /***********************************************************************
@@ -82,18 +122,14 @@ hb_work_object_t * hb_work_encfaac_init( hb_job_t * job, hb_audio_t * audio )
  ***********************************************************************
  *
  **********************************************************************/
-static void Close( hb_work_object_t ** _w )
+void encfaacClose( hb_work_object_t * w )
 {
-    hb_work_object_t * w = *_w;
-
-    faacEncClose( w->faac );
-    free( w->buf );
-    hb_list_empty( &w->list );
-    free( w->audio->config.faac.decinfo );
-
-    free( w->name );
-    free( w );
-    *_w = NULL;
+    hb_work_private_t * pv = w->private_data;
+    faacEncClose( pv->faac );
+    free( pv->buf );
+    hb_list_empty( &pv->list );
+    free( pv );
+    w->private_data = NULL;
 }
 
 /***********************************************************************
@@ -103,25 +139,25 @@ static void Close( hb_work_object_t ** _w )
  **********************************************************************/
 static hb_buffer_t * Encode( hb_work_object_t * w )
 {
+    hb_work_private_t * pv = w->private_data;
     hb_buffer_t * buf;
-    uint64_t      pts;
-    int           pos;
+    uint64_t      pts, pos;
 
-    if( hb_list_bytes( w->list ) < w->input_samples * sizeof( float ) )
+    if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
     {
         /* Need more data */
         return NULL;
     }
 
-    hb_list_getbytes( w->list, w->buf, w->input_samples * sizeof( float ),
+    hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
                       &pts, &pos );
 
-    buf        = hb_buffer_init( w->output_bytes );
-    buf->start = pts + 90000 * pos / 2 / sizeof( float ) / w->job->arate;
-    buf->stop  = buf->start + 90000 * w->input_samples / w->job->arate / 2;
-    buf->size  = faacEncEncode( w->faac, (int32_t *) w->buf,
-            w->input_samples, buf->data, w->output_bytes );
-    buf->key   = 1;
+    buf        = hb_buffer_init( pv->output_bytes );
+    buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / pv->job->arate;
+    buf->stop  = buf->start + 90000 * pv->input_samples / pv->job->arate / pv->out_discrete_channels;
+    buf->size  = faacEncEncode( pv->faac, (int32_t *) pv->buf,
+            pv->input_samples, buf->data, pv->output_bytes );
+    buf->frametype   = HB_FRAME_AUDIO;
 
     if( !buf->size )
     {
@@ -145,12 +181,13 @@ static hb_buffer_t * Encode( hb_work_object_t * w )
  ***********************************************************************
  *
  **********************************************************************/
-static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
+int encfaacWork( 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;
 
-    hb_list_add( w->list, *buf_in );
+    hb_list_add( pv->list, *buf_in );
     *buf_in = NULL;
 
     *buf_out = buf = Encode( w );