]> granicus.if.org Git - handbrake/commitdiff
First 5.1 support for MediaForkCLI. Uses a new command line option of "-6 --surround...
authormaurj <handbrake@maurj.com>
Mon, 12 Feb 2007 23:46:01 +0000 (23:46 +0000)
committermaurj <handbrake@maurj.com>
Mon, 12 Feb 2007 23:46:01 +0000 (23:46 +0000)
For now, this assumes that all selected audio tracks have the same audio format.  Since only one audio track works at present, this isn't a disaster.

git-svn-id: svn://svn.handbrake.fr/HandBrake/branches/0.8.0_beta2_5.1@309 b64f7644-9d1e-0410-96f1-a4d463321fa5

libmediafork/common.h
libmediafork/deca52.c
libmediafork/encfaac.c
libmediafork/scan.c
libmediafork/sync.c
libmediafork/work.c
test/test.c

index ed9d7c59ab0f8efa60ecff38857ec489f70464bd..20aab4def5256e9c5809fb6769c71feeb76c2089 100644 (file)
@@ -137,9 +137,19 @@ struct hb_job_s
        int                             crf;
        
     /* Audio tracks:
-         Indexes in hb_title_t's audios list, starting from 0.
-         -1 indicates the end of the list */
+         audios:         Indexes in hb_title_t's audios list, starting from 0.
+                         -1 indicates the end of the list
+                channels:       The # of normal channels in the last used audio
+                lfechannels:    The # of lfe channels in the last used audio
+                channelsused:   The # of channels we will actually use for this job -
+                                calculated based on surround, channels and lfechannels
+                                                in work.c
+            surround:       1 if 5.1 should be preserved for AAC, 0 otherwise */
     int             audios[8];
+    int             channels;
+    int             lfechannels;
+    int             channelsused;
+       int             surround;
 
     /* Audio settings:
          acodec:   output codec
@@ -208,7 +218,10 @@ struct hb_audio_s
     int  codec;
     int  rate;
     int  bitrate;
+       /* indicates the number of normal channels the source audio has */
     int  channels;
+       /* indicates the number of lfe channels the source audio has */
+       int  lfechannels;
 
 #ifdef __LIBMEDIAFORK__
     /* Internal data */
index 6d32c5c9be36ad38f003909943a6e595b7c23ce4..9e11ec5e60cda1925fd6c5086d0094006916cd89 100644 (file)
@@ -28,6 +28,9 @@ struct hb_work_private_s
     uint8_t       frame[3840];
 
     hb_list_t   * list;
+       
+       int           channelsused;
+       
 };
 
 int  deca52Init( hb_work_object_t *, hb_job_t * );
@@ -62,9 +65,25 @@ int deca52Init( hb_work_object_t * w, hb_job_t * job )
 
     pv->list      = hb_list_init();
     pv->state     = a52_init( 0 );
-       // we're either extracting 5.1 from AC3 for AAC,
-       // or mixing up/down to stereo otherwise
-    pv->flags_out = A52_STEREO;
+
+       if (job->channelsused == 6) {
+               /* we're going to be encoding to AAC,
+               and have turned on the "preserve 5.1" flag */
+               pv->flags_out = A52_3F2R | A52_LFE;
+       } else if (job->channelsused == 1) {
+               /* keep the mono-ness of the source audio */
+               pv->flags_out = A52_MONO;
+       } else if (job->channelsused == 2 && job->channels == 5 && job->lfechannels == 1) {
+               /* we are mixing a 5.1 source down to stereo, so use dolby surround */
+               pv->flags_out = A52_DOLBY;
+       } else {
+               /* mix everything else down to stereo */
+               pv->flags_out = A52_STEREO;
+       }
+
+       /* pass the number of channels used into the private work data */
+       pv->channelsused = job->channelsused;
+
     pv->level     = 32768.0;
 
     return 0;
