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,26 @@ if (!strcmp(preset_name, "AppleTV")) { + if (hb_list_count(audios) == 0) + { + audio = hb_audio_config_new(); + audio->in.track = audio->out.track = 0; + hb_list_add(audios, audio); + + audio = hb_audio_config_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; @@ -452,7 +495,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 +507,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 +519,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 +533,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 +544,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 +555,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 +568,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 +582,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 +596,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 +610,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 +623,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 +638,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 +649,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 +662,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 +677,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 +695,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 +775,13 @@ { job->pixel_ratio = pixelratio; } - + if (vfr) { detelecine = 1; job->vfr = 1; } - + /* Add selected filters */ job->filters = hb_list_init(); if( detelecine ) @@ -816,74 +859,228 @@ 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 = hb_audio_config_new(); + /* 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, i); + 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--; + hb_list_rem(audios, audio); + free(audio); + continue; + } + hb_audio_add( job, 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 +1424,21 @@ "### Audio Options-----------------------------------------------------------\n\n" - " -E, --aencoder 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 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 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 Set audio bitrate (default: 128)\n" - " -a, --audio 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 Format for surround sound downmixing\n" + " -B, --ab Set audio bitrate(s) (default: 128)\n" + " Seperated by commas for more than one audio track.\n" + " -6, --mixdown 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 +1446,11 @@ fprintf( stderr, "/" ); } fprintf( stderr, " kHz)\n" + " Seperated by commas for more than one audio track.\n" " -D, --drc 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 +1663,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_config_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_config_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 = 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 +1841,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 +1884,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 +1899,10 @@ size = atoi( optarg ); break; case 'B': - abitrate = atoi( optarg ); + if( optarg != NULL ) + { + abitrates = strdup( optarg ); + } break; case 'Q': crf = 0; @@ -1810,23 +2016,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; } } @@ -1834,3 +2040,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/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 #include #include +#include #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,93 @@ *_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 + ********************************************************************** + * + *********************************************************************/ +hb_audio_config_t *hb_audio_config_new(void) +{ + hb_audio_config_t *audiocfg = calloc(1, sizeof(*audiocfg)); + + /* Set read only paramaters to invalid values */ + audiocfg->in.codec = -1; + 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; + + return audiocfg; +} + +/********************************************************************** + * 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; + } + + /* 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 hb_audio_get_config(audio); +} + +hb_audio_config_t * hb_audio_get_config(hb_audio_t * audio) +{ + assert(audio != NULL); + 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,12 @@ int hb_calc_bitrate( hb_job_t *, int size ); +hb_audio_t *hb_audio_copy(const hb_audio_t *src); +hb_audio_config_t *hb_audio_config_new(void); +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); +hb_audio_config_t * hb_audio_get_config(hb_audio_t * audio); + struct hb_rate_s { char * string; @@ -175,77 +185,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 +242,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 +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 @@ -335,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 ) @@ -344,24 +311,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 +517,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) @@ -105,7 +105,9 @@ int h264_level; 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,8 +1467,8 @@ 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; job->chapter_end = [fSrcChapterEndPopUp 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,107 @@ 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]; + audio = (hb_audio_config_t*) hb_list_item( job->list_audio, 0 ); + hb_list_rem(job->list_audio, 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_new(); + /* We go ahead and assign values to our audio->out. */ + 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 ); + + /*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_new(); + /* We go ahead and assign values to our audio->out. */ + 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 ); + } + } - 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_new(); + /* We go ahead and assign values to our audio->out. */ + 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 ); + + /*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_new(); + /* We go ahead and assign values to our audio->out. */ + 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 ); + } } - /* - * 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; - } - - 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; - } - - 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; - } - - /* 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 +1826,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. @@ -1941,7 +1982,7 @@ otherwise, just rip the queue */ if( hb_count( fHandle ) == 0) { - [self doAddToQueue]; + [self doAddToQueue]; } NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent]; @@ -2787,17 +2828,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]]; - - /* 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]]; - + [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]]; } - (IBAction) addAllAudioTracksToPopUp: (id) sender @@ -2807,15 +2846,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]; @@ -2863,17 +2902,17 @@ - (IBAction) audioTrackPopUpChanged: (id) sender mixdownToUse: (int) mixdownToUse { - + /* make sure we have a selected title before continuing */ if (fTitle == NULL) return; - + /* find out if audio track 1 or 2 was changed - this is passed to us in the tag of the sender */ /* the sender will have been either fAudLang1PopUp (tag = 0) or fAudLang2PopUp (tag = 1) */ int thisAudio = [sender tag]; - + /* get the index of the selected audio */ int thisAudioIndex = [sender indexOfSelectedItem] - 1; - + #if 0 /* Handbrake can't currently cope with ripping the same source track twice */ /* So, if this audio is also selected in the other audio track popup, set that popup's selection to "none" */ @@ -2887,10 +2926,10 @@ [self audioTrackPopUpChanged: otherAudioPopUp]; } #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]; int codecs = [fDstCodecsPopUp indexOfSelectedItem]; @@ -2900,17 +2939,17 @@ 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 */ NSTextField * mixdownTextField; NSPopUpButton * mixdownPopUp; - + /* find our mixdown NSTextField and NSPopUpButton */ if (thisAudio == 0) { @@ -2922,125 +2961,124 @@ mixdownTextField = fAudTrack2MixLabel; mixdownPopUp = fAudTrack2MixPopUp; } - + /* delete the previous audio mixdown options */ [mixdownPopUp removeAllItems]; - + /* check if the audio mixdown controls need their enabled state changing */ [self setEnabledStateOfAudioMixdownControls: NULL]; - + if (thisAudioIndex != -1) { - + /* 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 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 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 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 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 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 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); - } + /* 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->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 (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 (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->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->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); + } + /* 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 */ @@ -3059,24 +3097,24 @@ /* if useMixdown > maxMixdownUsed, then use maxMixdownUsed */ if (useMixdown > maxMixdownUsed) useMixdown = maxMixdownUsed; - + /* if useMixdown < minMixdownUsed, then use minMixdownUsed */ if (useMixdown < minMixdownUsed) useMixdown = minMixdownUsed; - + /* select the (possibly-amended) preferred mixdown */ [mixdownPopUp selectItemWithTag: useMixdown]; /* lets call the audioTrackMixdownChanged method here to determine appropriate bitrates, etc. */ [self audioTrackMixdownChanged: NULL]; } - + } } - + /* see if the new audio track choice will change the bitrate we need */ [self calculateBitrate: sender]; - + } - (IBAction) audioTrackMixdownChanged: (id) sender { @@ -3095,9 +3133,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 +3200,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 @@ CFBundleExecutable HandBrake CFBundleGetInfoString - 0.9.2 + 0.9.3svn1364M CFBundleIconFile HandBrake CFBundleIdentifier @@ -21,11 +21,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.9.2 + 0.9.3svn1364M CFBundleSignature HB## CFBundleVersion - 2008021900 + 2008033101 NSHumanReadableCopyright HandBrake Devs NSMainNibFile 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)