All pastes #965034 Raw Edit

hb_config_per_audio.9.1 All

public diff v1 · immutable
#965034 ·published 2008-03-31 18:57 UTC
rendered paste body
Index: test/test.c===================================================================--- test/test.c	(revision 1364)+++ test/test.c	(working copy)@@ -37,22 +37,27 @@ static int    vcodec      = HB_VCODEC_FFMPEG; static int    h264_13     = 0; static int    h264_30     = 0;-static char * audios      = NULL;-static int    audio_mixdown = HB_AMIXDOWN_DOLBYPLII;-static float  dynamic_range_compression = 0;+static hb_list_t * audios = NULL;+static hb_audio_config_t * audio = NULL;+static int    num_audio_tracks = 0;+static char * mixdowns    = NULL;+static char * dynamic_range_compression = NULL;+static char * arates      = NULL;+static char * abitrates   = NULL;+static char * acodecs     = NULL;+static int    default_acodec = HB_ACODEC_FAAC;+static int    default_arate = 44100;+static int    default_abitrate = 128; static int    sub         = 0; static int    width       = 0; static int    height      = 0; static int    crop[4]     = { -1,-1,-1,-1 }; static int    cpu         = 0; static int    vrate       = 0;-static int    arate       = 0; static float  vquality    = -1.0; static int    vbitrate    = 0; static int    size        = 0;-static int    abitrate    = 0; static int    mux         = 0;-static int    acodec      = 0; static int    pixelratio  = 0; static int    loosePixelratio = 0; static int    modulus       = 0;@@ -87,6 +92,9 @@ static int  CheckOptions( int argc, char ** argv ); static int  HandleEvents( hb_handle_t * h ); +static int get_acodec_for_string( char *codec );+static int is_sample_rate_valid(int rate);+ /* Only print the "Muxing..." message once */ static int show_mux_warning = 1; @@ -107,6 +115,8 @@     int           build;     char        * version; +    audios = hb_list_init();+     /* Parse command line */     if( ParseOptions( argc, argv ) ||         CheckOptions( argc, argv ) )@@ -230,7 +240,20 @@     if( input )  free( input );     if( output ) free( output );     if( format ) free( format );-    if( audios ) free( audios );+    if( audios )+    {+        while( ( audio = hb_list_item( audios, 0 ) ) )+        {+            hb_list_rem( audios, audio );+            free( audio );+        }+        hb_list_close( &audios );+    }+    if( mixdowns ) free( mixdowns );+    if( dynamic_range_compression ) free( dynamic_range_compression );+    if( arates ) free( arates );+    if( abitrates ) free( abitrates );+    if( acodecs ) free( acodecs );     if (native_language ) free (native_language ); 	if( x264opts ) free (x264opts ); 	if( x264opts2 ) free (x264opts2 );@@ -253,7 +276,7 @@ static void PrintTitleInfo( hb_title_t * title ) {     hb_chapter_t  * chapter;-    hb_audio_t    * audio;+    hb_audio_config_t    * audio;     hb_subtitle_t * subtitle;     int i; @@ -282,15 +305,15 @@     fprintf( stderr, "  + audio tracks:\n" );     for( i = 0; i < hb_list_count( title->list_audio ); i++ )     {-        audio = hb_list_item( title->list_audio, i );-        if( ( audio->codec & HB_ACODEC_AC3 ) || ( audio->codec & HB_ACODEC_DCA) )+        audio = hb_list_audio_config_item( title->list_audio, i );+        if( ( audio->in.codec == HB_ACODEC_AC3 ) || ( audio->in.codec == HB_ACODEC_DCA) )         {             fprintf( stderr, "    + %d, %s, %dHz, %dbps\n", i + 1,-                     audio->lang, audio->rate, audio->bitrate );+                     audio->lang.description, audio->in.samplerate, audio->in.bitrate );         }         else         {-            fprintf( stderr, "    + %d, %s\n", i + 1, audio->lang );+            fprintf( stderr, "    + %d, %s\n", i + 1, audio->lang.description );         }     }     fprintf( stderr, "  + subtitle tracks:\n" );@@ -300,13 +323,13 @@         fprintf( stderr, "    + %d, %s (iso639-2: %s)\n", i + 1, subtitle->lang,             subtitle->iso639_2);     }-    +     if(title->detected_interlacing)     {         /* Interlacing was found in half or more of the preview frames */         fprintf( stderr, "  + combing detected, may be interlaced or telecined\n");     }-    + }  static int HandleEvents( hb_handle_t * h )@@ -334,7 +357,16 @@             hb_list_t  * list;             hb_title_t * title;             hb_job_t   * job;+            int i; +            /* Audio argument string parsing variables */+            int acodec = 0;+            int abitrate = 0;+            int arate = 0;+            int mixdown = HB_AMIXDOWN_DOLBYPLII;+            double d_r_c = 0;+            /* Audio argument string parsing variables */+             list = hb_get_titles( h );              if( !hb_list_count( list ) )@@ -419,9 +451,9 @@                     mux = HB_MUX_MKV;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 1000;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     x264opts = strdup("ref=5:mixed-refs:bframes=6:bime:weightb:b-rdo:direct=auto:b-pyramid:me=umh:subme=5:analyse=all:8x8dct:trellis=1:nr=150:no-fast-pskip:filter=2,2");                     deinterlace = 1;                     deinterlace_opt = "0";@@ -433,15 +465,28 @@                  if (!strcmp(preset_name, "AppleTV"))                 {+                    if (hb_list_count(audios) == 0)+                    {+                        audio = calloc(1, sizeof(*audio));+                        hb_audio_config_init(audio);+                        audio->in.track = audio->out.track = 0;+                        hb_list_add(audios, audio);++                        audio = calloc(1, sizeof(*audio));+                        hb_audio_config_init(audio);+                        audio->in.track = 0;+                        audio->out.track = 1;+                        hb_list_add(audios, audio);+                        if (acodecs) free(acodecs);+                        acodecs = strdup("faac,ac3");+                    }                     mux = HB_MUX_MP4;                     job->largeFileSize = 1;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 2500;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;-                    audio_mixdown = HB_AMIXDOWN_DOLBYPLII_AC3;-                    arate = 48000;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     x264opts = strdup("bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:trellis=1:cabac=0");                     job->chapter_markers = 1;                     pixelratio = 1;@@ -452,7 +497,7 @@                     mux = HB_MUX_MKV;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 1800;-                    acodec = HB_ACODEC_AC3;+                    default_acodec = HB_ACODEC_AC3;                     x264opts = strdup("ref=16:mixed-refs:bframes=16:bime:weightb:b-rdo:direct=auto:b-pyramid:me=esa:subme=7:me-range=64:analyse=all:8x8dct:trellis=1:no-fast-pskip:no-dct-decimate:filter=-2,-1");                     job->chapter_markers = 1;                     pixelratio = 1;@@ -464,9 +509,9 @@                 {                     mux = HB_MUX_MP4;                     job->vbitrate = 512;-                    job->abitrate = 128;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 128;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     job->width = 512;                     job->chapter_markers = 1;                 }@@ -476,9 +521,9 @@                     mux = HB_MUX_MP4;                     vcodec = HB_VCODEC_X264;                     size = 695;-                    job->abitrate = 128;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 128;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     job->width = 640;                     x264opts = strdup("ref=3:mixed-refs:bframes=16:bime:weightb:b-rdo:b-pyramid:direct=auto:me=umh:subme=6:trellis=1:analyse=all:8x8dct:no-fast-pskip");                     job->chapter_markers = 1;@@ -490,9 +535,9 @@                 {                     mux = HB_MUX_MP4;                     job->vbitrate = 1000;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                 }                  if (!strcmp(preset_name, "Constant Quality Rate"))@@ -501,7 +546,7 @@                     vcodec = HB_VCODEC_X264;                     job->vquality = 0.64709997177124023;                     job->crf = 1;-                    acodec = HB_ACODEC_AC3;+                    default_acodec = HB_ACODEC_AC3;                     x264opts = strdup("ref=3:mixed-refs:bframes=3:b-pyramid:b-rdo:bime:weightb:filter=-2,-1:subme=6:trellis=1:analyse=all:8x8dct:me=umh");                     job->chapter_markers = 1;                     pixelratio = 1;@@ -512,7 +557,7 @@                     mux = HB_MUX_MKV;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 1600;-                    acodec = HB_ACODEC_AC3;+                    default_acodec = HB_ACODEC_AC3;                     x264opts = strdup("ref=5:mixed-refs:bframes=3:bime:weightb:b-rdo:b-pyramid:me=umh:subme=7:trellis=1:analyse=all:8x8dct:no-fast-pskip");                     job->chapter_markers = 1;                     pixelratio = 1;@@ -525,7 +570,7 @@                     mux = HB_MUX_MKV;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 1800;-                    acodec = HB_ACODEC_AC3;+                    default_acodec = HB_ACODEC_AC3;                     x264opts = strdup("ref=3:mixed-refs:bframes=6:bime:weightb:b-rdo:direct=auto:b-pyramid:me=umh:subme=7:analyse=all:8x8dct:trellis=1:no-fast-pskip");                     job->chapter_markers = 1;                     pixelratio = 1;@@ -539,9 +584,9 @@                     job->ipod_atom = 1;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 960;-                    job->abitrate = 128;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 128;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     job->width = 480;                     x264opts = strdup("level=30:cabac=0:ref=1:analyse=all:me=umh:subme=6:no-fast-pskip=1:trellis=1");                     job->chapter_markers = 1;@@ -553,9 +598,9 @@                     job->ipod_atom = 1;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 1500;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     job->width = 640;                     x264opts = strdup("level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:subme=6:no-fast-pskip=1");                     job->chapter_markers = 1;@@ -567,9 +612,9 @@                     job->ipod_atom = 1;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 700;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     job->width = 320;                     x264opts = strdup("level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:subme=6:no-fast-pskip=1");                     job->chapter_markers = 1;@@ -580,9 +625,9 @@                     mux = HB_MUX_MP4;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 1500;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     x264opts = strdup("ref=2:bframes=2:subme=5:me=umh");                     job->chapter_markers = 1;                     pixelratio = 1;@@ -595,9 +640,9 @@                     mux = HB_MUX_MP4;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 2500;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     x264opts = strdup("level=41:subme=5:me=umh");                     pixelratio = 1;                 }@@ -606,9 +651,9 @@                 {                     mux = HB_MUX_MP4;                     job->vbitrate = 1024;-                    job->abitrate = 128;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 128;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     job->width = 368;                     job->height = 208;                     job->chapter_markers = 1;@@ -619,9 +664,9 @@                     mux = HB_MUX_MP4;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 2000;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     x264opts = strdup("ref=3:mixed-refs:bframes=3:bime:weightb:b-rdo:direct=auto:me=umh:subme=5:analyse=all:trellis=1:no-fast-pskip");                     job->chapter_markers = 1;                     pixelratio = 1;@@ -634,9 +679,9 @@                     mux = HB_MUX_MKV;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 1300;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     x264opts = strdup("ref=3:mixed-refs:bframes=6:bime:weightb:direct=auto:b-pyramid:me=umh:subme=6:analyse=all:8x8dct:trellis=1:nr=150:no-fast-pskip");                     deinterlace = 1;                     deinterlace_opt = "0";@@ -652,9 +697,9 @@                     mux = HB_MUX_MP4;                     vcodec = HB_VCODEC_X264;                     job->vbitrate = 2000;-                    job->abitrate = 160;-                    job->arate = 48000;-                    acodec = HB_ACODEC_FAAC;+                    default_abitrate = 160;+                    default_arate = 48000;+                    default_acodec = HB_ACODEC_FAAC;                     x264opts = strdup("level=40:ref=2:mixed-refs:bframes=3:bime:weightb:b-rdo:direct=auto:b-pyramid:me=umh:subme=5:analyse=all:no-fast-pskip:filter=-2,-1");                     pixelratio = 1;                 }@@ -732,13 +777,13 @@             {                 job->pixel_ratio = pixelratio;             }-            +             if (vfr)             {                 detelecine = 1;                 job->vfr = 1;             }-            +             /* Add selected filters */             job->filters = hb_list_init();             if( detelecine )@@ -816,74 +861,231 @@                 job->vrate = 27000000;                 job->vrate_base = vrate;             }-            if( arate )++            /* Parse audio tracks */+            if( hb_list_count(audios) == 0 )             {-                job->arate = arate;+                /* Create a new audio track with default settings */+                audio = calloc(1, sizeof(*audio));+                hb_audio_config_init(audio);+                /* Add it to our audios */+                hb_list_add(audios, audio);             }+            num_audio_tracks = hb_list_count(audios); -            if( audios )+            for (i = 0; i < num_audio_tracks; i++)             {-                if( strcasecmp( audios, "none" ) )+                audio = hb_list_item(audios, 0);+                if ( (audio->in.track == -1) || (audio->out.track == -1) ||+                     (audio->out.codec == 0) )                 {-                    int    audio_count = 0;-                    char * tmp         = audios;-                    while( *tmp )+                    num_audio_tracks--;+                }+                else+                {+                    hb_audio_add( job, audio );+                }+                hb_list_rem(audios, audio);+                free(audio);+            }+            /* Audio Tracks */++            /* Audio Codecs */+            i = 0;+            if( acodecs )+            {+                char * token = strtok(acodecs, ",");+                if (token == NULL)+                    token = acodecs;+                while ( token != NULL )+                {+                    if ((acodec = get_acodec_for_string(token)) == -1)                     {-                        if( *tmp < '0' || *tmp > '9' )+                        fprintf(stderr, "Invalid codec %s, using default for container.\n", token);+                        acodec = default_acodec;+                    }+                    audio = hb_list_audio_config_item(job->list_audio, i);+                    audio->out.codec = acodec;+                    if( (++i) >= num_audio_tracks )+                        break;  /* We have more inputs than audio tracks, oops */+                    token = strtok(NULL, ",");+                }+            }+            if (i < num_audio_tracks)+            {+                /* We have fewer inputs than audio tracks, use the default codec for+                 * this container for the remaining tracks. Unless we only have one input+                 * then use that codec instead.+                 */+                if (i != 1)+                    acodec = default_acodec;+                for ( ; i < num_audio_tracks; i++)+                {+                    audio = hb_list_audio_config_item(job->list_audio, i);+                    audio->out.codec = acodec;+                }+            }+            /* Audio Codecs */++            /* Sample Rate */+            i = 0;+            if( arates )+            {+                char * token = strtok(arates, ",");+                if (token == NULL)+                    token = arates;+                while ( token != NULL )+                {+                    arate = atoi(token);+                    audio = hb_list_audio_config_item(job->list_audio, i);+                    if (audio->out.codec == HB_ACODEC_AC3 || audio->out.codec == HB_ACODEC_DCA)+                    {+                        /* Would probably be better to have this handled in libhb. */+                        audio->out.samplerate = audio->in.samplerate;+                    }+                    else+                    {+                        if (!is_sample_rate_valid(arate))                         {-                            /* Skip non numeric char */-                            tmp++;-                            continue;+                            fprintf(stderr, "Invalid sample rate %d, using default\n", arate);+                            arate = default_arate;                         }-						job->audio_mixdowns[audio_count] = audio_mixdown;-                        job->audios[audio_count++] =-                            strtol( tmp, &tmp, 0 ) - 1;+                        audio->out.samplerate = arate;                     }-                    job->audios[audio_count] = -1;+                    if( (++i) >= num_audio_tracks )+                        break;  /* We have more inputs than audio tracks, oops */+                    token = strtok(NULL, ",");                 }-                else+            }+            if (i < num_audio_tracks)+            {+                /* We have fewer inputs than audio tracks, use default sample rate.+                 * Unless we only have one input, then use that for all tracks.+                 */+                if (i != 1)+                    arate = default_arate;+                for ( ; i < num_audio_tracks; i++)                 {-                    job->audios[0] = -1;+                    audio = hb_list_audio_config_item(job->list_audio, i);+                    if (audio->out.codec == HB_ACODEC_AC3 || audio->out.codec == HB_ACODEC_DCA)+                    {+                        audio->out.samplerate = audio->in.samplerate;+                        continue;+                    }+                    audio->out.samplerate = arate;                 }             }-			else-			{-			    /* default to the first audio track if none has been specified */-			    job->audios[0] = 0;-			    job->audio_mixdowns[0] = audio_mixdown;-			}+            /* Sample Rate */ -			if( audio_mixdown == HB_AMIXDOWN_DOLBYPLII_AC3)-			{-               int i;-               for( i = 3 ; i > 0; i--)-               {-                   job->audios[i*2+1] = job->audios[i];-                   job->audios[i*2] = job->audios[i];-                   if(job->audios[i] != -1  )-                   {-                       job->audio_mixdowns[i*2+1] = HB_AMIXDOWN_AC3;-                       job->audio_mixdowns[i*2] = HB_AMIXDOWN_DOLBYPLII;-                   }-               }--               job->audios[1] = job->audios[0];-               job->audio_mixdowns[1] = HB_AMIXDOWN_AC3;-               job->audio_mixdowns[0] = HB_AMIXDOWN_DOLBYPLII;+            /* Audio Bitrate */+            i = 0;+            if( abitrates )+            {+                char * token = strtok(abitrates, ",");+                if (token == NULL)+                    token = abitrates;+                while ( token != NULL )+                {+                    abitrate = atoi(token);+                    audio = hb_list_audio_config_item(job->list_audio, i);+                    if (audio->out.codec == HB_ACODEC_AC3 || audio->out.codec == HB_ACODEC_DCA)+                    {+                        audio->out.bitrate = audio->in.bitrate;   /* See note above about arate. */+                    }+                    else+                    {+                        audio->out.bitrate = abitrate;+                    }+                    if( (++i) >= num_audio_tracks )+                        break;  /* We have more inputs than audio tracks, oops */+                    token = strtok(NULL, ",");+                }             }+            if (i < num_audio_tracks)+            {+                /* We have fewer inputs than audio tracks, use the default bitrate+                 * for the remaining tracks. Unless we only have one input, then use+                 * that for all tracks.+                 */+                if (i != 1)+                    abitrate = default_abitrate;+                for (; i < num_audio_tracks; i++)+                {+                    audio = hb_list_audio_config_item(job->list_audio, i);+                    if (audio->out.codec == HB_ACODEC_AC3 || audio->out.codec == HB_ACODEC_DCA)+                    {+                        audio->out.bitrate = audio->in.bitrate;+                        continue;+                    }+                    audio->out.bitrate = abitrate;+                }+            }+            /* Audio Bitrate */ -            if( abitrate )+            /* Audio DRC */+            i = 0;+            if ( dynamic_range_compression )             {-                job->abitrate = abitrate;+                char * token = strtok(dynamic_range_compression, ",");+                if (token == NULL)+                    token = dynamic_range_compression;+                while ( token != NULL )+                {+                    d_r_c = atof(token);+                    audio = hb_list_audio_config_item(job->list_audio, i);+                    audio->out.dynamic_range_compression = d_r_c;+                    if( (++i) >= num_audio_tracks )+                        break;  /* We have more inputs than audio tracks, oops */+                    token = strtok(NULL, ",");+                }             }-            if( acodec )+            if (i < num_audio_tracks)             {-                job->acodec = acodec;+                /* We have fewer inputs than audio tracks, use no DRC for the remaining+                 * tracks. Unless we only have one input, then use the same DRC for all+                 * tracks.+                 */+                if (i != 1)+                    d_r_c = 0;+                for (; i < num_audio_tracks; i++)+                {+                    audio = hb_list_audio_config_item(job->list_audio, i);+                    audio->out.dynamic_range_compression = d_r_c;+                }             }-            if ( dynamic_range_compression )+            /* Audio DRC */++            /* Audio Mixdown */+            i = 0;+            if ( mixdowns )             {-                job->dynamic_range_compression = dynamic_range_compression;+                char * token = strtok(mixdowns, ",");+                if (token == NULL)+                    token = mixdowns;+                while ( token != NULL )+                {+                    mixdown = hb_mixdown_get_mixdown_from_short_name(token);+                    audio = hb_list_audio_config_item(job->list_audio, i);+                    audio->out.mixdown = mixdown;+                    if( (++i) >= num_audio_tracks )+                        break;  /* We have more inputs than audio tracks, oops */+                    token = strtok(NULL, ",");+                }             }+            if (i < num_audio_tracks)+            {+                /* We have fewer inputs than audio tracks, use DPLII for the rest. Unless+                 * we only have one input, then use that.+                 */+                if (i != 1)+                    mixdown = HB_AMIXDOWN_DOLBYPLII;+                for (; i < num_audio_tracks; i++)+                {+                   audio = hb_list_audio_config_item(job->list_audio, i);+                   audio->out.mixdown = mixdown;+                }+            }+            /* Audio Mixdown */              if( size )             {@@ -1227,18 +1429,21 @@   	"### Audio Options-----------------------------------------------------------\n\n"-	"    -E, --aencoder <string> Audio encoder (faac/lame/vorbis/ac3/aac+ac3) \n"-	"                            ac3 meaning passthrough, aac+ac3 meaning an\n"-	"                            aac dpl2 mixdown paired with ac3 pass-thru\n"+	"    -a, --audio <string>    Select audio channel(s), separated by commas\n"+    "                            More than one output track can be used for one\n"+    "                            input.\n"+    "                            (\"none\" for no audio, \"1,2,3\" for multiple\n"+    "                             tracks, default: first one)\n"+    "    -E, --aencoder <string> Audio encoder(s) (faac/lame/vorbis/ac3) \n"+	"                            ac3 meaning passthrough\n"+	"                            Seperated by commas for more than one audio track.\n" 	"                            (default: guessed)\n"-	"    -B, --ab <kb/s>         Set audio bitrate (default: 128)\n"-	"    -a, --audio <string>    Select audio channel(s), separated by commas\n"-	"                            (\"none\" for no audio, \"1,2,3\" for multiple\n"-	"                             tracks, default: first one,\n"-	"                             max 8 normally, max 4 with aac+ac3)\n"-    "    -6, --mixdown <string>  Format for surround sound downmixing\n"+	"    -B, --ab <kb/s>         Set audio bitrate(s)  (default: 128)\n"+    "                            Seperated by commas for more than one audio track.\n"+	"    -6, --mixdown <string>  Format(s) for surround sound downmixing\n"+    "                            Seperated by commas for more than one audio track.\n"     "                            (mono/stereo/dpl1/dpl2/6ch, default: dpl2)\n"-    "    -R, --arate             Set audio samplerate (" );+    "    -R, --arate             Set audio samplerate(s) (" );     for( i = 0; i < hb_audio_rates_count; i++ )     {         fprintf( stderr, hb_audio_rates[i].string );@@ -1246,9 +1451,11 @@             fprintf( stderr, "/" );     }     fprintf( stderr, " kHz)\n"+    "                            Seperated by commas for more than one audio track.\n"     "    -D, --drc <float>       Apply extra dynamic range compression to the audio,\n"     "                            making soft sounds louder. Range is 1.0 to 4.0\n"     "                            (too loud), with 1.5 - 2.5 being a useful range.\n"+    "                            Seperated by commas for more than one audio track.\n"   	"\n"@@ -1461,33 +1668,68 @@                 chapter_markers = 1;                 break;             case 'a':-                audios = strdup( optarg );+            {+                char * token = strtok(optarg, ",");+                if (token == NULL)+                    token = optarg;+                int track_start, track_end;+                while( token != NULL )+                {+                    audio = calloc(1, sizeof(*audio));+                    hb_audio_config_init(audio);+                    if (strlen(token) >= 3)+                    {+                        if (sscanf(token, "%d-%d", &track_start, &track_end) == 2)+                        {+                            int i;+                            for (i = track_start - 1; i < track_end; i++)+                            {+                                if (i != track_start - 1)+                                {+                                    audio = calloc(1, sizeof(*audio));+                                    hb_audio_config_init(audio);+                                }+                                audio->in.track = i;+                                audio->out.track = num_audio_tracks++;+                                hb_list_add(audios, audio);+                            }+                        }+                        else if( !strcasecmp(token, "none" ) )+                        {+                            audio->in.track = audio->out.track = -1;+                            audio->out.codec = 0;+                            hb_list_add(audios, audio);+                            break;+                        }+                        else+                        {+                            fprintf(stderr, "ERROR: Unable to parse audio input \"%s\", skipping.",+                                    token);+                            free(audio);+                        }+                    }+                    else+                    {+                        audio->in.track = atoi(token) - 1;+                        audio->out.track = num_audio_tracks++;+                        hb_list_add(audios, audio);+                    }+                    token = strtok(NULL, ",");+                }                 break;+            }             case '6':-                if( !strcasecmp( optarg, "mono" ) )+                if( optarg != NULL )                 {-                    audio_mixdown = HB_AMIXDOWN_MONO;+                    mixdowns = strdup( optarg );                 }-                else if( !strcasecmp( optarg, "stereo" ) )+                break;+            case 'D':+                if( optarg != NULL )                 {-                    audio_mixdown = HB_AMIXDOWN_STEREO;+                    dynamic_range_compression = strdup( optarg );                 }-                else if( !strcasecmp( optarg, "dpl1" ) )-                {-                    audio_mixdown = HB_AMIXDOWN_DOLBY;-                }-                else if( !strcasecmp( optarg, "dpl2" ) )-                {-                    audio_mixdown = HB_AMIXDOWN_DOLBYPLII;-                }-                else if( !strcasecmp( optarg, "6ch" ) )-                {-                    audio_mixdown = HB_AMIXDOWN_6CH;-                }                 break;-            case 'D':-                dynamic_range_compression = atof( optarg );-                break;             case 's':                 sub = atoi( optarg );                 break;@@ -1608,28 +1850,10 @@                 }                 break;             case 'E':-                if( !strcasecmp( optarg, "ac3" ) )+                if( optarg != NULL )                 {-                    acodec = HB_ACODEC_AC3;+                    acodecs = strdup( optarg );                 }-                else if( !strcasecmp( optarg, "lame" ) )-                {-                    acodec = HB_ACODEC_LAME;-                }-                else if( !strcasecmp( optarg, "faac" ) )-                {-                    acodec = HB_ACODEC_FAAC;-                }-                else if( !strcasecmp( optarg, "vorbis") )-                {-                    acodec = HB_ACODEC_VORBIS;-                }-                else if( !strcasecmp( optarg, "aac+ac3") )-                {-                    acodec = HB_ACODEC_FAAC;-                    audio_mixdown = HB_AMIXDOWN_DOLBYPLII_AC3;-                    arate = 48000;-                }                 break;             case 'w':                 width = atoi( optarg );@@ -1669,23 +1893,11 @@                 break;             }             case 'R':-            {-                int i;-                arate = 0;-                for( i = 0; i < hb_audio_rates_count; i++ )+                if( optarg != NULL )                 {-                    if( !strcmp( optarg, hb_audio_rates[i].string ) )-                    {-                        arate = hb_audio_rates[i].rate;-                        break;-                    }+                    arates = strdup( optarg );                 }-                if( !arate )-                {-                    fprintf( stderr, "invalid framerate %s\n", optarg );-                }                 break;-            }             case 'b':                 vbitrate = atoi( optarg );                 break;@@ -1696,7 +1908,10 @@                 size = atoi( optarg );                 break;             case 'B':-                abitrate = atoi( optarg );+                if( optarg != NULL )+                {+                    abitrates = strdup( optarg );+                }                 break;             case 'Q':                 crf = 0;@@ -1758,6 +1973,7 @@             if( p && !strcasecmp( p, ".avi" ) )             {                 mux = HB_MUX_AVI;+                default_acodec = HB_ACODEC_LAME;             }             else if( p && ( !strcasecmp( p, ".mp4" )  ||                             !strcasecmp( p, ".m4v" ) ) )@@ -1766,15 +1982,18 @@                     mux = HB_MUX_IPOD;                 else                     mux = HB_MUX_MP4;+                default_acodec = HB_ACODEC_FAAC;             }             else if( p && ( !strcasecmp( p, ".ogm" ) ||                             !strcasecmp( p, ".ogg" ) ) )             {                 mux = HB_MUX_OGM;+                default_acodec = HB_ACODEC_VORBIS;             }             else if( p && !strcasecmp(p, ".mkv" ) )             {                 mux = HB_MUX_MKV;+                default_acodec = HB_ACODEC_AC3;             }             else             {@@ -1786,6 +2005,7 @@         else if( !strcasecmp( format, "avi" ) )         {             mux = HB_MUX_AVI;+            default_acodec = HB_ACODEC_LAME;         }         else if( !strcasecmp( format, "mp4" ) )         {@@ -1793,15 +2013,18 @@                 mux = HB_MUX_IPOD;             else                 mux = HB_MUX_MP4;+            default_acodec = HB_ACODEC_FAAC;         }         else if( !strcasecmp( format, "ogm" ) ||                  !strcasecmp( format, "ogg" ) )         {             mux = HB_MUX_OGM;+            default_acodec = HB_ACODEC_VORBIS;         }         else if( !strcasecmp( format, "mkv" ) )         {             mux = HB_MUX_MKV;+            default_acodec = HB_ACODEC_AC3;         }         else         {@@ -1809,28 +2032,46 @@                      "choices are avi, mp4, m4v, ogm, ogg and mkv\n.", format );             return 1;         }+    } -        if( !acodec )-        {-            if( mux == HB_MUX_MP4 || mux == HB_MUX_IPOD )-            {-                acodec = HB_ACODEC_FAAC;-            }-            else if( mux == HB_MUX_AVI )-            {-                acodec = HB_ACODEC_LAME;-            }-            else if( mux == HB_MUX_OGM )-            {-                acodec = HB_ACODEC_VORBIS;-            }-            else if( mux == HB_MUX_MKV )-            {-                acodec = HB_ACODEC_AC3;-            }-        }+    return 0;+} +static int get_acodec_for_string( char *codec )+{+    if( !strcasecmp( codec, "ac3" ) )+    {+        return HB_ACODEC_AC3;     }+    else if( !strcasecmp( codec, "dts" ) || !strcasecmp( codec, "dca" ) )+    {+        return HB_ACODEC_DCA;+    }+    else if( !strcasecmp( codec, "lame" ) )+    {+        return HB_ACODEC_LAME;+    }+    else if( !strcasecmp( codec, "faac" ) )+    {+        return HB_ACODEC_FAAC;+    }+    else if( !strcasecmp( codec, "vorbis") )+    {+        return HB_ACODEC_VORBIS;+    }+    else+    {+        return -1;+    }+} +static int is_sample_rate_valid(int rate)+{+    int i;+    for( i = 0; i < hb_audio_rates_count; i++ )+    {+            if (rate == hb_audio_rates[i].rate)+                return 1;+    }     return 0; }Index: libhb/reader.c===================================================================--- libhb/reader.c	(revision 1364)+++ libhb/reader.c	(working copy)@@ -358,7 +358,7 @@             audio = hb_list_item( title->list_audio, i );             if( id == audio->id )             {-                fifos[n++] = audio->fifo_in;+                fifos[n++] = audio->priv.fifo_in;             }         } Index: libhb/deca52.c===================================================================--- libhb/deca52.c	(revision 1364)+++ libhb/deca52.c	(working copy)@@ -88,6 +88,7 @@ int deca52Init( hb_work_object_t * w, hb_job_t * job ) {     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );+    hb_audio_t * audio = w->audio;     w->private_data = pv;      pv->job   = job;@@ -98,14 +99,14 @@ 	/* Decide what format we want out of a52dec 	work.c has already done some of this deduction for us in do_job() */ -	pv->flags_out = HB_AMIXDOWN_GET_A52_FORMAT(w->amixdown);+	pv->flags_out = HB_AMIXDOWN_GET_A52_FORMAT(audio->config.out.mixdown);  	/* pass the number of channels used into the private work data */ 	/* will only be actually used if we're not doing AC3 passthru */-	pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown);+    pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);      pv->level     = 32768.0;-    pv->dynamic_range_compression = job->dynamic_range_compression;+    pv->dynamic_range_compression = audio->config.out.dynamic_range_compression;      pv->next_expected_pts = 0;     pv->sequence = 0;@@ -168,6 +169,7 @@ {     hb_work_private_t * pv = w->private_data;     hb_buffer_t * buf;+    hb_audio_t  * audio = w->audio;     int           i, j, k;     uint64_t      pts, pos; @@ -219,8 +221,7 @@     }      /* AC3 passthrough: don't decode the AC3 frame */-    if( pv->job->acodec & HB_ACODEC_AC3 ||-        w->amixdown == HB_AMIXDOWN_AC3 )+    if( audio->config.out.codec == HB_ACODEC_AC3 )     {         buf = hb_buffer_init( pv->size );         memcpy( buf->data, pv->frame, pv->size );Index: libhb/enclame.c===================================================================--- libhb/enclame.c	(revision 1364)+++ libhb/enclame.c	(working copy)@@ -39,6 +39,7 @@ int enclameInit( hb_work_object_t * w, hb_job_t * job ) {     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );+    hb_audio_t * audio = w->audio;     w->private_data = pv;      pv->job   = job;@@ -46,9 +47,9 @@     hb_log( "enclame: opening libmp3lame" );      pv->lame = lame_init();-    lame_set_brate( pv->lame, job->abitrate );-    lame_set_in_samplerate( pv->lame, job->arate );-    lame_set_out_samplerate( pv->lame, job->arate );+    lame_set_brate( pv->lame, audio->config.out.bitrate );+    lame_set_in_samplerate( pv->lame, audio->config.out.samplerate );+    lame_set_out_samplerate( pv->lame, audio->config.out.samplerate );     lame_init_params( pv->lame );      pv->input_samples = 1152 * 2;@@ -85,6 +86,7 @@ static hb_buffer_t * Encode( hb_work_object_t * w ) {     hb_work_private_t * pv = w->private_data;+    hb_audio_t * audio = w->audio;     hb_buffer_t * buf;     int16_t samples_s16[1152 * 2];     uint64_t pts, pos;@@ -104,8 +106,8 @@     }      buf        = hb_buffer_init( pv->output_bytes );-    buf->start = pts + 90000 * pos / 2 / sizeof( float ) / pv->job->arate;-    buf->stop  = buf->start + 90000 * 1152 / pv->job->arate;+    buf->start = pts + 90000 * pos / 2 / sizeof( float ) / audio->config.out.samplerate;+    buf->stop  = buf->start + 90000 * 1152 / audio->config.out.samplerate;     buf->size  = lame_encode_buffer_interleaved( pv->lame, samples_s16,             1152, buf->data, LAME_MAXMP3BUFFER );     buf->frametype   = HB_FRAME_AUDIO;Index: libhb/muxavi.c===================================================================--- libhb/muxavi.c	(revision 1364)+++ libhb/muxavi.c	(working copy)@@ -281,7 +281,7 @@     hb_mux_data_t * mux_data;      int audio_count = hb_list_count( title->list_audio );-    int is_ac3      = ( job->acodec & HB_ACODEC_AC3 );+    int is_ac3      = 0;     int hdrl_bytes;     int i; @@ -346,8 +346,10 @@     {         audio = hb_list_item( title->list_audio, i ); +        is_ac3 = (audio->config.out.codec == HB_ACODEC_AC3);+         mux_data = calloc( sizeof( hb_mux_data_t ), 1 );-        audio->mux_data = mux_data;+        audio->priv.mux_data = mux_data;  #define h mux_data->header #define f mux_data->format.a.f@@ -358,8 +360,8 @@         h.Type          = FOURCC( "auds" );         h.InitialFrames = 1;         h.Scale         = 1;-        h.Rate          = is_ac3 ? ( audio->bitrate / 8 ) :-                                   ( job->abitrate * 1000 / 8 );+        h.Rate          = is_ac3 ? ( audio->config.in.bitrate / 8 ) :+                                   ( audio->config.out.bitrate * 1000 / 8 );         h.Quality       = 0xFFFFFFFF;         h.SampleSize    = 1; @@ -369,16 +371,16 @@         {             f.BytesCount     = sizeof( hb_wave_formatex_t ) - 8;             f.FormatTag      = 0x2000;-            f.Channels       = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->input_channel_layout);-            f.SamplesPerSec  = audio->rate;+            f.Channels       = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout);+            f.SamplesPerSec  = audio->config.in.samplerate;         }         else         {             f.BytesCount     = sizeof( hb_wave_formatex_t ) +                                sizeof( hb_wave_mp3_t ) - 8;             f.FormatTag      = 0x55;-            f.Channels       = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(job->audio_mixdowns[i]);-            f.SamplesPerSec  = job->arate;+            f.Channels       = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);+            f.SamplesPerSec  = audio->config.out.samplerate;         }         f.AvgBytesPerSec = h.Rate;         f.BlockAlign     = 1;@@ -391,7 +393,7 @@             f.Size           = sizeof( hb_wave_mp3_t );             m.Id             = 1;             m.Flags          = 2;-            m.BlockSize      = 1152 * f.AvgBytesPerSec / job->arate;+            m.BlockSize      = 1152 * f.AvgBytesPerSec / audio->config.out.samplerate;             m.FramesPerBlock = 1;             m.CodecDelay     = 1393;         }@@ -439,7 +441,7 @@         char fourcc[4] = "00wb";          audio    = hb_list_item( title->list_audio, i );-        mux_data = audio->mux_data;+        mux_data = audio->priv.mux_data;          fourcc[1] = '1' + i; /* This is fine as we don't allow more                                 than 8 tracks */@@ -513,9 +515,9 @@     {         audio = hb_list_item( title->list_audio, i );         fseek( m->file, 264 + i *-               ( 102 + ( ( job->acodec & HB_ACODEC_AC3 ) ? 0 :+               ( 102 + ( ( audio->config.out.codec == HB_ACODEC_AC3 ) ? 0 :                  sizeof( hb_wave_mp3_t ) ) ), SEEK_SET );-        WriteInt32( m->file, audio->mux_data->header.Length );+        WriteInt32( m->file, audio->priv.mux_data->header.Length );     }      /* movi size */Index: libhb/dvd.c===================================================================--- libhb/dvd.c	(revision 1364)+++ libhb/dvd.c	(working copy)@@ -257,28 +257,28 @@         {             case 0x00:                 audio->id    = ( ( 0x80 + position ) << 8 ) | 0xbd;-                audio->codec = HB_ACODEC_AC3;+                audio->config.in.codec = HB_ACODEC_AC3;                 break;              case 0x02:             case 0x03:                 audio->id    = 0xc0 + position;-                audio->codec = HB_ACODEC_MPGA;+                audio->config.in.codec = HB_ACODEC_MPGA;                 break;              case 0x04:                 audio->id    = ( ( 0xa0 + position ) << 8 ) | 0xbd;-                audio->codec = HB_ACODEC_LPCM;+                audio->config.in.codec = HB_ACODEC_LPCM;                 break;              case 0x06:                 audio->id    = ( ( 0x88 + position ) << 8 ) | 0xbd;-                audio->codec = HB_ACODEC_DCA;+                audio->config.in.codec = HB_ACODEC_DCA;                 break;              default:                 audio->id    = 0;-                audio->codec = 0;+                audio->config.in.codec = 0;                 hb_log( "scan: unknown audio codec (%x)",                         audio_format );                 break;@@ -308,19 +308,20 @@          lang = lang_for_code( vts->vtsi_mat->vts_audio_attr[i].lang_code ); -        snprintf( audio->lang, sizeof( audio->lang ), "%s (%s)",+        snprintf( audio->config.lang.description, sizeof( audio->config.lang.description ), "%s (%s)",             strlen(lang->native_name) ? lang->native_name : lang->eng_name,-            audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec ==-                HB_ACODEC_DCA ? "DTS" : ( audio->codec ==+            audio->config.in.codec == HB_ACODEC_AC3 ? "AC3" : ( audio->config.in.codec ==+                HB_ACODEC_DCA ? "DTS" : ( audio->config.in.codec ==                 HB_ACODEC_MPGA ? "MPEG" : "LPCM" ) ) );-        snprintf( audio->lang_simple, sizeof( audio->lang_simple ), "%s",+        snprintf( audio->config.lang.simple, sizeof( audio->config.lang.simple ), "%s",                   strlen(lang->native_name) ? lang->native_name : lang->eng_name );-        snprintf( audio->iso639_2, sizeof( audio->iso639_2 ), "%s",+        snprintf( audio->config.lang.iso639_2, sizeof( audio->config.lang.iso639_2 ), "%s",                   lang->iso639_2);          hb_log( "scan: id=%x, lang=%s, 3cc=%s", audio->id,-                audio->lang, audio->iso639_2 );+                audio->config.lang.description, audio->config.lang.iso639_2 ); +        audio->config.in.track = i;         hb_list_add( title->list_audio, audio );     } Index: libhb/hb.c===================================================================--- libhb/hb.c	(revision 1364)+++ libhb/hb.c	(working copy)@@ -453,7 +453,7 @@     cc_1 = 0; cc_2 = 0;      int offset = 0;-    +     for( k = 0; k < 3; k++ )     {         /* One pas for Y, one pass for Cb, one pass for Cr */@@ -476,14 +476,14 @@                so it's width*height + (width / 2) * (height / 2)  */             offset *= 5/4;         }-        +         /* Look at one horizontal line at a time */         block = width;-        +         for( j = 0; j < block; ++j )         {             off = 0;-            +             for( n = 0; n < ( height - 4 ); n = n + 2 )             {                 /* Look at groups of 4 sequential horizontal lines */@@ -491,29 +491,29 @@                 s2 = ( ( buf->data + offset )[ off + j + block     ] & 0xff );                 s3 = ( ( buf->data + offset )[ off + j + 2 * block ] & 0xff );                 s4 = ( ( buf->data + offset )[ off + j + 3 * block ] & 0xff );-                +                 /* Note if the 1st and 2nd lines are more different in                    color than the 1st and 3rd lines are similar in color.*/-                if ( ( abs( s1 - s3 ) < color_equal ) && +                if ( ( abs( s1 - s3 ) < color_equal ) &&                      ( abs( s1 - s2 ) > color_diff ) )                         ++cc_1;-    +                 /* Note if the 2nd and 3rd lines are more different in                    color than the 2nd and 4th lines are similar in color.*/                 if ( ( abs( s2 - s4 ) < color_equal ) &&                      ( abs( s2 - s3 ) > color_diff) )                         ++cc_2;-                +                 /* Now move down 2 horizontal lines before starting over.*/                 off += 2 * block;             }         }-        +         // compare results         /* The final metric seems to be doing some kind of bits per pixel style calculation            to decide whether or not enough lines showed alternating colors for the frame size. */         cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );-        +         /* If the plane's cc score meets the threshold, flag it as combed. */         flag[k] = 0;         if ( cc[k] > threshold )@@ -521,13 +521,13 @@             flag[k] = 1;         }     }-    + #if 0 /* Debugging info */ //    if(flag)         hb_log("flags: %i/%i/%i | cc0: %i | cc1: %i | cc2: %i", flag[0], flag[1], flag[2], cc[0], cc[1], cc[2]); #endif-    +     /* When more than one plane shows combing, tell the caller. */     if (flag[0] || flag[1] || flag[2] )     {@@ -834,7 +834,7 @@     hb_job_t      * job_copy;     hb_title_t    * title,    * title_copy;     hb_chapter_t  * chapter,  * chapter_copy;-    hb_audio_t    * audio,    * audio_copy;+    hb_audio_t    * audio;     hb_subtitle_t * subtitle, * subtitle_copy;     int             i;     char            audio_lang[4];@@ -859,18 +859,12 @@     /* Do nothing about audio during first pass */     if( job->pass == 0 || job->pass == 2 )     {-        for( i = 0; i < 8; i++ )+        for( i = 0; i < hb_list_count(job->list_audio); i++ )         {-            if( job->audios[i] < 0 )+            if( ( audio = hb_list_item( job->list_audio, i ) ) )             {-                break;+                hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );             }-            if( ( audio = hb_list_item( title->list_audio, job->audios[i] ) ) )-            {-                audio_copy = malloc( sizeof( hb_audio_t ) );-                memcpy( audio_copy, audio, sizeof( hb_audio_t ) );-                hb_list_add( title_copy->list_audio, audio_copy );-            }         }     } @@ -900,17 +894,13 @@         /*          * Find the first audio language that is being encoded          */-        for( i = 0; i < 8; i++ )+        for( i = 0; i < hb_list_count(job->list_audio); i++ )         {-            if( job->audios[i] < 0 )+            if( ( audio = hb_list_item( job->list_audio, i ) ) )             {+                strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));                 break;             }-            if( ( audio = hb_list_item( title->list_audio, job->audios[i] ) ) )-            {-                strncpy(audio_lang, audio->iso639_2, sizeof(audio_lang));-                break;-            }         }          /*@@ -1035,6 +1025,7 @@     memcpy( job_copy, job, sizeof( hb_job_t ) );     title_copy->job = job_copy;     job_copy->title = title_copy;+    job_copy->list_audio = title_copy->list_audio;     job_copy->file  = strdup( job->file );     job_copy->h     = h;     job_copy->pause = h->pause_lock;Index: libhb/muxmp4.c===================================================================--- libhb/muxmp4.c	(revision 1364)+++ libhb/muxmp4.c	(working copy)@@ -27,6 +27,11 @@     MP4TrackId chapter_track;     int current_chapter;     uint64_t chapter_duration;++    /* Sample rate of the first audio track.+     * Used for the timescale+     */+    int samplerate; };  struct hb_mux_data_s@@ -137,6 +142,10 @@     /* Flags for enabling/disabling tracks in an MP4. */     typedef enum { TRACK_DISABLED = 0x0, TRACK_ENABLED = 0x1, TRACK_IN_MOVIE = 0x2, TRACK_IN_PREVIEW = 0x4, TRACK_IN_POSTER = 0x8}  track_header_flags; +    /* Need the sample rate of the first audio track to use as the timescale. */+    audio = hb_list_item(title->list_audio, 0);+    m->samplerate = audio->config.out.samplerate;+    audio = NULL;      /* Create an empty mp4 file */     if (job->largeFileSize)@@ -166,7 +175,7 @@        synchronization issues (audio not playing at the correct speed).        To workaround this, we use the audio samplerate as the        timescale */-    if (!(MP4SetTimeScale( m->file, job->arate )))+    if (!(MP4SetTimeScale( m->file, m->samplerate )))     {         hb_error("muxmp4.c: MP4SetTimeScale failed!");         *job->die = 1;@@ -183,7 +192,7 @@             return 0;         } -		mux_data->track = MP4AddH264VideoTrack( m->file, job->arate,+		mux_data->track = MP4AddH264VideoTrack( m->file, m->samplerate, 		        MP4_INVALID_DURATION, job->width, job->height, 		        job->config.h264.sps[1], /* AVCProfileIndication */ 		        job->config.h264.sps[2], /* profile_compat */@@ -211,7 +220,7 @@             *job->die = 1;             return 0;         }-        mux_data->track = MP4AddVideoTrack( m->file, job->arate,+        mux_data->track = MP4AddVideoTrack( m->file, m->samplerate,                 MP4_INVALID_DURATION, job->width, job->height,                 MP4_MPEG4_VIDEO_TYPE );         if (mux_data->track == MP4_INVALID_TRACK_ID)@@ -261,14 +270,13 @@          audio = hb_list_item( title->list_audio, i );         mux_data = malloc( sizeof( hb_mux_data_t ) );-        audio->mux_data = mux_data;+        audio->priv.mux_data = mux_data; -        if( job->acodec & HB_ACODEC_AC3 ||-            job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+        if( audio->config.out.codec == HB_ACODEC_AC3 )         {             mux_data->track = MP4AddAC3AudioTrack(                 m->file,-                job->arate, 1536, MP4_MPEG4_AUDIO_TYPE );+                m->samplerate, 1536, MP4_MPEG4_AUDIO_TYPE );             MP4SetTrackBytesProperty(                 m->file, mux_data->track,                 "udta.name.value",@@ -276,7 +284,7 @@         } else {             mux_data->track = MP4AddAudioTrack(                 m->file,-                job->arate, 1024, MP4_MPEG4_AUDIO_TYPE );+                m->samplerate, 1024, MP4_MPEG4_AUDIO_TYPE );             MP4SetTrackBytesProperty(                 m->file, mux_data->track,                 "udta.name.value",@@ -285,18 +293,18 @@             MP4SetAudioProfileLevel( m->file, 0x0F );             MP4SetTrackESConfiguration(                 m->file, mux_data->track,-                audio->config.aac.bytes, audio->config.aac.length );+                audio->priv.config.aac.bytes, audio->priv.config.aac.length );              /* Set the correct number of channels for this track */-            reserved2[9] = (u_int8_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown);+            reserved2[9] = (u_int8_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);             MP4SetTrackBytesProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.reserved2", reserved2, sizeof(reserved2));          }         /* Set the language for this track */         /* The language is stored as 5-bit text - 0x60 */-        language_code = audio->iso639_2[0] - 0x60;   language_code <<= 5;-        language_code |= audio->iso639_2[1] - 0x60;  language_code <<= 5;-        language_code |= audio->iso639_2[2] - 0x60;+        language_code = audio->config.lang.iso639_2[0] - 0x60;   language_code <<= 5;+        language_code |= audio->config.lang.iso639_2[1] - 0x60;  language_code <<= 5;+        language_code |= audio->config.lang.iso639_2[2] - 0x60;         MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.mdhd.language", language_code);  @@ -372,7 +380,7 @@              if ( job->areBframes )             {-                duration += buf->renderOffset * job->arate / 90000;+                duration += buf->renderOffset * m->samplerate / 90000;             }              sample = MP4GenerateChapterSample( m, duration );@@ -396,8 +404,8 @@         /* Because we use the audio samplerate as the timescale,            we have to use potentially variable durations so the video            doesn't go out of sync */-        int64_t bias = ( buf->start * job->arate / 90000 ) - m->sum_dur;-        duration = ( buf->stop - buf->start ) * job->arate / 90000 + bias;+        int64_t bias = ( buf->start * m->samplerate / 90000 ) - m->sum_dur;+        duration = ( buf->stop - buf->start ) * m->samplerate / 90000 + bias;         if ( duration <= 0 )         {             /* We got an illegal mp4/h264 duration. This shouldn't@@ -406,14 +414,14 @@                try to fix the error so that the file will still be playable. */             hb_log("MP4Mux: illegal duration %lld, bias %lld, start %lld (%lld),"                    "stop %lld (%lld), sum_dur %lld",-                   duration, bias, buf->start * job->arate / 90000, buf->start,-                   buf->stop * job->arate / 90000, buf->stop, m->sum_dur );+                   duration, bias, buf->start * m->samplerate / 90000, buf->start,+                   buf->stop * m->samplerate / 90000, buf->stop, m->sum_dur );             /* we don't know when the next frame starts so we can't pick a                valid duration for this one so we pick something "short"                (roughly 1/3 of an NTSC frame time) and rely on the bias calc                for the next frame to correct things (a duration underestimate                just results in a large bias on the next frame). */-            duration = 1000 * job->arate / 90000;+            duration = 1000 * m->samplerate / 90000;         }         m->sum_dur += duration;     }@@ -436,7 +444,7 @@                          duration,                          ((mux_data->track != 1) ||                           (job->areBframes==0) ||-                          (job->vcodec != HB_VCODEC_X264)) ? 0 : (  buf->renderOffset * job->arate / 90000),+                          (job->vcodec != HB_VCODEC_X264)) ? 0 : (  buf->renderOffset * m->samplerate / 90000),                          ((buf->frametype & HB_FRAME_KEY) != 0) ) )     {         hb_error("Failed to write to output file, disk full?");Index: libhb/stream.c===================================================================--- libhb/stream.c	(revision 1364)+++ libhb/stream.c	(working copy)@@ -340,7 +340,7 @@     if ( stream->frames )     {         hb_log( "stream: %d good frames, %d errors (%.0f%%)", stream->frames,-                stream->errors, (double)stream->errors * 100. / +                stream->errors, (double)stream->errors * 100. /                 (double)stream->frames );     }     /*@@ -444,7 +444,7 @@         for (i=0; i < stream->ts_number_audio_pids; i++)         {             hb_audio_t *audio = hb_ts_stream_set_audio_id_and_codec(stream, i);-            if (audio->codec)+            if (audio->config.in.codec)                 hb_list_add( aTitle->list_audio, audio );             else             {@@ -773,7 +773,7 @@         if (buf[3] == 0xbd)         {             audio->id = 0x80bd | (aud_pid_index << 8);-            audio->codec = HB_ACODEC_AC3;+            audio->config.in.codec = HB_ACODEC_AC3;             hb_log("transport stream pid 0x%x (type 0x%x) is AC-3 audio id 0x%x",                    stream->ts_audio_pids[aud_pid_index],                    stream->ts_audio_stream_type[1 + aud_pid_index],@@ -784,7 +784,7 @@         else if ((buf[3] & 0xe0) == 0xc0)         {             audio->id = buf[3] | aud_pid_index;-            audio->codec = HB_ACODEC_MPGA;+            audio->config.in.codec = HB_ACODEC_MPGA;             hb_log("transport stream pid 0x%x (type 0x%x) is MPEG audio id 0x%x",                    stream->ts_audio_pids[aud_pid_index],                    stream->ts_audio_stream_type[1 + aud_pid_index],@@ -794,7 +794,7 @@         }     }     fseeko(stream->file_handle, cur_pos, SEEK_SET);-    if (! audio->codec)+    if (! audio->config.in.codec)     {         hb_log("transport stream pid 0x%x (type 0x%x) isn't audio",                 stream->ts_audio_pids[aud_pid_index],@@ -811,7 +811,7 @@     switch ( id >> 12 )     {         case 0x0:-            audio->codec = HB_ACODEC_MPGA;+            audio->config.in.codec = HB_ACODEC_MPGA;             hb_log("add_audio_to_title: added MPEG audio stream 0x%x", id);             break;         case 0x2:@@ -819,11 +819,11 @@             free( audio );             return;         case 0x8:-            audio->codec = HB_ACODEC_AC3;+            audio->config.in.codec = HB_ACODEC_AC3;             hb_log("add_audio_to_title: added AC3 audio stream 0x%x", id);             break;         case 0xa:-            audio->codec = HB_ACODEC_LPCM;+            audio->config.in.codec = HB_ACODEC_LPCM;             hb_log("add_audio_to_title: added LPCM audio stream 0x%x", id);             break;         default:@@ -913,12 +913,12 @@         }  		lang = lang_for_code(stream->a52_info[i].lang_code);-		if (!audio->rate)-			audio->rate = stream->a52_info[i].rate;-		if (!audio->bitrate)-			audio->bitrate = stream->a52_info[i].bitrate;-		if (!audio->config.a52.ac3flags)-			audio->config.a52.ac3flags = audio->ac3flags = stream->a52_info[i].flags;+        if (!audio->config.in.samplerate)+            audio->config.in.samplerate = stream->a52_info[i].rate;+        if (!audio->config.in.bitrate)+            audio->config.in.bitrate = stream->a52_info[i].bitrate;+        if (!audio->priv.config.a52.ac3flags)+            audio->priv.config.a52.ac3flags = audio->config.flags.ac3 = stream->a52_info[i].flags;  	}     else@@ -927,74 +927,74 @@         lang = lang_for_code(0x0000);     } -	if (!audio->input_channel_layout)+	if (!audio->config.in.channel_layout) 	{-		switch( audio->ac3flags & A52_CHANNEL_MASK )+		switch( audio->config.flags.ac3 & A52_CHANNEL_MASK ) 		{ 			/* mono sources */ 			case A52_MONO: 			case A52_CHANNEL1: 			case A52_CHANNEL2:-				audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO;+				audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_MONO; 				break; 			/* stereo input */ 			case A52_CHANNEL: 			case A52_STEREO:-				audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;+				audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO; 				break; 			/* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */ 			case A52_DOLBY:-				audio->input_channel_layout = HB_INPUT_CH_LAYOUT_DOLBY;+				audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_DOLBY; 				break; 			/* 3F/2R input */ 			case A52_3F2R:-				audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R;+				audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F2R; 				break; 			/* 3F/1R input */ 			case A52_3F1R:-				audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R;+				audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F1R; 				break; 			/* other inputs */ 			case A52_3F:-				audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F;+				audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F; 				break; 			case A52_2F1R:-				audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R;+				audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F1R; 				break; 			case A52_2F2R:-				audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R;+				audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F2R; 				break; 			/* unknown */ 			default:-				audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;+				audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO; 		}  		/* add in our own LFE flag if the source has LFE */-		if (audio->ac3flags & A52_LFE)+		if (audio->config.flags.ac3 & A52_LFE) 		{-			audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;+			audio->config.in.channel_layout = audio->config.in.channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE; 		} 	} -	snprintf( audio->lang, sizeof( audio->lang ), "%s (%s)", strlen(lang->native_name) ? lang->native_name : lang->eng_name,-	  audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec == HB_ACODEC_MPGA ? "MPEG" : ( audio->codec == HB_ACODEC_DCA ? "DTS" : "LPCM" ) ) );-	snprintf( audio->lang_simple, sizeof( audio->lang_simple ), "%s", strlen(lang->native_name) ? lang->native_name : lang->eng_name );-	snprintf( audio->iso639_2, sizeof( audio->iso639_2 ), "%s", lang->iso639_2);+    snprintf( audio->config.lang.description, sizeof( audio->config.lang.description ), "%s (%s)", strlen(lang->native_name) ? lang->native_name : lang->eng_name,+	  audio->config.in.codec == HB_ACODEC_AC3 ? "AC3" : ( audio->config.in.codec == HB_ACODEC_MPGA ? "MPEG" : ( audio->config.in.codec == HB_ACODEC_DCA ? "DTS" : "LPCM" ) ) );+	snprintf( audio->config.lang.simple, sizeof( audio->config.lang.simple ), "%s", strlen(lang->native_name) ? lang->native_name : lang->eng_name );+	snprintf( audio->config.lang.iso639_2, sizeof( audio->config.lang.iso639_2 ), "%s", lang->iso639_2); -	if ( (audio->ac3flags & A52_CHANNEL_MASK) == A52_DOLBY ) {-		sprintf( audio->lang + strlen( audio->lang ),+	if ( (audio->config.flags.ac3 & A52_CHANNEL_MASK) == A52_DOLBY ) {+        sprintf( audio->config.lang.description + strlen( audio->config.lang.description ), 			 " (Dolby Surround)" ); 	} else {-		sprintf( audio->lang + strlen( audio->lang ),+        sprintf( audio->config.lang.description + strlen( audio->config.lang.description ), 			 " (%d.%d ch)",-			HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) +-			HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout),-			HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout));+			HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->config.in.channel_layout) ++			HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->config.in.channel_layout),+			HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->config.in.channel_layout)); 	}  	hb_log( "stream: audio %x: lang %s, rate %d, bitrate %d, "-            "flags = 0x%x", audio->id, audio->lang, audio->rate,-            audio->bitrate, audio->ac3flags );+            "flags = 0x%x", audio->id, audio->config.lang.description, audio->config.in.samplerate,+            audio->config.in.bitrate, audio->config.flags.ac3 );  } @@ -1879,7 +1879,7 @@             // remember the pcr across calls to this routine             stream->ts_lastpcr = pcr;         }-		+ 		if ( pcr == -1 ) 		{             // don't accumulate data until we get a pcr@@ -1903,7 +1903,7 @@                 // so ignore the rest.                 continue;             }-            if ( !start && (stream->ts_streamcont[curstream] != -1) && +            if ( !start && (stream->ts_streamcont[curstream] != -1) &&                  (continuity != ( (stream->ts_streamcont[curstream] + 1) & 0xf ) ) ) 			{ 				ts_err( stream, curstream,  "continuity error: got %d expected %d",@@ -1933,7 +1933,7 @@ 				stream->ts_skipbad[curstream] = 0; 			} -			// If we don't have video yet, check to see if this is an +			// If we don't have video yet, check to see if this is an             // i_frame (group of picture start) 			if ( curstream == 0 )             {Index: libhb/decdca.c===================================================================--- libhb/decdca.c	(revision 1364)+++ libhb/decdca.c	(working copy)@@ -61,6 +61,7 @@ int decdcaInit( hb_work_object_t * w, hb_job_t * job ) {     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );+    hb_audio_t * audio = w->audio;     w->private_data = pv;      pv->job   = job;@@ -71,11 +72,11 @@ 	/* Decide what format we want out of libdca 	work.c has already done some of this deduction for us in do_job() */ -	pv->flags_out = HB_AMIXDOWN_GET_DCA_FORMAT(w->amixdown);+	pv->flags_out = HB_AMIXDOWN_GET_DCA_FORMAT(audio->config.out.mixdown);  	/* pass the number of channels used into the private work data */ 	/* will only be actually used if we're not doing AC3 passthru */-	pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown);+    pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);      pv->level     = 32768.0; Index: libhb/muxogm.c===================================================================--- libhb/muxogm.c	(revision 1364)+++ libhb/muxogm.c	(working copy)@@ -135,9 +135,9 @@     {         audio                 = hb_list_item( title->list_audio, i );         mux_data              = malloc( sizeof( hb_mux_data_t ) );-        mux_data->codec       = job->acodec;+        mux_data->codec       = audio->config.out.codec;         mux_data->i_packet_no = 0;-        audio->mux_data       = mux_data;+        audio->priv.mux_data       = mux_data;         ogg_stream_init( &mux_data->os, i + 1 );     } @@ -200,9 +200,9 @@     for( i = 0; i < hb_list_count( title->list_audio ); i++ )     {         audio   = hb_list_item( title->list_audio, i );-        mux_data = audio->mux_data;+        mux_data = audio->priv.mux_data;         memset( &h, 0, sizeof( ogg_stream_header_t ) );-        switch( job->acodec )+        switch( audio->config.out.codec )         {             case HB_ACODEC_LAME:             {@@ -212,7 +212,7 @@                  SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1);                 SetQWLE( &h.i_time_unit, 0 );-                SetQWLE( &h.i_samples_per_unit, job->arate );+                SetQWLE( &h.i_samples_per_unit, audio->config.out.samplerate );                 SetDWLE( &h.i_default_len, 1 );                 SetDWLE( &h.i_buffer_size, 30 * 1024 );                 SetWLE ( &h.i_bits_per_sample, 0 );@@ -220,7 +220,7 @@                 SetDWLE( &h.header.audio.i_channels, 2 );                 SetDWLE( &h.header.audio.i_block_align, 0 );                 SetDWLE( &h.header.audio.i_avgbytespersec,-                         job->abitrate / 8 );+                         audio->config.out.bitrate / 8 );                  op.packet   = (unsigned char*) &h;                 op.bytes    = sizeof( ogg_stream_header_t );@@ -233,9 +233,9 @@             }             case HB_ACODEC_VORBIS:             {-                memcpy( &op, audio->config.vorbis.headers[0],+                memcpy( &op, audio->priv.config.vorbis.headers[0],                         sizeof( ogg_packet ) );-                op.packet = audio->config.vorbis.headers[0] ++                op.packet = audio->priv.config.vorbis.headers[0] +                                 sizeof( ogg_packet );                 ogg_stream_packetin( &mux_data->os, &op );                 break;@@ -275,16 +275,16 @@     for( i = 0; i < hb_list_count( title->list_audio ); i++ )     {         audio = hb_list_item( title->list_audio, i );-        if( job->acodec == HB_ACODEC_VORBIS )+        if( audio->config.out.codec == HB_ACODEC_VORBIS )         {             int       j;-            mux_data = audio->mux_data;+            mux_data = audio->priv.mux_data;              for( j = 1; j < 3; j++ )             {-                memcpy( &op, audio->config.vorbis.headers[j],+                memcpy( &op, audio->priv.config.vorbis.headers[j],                         sizeof( ogg_packet ) );-                op.packet = audio->config.vorbis.headers[j] ++                op.packet = audio->priv.config.vorbis.headers[j] +                                 sizeof( ogg_packet );                 ogg_stream_packetin( &mux_data->os, &op ); @@ -387,7 +387,7 @@     for( i = 0; i < hb_list_count( title->list_audio ); i++ )     {         audio = hb_list_item( title->list_audio, i );-        mux_data = audio->mux_data;+        mux_data = audio->priv.mux_data;         if( OGMFlush( m, mux_data ) < 0 )         {             return -1;Index: libhb/sync.c===================================================================--- libhb/sync.c	(revision 1364)+++ libhb/sync.c	(working copy)@@ -130,6 +130,7 @@     hb_work_private_t * pv = w->private_data;     hb_job_t          * job   = pv->job;     hb_title_t        * title = job->title;+    hb_audio_t        * audio = NULL;      int i; @@ -144,8 +145,8 @@                               pv->sync_audio[i].start_silence) / 90), i );         } -        if( job->acodec & HB_ACODEC_AC3 ||-            job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+        audio = hb_list_item( title->list_audio, i );+        if( audio->config.out.codec == HB_ACODEC_AC3 )         {             free( pv->sync_audio[i].ac3_buf );         }@@ -207,8 +208,7 @@     sync        = &pv->sync_audio[i];     sync->audio = hb_list_item( title->list_audio, i ); -    if( job->acodec & HB_ACODEC_AC3 ||-        job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+    if( sync->audio->config.out.codec == HB_ACODEC_AC3 )     {         /* Have a silent AC-3 frame ready in case we have to fill a            gap */@@ -219,9 +219,9 @@         codec = avcodec_find_encoder( CODEC_ID_AC3 );         c     = avcodec_alloc_context(); -        c->bit_rate    = sync->audio->bitrate;-        c->sample_rate = sync->audio->rate;-        c->channels    = 2;+        c->bit_rate    = sync->audio->config.in.bitrate;+        c->sample_rate = sync->audio->config.in.samplerate;+        c->channels    = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( sync->audio->config.in.channel_layout );          if( avcodec_open( c, codec ) < 0 )         {@@ -231,8 +231,8 @@          zeros          = calloc( AC3_SAMPLES_PER_FRAME *                                  sizeof( short ) * c->channels, 1 );-        sync->ac3_size = sync->audio->bitrate * AC3_SAMPLES_PER_FRAME /-                             sync->audio->rate / 8;+        sync->ac3_size = sync->audio->config.in.bitrate * AC3_SAMPLES_PER_FRAME /+                             sync->audio->config.in.samplerate / 8;         sync->ac3_buf  = malloc( sync->ac3_size );          if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,@@ -249,7 +249,7 @@     {         /* Initialize libsamplerate */         int error;-        sync->state             = src_new( SRC_LINEAR, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown), &error );+        sync->state             = src_new( SRC_LINEAR, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->config.out.mixdown), &error );         sync->data.end_of_input = 0;     } }@@ -432,9 +432,9 @@                              * Subtitle is on for less than three seconds, extend                              * the time that it is displayed to make it easier                              * to read. Make it 3 seconds or until the next-                             * subtitle is displayed. +                             * subtitle is displayed.                              *-                             * This is in response to Indochine which only +                             * This is in response to Indochine which only                              * displays subs for 1 second - too fast to read.                              */                             sub->stop = sub->start + ( 3 * 90000 );@@ -558,22 +558,22 @@ {     int64_t start = sync->next_start;     int64_t duration = buf->stop - buf->start;-    if (duration <= 0 || -        duration > ( 90000 * AC3_SAMPLES_PER_FRAME ) / audio->rate )+    if (duration <= 0 ||+        duration > ( 90000 * AC3_SAMPLES_PER_FRAME ) / audio->config.out.samplerate )     {         hb_log("sync: audio %d weird duration %lld, start %lld, stop %lld, next %lld",                i, duration, buf->start, buf->stop, sync->next_pts);         if ( duration <= 0 )         {-            duration = ( 90000 * AC3_SAMPLES_PER_FRAME ) / audio->rate;+            duration = ( 90000 * AC3_SAMPLES_PER_FRAME ) / audio->config.out.samplerate;             buf->stop = buf->start + duration;         }     }     sync->next_pts += duration;      if( /* audio->rate == job->arate || This should work but doesn't */-        job->acodec & HB_ACODEC_AC3 ||-        job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+        audio->config.out.codec == HB_ACODEC_AC3 ||+        audio->config.out.codec == HB_ACODEC_DCA )     {         /*          * If we don't have to do sample rate conversion or this audio is AC3@@ -586,11 +586,11 @@         /* Not pass-thru - do sample rate conversion */         int count_in, count_out;         hb_buffer_t * buf_raw = buf;-        int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) *+        int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) *                             sizeof( float );          count_in  = buf_raw->size / channel_count;-        count_out = ( buf_raw->stop - buf_raw->start ) * job->arate / 90000;+        count_out = ( buf_raw->stop - buf_raw->start ) * audio->config.out.samplerate / 90000;          sync->data.input_frames = count_in;         sync->data.output_frames = count_out;@@ -630,19 +630,18 @@     hb_fifo_t       * fifo;     int               rate; -    if( job->acodec & HB_ACODEC_AC3 ||-        job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+    if( audio->config.out.codec == HB_ACODEC_AC3 )     {-        fifo = audio->fifo_out;-        rate = audio->rate;+        fifo = audio->priv.fifo_out;+        rate = audio->config.in.samplerate;     }     else     {-        fifo = audio->fifo_sync;-        rate = job->arate;+        fifo = audio->priv.fifo_sync;+        rate = audio->config.out.samplerate;     } -    while( !hb_fifo_is_full( fifo ) && ( buf = hb_fifo_see( audio->fifo_raw ) ) )+    while( !hb_fifo_is_full( fifo ) && ( buf = hb_fifo_see( audio->priv.fifo_raw ) ) )     {         if ( sync->next_pts - buf->start > 500 )         {@@ -656,7 +655,7 @@                 sync->first_drop = buf->start;             }             ++sync->drop_count;-            buf = hb_fifo_get( audio->fifo_raw );+            buf = hb_fifo_get( audio->priv.fifo_raw );             hb_buffer_close( &buf );             continue;         }@@ -711,13 +710,13 @@          * audio stream and are ready to inject the next input frame into          * the output stream.          */-        buf = hb_fifo_get( audio->fifo_raw );+        buf = hb_fifo_get( audio->priv.fifo_raw );         OutputAudioFrame( job, audio, buf, sync, fifo, i );     }      if( NeedSilence( w, audio, i ) )     {-        InsertSilence( w, i, (90000 * AC3_SAMPLES_PER_FRAME) / sync->audio->rate );+        InsertSilence( w, i, (90000 * AC3_SAMPLES_PER_FRAME) / sync->audio->config.out.samplerate );     } } @@ -727,10 +726,10 @@     hb_job_t * job = pv->job;     hb_sync_audio_t * sync = &pv->sync_audio[i]; -    if( hb_fifo_size( audio->fifo_in ) ||-        hb_fifo_size( audio->fifo_raw ) ||-        hb_fifo_size( audio->fifo_sync ) ||-        hb_fifo_size( audio->fifo_out ) )+    if( hb_fifo_size( audio->priv.fifo_in ) ||+        hb_fifo_size( audio->priv.fifo_raw ) ||+        hb_fifo_size( audio->priv.fifo_sync ) ||+        hb_fifo_size( audio->priv.fifo_out ) )     {         /* We have some audio, we are fine */         return 0;@@ -759,22 +758,22 @@     hb_sync_audio_t *sync = &pv->sync_audio[i];     hb_buffer_t     *buf; -    if( job->acodec & HB_ACODEC_AC3 || job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+    if( sync->audio->config.out.codec == HB_ACODEC_AC3 )     {         buf        = hb_buffer_init( sync->ac3_size );         buf->start = sync->next_pts;         buf->stop  = buf->start + duration;         memcpy( buf->data, sync->ac3_buf, buf->size );-        OutputAudioFrame( job, sync->audio, buf, sync, sync->audio->fifo_out, i );+        OutputAudioFrame( job, sync->audio, buf, sync, sync->audio->priv.fifo_out, i );     }     else     {         buf = hb_buffer_init( duration * sizeof( float ) *-                    HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown) );+                    HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->config.out.mixdown) );         buf->start = sync->next_pts;         buf->stop  = buf->start + duration;         memset( buf->data, 0, buf->size );-        OutputAudioFrame( job, sync->audio, buf, sync, sync->audio->fifo_sync, i );+        OutputAudioFrame( job, sync->audio, buf, sync, sync->audio->priv.fifo_sync, i );     } } Index: libhb/encfaac.c===================================================================--- libhb/encfaac.c	(revision 1364)+++ libhb/encfaac.c	(working copy)@@ -45,6 +45,7 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job ) {     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );+    hb_audio_t * audio = w->audio;     faacEncConfigurationPtr cfg;     uint8_t * bytes;     unsigned long length;@@ -54,9 +55,9 @@     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->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); -    pv->faac = faacEncOpen( job->arate, pv->out_discrete_channels, &pv->input_samples,+    pv->faac = faacEncOpen( audio->config.out.samplerate, pv->out_discrete_channels, &pv->input_samples,                            &pv->output_bytes );     pv->buf  = malloc( pv->input_samples * sizeof( float ) ); @@ -74,12 +75,12 @@ 	}      cfg->useTns        = 0;-    cfg->bitRate       = job->abitrate * 1000 / pv->out_discrete_channels; /* Per channel */+    cfg->bitRate       = audio->config.out.bitrate * 1000 / pv->out_discrete_channels; /* Per channel */     cfg->bandWidth     = 0;     cfg->outputFormat  = 0;     cfg->inputFormat   =  FAAC_INPUT_FLOAT; -	if (w->amixdown == HB_AMIXDOWN_6CH && w->source_acodec == HB_ACODEC_AC3)+    if (audio->config.out.mixdown == HB_AMIXDOWN_6CH && audio->config.in.codec == 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@@ -140,6 +141,7 @@ static hb_buffer_t * Encode( hb_work_object_t * w ) {     hb_work_private_t * pv = w->private_data;+    hb_audio_t * audio = w->audio;     hb_buffer_t * buf;     uint64_t      pts, pos; @@ -153,8 +155,8 @@                       &pts, &pos );      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->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate;+    buf->stop  = buf->start + 90000 * pv->input_samples / audio->config.out.samplerate / 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;Index: libhb/muxcommon.c===================================================================--- libhb/muxcommon.c	(revision 1364)+++ libhb/muxcommon.c	(working copy)@@ -98,7 +98,7 @@         for( i = 0; i < hb_list_count( title->list_audio ); i++ )         {             audio = hb_list_item( title->list_audio, i );-            if( !hb_fifo_size( audio->fifo_out ) )+            if( !hb_fifo_size( audio->priv.fifo_out ) )             {                 ready = 0;                 break;@@ -131,8 +131,8 @@     {         audio           = hb_list_item( title->list_audio, i );         track           = calloc( sizeof( hb_track_t ), 1 );-        track->fifo     = audio->fifo_out;-        track->mux_data = audio->mux_data;+        track->fifo     = audio->priv.fifo_out;+        track->mux_data = audio->priv.mux_data;         hb_list_add( list, track );     } Index: libhb/work.c===================================================================--- libhb/work.c	(revision 1364)+++ libhb/work.c	(working copy)@@ -337,57 +337,55 @@         }     } -    if( job->audio_mixdowns[0] == HB_AMIXDOWN_AC3 || job->audio_mixdowns[1] == HB_AMIXDOWN_AC3 )-    {-        /* Hard set correct sample rate for AC3 when libhb-           mistakenly thinks the audio codec is AAC */-        job->arate = 48000;-    }--    if( job->acodec & HB_ACODEC_AC3 )-    {-        hb_log( " + audio AC3 passthrough" );--        /* Hard set correct sample rate for AC3 */-        job->arate = 48000;-    }-    else-    {-        hb_log( " + audio %d kbps, %d Hz", job->abitrate, job->arate );-        hb_log( " + encoder %s", ( job->acodec & HB_ACODEC_FAAC ) ?-                "faac" : ( ( job->acodec & HB_ACODEC_LAME ) ? "lame" :-                "vorbis" ) );-    }--    if ( job->dynamic_range_compression > 1 )-        hb_log(" + dynamic range compression: %f", job->dynamic_range_compression);--    /* if we are doing AC3 passthru (at the codec level, not pass-through),-     * then remove any non-AC3 audios from the job */+    /* if we are doing passthru, and the input codec is not the same as the output+     * codec, then remove this audio from the job */     /* otherwise, Bad Things will happen */     for( i = 0; i < hb_list_count( title->list_audio ); )     {         audio = hb_list_item( title->list_audio, i );-        if( ( job->acodec & HB_ACODEC_AC3 ) && ( audio->codec != HB_ACODEC_AC3 ) )+        if( ( ( audio->config.out.codec == HB_ACODEC_AC3 ) && ( audio->config.in.codec != HB_ACODEC_AC3 ) ) ||+            ( ( audio->config.out.codec == HB_ACODEC_DCA ) && ( audio->config.in.codec != HB_ACODEC_DCA ) ) )         {+            hb_log( "Passthru requested and input codec is not the same as output codec for track %d",+                    audio->config.out.track );             hb_list_rem( title->list_audio, audio );             free( audio );             continue;         }-        i++;+        /* Adjust output track number, in case we removed one.+         * Output tracks sadly still need to be in sequential order.+         */+        audio->config.out.track = i++;     }      for( i = 0; i < hb_list_count( title->list_audio ); i++ )     {         audio = hb_list_item( title->list_audio, i );-        hb_log( "   + %x, %s", audio->id, audio->lang );+        hb_log( " + audio track %d", audio->config.out.track );+        hb_log( "   + input track %d", audio->config.in.track );+        if( (audio->config.out.codec == HB_ACODEC_AC3) || (audio->config.out.codec == HB_ACODEC_DCA) )+        {+            hb_log( "   + %s passthrough", (audio->config.out.codec == HB_ACODEC_AC3) ?+                "AC3" : "DCA" );+        }+        else+        {+            hb_log( "   + audio %d kbps, %d Hz", audio->config.out.bitrate, audio->config.out.samplerate );+            hb_log( "   + encoder %s", ( audio->config.out.codec == HB_ACODEC_FAAC ) ?+            "faac" : ( ( audio->config.out.codec == HB_ACODEC_LAME ) ? "lame" :+            "vorbis" ) );+            if ( audio->config.out.dynamic_range_compression > 1 )+                hb_log("   + dynamic range compression: %f", audio->config.out.dynamic_range_compression);+        } +        hb_log( "     + %x, %s", audio->id, audio->config.lang.description );+ 		/* sense-check the current mixdown options */  		/* log the requested mixdown */ 		for (j = 0; j < hb_audio_mixdowns_count; j++) {-			if (hb_audio_mixdowns[j].amixdown == job->audio_mixdowns[i]) {-				hb_log( "     + Requested mixdown: %s (%s)", hb_audio_mixdowns[j].human_readable_name, hb_audio_mixdowns[j].internal_name );+			if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) {+				hb_log( "       + Requested mixdown: %s (%s)", hb_audio_mixdowns[j].human_readable_name, hb_audio_mixdowns[j].internal_name ); 				break; 			} 		}@@ -396,33 +394,22 @@          /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,            but this may change in the future, so they are separated for flexibility */-        int audioCodecsSupportMono = ((audio->codec == HB_ACODEC_AC3 ||-            audio->codec == HB_ACODEC_DCA) && (job->acodec == HB_ACODEC_FAAC || job->acodec == HB_ACODEC_VORBIS));-        int audioCodecsSupport6Ch =  ((audio->codec == HB_ACODEC_AC3 ||-            audio->codec == HB_ACODEC_DCA) && (job->acodec == HB_ACODEC_FAAC || job->acodec == HB_ACODEC_VORBIS));+        int audioCodecsSupportMono = ( (audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA) &&+            (audio->config.out.codec == HB_ACODEC_FAAC || audio->config.out.codec == HB_ACODEC_VORBIS) );+        int audioCodecsSupport6Ch =  ( (audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA) &&+            (audio->config.out.codec == HB_ACODEC_FAAC || audio->config.out.codec == HB_ACODEC_VORBIS)); -        if( audio->codec != HB_ACODEC_AC3 && job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )-        {-            /*-             * Sanity check that we haven't asked for AC3 from a non AC3 track - drop this track-             * to stereo to avoid a crash later.-             */-            job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO;-        }--        if( job->audio_mixdowns[i] != HB_AMIXDOWN_AC3 )-        {         /* find out what the format of our source audio is */-        switch (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK) {+        switch (audio->config.in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK) {              /* mono sources */             case HB_INPUT_CH_LAYOUT_MONO:                 /* regardless of what stereo mixdown we've requested, a mono source always get mixed down                 to mono if we can, and mixed up to stereo if we can't */-                if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_MONO;+                if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) {+                    audio->config.out.mixdown = HB_AMIXDOWN_MONO;                 } else {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO;+                    audio->config.out.mixdown = HB_AMIXDOWN_STEREO;                 }                 break; @@ -430,11 +417,11 @@             case HB_INPUT_CH_LAYOUT_STEREO:                 /* if we've requested a mono mixdown, and it is supported, then do the mix */                 /* use stereo if not supported */-                if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO;+                if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {+                    audio->config.out.mixdown = HB_AMIXDOWN_STEREO;                 /* otherwise, preserve stereo regardless of if we requested something higher */-                } else if (job->audio_mixdowns[i] > HB_AMIXDOWN_STEREO) {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO;+                } else if (audio->config.out.mixdown > HB_AMIXDOWN_STEREO) {+                    audio->config.out.mixdown = HB_AMIXDOWN_STEREO;                 }                 break; @@ -444,12 +431,12 @@             case HB_INPUT_CH_LAYOUT_DOLBY:                 /* if we've requested a mono mixdown, and it is supported, then do the mix */                 /* preserve dolby if not supported */-                if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBY;+                if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {+                    audio->config.out.mixdown = HB_AMIXDOWN_DOLBY;                 /* otherwise, preserve dolby even if we requested something higher */                 /* a stereo mixdown will still be honoured here */-                } else if (job->audio_mixdowns[i] > HB_AMIXDOWN_DOLBY) {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBY;+                } else if (audio->config.out.mixdown > HB_AMIXDOWN_DOLBY) {+                    audio->config.out.mixdown = HB_AMIXDOWN_DOLBY;                 }                 break; @@ -457,21 +444,21 @@             case HB_INPUT_CH_LAYOUT_3F2R:                 /* if we've requested a mono mixdown, and it is supported, then do the mix */                 /* use dpl2 if not supported */-                if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBYPLII;+                if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {+                    audio->config.out.mixdown = HB_AMIXDOWN_DOLBYPLII;                 } else {                     /* check if we have 3F2R input and also have an LFE - i.e. we have a 5.1 source) */-                    if (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE) {+                    if (audio->config.in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE) {                         /* we have a 5.1 source */                         /* if we requested 6ch, but our audio format doesn't support it, then mix to DPLII instead */-                        if (job->audio_mixdowns[i] == HB_AMIXDOWN_6CH && audioCodecsSupport6Ch == 0) {-                            job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBYPLII;+                        if (audio->config.out.mixdown == HB_AMIXDOWN_6CH && audioCodecsSupport6Ch == 0) {+                            audio->config.out.mixdown = HB_AMIXDOWN_DOLBYPLII;                         }                     } else {                         /* we have a 5.0 source, so we can't do 6ch conversion                         default to DPL II instead */-                        if (job->audio_mixdowns[i] > HB_AMIXDOWN_DOLBYPLII) {-                            job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBYPLII;+                        if (audio->config.out.mixdown > HB_AMIXDOWN_DOLBYPLII) {+                            audio->config.out.mixdown = HB_AMIXDOWN_DOLBYPLII;                         }                     }                 }@@ -482,13 +469,13 @@             case HB_INPUT_CH_LAYOUT_3F1R:                 /* if we've requested a mono mixdown, and it is supported, then do the mix */                 /* use dpl1 if not supported */-                if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBY;+                if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {+                    audio->config.out.mixdown = HB_AMIXDOWN_DOLBY;                 } else {                     /* we have a 4.0 or 4.1 source, so we can't do DPLII or 6ch conversion                     default to DPL I instead */-                    if (job->audio_mixdowns[i] > HB_AMIXDOWN_DOLBY) {-                        job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBY;+                    if (audio->config.out.mixdown > HB_AMIXDOWN_DOLBY) {+                        audio->config.out.mixdown = HB_AMIXDOWN_DOLBY;                     }                 }                 /* all other mixdowns will have been preserved here */@@ -496,41 +483,37 @@              default:                 /* if we've requested a mono mixdown, and it is supported, then do the mix */-                if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_MONO;+                if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) {+                    audio->config.out.mixdown = HB_AMIXDOWN_MONO;                 /* mix everything else down to stereo */                 } else {-                    job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO;+                    audio->config.out.mixdown = HB_AMIXDOWN_STEREO;                 }          }-        }  		/* log the output mixdown */ 		for (j = 0; j < hb_audio_mixdowns_count; j++) {-			if (hb_audio_mixdowns[j].amixdown == job->audio_mixdowns[i]) {-				hb_log( "     + Actual mixdown: %s (%s)", hb_audio_mixdowns[j].human_readable_name, hb_audio_mixdowns[j].internal_name );+			if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) {+				hb_log( "       + Actual mixdown: %s (%s)", hb_audio_mixdowns[j].human_readable_name, hb_audio_mixdowns[j].internal_name ); 				break; 			} 		} -		/* we now know we have a valid mixdown for the input source and the audio output format */-		/* remember the mixdown for this track */-		audio->amixdown = job->audio_mixdowns[i];+        if (audio->config.out.codec == HB_ACODEC_VORBIS)+            audio->priv.config.vorbis.language = audio->config.lang.simple; -        audio->config.vorbis.language = audio->lang_simple;-         /* set up the audio work structures */-        audio->fifo_in   = hb_fifo_init( 2048 );-        audio->fifo_raw  = hb_fifo_init( FIFO_CPU_MULT * cpu_count );-        audio->fifo_sync = hb_fifo_init( FIFO_CPU_MULT * cpu_count );-        audio->fifo_out  = hb_fifo_init( FIFO_CPU_MULT * cpu_count );+        audio->priv.fifo_in   = hb_fifo_init( 2048 );+        audio->priv.fifo_raw  = hb_fifo_init( FIFO_CPU_MULT * cpu_count );+        audio->priv.fifo_sync = hb_fifo_init( FIFO_CPU_MULT * cpu_count );+        audio->priv.fifo_out  = hb_fifo_init( FIFO_CPU_MULT * cpu_count );           /*          * Audio Decoder Thread          */-        switch( audio->codec )+        switch( audio->config.in.codec )         {             case HB_ACODEC_AC3:                 w = getWork( WORK_DECA52 );@@ -544,12 +527,16 @@             case HB_ACODEC_LPCM:                 w = getWork( WORK_DECLPCM );                 break;+            default:+                /* Invalid input codec */+                hb_error("Invalid input codec: %d", audio->config.in.codec);+                *job->die = 1;+                goto cleanup;         }-        w->fifo_in       = audio->fifo_in;-        w->fifo_out      = audio->fifo_raw;-        w->config        = &audio->config;-        w->amixdown      = audio->amixdown;-        w->source_acodec = audio->codec;+        w->fifo_in       = audio->priv.fifo_in;+        w->fifo_out      = audio->priv.fifo_raw;+        w->config        = &audio->priv.config;+        w->audio         = audio;          /* FIXME: This feels really hackish, anything better? */         audio_w = calloc( sizeof( hb_work_object_t ), 1 );@@ -560,10 +547,8 @@         /*          * Audio Encoder Thread          */-        if( job->audio_mixdowns[i] != HB_AMIXDOWN_AC3 )+        switch( audio->config.out.codec )         {-            switch( job->acodec )-            {             case HB_ACODEC_FAAC:                 w = getWork( WORK_ENCFAAC );                 break;@@ -573,20 +558,25 @@             case HB_ACODEC_VORBIS:                 w = getWork( WORK_ENCVORBIS );                 break;-            }+            case HB_ACODEC_AC3:+                break;+            case HB_ACODEC_DCA:    /* These are all invalid output codecs. */+            default:+                hb_error("Invalid audio codec: %#x", audio->config.out.codec);+                w = NULL;+                *job->die = 1;+                goto cleanup;         } -        if( job->acodec != HB_ACODEC_AC3 &&-            job->audio_mixdowns[i] != HB_AMIXDOWN_AC3)+        if( audio->config.out.codec != HB_ACODEC_AC3 )         {             /*              * Add the encoder thread if not doing AC-3 pass through              */-            w->fifo_in       = audio->fifo_sync;-            w->fifo_out      = audio->fifo_out;-            w->config        = &audio->config;-            w->amixdown      = audio->amixdown;-            w->source_acodec = audio->codec;+            w->fifo_in       = audio->priv.fifo_sync;+            w->fifo_out      = audio->priv.fifo_out;+            w->config        = &audio->priv.config;+            w->audio         = audio;              /* FIXME: This feels really hackish, anything better? */             audio_w = calloc( sizeof( hb_work_object_t ), 1 );@@ -640,12 +630,16 @@     w->close( w );     job->done = 1; +cleanup:     /* Close work objects */     while( ( w = hb_list_item( job->list_work, 0 ) ) )     {         hb_list_rem( job->list_work, w );-        hb_thread_close( &w->thread );-        w->close( w );+        if( w != NULL && w->thread != NULL )+        {+            hb_thread_close( &w->thread );+            w->close( w );+        }          /* FIXME: This feels really hackish, anything better? */         if ( w->id == WORK_DECA52 ||@@ -663,8 +657,10 @@     hb_list_close( &job->list_work );      /* Stop read & write threads */-    hb_thread_close( &job->reader );-    hb_thread_close( &job->muxer );+    if( job->reader != NULL )+        hb_thread_close( &job->reader );+    if( job->muxer != NULL )+        hb_thread_close( &job->muxer );      /* Close fifos */     hb_fifo_close( &job->fifo_mpeg2 );@@ -684,10 +680,14 @@     for( i = 0; i < hb_list_count( title->list_audio ); i++ )     {         audio = hb_list_item( title->list_audio, i );-        hb_fifo_close( &audio->fifo_in );-        hb_fifo_close( &audio->fifo_raw );-        hb_fifo_close( &audio->fifo_sync );-        hb_fifo_close( &audio->fifo_out );+        if( audio->priv.fifo_in != NULL )+            hb_fifo_close( &audio->priv.fifo_in );+        if( audio->priv.fifo_raw != NULL )+            hb_fifo_close( &audio->priv.fifo_raw );+        if( audio->priv.fifo_sync != NULL )+            hb_fifo_close( &audio->priv.fifo_sync );+        if( audio->priv.fifo_out != NULL )+            hb_fifo_close( &audio->priv.fifo_out );     }      if( job->indepth_scan )Index: libhb/scan.c===================================================================--- libhb/scan.c	(revision 1364)+++ libhb/scan.c	(working copy)@@ -147,8 +147,8 @@ 			for( j = 0; j < hb_list_count( title->list_audio ); ) 			{ 				audio = hb_list_item( title->list_audio, j );-				if( audio->codec == HB_ACODEC_AC3 &&-					!audio->bitrate )+				if( audio->config.in.codec == HB_ACODEC_AC3 &&+                    !audio->config.in.bitrate ) 				{ 					hb_list_rem( title->list_audio, audio ); 					free( audio );@@ -162,11 +162,11 @@         for( j = 0; j < hb_list_count( title->list_audio ); )         {             audio = hb_list_item( title->list_audio, j );-            if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) &&-                !audio->bitrate )+            if( ( audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA ) &&+                !audio->config.in.bitrate )             {                 hb_log( "scan: removing audio with codec of 0x%x because of no bitrate",-                    audio->codec );+                        audio->config.in.codec );                 hb_list_rem( title->list_audio, audio );                 free( audio );                 continue;@@ -188,9 +188,9 @@         for( j = 0; j < hb_list_count( title->list_audio ); j++ )         {             audio = hb_list_item( title->list_audio, j );-            if( audio->codec == HB_ACODEC_LPCM || audio->codec == HB_ACODEC_MPGA )+            if( audio->config.in.codec == HB_ACODEC_LPCM || audio->config.in.codec == HB_ACODEC_MPGA )             {-                audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;+                audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;             }         } @@ -247,13 +247,8 @@         job->vrate      = title->rate;         job->vrate_base = title->rate_base; -        job->audios[0] = 0;-        job->audios[1] = -1;+        job->list_audio = hb_list_init(); -        job->acodec   = HB_ACODEC_FAAC;-        job->abitrate = 128;-        job->arate    = 44100;-         job->subtitle = -1;          job->mux = HB_MUX_MP4;@@ -451,14 +446,14 @@         }          buf_raw = hb_list_item( list_raw, 0 );-        +         /* Check preview for interlacing artifacts */         if( hb_detect_comb( buf_raw, title->width, title->height, 10, 30, 9 ) )         {             hb_log("Interlacing detected in preview frame %i", i);             interlaced_preview_count++;         }-        +         hb_get_tempory_filename( data->h, filename, "%x%d",                                  (intptr_t)title, i ); @@ -584,7 +579,7 @@     {         audio = hb_list_item( title->list_audio, i );         /* check if we have an AC3 or DCA which we recognise */-        if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) &&+        if( ( audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA ) &&             audio->id    == b->id )         {             break;@@ -599,7 +594,7 @@         return;     } -    if( audio->bitrate )+    if( audio->config.in.bitrate )     {         /* Already done for this track */         return;@@ -608,78 +603,77 @@     for( i = 0; i < b->size - 7; i++ )     { -        if ( audio->codec == HB_ACODEC_AC3 )+        if ( audio->config.in.codec == HB_ACODEC_AC3 )         {              /* check for a52 */             if( a52_syncinfo( &b->data[i], &flags, &rate, &bitrate ) )             {                 hb_log( "scan: AC3, rate=%dHz, bitrate=%d", rate, bitrate );-                audio->rate    = rate;-                audio->bitrate = bitrate;+                audio->config.in.samplerate = rate;+                audio->config.in.bitrate = bitrate;                 switch( flags & A52_CHANNEL_MASK )                 {                     /* mono sources */                     case A52_MONO:                     case A52_CHANNEL1:                     case A52_CHANNEL2:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_MONO;                         break;                     /* stereo input */                     case A52_CHANNEL:                     case A52_STEREO:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;                         break;                     /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */                     case A52_DOLBY:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_DOLBY;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_DOLBY;                         break;                     /* 3F/2R input */                     case A52_3F2R:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F2R;                         break;                     /* 3F/1R input */                     case A52_3F1R:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F1R;                         break;                     /* other inputs */                     case A52_3F:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F;                         break;                     case A52_2F1R:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F1R;                         break;                     case A52_2F2R:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F2R;                         break;                     /* unknown */                     default:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;                 }                  /* add in our own LFE flag if the source has LFE */                 if (flags & A52_LFE)                 {-                    audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;+                    audio->config.in.channel_layout = audio->config.in.channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;                 }                  /* store the AC3 flags for future reference-                This enables us to find out if we had a stereo or Dolby source later on */-                audio->config.a52.ac3flags = flags;+                 * This enables us to find out if we had a stereo or Dolby source later on+                 * Store the ac3 flags in the public ac3flags property too, so we can access it from the GUI+                 */+                audio->config.flags.ac3 = audio->priv.config.a52.ac3flags = flags; -                /* store the ac3 flags in the public ac3flags property too, so we can access it from the GUI */-                audio->ac3flags = audio->config.a52.ac3flags;-                 /* XXX */                 if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY ) {-                    sprintf( audio->lang + strlen( audio->lang ),+                    sprintf( audio->config.lang.description + strlen( audio->config.lang.description ),                          " (Dolby Surround)" );                 } else {-                    sprintf( audio->lang + strlen( audio->lang ),+                    sprintf( audio->config.lang.description + strlen( audio->config.lang.description ),                          " (%d.%d ch)",-                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) +-                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout),-                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout));+                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->config.in.channel_layout) ++                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->config.in.channel_layout),+                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->config.in.channel_layout));                 }                  break;@@ -687,7 +681,7 @@             }          }-        else if ( audio->codec == HB_ACODEC_DCA )+        else if ( audio->config.in.codec == HB_ACODEC_DCA )         {              hb_log( "scan: checking for DCA syncinfo" );@@ -697,70 +691,69 @@             if( dca_syncinfo( state, &b->data[i], &flags, &rate, &bitrate, &frame_length ) )             {                 hb_log( "scan: DCA, rate=%dHz, bitrate=%d", rate, bitrate );-                audio->rate    = rate;-                audio->bitrate = bitrate;+                audio->config.in.samplerate    = rate;+                audio->config.in.bitrate = bitrate;                 switch( flags & DCA_CHANNEL_MASK )                 {                     /* mono sources */                     case DCA_MONO:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_MONO;                         break;                     /* stereo input */                     case DCA_CHANNEL:                     case DCA_STEREO:                     case DCA_STEREO_SUMDIFF:                     case DCA_STEREO_TOTAL:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;                         break;                     /* 3F/2R input */                     case DCA_3F2R:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F2R;                         break;                     /* 3F/1R input */                     case DCA_3F1R:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F1R;                         break;                     /* other inputs */                     case DCA_3F:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F;                         break;                     case DCA_2F1R:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F1R;                         break;                     case DCA_2F2R:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F2R;                         break;                     case DCA_4F2R:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_4F2R;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_4F2R;                         break;                     /* unknown */                     default:-                        audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;+                        audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;                 }                  /* add in our own LFE flag if the source has LFE */                 if (flags & DCA_LFE)                 {-                    audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;+                    audio->config.in.channel_layout = audio->config.in.channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;                 }                  /* store the DCA flags for future reference-                This enables us to find out if we had a stereo or Dolby source later on */-                audio->config.dca.dcaflags = flags;+                 * This enables us to find out if we had a stereo or Dolby source later on+                 * store the dca flags in the public dcaflags property too, so we can access it from the GUI+                 */+                audio->config.flags.dca = audio->priv.config.dca.dcaflags = flags; -                /* store the dca flags in the public dcaflags property too, so we can access it from the GUI */-                audio->dcaflags = audio->config.dca.dcaflags;-                 /* XXX */                 if ( (flags & DCA_CHANNEL_MASK) == DCA_DOLBY ) {-                    sprintf( audio->lang + strlen( audio->lang ),+                    sprintf( audio->config.lang.description + strlen( audio->config.lang.description ),                          " (Dolby Surround)" );                 } else {-                    sprintf( audio->lang + strlen( audio->lang ),+                    sprintf( audio->config.lang.description + strlen( audio->config.lang.description ),                          " (%d.%d ch)",-                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) +-                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout),-                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout));+                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->config.in.channel_layout) ++                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->config.in.channel_layout),+                        HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->config.in.channel_layout));                 }                  break;@@ -778,8 +771,8 @@     for( i = 0; i < hb_list_count( title->list_audio ); i++ )     {         audio = hb_list_item( title->list_audio, i );-        if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) &&-            !audio->bitrate )+        if( ( audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA ) &&+            !audio->config.in.bitrate )         {             return 0;         }Index: libhb/muxmkv.c===================================================================--- libhb/muxmkv.c	(revision 1364)+++ libhb/muxmkv.c	(working copy)@@ -29,6 +29,7 @@     mk_Track  * track;     uint64_t  prev_chapter_tc;     uint16_t  current_chapter;+    int       codec; };  /**********************************************************************@@ -158,9 +159,11 @@     {         audio = hb_list_item( title->list_audio, i );         mux_data = malloc( sizeof( hb_mux_data_t ) );-        audio->mux_data = mux_data;+        audio->priv.mux_data = mux_data; -        switch (job->acodec)+        mux_data->codec = audio->config.out.codec;++        switch (audio->config.out.codec)         {             case HB_ACODEC_AC3:                 track->codecPrivate = NULL;@@ -180,8 +183,8 @@                     uint64_t  header_sizes[3];                     for (i = 0; i < 3; ++i)                     {-                        ogg_headers[i] = (ogg_packet *)audio->config.vorbis.headers[i];-                        ogg_headers[i]->packet = (unsigned char *)&audio->config.vorbis.headers[i] + sizeof( ogg_packet );+                        ogg_headers[i] = (ogg_packet *)audio->priv.config.vorbis.headers[i];+                        ogg_headers[i]->packet = (unsigned char *)&audio->priv.config.vorbis.headers[i] + sizeof( ogg_packet );                         header_sizes[i] = ogg_headers[i]->bytes;                     }                     track->codecPrivate = mk_laceXiph(header_sizes, 2, &cp_size);@@ -195,22 +198,13 @@                 }                 break;             case HB_ACODEC_FAAC:-                if( job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )-                {-                    track->codecPrivate = NULL;-                    track->codecPrivateSize = 0;-                    track->codecID = MK_ACODEC_AC3;-                }-                else-                {-                    track->codecPrivate = audio->config.aac.bytes;-                    track->codecPrivateSize = audio->config.aac.length;-                    track->codecID = MK_ACODEC_AAC;-                }+                track->codecPrivate = audio->priv.config.aac.bytes;+                track->codecPrivateSize = audio->priv.config.aac.length;+                track->codecID = MK_ACODEC_AAC;                 break;             default:                 *job->die = 1;-                hb_error("muxmkv: Unknown audio codec: %x", job->acodec);+                hb_error("muxmkv: Unknown audio codec: %x", audio->config.out.codec);                 return 0;         } @@ -221,12 +215,12 @@         }         track->flagEnabled = 1;         track->trackType = MK_TRACK_AUDIO;-        track->language = audio->iso639_2;-        track->extra.audio.samplingFreq = (float)job->arate;-        track->extra.audio.channels = (job->acodec == HB_ACODEC_AC3 || job->audio_mixdowns[i] == HB_AMIXDOWN_AC3  ) ? HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->input_channel_layout) : HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown);+        track->language = audio->config.lang.iso639_2;+        track->extra.audio.samplingFreq = (float)audio->config.out.samplerate;+        track->extra.audio.channels = (audio->config.out.codec == HB_ACODEC_AC3 ) ? HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout) : HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); //        track->defaultDuration = job->arate * 1000;         mux_data->track = mk_createTrack(m->file, track);-        if (job->acodec == HB_ACODEC_VORBIS && track->codecPrivate != NULL)+        if (audio->config.out.codec == HB_ACODEC_VORBIS && track->codecPrivate != NULL)           free(track->codecPrivate);     } @@ -308,7 +302,7 @@     {         /* Audio */         timecode = buf->start * TIMECODE_SCALE;-        if (job->acodec == HB_ACODEC_VORBIS)+        if (mux_data->codec == HB_ACODEC_VORBIS)         {             /* ughhh, vorbis is a pain :( */             op = (ogg_packet *)buf->data;Index: libhb/common.c===================================================================--- libhb/common.c	(revision 1364)+++ libhb/common.c	(working copy)@@ -7,6 +7,7 @@ #include <stdarg.h> #include <time.h> #include <sys/time.h>+#include <assert.h>  #include "common.h" @@ -43,9 +44,7 @@   { "Stereo",             "HB_AMIXDOWN_STEREO",    "stereo", HB_AMIXDOWN_STEREO    },   { "Dolby Surround",     "HB_AMIXDOWN_DOLBY",     "dpl1",   HB_AMIXDOWN_DOLBY     },   { "Dolby Pro Logic II", "HB_AMIXDOWN_DOLBYPLII", "dpl2",   HB_AMIXDOWN_DOLBYPLII },-  { "6-channel discrete", "HB_AMIXDOWN_6CH",       "6ch",    HB_AMIXDOWN_6CH       },-  { "AC-3 Pass-through",  "HB_AMIXDOWN_AC3",       "ac-3",   HB_AMIXDOWN_AC3       },-  { "Dolby Pro Logic II + AC-3",  "HB_AMIXDOWN_DOLBYPLII_AC3", "dpl2+ac3", HB_AMIXDOWN_DOLBYPLII_AC3 },+  { "6-channel discrete", "HB_AMIXDOWN_6CH",       "6ch",    HB_AMIXDOWN_6CH       } }; int hb_audio_mixdowns_count = sizeof( hb_audio_mixdowns ) /                               sizeof( hb_mixdown_t );@@ -115,7 +114,7 @@     if ( title->height == 0 || title->width == 0 || title->aspect == 0 )     {         hb_log( "hb_fix_aspect: incomplete info for title %d: "-                "height = %d, width = %d, aspect = %d", +                "height = %d, width = %d, aspect = %d",                 title->height, title->width, title->aspect );         return;     }@@ -202,23 +201,6 @@             return 0;     } -    /* How many audio samples we put in each frame */-    switch( job->acodec )-    {-        case HB_ACODEC_FAAC:-        case HB_ACODEC_VORBIS:-            samples_per_frame = 1024;-            break;-        case HB_ACODEC_LAME:-            samples_per_frame = 1152;-            break;-        case HB_ACODEC_AC3:-            samples_per_frame = 1536;-            break;-        default:-            return 0;-    }-     /* Get the duration in seconds */     length = 0;     for( i = job->chapter_start; i <= job->chapter_end; i++ )@@ -232,19 +214,37 @@     /* Video overhead */     avail -= length * job->vrate * overhead / job->vrate_base; -    for( i = 0; job->audios[i] >= 0; i++ )+    for( i = 0; i < hb_list_count(job->list_audio); i++ )     {         /* Audio data */         int abitrate;-        if( job->acodec & HB_ACODEC_AC3 ||-            job->audio_mixdowns[i] == HB_AMIXDOWN_AC3)+        audio = hb_list_item( job->list_audio, i);++        /* How many audio samples we put in each frame */+        switch( audio->config.out.codec )         {+            case HB_ACODEC_FAAC:+            case HB_ACODEC_VORBIS:+                samples_per_frame = 1024;+                break;+            case HB_ACODEC_LAME:+                samples_per_frame = 1152;+                break;+            case HB_ACODEC_AC3:+                samples_per_frame = 1536;+                break;+            default:+                return 0;+        }++        if( audio->config.out.codec == HB_ACODEC_AC3 ||+            audio->config.out.codec == HB_ACODEC_DCA)+        {             /*-             * For AC-3 we take the bitrate from the input audio+             * For pass through we take the bitrate from the input audio              * bitrate as we are simply passing it through.              */-            audio = hb_list_item( title->list_audio, job->audios[i] );-            abitrate = audio->bitrate / 8;+            abitrate = audio->config.in.bitrate / 8;         }         else         {@@ -252,12 +252,12 @@              * Where we are transcoding the audio we use the destination              * bitrate.              */-            abitrate = job->abitrate * 1000 / 8;+            abitrate = audio->config.out.bitrate * 1000 / 8;         }         avail -= length * abitrate;          /* Audio overhead */-        avail -= length * job->arate * overhead / samples_per_frame;+        avail -= length * audio->config.out.samplerate * overhead / samples_per_frame;     }      if( avail < 0 )@@ -654,3 +654,91 @@     *_f = NULL; } +/**********************************************************************+ * hb_audio_copy+ **********************************************************************+ *+ *********************************************************************/+hb_audio_t *hb_audio_copy(const hb_audio_t *src)+{+    hb_audio_t *audio = calloc(1, sizeof(*audio));+    memcpy(audio, src, sizeof(*audio));+    return audio;+}++/**********************************************************************+ * hb_audio_new+ **********************************************************************+ *+ *********************************************************************/+void hb_audio_config_init(hb_audio_config_t * audiocfg)+{+    /* Set read only paramaters to invalid values */+    audiocfg->in.codec = 0xDEADBEEF;+    audiocfg->in.bitrate = -1;+    audiocfg->in.samplerate = -1;+    audiocfg->in.channel_layout = 0;+    audiocfg->flags.ac3 = 0;+    audiocfg->lang.description[0] = 0;+    audiocfg->lang.simple[0] = 0;+    audiocfg->lang.iso639_2[0] = 0;++    /* Initalize some sensable defaults */+    audiocfg->in.track = audiocfg->out.track = 0;+    audiocfg->out.codec = HB_ACODEC_FAAC;+    audiocfg->out.bitrate = 128;+    audiocfg->out.samplerate = 44100;+    audiocfg->out.mixdown = HB_AMIXDOWN_DOLBYPLII;+    audiocfg->out.dynamic_range_compression = 0;+}++/**********************************************************************+ * hb_audio_add+ **********************************************************************+ *+ *********************************************************************/+int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg)+{+    assert(job != NULL);+    assert(audiocfg != NULL);++    hb_title_t *title = job->title;+    hb_audio_t *audio;++    audio = hb_audio_copy( hb_list_item( title->list_audio, audiocfg->in.track ) );+    if( audio == NULL )+    {+        /* We fail! */+        return 0;+    }++    if( (audiocfg->in.bitrate != -1) && (audiocfg->in.codec != 0xDEADBEEF) )+    {+        /* This most likely means the client didn't call hb_audio_config_init+         * so bail.+         */+        return 0;+    }++    /* Really shouldn't ignore the passed out track, but there is currently no+     * way to handle duplicates or out-of-order track numbers.+     */+    audio->config.out.track = hb_list_count(job->list_audio) + 1;+    audio->config.out.codec = audiocfg->out.codec;+    audio->config.out.samplerate = audiocfg->out.samplerate;+    audio->config.out.bitrate = audiocfg->out.bitrate;+    audio->config.out.mixdown = audiocfg->out.mixdown;+    audio->config.out.dynamic_range_compression = audiocfg->out.dynamic_range_compression;++    hb_list_add(job->list_audio, audio);+    return 1;+}++hb_audio_config_t * hb_list_audio_config_item(hb_list_t * list, int i)+{+    assert(list != NULL);++    hb_audio_t *audio = hb_list_item(list, i);++    return &(audio->config);+}Index: libhb/encvorbis.c===================================================================--- libhb/encvorbis.c	(revision 1364)+++ libhb/encvorbis.c	(working copy)@@ -44,13 +44,14 @@  int encvorbisInit( hb_work_object_t * w, hb_job_t * job ) {+    hb_audio_t * audio = w->audio;     int i;     ogg_packet header[3];     struct ovectl_ratemanage2_arg  ctl_rate_arg;      hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );     w->private_data = pv;-    pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown);+    pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);      pv->job   = job; @@ -58,17 +59,18 @@      /* 28kbps/channel seems to be the minimum for 6ch vorbis. */     int min_bitrate = 28 * pv->out_discrete_channels;-    if (pv->out_discrete_channels > 2 && job->abitrate < min_bitrate)+    if (pv->out_discrete_channels > 2 && audio->config.out.bitrate < min_bitrate)     {-        hb_log( "encvorbis: Selected bitrate (%d kbps) too low for %d channel audio.", job->abitrate, pv->out_discrete_channels);+        hb_log( "encvorbis: Selected bitrate (%d kbps) too low for %d channel audio.", audio->config.out.bitrate, pv->out_discrete_channels);         hb_log( "encvorbis: Resetting bitrate to %d kbps", min_bitrate);-        job->abitrate = min_bitrate;+        /* Naughty! We shouldn't modify the audio from here. */+        audio->config.out.bitrate = min_bitrate;     }      /* init */     vorbis_info_init( &pv->vi );     if( vorbis_encode_setup_managed( &pv->vi, pv->out_discrete_channels,-          job->arate, -1, 1000 * job->abitrate, -1 ) )+          audio->config.out.samplerate, -1, 1000 * audio->config.out.bitrate, -1 ) )     {         hb_error( "encvorbis: vorbis_encode_setup_managed failed.\n" );         *job->die = 1;@@ -80,7 +82,7 @@         hb_log( "encvorbis: vorbis_encode_ctl( ratemanage2_get ) failed" );     } -    ctl_rate_arg.bitrate_average_kbps = job->abitrate;+    ctl_rate_arg.bitrate_average_kbps = audio->config.out.bitrate;     ctl_rate_arg.management_active = 1;      if( vorbis_encode_ctl( &pv->vi, OV_ECTL_RATEMANAGE2_SET, &ctl_rate_arg ) ||Index: libhb/common.h===================================================================--- libhb/common.h	(revision 1364)+++ libhb/common.h	(working copy)@@ -39,6 +39,7 @@ typedef struct hb_title_s hb_title_t; typedef struct hb_chapter_s hb_chapter_t; typedef struct hb_audio_s hb_audio_t;+typedef struct hb_audio_config_s hb_audio_config_t; typedef struct hb_subtitle_s hb_subtitle_t; typedef struct hb_state_s hb_state_t; typedef union  hb_esconfig_u     hb_esconfig_t;@@ -53,6 +54,9 @@ #include "ports.h" #ifdef __LIBHB__ #include "internal.h"+#define PRIVATE+#else+#define PRIVATE const #endif  hb_list_t * hb_list_init();@@ -70,6 +74,11 @@  int hb_calc_bitrate( hb_job_t *, int size ); +hb_audio_t *hb_audio_copy(const hb_audio_t *src);+void hb_audio_config_init(hb_audio_config_t * audiocfg);+int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg);+hb_audio_config_t * hb_list_audio_config_item(hb_list_t * list, int i);+ struct hb_rate_s {     char * string;@@ -175,77 +184,9 @@     int             areBframes;     int             vfr; -    /* Audio tracks:-         audios:          Indexes in hb_title_t's audios list, starting from 0.-                          -1 indicates the end of the list-        audio_mixdowns:  The mixdown to be used for each audio track in audios[] */+    /* List of audio settings. */+    hb_list_t     * list_audio; -/* define some masks, used to extract the various information from the HB_AMIXDOWN_XXXX values */-#define HB_AMIXDOWN_DCA_FORMAT_MASK             0x00FFF000-#define HB_AMIXDOWN_A52_FORMAT_MASK             0x00000FF0-#define HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK 0x0000000F--/* define the HB_AMIXDOWN_XXXX values */--#define HB_AMIXDOWN_MONO                        0x01000001-// DCA_FORMAT of DCA_MONO                  = 0    = 0x000-// A52_FORMAT of A52_MONO                  = 1    = 0x01-// discrete channel count of 1--#define HB_AMIXDOWN_STEREO                      0x02002022-// DCA_FORMAT of DCA_STEREO                = 2    = 0x002-// A52_FORMAT of A52_STEREO                = 2    = 0x02-// discrete channel count of 2--#define HB_AMIXDOWN_DOLBY                       0x042070A2-// DCA_FORMAT of DCA_3F1R | DCA_OUT_DPLI   = 519  = 0x207-// A52_FORMAT of A52_DOLBY                 = 10   = 0x0A-// discrete channel count of 2--#define HB_AMIXDOWN_DOLBYPLII                   0x084094A2-// DCA_FORMAT of DCA_3F2R | DCA_OUT_DPLII  = 1033 = 0x409-// A52_FORMAT of A52_DOLBY | A52_USE_DPLII = 74   = 0x4A-// discrete channel count of 2--#define HB_AMIXDOWN_6CH                         0x10089176-// DCA_FORMAT of DCA_3F2R | DCA_LFE        = 137  = 0x089-// A52_FORMAT of A52_3F2R | A52_LFE        = 23   = 0x17-// discrete channel count of 6--#define HB_AMIXDOWN_AC3                         0x20000000--#define HB_AMIXDOWN_DOLBYPLII_AC3               0x404094A2-// DCA_FORMAT of DCA_3F2R | DCA_OUT_DPLII  = 1033 = 0x409-// A52_FORMAT of A52_DOLBY | A52_USE_DPLII = 74   = 0x4A-// discrete channel count of 2--/* define some macros to extract the various information from the HB_AMIXDOWN_XXXX values */-#define HB_AMIXDOWN_GET_DCA_FORMAT( a ) ( ( a & HB_AMIXDOWN_DCA_FORMAT_MASK ) >> 12 )-#define HB_AMIXDOWN_GET_A52_FORMAT( a ) ( ( a & HB_AMIXDOWN_A52_FORMAT_MASK ) >> 4 )-#define HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT( a ) ( ( a & HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK ) )--    int             audios[8];-	int             audio_mixdowns[8];--    /* Audio settings:-         acodec:   output codec-         abitrate: output bitrate (kbps)-         arate:    output samplerate (Hz)-       HB_ACODEC_AC3 means pass-through, then abitrate and arate are-       ignored */-#define HB_ACODEC_MASK   0x00FF00-#define HB_ACODEC_FAAC   0x000100-#define HB_ACODEC_LAME   0x000200-#define HB_ACODEC_VORBIS 0x000400-#define HB_ACODEC_AC3    0x000800-#define HB_ACODEC_MPGA   0x001000-#define HB_ACODEC_LPCM   0x002000-#define HB_ACODEC_DCA    0x004000-    int             acodec;-    int             abitrate;-    int             arate;-    float           dynamic_range_compression;-     /* Subtitle settings:          subtitle: index in hb_title_t's subtitles list, starting          from 0. -1 means no subtitle */@@ -300,22 +241,49 @@ #endif }; -struct hb_audio_s-{-    int  id;-    char lang[1024];-    char lang_simple[1024];-    char iso639_2[4];-    int  codec;-    int  rate;-    int  bitrate;+/* Audio starts here */+/* Audio Codecs */+#define HB_ACODEC_MASK   0x00FF00+#define HB_ACODEC_FAAC   0x000100+#define HB_ACODEC_LAME   0x000200+#define HB_ACODEC_VORBIS 0x000400+#define HB_ACODEC_AC3    0x000800+#define HB_ACODEC_MPGA   0x001000+#define HB_ACODEC_LPCM   0x002000+#define HB_ACODEC_DCA    0x004000 -    /* ac3flags is only set when the source audio format is HB_ACODEC_AC3 */-    int ac3flags;+/* Audio Mixdown */+/* define some masks, used to extract the various information from the HB_AMIXDOWN_XXXX values */+#define HB_AMIXDOWN_DCA_FORMAT_MASK             0x00FFF000+#define HB_AMIXDOWN_A52_FORMAT_MASK             0x00000FF0+#define HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK 0x0000000F+/* define the HB_AMIXDOWN_XXXX values */+#define HB_AMIXDOWN_MONO                        0x01000001+// DCA_FORMAT of DCA_MONO                  = 0    = 0x000+// A52_FORMAT of A52_MONO                  = 1    = 0x01+// discrete channel count of 1+#define HB_AMIXDOWN_STEREO                      0x02002022+// DCA_FORMAT of DCA_STEREO                = 2    = 0x002+// A52_FORMAT of A52_STEREO                = 2    = 0x02+// discrete channel count of 2+#define HB_AMIXDOWN_DOLBY                       0x042070A2+// DCA_FORMAT of DCA_3F1R | DCA_OUT_DPLI   = 519  = 0x207+// A52_FORMAT of A52_DOLBY                 = 10   = 0x0A+// discrete channel count of 2+#define HB_AMIXDOWN_DOLBYPLII                   0x084094A2+// DCA_FORMAT of DCA_3F2R | DCA_OUT_DPLII  = 1033 = 0x409+// A52_FORMAT of A52_DOLBY | A52_USE_DPLII = 74   = 0x4A+// discrete channel count of 2+#define HB_AMIXDOWN_6CH                         0x10089176+// DCA_FORMAT of DCA_3F2R | DCA_LFE        = 137  = 0x089+// A52_FORMAT of A52_3F2R | A52_LFE        = 23   = 0x17+// discrete channel count of 6+/* define some macros to extract the various information from the HB_AMIXDOWN_XXXX values */+#define HB_AMIXDOWN_GET_DCA_FORMAT( a ) ( ( a & HB_AMIXDOWN_DCA_FORMAT_MASK ) >> 12 )+#define HB_AMIXDOWN_GET_A52_FORMAT( a ) ( ( a & HB_AMIXDOWN_A52_FORMAT_MASK ) >> 4 )+#define HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT( a ) ( ( a & HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK ) ) -    /* dcaflags is only set when the source audio format is HB_ACODEC_DCA */-    int dcaflags;-+/* Input Channel Layout */ /* define some masks, used to extract the various information from the HB_AMIXDOWN_XXXX values */ #define HB_INPUT_CH_LAYOUT_DISCRETE_FRONT_MASK  0x00F0000 #define HB_INPUT_CH_LAYOUT_DISCRETE_REAR_MASK   0x000F000@@ -323,7 +291,6 @@ #define HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK 0xFFFF0FF #define HB_INPUT_CH_LAYOUT_ENCODED_FRONT_MASK   0x00000F0 #define HB_INPUT_CH_LAYOUT_ENCODED_REAR_MASK    0x000000F- /* define the input channel layouts used to describe the channel layout of this audio */ #define HB_INPUT_CH_LAYOUT_MONO    0x0110010 #define HB_INPUT_CH_LAYOUT_STEREO  0x0220020@@ -335,7 +302,6 @@ #define HB_INPUT_CH_LAYOUT_3F2R    0x0832032 #define HB_INPUT_CH_LAYOUT_4F2R    0x0942042 #define HB_INPUT_CH_LAYOUT_HAS_LFE 0x0000100- /* define some macros to extract the various information from the HB_AMIXDOWN_XXXX values */ #define HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT( a ) ( ( a & HB_INPUT_CH_LAYOUT_DISCRETE_FRONT_MASK ) >> 16 ) #define HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT( a )  ( ( a & HB_INPUT_CH_LAYOUT_DISCRETE_REAR_MASK ) >> 12 )@@ -344,24 +310,68 @@ #define HB_INPUT_CH_LAYOUT_GET_ENCODED_FRONT_COUNT( a )   ( ( a & HB_INPUT_CH_LAYOUT_ENCODED_FRONT_MASK ) >> 4 ) #define HB_INPUT_CH_LAYOUT_GET_ENCODED_REAR_COUNT( a )   ( ( a & HB_INPUT_CH_LAYOUT_ENCODED_REAR_MASK ) ) -	/* input_channel_layout is the channel layout of this audio */-	/* this is used to provide a common way of describing the source audio */-	int input_channel_layout;+struct hb_audio_config_s+{+    /* Output */+    struct+    {+            int track;      /* Output track number */+            uint32_t codec;  /* Output audio codec.+                                 * HB_ACODEC_AC3 means pass-through, then bitrate and samplerate+                                 * are ignored.+                                 */+            int samplerate; /* Output sample rate (Hz) */+            int bitrate;    /* Output bitrate (kbps) */+            int mixdown;    /* The mixdown format to be used for this audio track (see HB_AMIXDOWN_*) */+            double dynamic_range_compression; /* Amount of DRC that gets applied to this track */+    } out; +    /* Input */+    struct+    {+                int track;      /* Input track number */+        PRIVATE uint32_t codec;      /* Input audio codec */+        PRIVATE int samplerate; /* Input sample rate (Hz) */+        PRIVATE int bitrate;    /* Input bitrate (kbps) */+        PRIVATE int channel_layout;+        /* channel_layout is the channel layout of this audio this is used to+        * provide a common way of describing the source audio+        */+    } in;++    /* Misc. */+    union+    {+        PRIVATE int ac3;    /* flags.ac3 is only set when the source audio format is HB_ACODEC_AC3 */+        PRIVATE int dca;    /* flags.dca is only set when the source audio format is HB_ACODEC_DCA */+    } flags;++    struct+    {+        PRIVATE char description[1024];+        PRIVATE char simple[1024];+        PRIVATE char iso639_2[4];+    } lang;+};+ #ifdef __LIBHB__-    /* Internal data */-    hb_fifo_t * fifo_in;   /* AC3/MPEG/LPCM ES */-    hb_fifo_t * fifo_raw;  /* Raw audio */-    hb_fifo_t * fifo_sync; /* Resampled, synced raw audio */-    hb_fifo_t * fifo_out;  /* MP3/AAC/Vorbis ES */+struct hb_audio_s+{+    int id; -    hb_esconfig_t config;-    hb_mux_data_t * mux_data;+    hb_audio_config_t config; -	/* amixdown is the mixdown format to be used for this audio track */-   	int amixdown;+    struct {+        hb_fifo_t * fifo_in;   /* AC3/MPEG/LPCM ES */+        hb_fifo_t * fifo_raw;  /* Raw audio */+        hb_fifo_t * fifo_sync; /* Resampled, synced raw audio */+        hb_fifo_t * fifo_out;  /* MP3/AAC/Vorbis ES */++        hb_esconfig_t config;+        hb_mux_data_t * mux_data;+    } priv;+}; #endif-};  struct hb_chapter_s {@@ -506,10 +516,8 @@     hb_fifo_t         * fifo_out;     hb_esconfig_t     * config; -	/* amixdown is the mixdown format to be used if the work object is an audio track */-   	int               amixdown;-    /* source_acodec is the source audio codec if the work object is an audio track */-    int               source_acodec;+    /* Pointer hb_audio_t so we have access to the info in the audio worker threads. */+    hb_audio_t *audio;      hb_work_private_t * private_data; Index: macosx/HBQueueController.h===================================================================--- macosx/HBQueueController.h	(revision 1364)+++ macosx/HBQueueController.h	(working copy)@@ -106,6 +106,8 @@     int                         crf;     NSString                    *x264opts; +    NSString                    *audioinfo_codecs;+    NSString                    *audioinfo_summary;  //<-hack to use a string to display all audio info for each job in one string     int                         audio_mixdowns[8];     int                         acodec;     int                         abitrate;Index: macosx/Controller.mm===================================================================--- macosx/Controller.mm	(revision 1364)+++ macosx/Controller.mm	(working copy)@@ -1467,7 +1467,7 @@     hb_title_t * title = (hb_title_t *) hb_list_item( list,             [fSrcTitlePopUp indexOfSelectedItem] );     hb_job_t * job = title->job;-    //int i;+    hb_audio_config_t * audio;      /* Chapter selection */     job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;@@ -1478,7 +1478,8 @@     int codecs = [fDstCodecsPopUp indexOfSelectedItem];     job->mux    = FormatSettings[format][codecs] & HB_MUX_MASK;     job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;-    job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;++     /* If mpeg-4, then set mpeg-4 specific options like chapters and > 4gb file sizes */ 	if ([fDstFormatPopUp indexOfSelectedItem] == 0) 	{@@ -1594,67 +1595,119 @@     job->subtitle = [fSubPopUp indexOfSelectedItem] - 2;      /* Audio tracks and mixdowns */-    /* check for the condition where track 2 has an audio selected, but track 1 does not */-    /* we will use track 2 as track 1 in this scenario */-    if ([fAudLang1PopUp indexOfSelectedItem] > 0)+    /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/+    for( int i = 0; i < hb_list_count(job->list_audio);i++)     {-        job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;-        job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1; /* will be -1 if "none" is selected */-        job->audios[2] = -1;-        job->audio_mixdowns[0] = [[fAudTrack1MixPopUp selectedItem] tag];-        job->audio_mixdowns[1] = [[fAudTrack2MixPopUp selectedItem] tag];+        hb_audio_t * temp_audio = (hb_audio_t*) hb_list_item( job->list_audio, 0 );+        hb_list_rem(job->list_audio, temp_audio);     }-    else if ([fAudLang2PopUp indexOfSelectedItem] > 0)+    /* Now lets add our new tracks to the audio list here */+    if ([fAudLang1PopUp indexOfSelectedItem] > 0)     {-        job->audios[0] = [fAudLang2PopUp indexOfSelectedItem] - 1;-        job->audio_mixdowns[0] = [[fAudTrack2MixPopUp selectedItem] tag];-        job->audios[1] = -1;+        /* First we copy the source audio structure (remember, in the popup 0 is "None" so we subtract 1 to match the list->audio*/+        //audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, [fAudLang1PopUp indexOfSelectedItem] - 1);+        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));+        hb_audio_config_init(audio);++        /* We go ahead and assign values to our audio->out.<properties> */+        audio->out.track = [fAudLang1PopUp indexOfSelectedItem] - 1;+        if ([[fAudTrack1MixPopUp titleOfSelectedItem] isEqualToString: @"AC3 Passthru"])+        {+        audio->out.codec = HB_ACODEC_AC3;+        audio->out.mixdown = HB_ACODEC_AC3;+        audio->out.bitrate = audio->in.bitrate / 1000; // we use the audio.in bitrate for passthru, / 1000 so it displays right.+        audio->out.samplerate = 48000;+        audio->out.dynamic_range_compression = 1.00;+        }+        else+        {+        audio->out.codec = FormatSettings[format][codecs] & HB_ACODEC_MASK;+        audio->out.mixdown = [[fAudTrack1MixPopUp selectedItem] tag];+        audio->out.bitrate = [[fAudBitratePopUp selectedItem] tag];+        audio->out.samplerate = hb_audio_rates[[fAudRatePopUp indexOfSelectedItem]].rate;+        audio->out.dynamic_range_compression = [fAudDrcField floatValue];+        }++        /* We add the newly modified audio track to job->list_audio */+        //hb_list_add(job->list_audio, audio );+        hb_audio_add( job, audio );+        free(audio);++        /*HACK: We use the format and codecs popups to determine if we should slide in the extra ac3 passthru track for the atv hybrid mp4 */+        if (format == 0 && codecs == 2 && audio->in.codec != HB_ACODEC_DCA) // if mp4 and aac + ac3 and input is NOT DTS (dts cannot be passed through as ac3)+        {+            //audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, [fAudLang1PopUp indexOfSelectedItem] - 1 );+            audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));+            hb_audio_config_init(audio);++            /* We go ahead and assign values to our audio->out.<properties> */+            audio->out.track = [fAudLang1PopUp indexOfSelectedItem] - 1;+            audio->out.codec = HB_ACODEC_AC3;+            audio->out.codec = HB_ACODEC_AC3;+            audio->out.samplerate = 48000;+            audio->out.bitrate = audio->in.bitrate / 1000; // we use the audio.in bitrate for passthru, / 1000 do it displays right.+            audio->out.mixdown = HB_ACODEC_AC3;//<-- Lets manually set the mixdown int+            audio->out.dynamic_range_compression = 1.00;+            /* We add the newly modified audio track to job->list_audio */+            //hb_list_add(job->list_audio, audio );+            hb_audio_add( job, audio );+            free(audio);+        }+     }-    else+    if ([fAudLang2PopUp indexOfSelectedItem] > 0)     {-        job->audios[0] = -1;-    }+        /* First we copy the source audio structure (remember, in the popup 0 is "None" so we subtract 1 to match the list->audio*/+        //audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, [fAudLang2PopUp indexOfSelectedItem] - 1 );+        /* Now we modify it according to the gui settings for the specified track number */+        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));+        hb_audio_config_init(audio); -    /*-     * Where one or more of the audio tracks has a mixdown of DPLII+AC3 we need to create an extra-     * track for each.-     */-    if (job->audio_mixdowns[0] == HB_AMIXDOWN_DOLBYPLII_AC3)-    {-        /*-         * Make space for the AC3 track by moving 1 to 2-         */-        job->audios[2] = job->audios[1];-        job->audio_mixdowns[2] = job->audio_mixdowns[1];-        job->audios[1] = job->audios[0];-        job->audio_mixdowns[0] = HB_AMIXDOWN_DOLBYPLII;-        job->audio_mixdowns[1] = HB_AMIXDOWN_AC3;-    }+        /* We go ahead and assign values to our audio->out.<properties> */+        audio->out.track = [fAudLang2PopUp indexOfSelectedItem] - 1;+        if ([[fAudTrack2MixPopUp titleOfSelectedItem] isEqualToString: @"AC3 Passthru"])+        {+        audio->out.codec = HB_ACODEC_AC3;+        audio->out.mixdown = HB_ACODEC_AC3;+        audio->out.bitrate = audio->in.bitrate / 1000; // we use the audio.in bitrate for passthru, / 1000 so it displays right.+        audio->out.samplerate = 48000;+        }+        else+        {+        audio->out.codec = FormatSettings[format][codecs] & HB_ACODEC_MASK;+        audio->out.mixdown = [[fAudTrack2MixPopUp selectedItem] tag];+        audio->out.bitrate = [[fAudBitratePopUp selectedItem] tag];+        audio->out.samplerate = hb_audio_rates[[fAudRatePopUp indexOfSelectedItem]].rate;+        }+        audio->out.dynamic_range_compression = [fAudDrcField floatValue];+        /* We add the newly modified audio track to job->list_audio */+        //hb_list_add(job->list_audio, audio );+        hb_audio_add( job, audio );+        free(audio); -    if (job->audio_mixdowns[1] == HB_AMIXDOWN_DOLBYPLII_AC3)-    {-        job->audios[2] = job->audios[1];-        job->audio_mixdowns[1] = HB_AMIXDOWN_DOLBYPLII;-        job->audio_mixdowns[2] = HB_AMIXDOWN_AC3;-        job->audios[3] = -1;-    }+        /*HACK: We use the format and codecs popups to determine if we should slide in the extra ac3 passthru track for the atv hybrid mp4 */+        if (format == 0 && codecs == 2 && audio->in.codec != HB_ACODEC_DCA) // if mp4 and aac + ac3 and input is NOT DTS (dts cannot be passed through as ac3)+        {+            //audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, [fAudLang2PopUp indexOfSelectedItem] - 1 );+            audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));+            hb_audio_config_init(audio); -    if (job->audio_mixdowns[2] == HB_AMIXDOWN_DOLBYPLII_AC3)-    {-        job->audios[3] = job->audios[2];-        job->audio_mixdowns[2] = HB_AMIXDOWN_DOLBYPLII;-        job->audio_mixdowns[3] = HB_AMIXDOWN_AC3;-        job->audios[4] = -1;+            /* We go ahead and assign values to our audio->out.<properties> */+            audio->out.track = [fAudLang2PopUp indexOfSelectedItem] - 1;+            audio->out.codec = HB_ACODEC_AC3;+            audio->out.codec = HB_ACODEC_AC3;+            audio->out.samplerate = 48000;+            audio->out.bitrate = audio->in.bitrate / 1000; // we use the audio.in bitrate for passthru, / 1000 so it displays right.+            audio->out.mixdown = HB_ACODEC_AC3;//<-- Lets manually set the mixdown int+            audio->out.dynamic_range_compression = [fAudDrcField floatValue];+            /* We add the newly modified audio track to job->list_audio */+            //hb_list_add(job->list_audio, audio );+            hb_audio_add( job, audio );+            free(audio);+        }     } -    /* Audio settings */-    job->arate = hb_audio_rates[[fAudRatePopUp-                     indexOfSelectedItem]].rate;-    job->abitrate = [[fAudBitratePopUp selectedItem] tag];     -    /* Dynamic Range Compression */-    job->dynamic_range_compression = [fAudDrcField floatValue];-         /* set vfr according to the Picture Window */     if ([fPictureController vfr])     {@@ -1785,16 +1838,16 @@      // Create a Queue Controller job group. Each job that we submit to libhb will also     // get added to the job group so that the queue can track the jobs.-    HBJobGroup * jobGroup = [HBJobGroup jobGroup];+   HBJobGroup * jobGroup = [HBJobGroup jobGroup];     // The job group can maintain meta data that libhb can not...-    [jobGroup setPresetName: [fPresetSelectedDisplay stringValue]];+   [jobGroup setPresetName: [fPresetSelectedDisplay stringValue]];      // Job groups require that each job within the group be assigned a unique id so     // that the queue can xref between itself and the private jobs that libhb     // maintains. The ID is composed a group id number and a "sequence" number. libhb     // does not use this id.-    static int jobGroupID = 0;-    jobGroupID++;+   static int jobGroupID = 0;+   jobGroupID++;          // A sequence number, starting at zero, is used to identifiy to each pass. This is     // used by the queue UI to determine if a pass if the first pass of an encode.@@ -2787,17 +2840,15 @@  - (IBAction) setEnabledStateOfAudioMixdownControls: (id) sender {-     /* enable/disable the mixdown text and popupbutton for audio track 1 */-    [fAudTrack1MixPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];-    [fAudTrack1MixLabel setTextColor: ([fAudLang1PopUp indexOfSelectedItem] == 0) ?-        [NSColor disabledControlTextColor] : [NSColor controlTextColor]];+        [fAudTrack1MixPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];+        [fAudTrack1MixLabel setTextColor: ([fAudLang1PopUp indexOfSelectedItem] == 0) ?+         [NSColor disabledControlTextColor] : [NSColor controlTextColor]]; -    /* enable/disable the mixdown text and popupbutton for audio track 2 */-    [fAudTrack2MixPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];-    [fAudTrack2MixLabel setTextColor: ([fAudLang2PopUp indexOfSelectedItem] == 0) ?-        [NSColor disabledControlTextColor] : [NSColor controlTextColor]];-+        /* enable/disable the mixdown text and popupbutton for audio track 2 */+        [fAudTrack2MixPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];+        [fAudTrack2MixLabel setTextColor: ([fAudLang2PopUp indexOfSelectedItem] == 0) ?+         [NSColor disabledControlTextColor] : [NSColor controlTextColor]]; }  - (IBAction) addAllAudioTracksToPopUp: (id) sender@@ -2807,15 +2858,15 @@     hb_title_t * title = (hb_title_t*)         hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] ); -	hb_audio_t * audio;+	hb_audio_config_t * audio;      [sender removeAllItems];     [sender addItemWithTitle: _( @"None" )];     for( int i = 0; i < hb_list_count( title->list_audio ); i++ )     {-        audio = (hb_audio_t *) hb_list_item( title->list_audio, i );+        audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, i );         [[sender menu] addItemWithTitle:-            [NSString stringWithCString: audio->lang]+            [NSString stringWithCString: audio->lang.description]             action: NULL keyEquivalent: @""];     }     [sender selectItemAtIndex: 0];@@ -2889,7 +2940,7 @@ #endif      /* pointer for the hb_audio_s struct we will use later on */-    hb_audio_t * audio;+    hb_audio_config_t * audio;      /* find out what the currently-selected output audio codec is */     int format = [fDstFormatPopUp indexOfSelectedItem];@@ -2900,11 +2951,11 @@     bool mp4AacAc3;     if (format == 0 && codecs == 2) // if mp4 and aac + ac3     {-    mp4AacAc3 = 1;+        mp4AacAc3 = 1;     }     else     {-    mp4AacAc3 = 0;+        mp4AacAc3 = 0;     }      /* pointer to this track's mixdown NSPopUpButton */@@ -2933,114 +2984,113 @@     {          /* get the audio */-        audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, thisAudioIndex );+        audio = (hb_audio_config_t *) hb_list_audio_config_item( fTitle->list_audio, thisAudioIndex );// Should "fTitle" be title and be setup ?         if (audio != NULL)         {              /* find out if our selected output audio codec supports mono and / or 6ch */             /* we also check for an input codec of AC3 or DCA,-               as they are the only libraries able to do the mixdown to mono / conversion to 6-ch */+             as they are the only libraries able to do the mixdown to mono / conversion to 6-ch */             /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,-               but this may change in the future, so they are separated for flexibility */-            int audioCodecsSupportMono = ((audio->codec == HB_ACODEC_AC3 ||-                audio->codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);-            int audioCodecsSupport6Ch =  ((audio->codec == HB_ACODEC_AC3 ||-                audio->codec == HB_ACODEC_DCA) && (acodec == HB_ACODEC_FAAC ||-                acodec == HB_ACODEC_VORBIS));+             but this may change in the future, so they are separated for flexibility */+            int audioCodecsSupportMono = ((audio->in.codec == HB_ACODEC_AC3 ||+                                           audio->in.codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);+            int audioCodecsSupport6Ch =  ((audio->in.codec == HB_ACODEC_AC3 ||+                                           audio->in.codec == HB_ACODEC_DCA) && (acodec == HB_ACODEC_FAAC ||+                                                                                 acodec == HB_ACODEC_VORBIS));              /* check for AC-3 passthru */-            if (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3)+            if (audio->in.codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3)             {             -                    [[mixdownPopUp menu] addItemWithTitle:-                        [NSString stringWithCString: "AC3 Passthru"]-                        action: NULL keyEquivalent: @""];+                [[mixdownPopUp menu] addItemWithTitle:+                 [NSString stringWithCString: "AC3 Passthru"]+                                               action: NULL keyEquivalent: @""];             }             else             {                  /* add the appropriate audio mixdown menuitems to the popupbutton */                 /* in each case, we set the new menuitem's tag to be the amixdown value for that mixdown,-                   so that we can reference the mixdown later */+                 so that we can reference the mixdown later */                  /* keep a track of the min and max mixdowns we used, so we can select the best match later */                 int minMixdownUsed = 0;                 int maxMixdownUsed = 0;                                  /* get the input channel layout without any lfe channels */-                int layout = audio->input_channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;+                int layout = audio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK; -                /* do we want to add a mono option? */-                if (!mp4AacAc3 && audioCodecsSupportMono == 1) {-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:-                        [NSString stringWithCString: hb_audio_mixdowns[0].human_readable_name]-                        action: NULL keyEquivalent: @""];-                    [menuItem setTag: hb_audio_mixdowns[0].amixdown];-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[0].amixdown;-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[0].amixdown);-                }+                    /* do we want to add a mono option? */+                    //if (!mp4AacAc3 && audioCodecsSupportMono == 1)+                    if (audioCodecsSupportMono == 1)+                    {+                        NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:+                                                [NSString stringWithCString: hb_audio_mixdowns[0].human_readable_name]+                                                                              action: NULL keyEquivalent: @""];+                        [menuItem setTag: hb_audio_mixdowns[0].amixdown];+                        if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[0].amixdown;+                        maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[0].amixdown);+                    } -                /* do we want to add a stereo option? */-                /* offer stereo if we have a mono source and non-mono-supporting codecs, as otherwise we won't have a mixdown at all */-                /* also offer stereo if we have a stereo-or-better source */-                if (((!mp4AacAc3 || audio->codec == HB_ACODEC_MPGA ||  audio->codec == HB_ACODEC_LPCM || audio->codec == HB_ACODEC_DCA) && ((layout == HB_INPUT_CH_LAYOUT_MONO && audioCodecsSupportMono == 0) || layout >= HB_INPUT_CH_LAYOUT_STEREO))) {-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:-                        [NSString stringWithCString: hb_audio_mixdowns[1].human_readable_name]-                        action: NULL keyEquivalent: @""];-                    [menuItem setTag: hb_audio_mixdowns[1].amixdown];-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[1].amixdown;-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[1].amixdown);-                }+                    /* do we want to add a stereo option? */+                    /* offer stereo if we have a mono source and non-mono-supporting codecs, as otherwise we won't have a mixdown at all */+                    /* also offer stereo if we have a stereo-or-better source */+                    //if (((!mp4AacAc3 || audio->in.codec == HB_ACODEC_MPGA ||  audio->in.codec == HB_ACODEC_LPCM || audio->in.codec == HB_ACODEC_DCA) && ((layout == HB_INPUT_CH_LAYOUT_MONO && audioCodecsSupportMono == 0) || layout >= HB_INPUT_CH_LAYOUT_STEREO)))+                    //if (((audio->in.codec == HB_ACODEC_MPGA ||  audio->in.codec == HB_ACODEC_LPCM || audio->in.codec == HB_ACODEC_DCA) && ((layout == HB_INPUT_CH_LAYOUT_MONO && audioCodecsSupportMono == 0) || layout >= HB_INPUT_CH_LAYOUT_STEREO)))+                    if ((layout == HB_INPUT_CH_LAYOUT_MONO && audioCodecsSupportMono == 0) || layout >= HB_INPUT_CH_LAYOUT_STEREO)+                    {+                        NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:+                                                [NSString stringWithCString: hb_audio_mixdowns[1].human_readable_name]+                                                                              action: NULL keyEquivalent: @""];+                        [menuItem setTag: hb_audio_mixdowns[1].amixdown];+                        if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[1].amixdown;+                        maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[1].amixdown);+                    } -                /* do we want to add a dolby surround (DPL1) option? */-                if (!mp4AacAc3 && (layout == HB_INPUT_CH_LAYOUT_3F1R || layout == HB_INPUT_CH_LAYOUT_3F2R || layout == HB_INPUT_CH_LAYOUT_DOLBY)) {-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:-                        [NSString stringWithCString: hb_audio_mixdowns[2].human_readable_name]-                        action: NULL keyEquivalent: @""];-                    [menuItem setTag: hb_audio_mixdowns[2].amixdown];-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[2].amixdown;-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[2].amixdown);-                }+                    /* do we want to add a dolby surround (DPL1) option? */+                    if (layout == HB_INPUT_CH_LAYOUT_3F1R || layout == HB_INPUT_CH_LAYOUT_3F2R || layout == HB_INPUT_CH_LAYOUT_DOLBY)+                    {+                        NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:+                                                [NSString stringWithCString: hb_audio_mixdowns[2].human_readable_name]+                                                                              action: NULL keyEquivalent: @""];+                        [menuItem setTag: hb_audio_mixdowns[2].amixdown];+                        if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[2].amixdown;+                        maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[2].amixdown);+                    } -                /* do we want to add a dolby pro logic 2 (DPL2) option? */-                if ((!mp4AacAc3 || audio->codec == HB_ACODEC_DCA) && layout == HB_INPUT_CH_LAYOUT_3F2R) {-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:-                        [NSString stringWithCString: hb_audio_mixdowns[3].human_readable_name]-                        action: NULL keyEquivalent: @""];-                    [menuItem setTag: hb_audio_mixdowns[3].amixdown];-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[3].amixdown;-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[3].amixdown);-                }+                    /* do we want to add a dolby pro logic 2 (DPL2) option? */+                    if (layout == HB_INPUT_CH_LAYOUT_3F2R)+                    {+                        NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:+                                                [NSString stringWithCString: hb_audio_mixdowns[3].human_readable_name]+                                                                              action: NULL keyEquivalent: @""];+                        [menuItem setTag: hb_audio_mixdowns[3].amixdown];+                        if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[3].amixdown;+                        maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[3].amixdown);+                    } -                /* do we want to add a 6-channel discrete option? */-                if (!mp4AacAc3 && (audioCodecsSupport6Ch == 1 && layout == HB_INPUT_CH_LAYOUT_3F2R && (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE))) {-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:-                        [NSString stringWithCString: hb_audio_mixdowns[4].human_readable_name]-                        action: NULL keyEquivalent: @""];-                    [menuItem setTag: hb_audio_mixdowns[4].amixdown];-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[4].amixdown;-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[4].amixdown);-                }+                    /* do we want to add a 6-channel discrete option? */+                    if (!mp4AacAc3 && (audioCodecsSupport6Ch == 1 && layout == HB_INPUT_CH_LAYOUT_3F2R && (audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE)))+                    {+                        NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:+                                                [NSString stringWithCString: hb_audio_mixdowns[4].human_readable_name]+                                                                              action: NULL keyEquivalent: @""];+                        [menuItem setTag: hb_audio_mixdowns[4].amixdown];+                        if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[4].amixdown;+                        maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[4].amixdown);+                    } -                /* do we want to add an AC-3 passthrough option? */-                if (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3) {-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:-                        [NSString stringWithCString: hb_audio_mixdowns[5].human_readable_name]-                        action: NULL keyEquivalent: @""];-                    [menuItem setTag: hb_audio_mixdowns[5].amixdown];-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[5].amixdown;-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[5].amixdown);-                }+                    /* do we want to add an AC-3 passthrough option? */+                    if (audio->in.codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3) {+                        NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:+                                                [NSString stringWithCString: hb_audio_mixdowns[5].human_readable_name]+                                                                              action: NULL keyEquivalent: @""];+                        [menuItem setTag: hb_audio_mixdowns[5].amixdown];+                        if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[5].amixdown;+                        maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[5].amixdown);+                    } -                /* do we want to add the DPLII+AC3 passthrough option? */-                if (mp4AacAc3 && audio->codec == HB_ACODEC_AC3) {-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:-                        [NSString stringWithCString: hb_audio_mixdowns[6].human_readable_name]-                        action: NULL keyEquivalent: @""];-                    [menuItem setTag: hb_audio_mixdowns[6].amixdown];-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[6].amixdown;-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[6].amixdown);-                }                 /* auto-select the best mixdown based on our saved mixdown preference */                                  /* for now, this is hard-coded to a "best" mixdown of HB_AMIXDOWN_DOLBYPLII */@@ -3095,9 +3145,7 @@         case HB_ACODEC_FAAC:             /* check if we have a 6ch discrete conversion in either audio track */             if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || -                [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || -                [[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_AC3 || -                [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_AC3)+                [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)             {                 /* FAAC is happy using our min bitrate of 32 kbps, even for 6ch */                 minbitrate = 32;@@ -3164,9 +3212,7 @@      /* select the default bitrate (but use 384 for 6-ch AAC) */     if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || -        [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH ||-        [[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_AC3 || -        [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_AC3)+        [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)     {         [fAudBitratePopUp selectItemWithTag: 384];     }Index: macosx/HandBrake.plist===================================================================--- macosx/HandBrake.plist	(revision 1364)+++ macosx/HandBrake.plist	(working copy)@@ -9,7 +9,7 @@ 	<key>CFBundleExecutable</key> 	<string>HandBrake</string> 	<key>CFBundleGetInfoString</key>-	<string>0.9.2</string>+	<string>0.9.3svn1364M</string> 	<key>CFBundleIconFile</key> 	<string>HandBrake</string> 	<key>CFBundleIdentifier</key>@@ -21,11 +21,11 @@ 	<key>CFBundlePackageType</key> 	<string>APPL</string> 	<key>CFBundleShortVersionString</key>-	<string>0.9.2</string>+	<string>0.9.3svn1364M</string> 	<key>CFBundleSignature</key> 	<string>HB##</string> 	<key>CFBundleVersion</key>-	<string>2008021900</string>+	<string>2008033101</string> 	<key>NSHumanReadableCopyright</key> 	<string>HandBrake Devs</string> 	<key>NSMainNibFile</key>Index: macosx/HBQueueController.mm===================================================================--- macosx/HBQueueController.mm	(revision 1364)+++ macosx/HBQueueController.mm	(working copy)@@ -141,10 +141,62 @@         crf = job->crf;         if (job->x264opts)             x264opts = [[NSString stringWithUTF8String:job->x264opts] retain];-        memcpy(audio_mixdowns, job->audio_mixdowns, sizeof(audio_mixdowns));-        acodec = job->acodec;-        abitrate = job->abitrate;-        arate = job->arate;+        /* So, with the advent of job->list_audio's I decided why not just use an NSString and concatanate+         all of the info we need for all of the audio values to display right into an NSString here ? So I+         did. I have no idea why we are reading libhb stuff just to display it in the queue gui. So here we+         are with a huge string. But its easy to change and saves alot of messing about. Maybe we move a bunch+         of other display stuff into strings for display for each job. It's not like they have to actually do+         anything.*/+        hb_audio_config_t * audio;+        NSString * thisJobAudioCodecs = [NSString stringWithFormat:@""];+        NSString * thisJobAudioInfo = [NSString stringWithFormat:@""]; // Setup a simple way to start the string+        for( int i = 0; i < hb_list_count(job->list_audio); i++ )+        {+           audio = (hb_audio_config_t *) hb_list_audio_config_item( job->list_audio, i );+            /* Output Codec */+            NSString *outputCodec;+            if (audio->out.codec == HB_ACODEC_AC3)+                outputCodec = @"AC3";+            else if (audio->out.codec == HB_ACODEC_FAAC)+                outputCodec = @"AAC";+            else if (audio->out.codec == HB_ACODEC_LAME)+                outputCodec = @"MP3";+            else if (audio->out.codec == HB_ACODEC_VORBIS)+                outputCodec = @"Vorbis";+            else+                outputCodec = @"Unknown Codec";       +            /* Add the codec to the audio codecs list ( We should check against dupes)*/+            thisJobAudioCodecs = [thisJobAudioCodecs stringByAppendingString:[NSString stringWithFormat:@" %@,",outputCodec]];+            if (i > 0)+            {+                /* Insert a line break so that we get each track on a separate line */+                /* Wicked HACK alert!!, use 18 whitespaces to align offset in display for list > 2 to offset "Audio" in the queue display+                 Please Fix Me because this is embarrassing (but it works) */+                thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:@"\n                  "];+            }+            /* Detailed Job audio track info*/+            /* Track Number and Mixdown Info */+            if (audio->out.mixdown == HB_ACODEC_AC3)// Remember for ac3 passthru the mixdown uses the source codec+                thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@" - Track %d: Source: %@ Output: %@, Pass-Thru", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]];+            else if (audio->out.mixdown == HB_AMIXDOWN_MONO)+                thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@" - Track %d: Source: %@ Output: %@, Mono", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]];+            else if (audio->out.mixdown == HB_AMIXDOWN_STEREO)+                thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@" - Track %d: Source: %@ Output: %@, Stereo", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]];+            else if (audio->out.mixdown == HB_AMIXDOWN_DOLBY)+                thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@" - Track %d: Source: %@ Output: %@, Dolby Surround", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]];+            else if (audio->out.mixdown == HB_AMIXDOWN_DOLBYPLII)+                thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@" - Track %d: Source: %@ Output: %@, Dolby Pro Logic II", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]];+            else if (audio->out.mixdown == HB_AMIXDOWN_6CH)+                thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@" - Track %d: Source: %@ Output: %@, 6 Channel Discreet", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]];+            else+                thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@" - Track %d: Source: %@ Output: Unknown Codec Info", i + 1, [NSString stringWithUTF8String:audio->lang.description]]];+            +            thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", %d kbps, %d Hz", audio->out.bitrate, audio->out.samplerate]];+            +        }+        audioinfo_summary = [[NSString stringWithFormat:@"%@",thisJobAudioInfo]retain];+        audioinfo_codecs = [[NSString stringWithFormat:@"%@",thisJobAudioCodecs]retain];+                 subtitle = job->subtitle;         mux = job->mux;         if (job->file)@@ -197,6 +249,8 @@     [file release];     [titleName release];     [subtitleLang release];+    [audioinfo_summary release];+    [audioinfo_codecs release];     [super dealloc]; } @@ -407,9 +461,9 @@             jobFormatInfo = @"unknown";                          if (chapter_markers == 1)-            jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video + %@ Audio, Chapter Markers\n", jobFormatInfo, jobVideoCodec, jobAudioCodec];+            jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video + %@ Audio, Chapter Markers\n", jobFormatInfo, jobVideoCodec, audioinfo_codecs];         else-            jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video + %@ Audio\n", jobFormatInfo, jobVideoCodec, jobAudioCodec];+            jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video + %@ Audio\n", jobFormatInfo, jobVideoCodec, audioinfo_codecs];                      [finalString appendString: @"Format: " withAttributes:detailBoldAttr];         [finalString appendString: jobFormatInfo withAttributes:detailAttr];@@ -497,34 +551,10 @@      if (withAudioInfo)     {-        NSString * jobAudioInfo;-        if ([jobAudioCodec isEqualToString: @"AC3"])-            jobAudioInfo = [NSString stringWithFormat:@"%@, Pass-Through", jobAudioCodec];-        else-            jobAudioInfo = [NSString stringWithFormat:@"%@, %d kbps, %d Hz", jobAudioCodec, abitrate, arate];-        -        // we now get the audio mixdown info for each of the two gui audio tracks-        // lets do it the long way here to get a handle on things.-        // Hardcoded for two tracks for gui: audio_mixdowns[i] audio_mixdowns[i]-        int ai; // counter for each audios [] , macgui only allows for two audio tracks currently-        for( ai = 0; ai < 2; ai++ )-        {-            if (audio_mixdowns[ai] == HB_AMIXDOWN_MONO)-                jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Track %d: Mono", ai + 1]];-            if (audio_mixdowns[ai] == HB_AMIXDOWN_STEREO)-                jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Track %d: Stereo", ai + 1]];-            if (audio_mixdowns[ai] == HB_AMIXDOWN_DOLBY)-                jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Track %d: Dolby Surround", ai + 1]];-            if (audio_mixdowns[ai] == HB_AMIXDOWN_DOLBYPLII)-                jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Track %d: Dolby Pro Logic II", ai + 1]];-            if (audio_mixdowns[ai] == HB_AMIXDOWN_AC3)-                jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Pass-Through", ai + 1]];-                -        }         if (withIcon)   // implies indent the info             [finalString appendString: @"\t" withAttributes:detailBoldAttr];         [finalString appendString: @"Audio: " withAttributes:detailBoldAttr];-        [finalString appendString:[NSString stringWithFormat:@"%@\n", jobAudioInfo] withAttributes:detailAttr];+        [finalString appendString:[NSString stringWithFormat:@"%@\n", audioinfo_summary] withAttributes:detailAttr];     }          if (withSubtitleInfo)