@@ -116,7 +135,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
 {
     hb_work_private_t * pv = w->private_data;
     hb_buffer_t * buf;
-    int           i, j;
+    int           i, j, k;
     uint64_t      pts;
     int           pos;
 
@@ -177,8 +196,8 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
     /* Feed liba52 */
     a52_frame( pv->state, pv->frame, &pv->flags_out, &pv->level, 0 );
 
-    /* 6 blocks per frame, 256 samples per block, 2 channels */
-    buf        = hb_buffer_init( 3072 * sizeof( float ) );
+    /* 6 blocks per frame, 256 samples per block, channelsused channels */
+    buf        = hb_buffer_init( 6 * 256 * pv->channelsused * sizeof( float ) );
     buf->start = pts + ( pos / pv->size ) * 6 * 256 * 90000 / pv->rate;
     buf->stop  = buf->start + 6 * 256 * 90000 / pv->rate;
 
@@ -189,13 +208,15 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
 
         a52_block( pv->state );
         samples_in  = a52_samples( pv->state );
-        samples_out = ((float *) buf->data) + 512 * i;
+        samples_out = ((float *) buf->data) + 256 * pv->channelsused * i;
 
         /* Interleave */
         for( j = 0; j < 256; j++ )
         {
-            samples_out[2*j]   = samples_in[j];
-            samples_out[2*j+1] = samples_in[256+j];
+                       for ( k = 0; k < pv->channelsused; k++ )
+                       {
+                               samples_out[(pv->channelsused*j)+k]   = samples_in[(256*k)+j]; // DJA
+                       }
         }
     }
 
index 19787a56043a215b1d09f34e183eaf13bdcf2ab6..d60cac01549498ccb576abd389c749671bee624f 100644 (file)
@@ -19,6 +19,9 @@ struct hb_work_private_s
 
     hb_list_t     * list;
     int64_t         pts;
+       
+       int             channelsused;
+
 };
 
 int  encfaacInit( hb_work_object_t *, hb_job_t * );
@@ -50,7 +53,10 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job )
 
     pv->job   = job;
 
-    pv->faac = faacEncOpen( job->arate, 2, &pv->input_samples,
+       /* pass the number of channels used into the private work data */
+       pv->channelsused = job->channelsused;
+
+    pv->faac = faacEncOpen( job->arate, job->channelsused, &pv->input_samples,
                            &pv->output_bytes );
     pv->buf  = malloc( pv->input_samples * sizeof( float ) );
     
@@ -58,12 +64,33 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job )
     cfg->mpegVersion   = MPEG4;
     cfg->aacObjectType = LOW;
     cfg->allowMidside  = 1;
-    cfg->useLfe        = 0;
+       
+       if (job->channelsused == 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->bandWidth     = 0;
     cfg->outputFormat  = 0;
     cfg->inputFormat   =  FAAC_INPUT_FLOAT;
+       
+       if (job->channelsused == 6) {
+               /* we are preserving 5.1 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 */
+               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" );
@@ -118,8 +145,8 @@ static hb_buffer_t * Encode( hb_work_object_t * w )
                       &pts, &pos );
 
     buf        = hb_buffer_init( pv->output_bytes );
-    buf->start = pts + 90000 * pos / 2 / sizeof( float ) / pv->job->arate;
-    buf->stop  = buf->start + 90000 * pv->input_samples / pv->job->arate / 2;
+    buf->start = pts + 90000 * pos / pv->channelsused / sizeof( float ) / pv->job->arate;
+    buf->stop  = buf->start + 90000 * pv->input_samples / pv->job->arate / pv->channelsused;
     buf->size  = faacEncEncode( pv->faac, (int32_t *) pv->buf,
             pv->input_samples, buf->data, pv->output_bytes );
     buf->key   = 1;
index 1f74f629dcd4c5e0641fb0bb0f33365e35885d8c..a32ddf61d9f68325fb15fd05682995c4c75e459b 100644 (file)
@@ -484,9 +484,16 @@ static void LookForAC3( hb_title_t * title, hb_buffer_t * b )
                     audio->channels = 5;
                     break;
             }
+
+                       if (flags & A52_LFE) {
+                               audio->lfechannels = 1;
+                       } else {
+                               audio->lfechannels = 0;
+                       }
+
             /* XXX */
             sprintf( audio->lang + strlen( audio->lang ),
-                     " (%d ch)", audio->channels );
+                     " (%d.%d ch)", audio->channels, audio->lfechannels );
             break;
         }
     }
index 7053016e0dfcc9647d4ea7e2a6f2d86b38ff02a2..d9bcaf9319bb1dfbe7e03e4450ea5b86430b926c 100644 (file)
@@ -56,11 +56,11 @@ struct hb_work_private_s
 /***********************************************************************
  * Local prototypes
  **********************************************************************/
-static void InitAudio( hb_work_object_t * w, int i );
+static void InitAudio( hb_work_object_t * w, int i, int channelsused );
 static int  SyncVideo( hb_work_object_t * w );
-static void SyncAudio( hb_work_object_t * w, int i );
+static void SyncAudio( hb_work_object_t * w, int i, int channelsused );
 static int  NeedSilence( hb_work_object_t * w, hb_audio_t * );
