rendered paste bodyIndex: test/test.c===================================================================--- test/test.c (revision 1318)+++ 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_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 );@@ -283,14 +306,14 @@ 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) )+ 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" );@@ -327,7 +350,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 ) )@@ -412,9 +444,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";@@ -426,15 +458,26 @@ if (!strcmp(preset_name, "AppleTV")) {+ if (hb_list_count(audios) == 0)+ {+ audio = hb_audio_new();+ audio->in.track = audio->out.track = 0;+ hb_list_add(audios, audio);++ audio = hb_audio_new();+ 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;@@ -445,7 +488,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;@@ -457,9 +500,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; }@@ -469,9 +512,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;@@ -483,9 +526,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"))@@ -494,7 +537,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;@@ -505,7 +548,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;@@ -518,7 +561,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;@@ -532,9 +575,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;@@ -546,9 +589,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;@@ -560,9 +603,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;@@ -573,9 +616,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;@@ -588,9 +631,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; }@@ -599,9 +642,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;@@ -612,9 +655,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;@@ -627,9 +670,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";@@ -645,9 +688,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; }@@ -802,74 +845,230 @@ job->vrate = 27000000; job->vrate_base = vrate; }- if( arate )++ /* Parse audio tracks */+ /* First audio struct is already on the list */+ audio = hb_list_item(job->list_audio, 0);+ if( hb_list_count(audios) == 0 ) {- job->arate = arate;+ /* Add it to our audios */+ hb_list_add(audios, audio); }+ /* Get rid of it! */+ hb_list_rem(job->list_audio, 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, i);+ if ( (audio->in.track == -1) || (audio->out.track == -1) ||+ (audio->out.codec == HB_ACODEC_NONE) ) {- int audio_count = 0;- char * tmp = audios;- while( *tmp )+ num_audio_tracks--;+ hb_list_rem(audios, audio);+ free(audio);+ continue;+ }+ hb_list_add(job->list_audio, hb_audio_copy( hb_list_item( title->list_audio, audio->in.track ) ) );+ }+ /* 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_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_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_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_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_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_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_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_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_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_item(job->list_audio, i);+ audio->out.mixdown = mixdown;+ }+ }+ /* Audio Mixdown */ if( size ) {@@ -1216,18 +1415,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 );@@ -1235,9 +1437,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"@@ -1450,33 +1654,64 @@ 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 = hb_audio_new();+ 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 = hb_audio_new();+ 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 = HB_ACODEC_NONE;+ 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;@@ -1593,28 +1828,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 );@@ -1654,23 +1871,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;@@ -1681,7 +1886,10 @@ size = atoi( optarg ); break; case 'B':- abitrate = atoi( optarg );+ if( optarg != NULL )+ {+ abitrates = strdup( optarg );+ } break; case 'Q': crf = 0;@@ -1795,23 +2003,23 @@ return 1; } - if( !acodec )+ if( !acodecs ) { if( mux == HB_MUX_MP4 || mux == HB_MUX_IPOD ) {- acodec = HB_ACODEC_FAAC;+ default_acodec = HB_ACODEC_FAAC; } else if( mux == HB_MUX_AVI ) {- acodec = HB_ACODEC_LAME;+ default_acodec = HB_ACODEC_LAME; } else if( mux == HB_MUX_OGM ) {- acodec = HB_ACODEC_VORBIS;+ default_acodec = HB_ACODEC_VORBIS; } else if( mux == HB_MUX_MKV ) {- acodec = HB_ACODEC_AC3;+ default_acodec = HB_ACODEC_AC3; } } @@ -1819,3 +2027,42 @@ 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/deca52.c===================================================================--- libhb/deca52.c (revision 1318)+++ 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->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->out.mixdown); pv->level = 32768.0;- pv->dynamic_range_compression = job->dynamic_range_compression;+ pv->dynamic_range_compression = audio->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; @@ -215,8 +217,7 @@ hb_list_getbytes( pv->list, pv->frame, pv->size, &pts, &pos ); /* AC3 passthrough: don't decode the AC3 frame */- if( pv->job->acodec & HB_ACODEC_AC3 ||- w->amixdown == HB_AMIXDOWN_AC3 )+ if( audio->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 1318)+++ 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->out.bitrate );+ lame_set_in_samplerate( pv->lame, audio->out.samplerate );+ lame_set_out_samplerate( pv->lame, audio->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->out.samplerate;+ buf->stop = buf->start + 90000 * 1152 / audio->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 1318)+++ 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,6 +346,8 @@ { audio = hb_list_item( title->list_audio, i ); + is_ac3 = (audio->out.codec == HB_ACODEC_AC3);+ mux_data = calloc( sizeof( hb_mux_data_t ), 1 ); audio->mux_data = mux_data; @@ -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->in.bitrate / 8 ) :+ ( audio->out.bitrate * 1000 / 8 ); h.Quality = 0xFFFFFFFF; h.SampleSize = 1; @@ -370,15 +372,15 @@ 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.SamplesPerSec = audio->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->out.mixdown);+ f.SamplesPerSec = audio->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->out.samplerate; m.FramesPerBlock = 1; m.CodecDelay = 1393; }@@ -513,7 +515,7 @@ { audio = hb_list_item( title->list_audio, i ); fseek( m->file, 264 + i *- ( 102 + ( ( job->acodec & HB_ACODEC_AC3 ) ? 0 :+ ( 102 + ( ( audio->out.codec == HB_ACODEC_AC3 ) ? 0 : sizeof( hb_wave_mp3_t ) ) ), SEEK_SET ); WriteInt32( m->file, audio->mux_data->header.Length ); }Index: libhb/dvd.c===================================================================--- libhb/dvd.c (revision 1318)+++ libhb/dvd.c (working copy)@@ -251,28 +251,28 @@ { case 0x00: audio->id = ( ( 0x80 + position ) << 8 ) | 0xbd;- audio->codec = HB_ACODEC_AC3;+ audio->in.codec = HB_ACODEC_AC3; break; case 0x02: case 0x03: audio->id = 0xc0 + position;- audio->codec = HB_ACODEC_MPGA;+ audio->in.codec = HB_ACODEC_MPGA; break; case 0x04: audio->id = ( ( 0xa0 + position ) << 8 ) | 0xbd;- audio->codec = HB_ACODEC_LPCM;+ audio->in.codec = HB_ACODEC_LPCM; break; case 0x06: audio->id = ( ( 0x88 + position ) << 8 ) | 0xbd;- audio->codec = HB_ACODEC_DCA;+ audio->in.codec = HB_ACODEC_DCA; break; default: audio->id = 0;- audio->codec = 0;+ audio->in.codec = HB_ACODEC_NONE; hb_log( "scan: unknown audio codec (%x)", audio_format ); break;@@ -302,18 +302,18 @@ lang = lang_for_code( vts->vtsi_mat->vts_audio_attr[i].lang_code ); - snprintf( audio->lang, sizeof( audio->lang ), "%s (%s)",+ snprintf( audio->lang.description, sizeof( audio->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->in.codec == HB_ACODEC_AC3 ? "AC3" : ( audio->in.codec ==+ HB_ACODEC_DCA ? "DTS" : ( audio->in.codec == HB_ACODEC_MPGA ? "MPEG" : "LPCM" ) ) );- snprintf( audio->lang_simple, sizeof( audio->lang_simple ), "%s",+ 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",+ snprintf( audio->lang.iso639_2, sizeof( audio->lang.iso639_2 ), "%s", lang->iso639_2); hb_log( "scan: id=%x, lang=%s, 3cc=%s", audio->id,- audio->lang, audio->iso639_2 );+ audio->lang.description, audio->lang.iso639_2 ); hb_list_add( title->list_audio, audio ); }Index: libhb/hb.c===================================================================--- libhb/hb.c (revision 1318)+++ libhb/hb.c (working copy)@@ -722,7 +722,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];@@ -747,18 +747,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 );- } } } @@ -788,17 +782,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->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;- } } /*@@ -923,6 +913,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 1318)+++ 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->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)@@ -263,12 +272,11 @@ mux_data = malloc( sizeof( hb_mux_data_t ) ); audio->mux_data = mux_data; - if( job->acodec & HB_ACODEC_AC3 ||- job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+ if( audio->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",@@ -288,15 +296,15 @@ audio->config.aac.bytes, audio->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->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->lang.iso639_2[0] - 0x60; language_code <<= 5;+ language_code |= audio->lang.iso639_2[1] - 0x60; language_code <<= 5;+ language_code |= audio->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 1318)+++ libhb/stream.c (working copy)@@ -333,7 +333,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->in.codec) hb_list_add( aTitle->list_audio, audio ); else {@@ -732,7 +732,7 @@ if (buf[3] == 0xbd) { audio->id = 0x80bd | (aud_pid_index << 8);- audio->codec = HB_ACODEC_AC3;+ audio->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[aud_pid_index],@@ -743,7 +743,7 @@ else if ((buf[3] & 0xe0) == 0xc0) { audio->id = buf[3] | aud_pid_index;- audio->codec = HB_ACODEC_MPGA;+ audio->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[aud_pid_index],@@ -753,7 +753,7 @@ } } fseeko(stream->file_handle, cur_pos, SEEK_SET);- if (! audio->codec)+ if (! audio->in.codec) { hb_log("transport stream pid 0x%x (type 0x%x) isn't audio", stream->ts_audio_pids[aud_pid_index],@@ -770,7 +770,7 @@ switch ( id >> 12 ) { case 0x0:- audio->codec = HB_ACODEC_MPGA;+ audio->in.codec = HB_ACODEC_MPGA; hb_log("add_audio_to_title: added MPEG audio stream 0x%x", id); break; case 0x2:@@ -778,11 +778,11 @@ free( audio ); return; case 0x8:- audio->codec = HB_ACODEC_AC3;+ audio->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->in.codec = HB_ACODEC_LPCM; hb_log("add_audio_to_title: added LPCM audio stream 0x%x", id); break; default:@@ -872,12 +872,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->in.samplerate)+ audio->in.samplerate = stream->a52_info[i].rate;+ if (!audio->in.bitrate)+ audio->in.bitrate = stream->a52_info[i].bitrate;+ if (!audio->config.a52.ac3flags)+ audio->config.a52.ac3flags = audio->flags.ac3 = stream->a52_info[i].flags; } else@@ -888,7 +888,7 @@ if (!audio->input_channel_layout) {- switch( audio->ac3flags & A52_CHANNEL_MASK )+ switch( audio->flags.ac3 & A52_CHANNEL_MASK ) { /* mono sources */ case A52_MONO:@@ -929,29 +929,29 @@ } /* add in our own LFE flag if the source has LFE */- if (audio->ac3flags & A52_LFE)+ if (audio->flags.ac3 & A52_LFE) { audio->input_channel_layout = audio->input_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->lang.description, sizeof( audio->lang.description ), "%s (%s)", strlen(lang->native_name) ? lang->native_name : lang->eng_name,+ audio->in.codec == HB_ACODEC_AC3 ? "AC3" : ( audio->in.codec == HB_ACODEC_MPGA ? "MPEG" : ( audio->in.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->lang.iso639_2, sizeof( audio->lang.iso639_2 ), "%s", lang->iso639_2); - if ( (audio->ac3flags & A52_CHANNEL_MASK) == A52_DOLBY ) {- sprintf( audio->lang + strlen( audio->lang ),+ if ( (audio->flags.ac3 & A52_CHANNEL_MASK) == A52_DOLBY ) {+ sprintf( audio->lang.description + strlen( audio->lang.description ), " (Dolby Surround)" ); } else {- sprintf( audio->lang + strlen( audio->lang ),+ sprintf( audio->lang.description + strlen( audio->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_log( "hb_stream_update_audio: id=%x, lang=%s, 3cc=%s, rate = %d, bitrate = %d, flags = 0x%x (%d)", audio->id, audio->lang, audio->iso639_2, audio->rate, audio->bitrate, audio->ac3flags, audio->ac3flags );+ hb_log( "hb_stream_update_audio: id=%x, lang=%s, 3cc=%s, rate = %d, bitrate = %d, flags = 0x%x (%d)", audio->id, audio->lang.description, audio->lang.iso639_2, audio->in.samplerate, audio->in.bitrate, audio->flags.ac3, audio->flags.ac3 ); } Index: libhb/decdca.c===================================================================--- libhb/decdca.c (revision 1318)+++ 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->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->out.mixdown); pv->level = 32768.0; Index: libhb/muxogm.c===================================================================--- libhb/muxogm.c (revision 1318)+++ libhb/muxogm.c (working copy)@@ -135,7 +135,7 @@ { 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->out.codec; mux_data->i_packet_no = 0; audio->mux_data = mux_data; ogg_stream_init( &mux_data->os, i + 1 );@@ -185,7 +185,7 @@ audio = hb_list_item( title->list_audio, i ); mux_data = audio->mux_data; memset( &h, 0, sizeof( ogg_stream_header_t ) );- switch( job->acodec )+ switch( audio->out.codec ) { case HB_ACODEC_LAME: {@@ -195,7 +195,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->out.samplerate ); SetDWLE( &h.i_default_len, 1 ); SetDWLE( &h.i_buffer_size, 30 * 1024 ); SetWLE ( &h.i_bits_per_sample, 0 );@@ -203,7 +203,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->out.bitrate / 8 ); op.packet = (unsigned char*) &h; op.bytes = sizeof( ogg_stream_header_t );@@ -234,7 +234,7 @@ 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->out.codec == HB_ACODEC_VORBIS ) { int j; mux_data = audio->mux_data;@@ -259,44 +259,48 @@ static int OGMMux( hb_mux_object_t * m, hb_mux_data_t * mux_data, hb_buffer_t * buf ) {+ hb_job_t * job = m->job; ogg_packet op; - switch( mux_data->codec )+ if( mux_data == job->mux_data ) {- case HB_VCODEC_FFMPEG:- case HB_VCODEC_XVID:- case HB_VCODEC_X264:- op.bytes = buf->size + 1;- op.packet = malloc( op.bytes );- op.packet[0] = (buf->frametype & HB_FRAME_KEY) ? 0x08 : 0x00;- memcpy( &op.packet[1], buf->data, buf->size );- op.b_o_s = 0;- op.e_o_s = 0;- op.granulepos = mux_data->i_packet_no;- op.packetno = mux_data->i_packet_no++;- break;- case HB_ACODEC_LAME:- op.bytes = buf->size + 1;- op.packet = malloc( op.bytes );- op.packet[0] = 0x08;- memcpy( &op.packet[1], buf->data, buf->size );- op.b_o_s = 0;- op.e_o_s = 0;- op.granulepos = mux_data->i_packet_no * 1152;- op.packetno = mux_data->i_packet_no++;- break;- case HB_ACODEC_VORBIS:- memcpy( &op, buf->data, sizeof( ogg_packet ) );- op.packet = malloc( op.bytes );- memcpy( op.packet, buf->data + sizeof( ogg_packet ), op.bytes );- break;-- default:- hb_log( "muxogm: unhandled codec" );- op.bytes = 0;- op.packet = NULL;- break;+ /* Video */+ op.bytes = buf->size + 1;+ op.packet = malloc( op.bytes );+ op.packet[0] = (buf->frametype & HB_FRAME_KEY) ? 0x08 : 0x00;+ memcpy( &op.packet[1], buf->data, buf->size );+ op.b_o_s = 0;+ op.e_o_s = 0;+ op.granulepos = mux_data->i_packet_no;+ op.packetno = mux_data->i_packet_no++; }+ else+ {+ /* Audio */+ switch( mux_data->codec )+ {+ case HB_ACODEC_LAME:+ op.bytes = buf->size + 1;+ op.packet = malloc( op.bytes );+ op.packet[0] = 0x08;+ memcpy( &op.packet[1], buf->data, buf->size );+ op.b_o_s = 0;+ op.e_o_s = 0;+ op.granulepos = mux_data->i_packet_no * 1152;+ op.packetno = mux_data->i_packet_no++;+ break;+ case HB_ACODEC_VORBIS:+ memcpy( &op, buf->data, sizeof( ogg_packet ) );+ op.packet = malloc( op.bytes );+ memcpy( op.packet, buf->data + sizeof( ogg_packet ), op.bytes );+ break;+ default:+ hb_log( "muxogm: unhandled codec" );+ op.bytes = 0;+ op.packet = NULL;+ break;+ }+ } if( op.packet ) {Index: libhb/sync.c===================================================================--- libhb/sync.c (revision 1318)+++ libhb/sync.c (working copy)@@ -137,6 +137,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 @@ for( i = 0; i < hb_list_count( title->list_audio ); i++ ) {- if( job->acodec & HB_ACODEC_AC3 ||- job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+ audio = hb_list_item( title->list_audio, i );+ if( audio->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->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->in.bitrate;+ c->sample_rate = sync->audio->in.samplerate;+ c->channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( sync->audio->input_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->in.bitrate * AC3_SAMPLES_PER_FRAME /+ sync->audio->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->out.mixdown), &error ); sync->data.end_of_input = 0; } }@@ -659,16 +659,15 @@ sync = &pv->sync_audio[i]; audio = sync->audio; - if( job->acodec & HB_ACODEC_AC3 ||- job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+ if( audio->out.codec == HB_ACODEC_AC3 ) { fifo = audio->fifo_out;- rate = audio->rate;+ rate = audio->in.samplerate; } else { fifo = audio->fifo_sync;- rate = job->arate;+ rate = audio->out.samplerate; } while( !hb_fifo_is_full( fifo ) &&@@ -822,8 +821,7 @@ } } - if( job->acodec & HB_ACODEC_AC3 ||- job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+ if( audio->out.codec == HB_ACODEC_AC3 ) { buf = hb_fifo_get( audio->fifo_raw ); buf->start = start;@@ -837,8 +835,8 @@ int count_in, count_out; - count_in = buf_raw->size / HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) / sizeof( float );- count_out = ( buf_raw->stop - buf_raw->start ) * job->arate / 90000;+ count_in = buf_raw->size / HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->out.mixdown) / sizeof( float );+ count_out = ( buf_raw->stop - buf_raw->start ) * audio->out.samplerate / 90000; if( buf->start < pts_expected - 1500 ) count_out--; else if( buf->start > pts_expected + 1500 )@@ -851,7 +849,7 @@ sync->data.src_ratio = (double) sync->data.output_frames / (double) sync->data.input_frames; - buf = hb_buffer_init( sync->data.output_frames * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) *+ buf = hb_buffer_init( sync->data.output_frames * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->out.mixdown) * sizeof( float ) ); sync->data.data_out = (float *) buf->data; if( src_process( sync->state, &sync->data ) )@@ -861,12 +859,12 @@ } hb_buffer_close( &buf_raw ); - buf->size = sync->data.output_frames_gen * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) * sizeof( float );+ buf->size = sync->data.output_frames_gen * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->out.mixdown) * sizeof( float ); /* Set dates for resampled data */ buf->start = start; buf->stop = start + sync->data.output_frames_gen *- 90000 / job->arate;+ 90000 / audio->out.samplerate; sync->count_frames += sync->data.output_frames_gen; }@@ -939,13 +937,12 @@ job = pv->job; sync = &pv->sync_audio[i]; - if( job->acodec & HB_ACODEC_AC3 ||- job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )+ if( sync->audio->out.codec == HB_ACODEC_AC3 ) { buf = hb_buffer_init( sync->ac3_size );- buf->start = sync->count_frames * 90000 / sync->audio->rate;+ buf->start = sync->count_frames * 90000 / sync->audio->in.samplerate; buf->stop = buf->start + 90000 * AC3_SAMPLES_PER_FRAME /- sync->audio->rate;+ sync->audio->in.samplerate; memcpy( buf->data, sync->ac3_buf, buf->size ); hb_log( "sync: adding a silent AC-3 frame for track %x",@@ -957,15 +954,15 @@ } else {- buf = hb_buffer_init( HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown) * job->arate / 20 *+ buf = hb_buffer_init( HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->out.mixdown) * sync->audio->out.samplerate / 20 * sizeof( float ) );- buf->start = sync->count_frames * 90000 / job->arate;+ buf->start = sync->count_frames * 90000 / sync->audio->out.samplerate; buf->stop = buf->start + 90000 / 20; memset( buf->data, 0, buf->size ); hb_fifo_push( sync->audio->fifo_sync, buf ); - sync->count_frames += job->arate / 20;+ sync->count_frames += sync->audio->out.samplerate / 20; } } Index: libhb/encfaac.c===================================================================--- libhb/encfaac.c (revision 1318)+++ 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->out.mixdown); - pv->faac = faacEncOpen( job->arate, pv->out_discrete_channels, &pv->input_samples,+ pv->faac = faacEncOpen( audio->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->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->out.mixdown == HB_AMIXDOWN_6CH && audio->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->out.samplerate;+ buf->stop = buf->start + 90000 * pv->input_samples / audio->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 1318)+++ libhb/muxcommon.c (working copy)@@ -82,6 +82,12 @@ break; case HB_MUX_MKV: m = hb_mux_mkv_init( job );+ break;+ case HB_MUX_NONE:+ default:+ m = NULL;+ hb_error("Invalid muxer: %d", job->mux);+ *job->die = 1; } } @@ -116,7 +122,8 @@ /* Create file, write headers */ if( job->pass == 0 || job->pass == 2 ) {- m->init( m );+ if( m )+ m->init( m ); } /* Build list of fifos we're interested in */@@ -170,7 +177,8 @@ p.progress = 0; hb_set_state( job->h, &state ); #undef p- m->end( m );+ if( m )+ m->end( m ); if( !stat( job->file, &sb ) ) {@@ -204,7 +212,7 @@ } } - free( m );+ if( m ) free( m ); for( i = 0; i < hb_list_count( list ); i++ ) {@@ -217,7 +225,7 @@ } hb_list_close( &list ); - free( mux );+ if( mux ) free( mux ); } hb_thread_t * hb_muxer_init( hb_job_t * job )Index: libhb/work.c===================================================================--- libhb/work.c (revision 1318)+++ libhb/work.c (working copy)@@ -264,6 +264,12 @@ hb_log( " + x264 options: %s", job->x264opts); w = getWork( WORK_ENCX264 ); break;+ case HB_VCODEC_NONE:+ default:+ hb_error("Invalid video codec: %d", job->vcodec);+ w = NULL;+ *job->die = 1;+ goto cleanup; } w->fifo_in = job->fifo_render; w->fifo_out = job->fifo_mpeg4;@@ -333,57 +339,53 @@ } } - 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->out.codec == HB_ACODEC_AC3 ) && ( audio->in.codec != HB_ACODEC_AC3 ) ) ||+ ( ( audio->out.codec == HB_ACODEC_DCA ) && ( audio->in.codec != HB_ACODEC_DCA ) ) ) {+ hb_log( "Passthru requested and input codec is not the same as output codec for track %d", audio->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->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->out.track );+ if( (audio->out.codec == HB_ACODEC_AC3) || (audio->out.codec == HB_ACODEC_DCA) )+ {+ hb_log( " + %s passthrough", (audio->out.codec == HB_ACODEC_AC3) ?+ "AC3" : "DCA" );+ }+ else+ {+ hb_log( " + audio %d kbps, %d Hz", audio->out.bitrate, audio->out.samplerate );+ hb_log( " + encoder %s", ( audio->out.codec == HB_ACODEC_FAAC ) ?+ "faac" : ( ( audio->out.codec == HB_ACODEC_LAME ) ? "lame" :+ "vorbis" ) );+ if ( audio->out.dynamic_range_compression > 1 )+ hb_log(" + dynamic range compression: %f", audio->out.dynamic_range_compression);+ } + hb_log( " + %x, %s", audio->id, audio->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->out.mixdown) {+ hb_log( " + Requested mixdown: %s (%s)", hb_audio_mixdowns[j].human_readable_name, hb_audio_mixdowns[j].internal_name ); break; } }@@ -392,22 +394,11 @@ /* 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->in.codec == HB_ACODEC_AC3 || audio->in.codec == HB_ACODEC_DCA) &&+ (audio->out.codec == HB_ACODEC_FAAC || audio->out.codec == HB_ACODEC_VORBIS) );+ int audioCodecsSupport6Ch = ( (audio->in.codec == HB_ACODEC_AC3 || audio->in.codec == HB_ACODEC_DCA) &&+ (audio->out.codec == HB_ACODEC_FAAC || audio->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) { @@ -415,10 +406,10 @@ 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->out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) {+ audio->out.mixdown = HB_AMIXDOWN_MONO; } else {- job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO;+ audio->out.mixdown = HB_AMIXDOWN_STEREO; } break; @@ -426,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->out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {+ audio->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->out.mixdown > HB_AMIXDOWN_STEREO) {+ audio->out.mixdown = HB_AMIXDOWN_STEREO; } break; @@ -440,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->out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {+ audio->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->out.mixdown > HB_AMIXDOWN_DOLBY) {+ audio->out.mixdown = HB_AMIXDOWN_DOLBY; } break; @@ -453,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->out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {+ audio->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) { /* 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->out.mixdown == HB_AMIXDOWN_6CH && audioCodecsSupport6Ch == 0) {+ audio->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->out.mixdown > HB_AMIXDOWN_DOLBYPLII) {+ audio->out.mixdown = HB_AMIXDOWN_DOLBYPLII; } } }@@ -478,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->out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) {+ audio->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->out.mixdown > HB_AMIXDOWN_DOLBY) {+ audio->out.mixdown = HB_AMIXDOWN_DOLBY; } } /* all other mixdowns will have been preserved here */@@ -492,30 +483,26 @@ 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->out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) {+ audio->out.mixdown = HB_AMIXDOWN_MONO; /* mix everything else down to stereo */ } else {- job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO;+ audio->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->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->out.codec == HB_ACODEC_VORBIS)+ audio->config.vorbis.language = audio->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 );@@ -526,7 +513,7 @@ /* * Audio Decoder Thread */- switch( audio->codec )+ switch( audio->in.codec ) { case HB_ACODEC_AC3: w = getWork( WORK_DECA52 );@@ -540,12 +527,16 @@ case HB_ACODEC_LPCM: w = getWork( WORK_DECLPCM ); break;+ default:+ /* Invalid input codec */+ hb_error("Invalid input codec: %d", audio->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->audio = audio; /* FIXME: This feels really hackish, anything better? */ audio_w = calloc( sizeof( hb_work_object_t ), 1 );@@ -556,10 +547,8 @@ /* * Audio Encoder Thread */- if( job->audio_mixdowns[i] != HB_AMIXDOWN_AC3 )+ switch( audio->out.codec ) {- switch( job->acodec )- { case HB_ACODEC_FAAC: w = getWork( WORK_ENCFAAC ); break;@@ -569,11 +558,17 @@ 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: %d", audio->out.codec);+ w = NULL;+ *job->die = 1;+ goto cleanup; } - if( job->acodec != HB_ACODEC_AC3 &&- job->audio_mixdowns[i] != HB_AMIXDOWN_AC3)+ if( audio->out.codec != HB_ACODEC_AC3 ) { /* * Add the encoder thread if not doing AC-3 pass through@@ -581,8 +576,7 @@ 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->audio = audio; /* FIXME: This feels really hackish, anything better? */ audio_w = calloc( sizeof( hb_work_object_t ), 1 );@@ -636,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 && w->thread )+ {+ hb_thread_close( &w->thread );+ w->close( w );+ } /* FIXME: This feels really hackish, anything better? */ if ( w->id == WORK_DECA52 ||@@ -659,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 )+ hb_thread_close( &job->reader );+ if( job->muxer )+ hb_thread_close( &job->muxer ); /* Close fifos */ hb_fifo_close( &job->fifo_mpeg2 );@@ -680,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->fifo_in )+ hb_fifo_close( &audio->fifo_in );+ if( audio->fifo_raw )+ hb_fifo_close( &audio->fifo_raw );+ if( audio->fifo_sync )+ hb_fifo_close( &audio->fifo_sync );+ if( audio->fifo_out )+ hb_fifo_close( &audio->fifo_out ); } if( job->indepth_scan )Index: libhb/scan.c===================================================================--- libhb/scan.c (revision 1318)+++ 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->in.codec == HB_ACODEC_AC3 &&+ !audio->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->in.codec == HB_ACODEC_AC3 || audio->in.codec == HB_ACODEC_DCA ) &&+ !audio->in.bitrate ) { hb_log( "scan: removing audio with codec of 0x%x because of no bitrate",- audio->codec );+ audio->in.codec ); hb_list_rem( title->list_audio, audio ); free( audio ); continue;@@ -188,7 +188,7 @@ 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->in.codec == HB_ACODEC_LPCM || audio->in.codec == HB_ACODEC_MPGA ) { audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; }@@ -201,6 +201,7 @@ for( i = 0; i < hb_list_count( data->list_title ); i++ ) { hb_job_t * job;+ hb_audio_t * audio; title = hb_list_item( data->list_title, i ); job = calloc( sizeof( hb_job_t ), 1 );@@ -247,13 +248,15 @@ job->vrate = title->rate; job->vrate_base = title->rate_base; - job->audios[0] = 0;- job->audios[1] = -1;+ audio = hb_audio_copy(hb_list_item(title->list_audio, 0));+ audio->in.track = 0;+ audio->out.track = 0;+ audio->out.codec = HB_ACODEC_FAAC;+ audio->out.bitrate = 128;+ audio->out.samplerate = 44100;+ job->list_audio = hb_list_init();+ hb_list_add(job->list_audio, audio); - job->acodec = HB_ACODEC_FAAC;- job->abitrate = 128;- job->arate = 44100;- job->subtitle = -1; job->mux = HB_MUX_MP4;@@ -553,7 +556,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->in.codec == HB_ACODEC_AC3 || audio->in.codec == HB_ACODEC_DCA ) && audio->id == b->id ) { break;@@ -568,7 +571,7 @@ return; } - if( audio->bitrate )+ if( audio->in.bitrate ) { /* Already done for this track */ return;@@ -577,15 +580,15 @@ for( i = 0; i < b->size - 7; i++ ) { - if ( audio->codec == HB_ACODEC_AC3 )+ if ( audio->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->in.samplerate = rate;+ audio->in.bitrate = bitrate; switch( flags & A52_CHANNEL_MASK ) { /* mono sources */@@ -637,14 +640,14 @@ audio->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;+ audio->flags.ac3 = audio->config.a52.ac3flags; /* XXX */ if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY ) {- sprintf( audio->lang + strlen( audio->lang ),+ sprintf( audio->lang.description + strlen( audio->lang.description ), " (Dolby Surround)" ); } else {- sprintf( audio->lang + strlen( audio->lang ),+ sprintf( audio->lang.description + strlen( audio->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),@@ -656,7 +659,7 @@ } }- else if ( audio->codec == HB_ACODEC_DCA )+ else if ( audio->in.codec == HB_ACODEC_DCA ) { hb_log( "scan: checking for DCA syncinfo" );@@ -666,8 +669,8 @@ 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->in.samplerate = rate;+ audio->in.bitrate = bitrate; switch( flags & DCA_CHANNEL_MASK ) { /* mono sources */@@ -718,14 +721,14 @@ audio->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;+ audio->flags.dca = audio->config.dca.dcaflags; /* XXX */ if ( (flags & DCA_CHANNEL_MASK) == DCA_DOLBY ) {- sprintf( audio->lang + strlen( audio->lang ),+ sprintf( audio->lang.description + strlen( audio->lang.description ), " (Dolby Surround)" ); } else {- sprintf( audio->lang + strlen( audio->lang ),+ sprintf( audio->lang.description + strlen( audio->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),@@ -747,8 +750,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->in.codec == HB_ACODEC_AC3 || audio->in.codec == HB_ACODEC_DCA ) &&+ !audio->in.bitrate ) { return 0; }Index: libhb/muxmkv.c===================================================================--- libhb/muxmkv.c (revision 1318)+++ libhb/muxmkv.c (working copy)@@ -29,6 +29,7 @@ mk_Track * track; uint64_t prev_chapter_tc; uint16_t current_chapter;+ int codec; }; /**********************************************************************@@ -138,7 +139,9 @@ mux_data = malloc( sizeof( hb_mux_data_t ) ); audio->mux_data = mux_data; - switch (job->acodec)+ mux_data->codec = audio->out.codec;++ switch (audio->out.codec) { case HB_ACODEC_AC3: track->codecPrivate = NULL;@@ -173,22 +176,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->config.aac.bytes;+ track->codecPrivateSize = audio->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->out.codec); return 0; } @@ -199,12 +193,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->lang.iso639_2;+ track->extra.audio.samplingFreq = (float)audio->out.samplerate;+ track->extra.audio.channels = (audio->out.codec == HB_ACODEC_AC3 ) ? HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->input_channel_layout) : HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->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->out.codec == HB_ACODEC_VORBIS && track->codecPrivate != NULL) free(track->codecPrivate); } @@ -269,7 +263,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 :( */ ogg_packet *op;Index: libhb/common.c===================================================================--- libhb/common.c (revision 1318)+++ libhb/common.c (working copy)@@ -43,9 +43,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 );@@ -193,23 +191,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++ )@@ -223,19 +204,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->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->out.codec == HB_ACODEC_AC3 ||+ audio->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->in.bitrate / 8; } else {@@ -243,12 +242,12 @@ * Where we are transcoding the audio we use the destination * bitrate. */- abitrate = job->abitrate * 1000 / 8;+ abitrate = audio->out.bitrate * 1000 / 8; } avail -= length * abitrate; /* Audio overhead */- avail -= length * job->arate * overhead / samples_per_frame;+ avail -= length * audio->out.samplerate * overhead / samples_per_frame; } if( avail < 0 )@@ -645,3 +644,33 @@ *_f = NULL; } +/**********************************************************************+ * hb_audio_copy+ **********************************************************************+ *+ *********************************************************************/+hb_audio_t *hb_audio_copy(const hb_audio_t *src)+{+ hb_audio_t *audio = hb_audio_new();+ memcpy(audio, src, sizeof(*audio));+ return audio;+}++/**********************************************************************+ * hb_audio_new+ **********************************************************************+ *+ *********************************************************************/+hb_audio_t *hb_audio_new(void)+{+ hb_audio_t *audio = calloc(1, sizeof(*audio));+ /* Initalize some sensable defaults */+ audio->in.codec = HB_ACODEC_NONE;+ audio->out.codec = HB_ACODEC_FAAC;+ audio->out.bitrate = 128;+ audio->out.samplerate = 44100;+ audio->out.mixdown = HB_AMIXDOWN_DOLBYPLII;+ audio->out.dynamic_range_compression = 0;++ return audio;+}Index: libhb/encvorbis.c===================================================================--- libhb/encvorbis.c (revision 1318)+++ 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->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->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->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->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->out.samplerate, -1, 1000 * audio->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->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 1318)+++ libhb/common.h (working copy)@@ -70,6 +70,41 @@ int hb_calc_bitrate( hb_job_t *, int size ); +hb_audio_t *hb_audio_copy(const hb_audio_t *src);+hb_audio_t *hb_audio_new();++/* Video codecs */+typedef enum {+ HB_VCODEC_NONE,+ HB_VCODEC_FFMPEG,+ HB_VCODEC_XVID,+ HB_VCODEC_X264+} hb_vcodec_t;++/* Muxers */+typedef enum {+ HB_MUX_NONE,+ HB_MUX_MP4,+ HB_MUX_PSP,+ HB_MUX_AVI,+ HB_MUX_OGM,+ HB_MUX_IPOD,+ HB_MUX_MKV+} hb_format_t;++/* Audio codecs */+typedef enum+{+ HB_ACODEC_NONE,+ HB_ACODEC_FAAC,+ HB_ACODEC_LAME,+ HB_ACODEC_VORBIS,+ HB_ACODEC_AC3,+ HB_ACODEC_MPGA,+ HB_ACODEC_LPCM,+ HB_ACODEC_DCA+} hb_acodec_t;+ struct hb_rate_s { char * string;@@ -156,12 +191,7 @@ crf: boolean for whether to use constant rate factor with x264 x264opts: string of extra x264 options areBframes: boolean to note if b-frames are included in x264opts */-#define HB_VCODEC_MASK 0x0000FF-#define HB_VCODEC_FFMPEG 0x000001-#define HB_VCODEC_XVID 0x000002-#define HB_VCODEC_X264 0x000004-- int vcodec;+ hb_vcodec_t vcodec; float vquality; int vbitrate; int vrate;@@ -174,77 +204,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 */@@ -254,15 +216,7 @@ /* Muxer settings mux: output file format file: file path */-#define HB_MUX_MASK 0xFF0000-#define HB_MUX_MP4 0x010000-#define HB_MUX_PSP 0x020000-#define HB_MUX_AVI 0x040000-#define HB_MUX_OGM 0x080000-#define HB_MUX_IPOD 0x100000-#define HB_MUX_MKV 0x200000-- int mux;+ hb_format_t mux; const char * file; /* Allow MP4 files > 4 gigs */@@ -299,22 +253,38 @@ #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 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 ) ) - /* ac3flags is only set when the source audio format is HB_ACODEC_AC3 */- int ac3flags;-- /* 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@@ -322,7 +292,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@@ -334,7 +303,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 )@@ -343,12 +311,55 @@ #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_s+{+ /* Input */+ struct+ {+ int track; /* Input track number */+ hb_acodec_t codec; /* Input audio codec */+ int samplerate; /* Input sample rate (Hz) */+ int bitrate; /* Input bitrate (kbps) */+ } in; + /* Output */+ struct+ {+ int track; /* Output track number */+ hb_acodec_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;++ /* Misc. */+ union+ {+ int ac3; /* flags.ac3 is only set when the source audio format is HB_ACODEC_AC3 */+ int dca; /* flags.dca is only set when the source audio format is HB_ACODEC_DCA */+ } flags;++ struct+ {+ char description[1024];+ char simple[1024];+ char iso639_2[4];+ } lang;+ #ifdef __LIBHB__ /* Internal data */+ /* Input */+ int id;+ /* 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;++ /* Misc. */ 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 */@@ -356,9 +367,6 @@ hb_esconfig_t config; hb_mux_data_t * mux_data;-- /* amixdown is the mixdown format to be used for this audio track */- int amixdown; #endif }; @@ -477,7 +485,9 @@ /* HB_STATE_WORKDONE */ #define HB_ERROR_NONE 0 #define HB_ERROR_CANCELED 1-#define HB_ERROR_UNKNOWN 2+#define HB_ERROR_INVALID_VCODEC 0x02+#define HB_ERROR_INVALID_ACODEC 0x04+#define HB_ERROR_UNKNOWN 0x08 int error; } workdone; @@ -504,10 +514,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;