-static void InsertSilence( hb_work_object_t * w, int i );
+static void InsertSilence( hb_work_object_t * w, int i, int channelsused );
 static void UpdateState( hb_work_object_t * w );
 
 /***********************************************************************
@@ -100,7 +100,9 @@ int syncInit( hb_work_object_t * w, hb_job_t * job )
     /* Initialize libsamplerate for every audio track we have */
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
-        InitAudio( w, i );
+               /* this should really pass in a channelsused value for this audio
+               but for now, it uses the global job value of channelsused */
+        InitAudio( w, i, job->channelsused );
     }
 
     /* Get subtitle info, if any */
@@ -153,7 +155,9 @@ int syncWork( hb_work_object_t * w, hb_buffer_t ** unused1,
     {
         for( i = 0; i < hb_list_count( pv->job->title->list_audio ); i++ )
         {
-            SyncAudio( w, i );
+                       /* this should really pass in a channelsused value for this audio
+                       but for now, it uses the global job value of channelsused */
+            SyncAudio( w, i, pv->job->channelsused );
         }
     }
 
@@ -170,7 +174,7 @@ hb_work_object_t hb_sync =
     syncClose
 };
 
-static void InitAudio( hb_work_object_t * w, int i )
+static void InitAudio( hb_work_object_t * w, int i, int channelsused )
 {
     hb_work_private_t * pv = w->private_data;
     hb_job_t        * job   = pv->job;
@@ -221,7 +225,7 @@ static void InitAudio( hb_work_object_t * w, int i )
     {
         /* Initialize libsamplerate */
         int error;
-        sync->state             = src_new( SRC_LINEAR, 2, &error );
+        sync->state             = src_new( SRC_LINEAR, channelsused, &error );
         sync->data.end_of_input = 0;
     }
 }
@@ -408,7 +412,7 @@ static int SyncVideo( hb_work_object_t * w )
  ***********************************************************************
  * 
  **********************************************************************/
-static void SyncAudio( hb_work_object_t * w, int i )
+static void SyncAudio( hb_work_object_t * w, int i, int channelsused )
 {
     hb_work_private_t * pv = w->private_data;
     hb_job_t        * job;
@@ -481,7 +485,7 @@ static void SyncAudio( hb_work_object_t * w, int i )
         else if( buf->start > pts_expected + 9000 )
         {
             /* Missing audio, send a frame of silence */
-            InsertSilence( w, i );
+            InsertSilence( w, i, channelsused );
             continue;
         }
 
@@ -499,7 +503,7 @@ static void SyncAudio( hb_work_object_t * w, int i )
 
             int count_in, count_out;
 
-            count_in  = buf_raw->size / 2 / sizeof( float );
+            count_in  = buf_raw->size / channelsused / sizeof( float );
             count_out = ( buf_raw->stop - buf_raw->start ) * job->arate / 90000;
             if( buf->start < pts_expected - 1500 )
                 count_out--;
@@ -513,7 +517,7 @@ static void SyncAudio( hb_work_object_t * w, int i )
             sync->data.src_ratio = (double) sync->data.output_frames /
                                    (double) sync->data.input_frames;
 
-            buf = hb_buffer_init( sync->data.output_frames * 2 *
+            buf = hb_buffer_init( sync->data.output_frames * channelsused *
                                   sizeof( float ) );
             sync->data.data_out = (float *) buf->data;
             if( src_process( sync->state, &sync->data ) )
@@ -523,7 +527,7 @@ static void SyncAudio( hb_work_object_t * w, int i )
             }
             hb_buffer_close( &buf_raw );
 
-            buf->size = sync->data.output_frames_gen * 2 * sizeof( float );
+            buf->size = sync->data.output_frames_gen * channelsused * sizeof( float );
 
             /* Set dates for resampled data */
             buf->start = start;
@@ -539,7 +543,7 @@ static void SyncAudio( hb_work_object_t * w, int i )
 
     if( NeedSilence( w, audio ) )
     {
-        InsertSilence( w, i );
+        InsertSilence( w, i, channelsused );
     }
 }
 
@@ -579,7 +583,7 @@ static int NeedSilence( hb_work_object_t * w, hb_audio_t * audio )
     return 0;
 }
 
-static void InsertSilence( hb_work_object_t * w, int i )
+static void InsertSilence( hb_work_object_t * w, int i, int channelsused )
 {
     hb_work_private_t * pv = w->private_data;
     hb_job_t        * job;
@@ -606,7 +610,7 @@ static void InsertSilence( hb_work_object_t * w, int i )
     }
     else
     {
-        buf        = hb_buffer_init( 2 * job->arate / 20 *
+        buf        = hb_buffer_init( channelsused * job->arate / 20 *
                                      sizeof( float ) );
         buf->start = sync->count_frames * 90000 / job->arate;
         buf->stop  = buf->start + 90000 / 20;
index b692754182c19c69ef3674fd1c258525c3139da1..9a19b643a5f3c3f5d42c70f75e84145e7e943e71 100644 (file)
@@ -242,6 +242,33 @@ static void do_job( hb_job_t * job, int cpu_count )
             w->config   = &audio->config;
             hb_list_add( job->list_work, w );
         }
+               
+               /* store this audio's channel counts with the job */
+               /* this should be an array -
+               we just use the last channel count for now */
+               if (audio->channels == 5 && audio->lfechannels == 1) {
+                       /* we have a 5.1 AC-3 source soundtrack */
+                       if (job->acodec == HB_ACODEC_FAAC && job->surround) {
+                               /* we're going to be encoding to AAC,
+                               and have turned on the "preserve 5.1" flag */
+                               job->channelsused = 6;
+                       } else {
+                               /* mix 5.1 down to Dolby Digital (2-channel) */
+                               job->channelsused = 2;
+                       }
+               } else if (audio->channels == 1 && audio->lfechannels == 0) {
+                       /* keep the mono-ness of the source audio */
+                       job->channelsused = 1;
+               } else {
+                       /* mix everything else down to stereo */
+                       job->channelsused = 2;
+               }
+               
+               /* remember the actual number of channels and lfe channels */
+               /* again, we are using the last channel's count for now */
+               job->channels = audio->channels;
+               job->lfechannels = audio->lfechannels;
+               
     }
 
     /* Init read & write threads */
index 1d9781c494737cc31986c2ecfc30016d48606329..57fd7598248c714184c241b9340597e911fe1805 100644 (file)
@@ -26,6 +26,7 @@ static int    vcodec      = HB_VCODEC_FFMPEG;
 static int    h264_13     = 0;
 static int    h264_30     = 0;
 static char * audios      = NULL;
+static int    surround    = 0;
 static int    sub         = 0;
 static int    width       = 0;
 static int    height      = 0;
@@ -351,9 +352,9 @@ static int HandleEvents( hb_handle_t * h )
             { 
                 job->h264_level = 13; 
             }
-           if( h264_30 )
-           {
-               job->h264_level = 30;
+               if( h264_30 )
+               {
+                   job->h264_level = 30;
             }
             if( vrate )
             {
@@ -389,6 +390,10 @@ static int HandleEvents( hb_handle_t * h )
                     job->audios[0] = -1;
                 }
             }
+                       if( surround )
+                       {
+                               job->surround = 1;
+                       }
             if( abitrate )
             {
                 job->abitrate = abitrate;
@@ -527,6 +532,7 @@ static void ShowHelp()
     "                            default: all chapters)\n"
     "    -a, --audio <string>    Select audio channel(s) (\"none\" for no \n"
     "                            audio, default: first one)\n"
+    "    -6, --surround          Export 5.1 surround as 6-channel AAC\n"
     "\n"
     "    -s, --subtitle <number> Select subtitle (default: none)\n"
     "    -e, --encoder <string>  Set video library encoder (ffmpeg,xvid,\n"
@@ -585,6 +591,7 @@ static int ParseOptions( int argc, char ** argv )
             { "title",       required_argument, NULL,    't' },
             { "chapters",    required_argument, NULL,    'c' },
             { "audio",       required_argument, NULL,    'a' },
+            { "surround",    no_argument,       NULL,    '6' },
             { "subtitle",    required_argument, NULL,    's' },
 
             { "encoder",     required_argument, NULL,    'e' },
@@ -612,7 +619,7 @@ static int ParseOptions( int argc, char ** argv )
         int c;
 
         c = getopt_long( argc, argv,
-                         "hvuC:f:i:o:t:c:a:s:e:E:2dgpw:l:n:b:q:S:B:r:R:Q",
+                         "hvuC:f:i:o:t:c:a:6s:e:E:2dgpw:l:n:b:q:S:B:r:R:Q",
                          long_options, &option_index );
         if( c < 0 )
         {
@@ -671,6 +678,9 @@ static int ParseOptions( int argc, char ** argv )
             case 'a':
                 audios = strdup( optarg );
                 break;
+            case '6':
+                surround = 1;
+                break;
             case 's':
                 sub = atoi( optarg );
                 break;
@@ -896,6 +906,13 @@ static int CheckOptions( int argc, char ** argv )
                 acodec = HB_ACODEC_VORBIS;
             }
         }
+               
+               if (acodec != HB_ACODEC_FAAC)
+               {
+                       /* only attempt 5.1 export if exporting to AAC */
+                       surround = 0;
+               }
+               
     }
 
     return 0;