diff options
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/audio_resample.c | 39 | ||||
-rw-r--r-- | libhb/audio_resample.h | 3 | ||||
-rw-r--r-- | libhb/common.c | 815 | ||||
-rw-r--r-- | libhb/common.h | 12 | ||||
-rw-r--r-- | libhb/encfaac.c | 67 | ||||
-rw-r--r-- | libhb/encvorbis.c | 12 | ||||
-rw-r--r-- | libhb/hb.c | 20 | ||||
-rw-r--r-- | libhb/muxmp4.c | 6 | ||||
-rw-r--r-- | libhb/work.c | 76 |
9 files changed, 636 insertions, 414 deletions
diff --git a/libhb/audio_resample.c b/libhb/audio_resample.c index 44f2a0144..ce80bc5fe 100644 --- a/libhb/audio_resample.c +++ b/libhb/audio_resample.c @@ -27,6 +27,21 @@ hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat sample_fmt, uint64_t channel_layout = hb_ff_mixdown_xlat(hb_amixdown, &matrix_encoding); channels = av_get_channel_layout_nb_channels(channel_layout); + if (do_remix && (hb_amixdown == HB_AMIXDOWN_LEFT || + hb_amixdown == HB_AMIXDOWN_RIGHT)) + { + /* When downmixing, Dual Mono to Mono is a special case: + * the audio must remain 2-channel until all conversions are done. */ + channels = 2; + channel_layout = AV_CH_LAYOUT_STEREO; + resample->dual_mono_downmix = 1; + resample->dual_mono_right_only = (hb_amixdown == HB_AMIXDOWN_RIGHT); + } + else + { + resample->dual_mono_downmix = 0; + } + // requested channel_layout resample->out.channels = channels; resample->out.channel_layout = channel_layout; @@ -193,12 +208,12 @@ hb_buffer_t* hb_audio_resample(hb_audio_resample_t *resample, return NULL; } - int out_size; hb_buffer_t *out; + int out_size, out_samples; if (resample->resample_needed) { - int in_linesize, out_linesize, out_samples; + int in_linesize, out_linesize; // set in/out linesize and out_size av_samples_get_buffer_size(&in_linesize, resample->resample.channels, nsamples, @@ -225,11 +240,29 @@ hb_buffer_t* hb_audio_resample(hb_audio_resample_t *resample, } else { - out_size = (nsamples * + out_samples = nsamples; + out_size = (out_samples * resample->out.sample_size * resample->out.channels); out = hb_buffer_init(out_size); memcpy(out->data, samples, out_size); } + /* Dual Mono to Mono. + * + * Copy all left or right samples to the first half of the buffer + * and halve the size */ + if (resample->dual_mono_downmix) + { + int ii; + int jj = !!resample->dual_mono_right_only; + float *audio_samples = (float*)out->data; + for (ii = 0; ii < out_samples; ii++) + { + audio_samples[ii] = audio_samples[jj]; + jj += 2; + } + out->size = out_samples * resample->out.sample_size; + } + return out; } diff --git a/libhb/audio_resample.h b/libhb/audio_resample.h index 3a01d8696..baee471a6 100644 --- a/libhb/audio_resample.h +++ b/libhb/audio_resample.h @@ -28,6 +28,9 @@ typedef struct { int do_remix; + int dual_mono_downmix; + int dual_mono_right_only; + int resample_needed; AVAudioResampleContext *avresample; diff --git a/libhb/common.c b/libhb/common.c index 6315498cc..821f17e76 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -20,93 +20,241 @@ * Global variables *********************************************************************/ hb_rate_t hb_video_rates[] = -{ { "5", 5400000 }, { "10", 2700000 }, { "12", 2250000 }, - { "15", 1800000 }, { "23.976", 1126125 }, { "24", 1125000 }, - { "25", 1080000 }, { "29.97", 900900 }, { "30", 900000 }, - { "50", 540000 }, { "59.94", 450450 }, { "60", 450000 } }; -int hb_video_rates_count = sizeof( hb_video_rates ) / - sizeof( hb_rate_t ); +{ + { "5", 5400000 }, + { "10", 2700000 }, + { "12", 2250000 }, + { "15", 1800000 }, + { "23.976", 1126125 }, + { "24", 1125000 }, + { "25", 1080000 }, + { "29.97", 900900 }, + { "30", 900000 }, + { "50", 540000 }, + { "59.94", 450450 }, + { "60", 450000 }, +}; +int hb_video_rates_count = sizeof(hb_video_rates) / sizeof(hb_rate_t); hb_rate_t hb_audio_rates[] = -{ { "22.05", 22050 }, { "24", 24000 }, { "32", 32000 }, - { "44.1", 44100 }, { "48", 48000 } }; -int hb_audio_rates_count = sizeof( hb_audio_rates ) / - sizeof( hb_rate_t ); -int hb_audio_rates_default = 3; /* 44100 Hz */ +{ + { "8", 8000 }, + { "11.025", 11025 }, + { "12", 12000 }, + { "16", 16000 }, + { "22.05", 22050 }, + { "24", 24000 }, + { "32", 32000 }, + { "44.1", 44100 }, + { "48", 48000 }, +}; +int hb_audio_rates_count = sizeof(hb_audio_rates) / sizeof(hb_rate_t); hb_rate_t hb_audio_bitrates[] = -{ { "32", 32 }, { "40", 40 }, { "48", 48 }, { "56", 56 }, - { "64", 64 }, { "80", 80 }, { "96", 96 }, { "112", 112 }, - { "128", 128 }, { "160", 160 }, { "192", 192 }, { "224", 224 }, - { "256", 256 }, { "320", 320 }, { "384", 384 }, { "448", 448 }, - { "512", 512 }, { "576", 576 }, { "640", 640 }, { "768", 768 } }; -int hb_audio_bitrates_count = sizeof( hb_audio_bitrates ) / - sizeof( hb_rate_t ); +{ + // AC3-compatible bitrates + { "32", 32 }, + { "40", 40 }, + { "48", 48 }, + { "56", 56 }, + { "64", 64 }, + { "80", 80 }, + { "96", 96 }, + { "112", 112 }, + { "128", 128 }, + { "160", 160 }, + { "192", 192 }, + { "224", 224 }, + { "256", 256 }, + { "320", 320 }, + { "384", 384 }, + { "448", 448 }, + { "512", 512 }, + { "576", 576 }, + { "640", 640 }, + // additional bitrates + { "768", 768 }, + { "960", 960 }, + { "1152", 1152 }, + { "1344", 1344 }, + { "1536", 1536 }, +}; +int hb_audio_bitrates_count = sizeof(hb_audio_bitrates) / sizeof(hb_rate_t); static hb_error_handler_t *error_handler = NULL; hb_mixdown_t hb_audio_mixdowns[] = -{ { "None", "HB_AMIXDOWN_NONE", "none", HB_AMIXDOWN_NONE }, - { "Mono", "HB_AMIXDOWN_MONO", "mono", HB_AMIXDOWN_MONO }, - { "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 } }; -int hb_audio_mixdowns_count = sizeof( hb_audio_mixdowns ) / - sizeof( hb_mixdown_t ); +{ + { "None", "HB_AMIXDOWN_NONE", "none", HB_AMIXDOWN_NONE }, + { "Mono", "HB_AMIXDOWN_MONO", "mono", HB_AMIXDOWN_MONO }, + { "Mono (Left Only)", "HB_AMIXDOWN_LEFT", "left_only", HB_AMIXDOWN_LEFT }, + { "Mono (Right Only)", "HB_AMIXDOWN_RIGHT", "right_only", HB_AMIXDOWN_RIGHT }, + { "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 }, + { "5.1 Channels", "HB_AMIXDOWN_5POINT1", "5point1", HB_AMIXDOWN_5POINT1 }, + { "6.1 Channels", "HB_AMIXDOWN_6POINT1", "6point1", HB_AMIXDOWN_6POINT1 }, + { "7.1 Channels", "HB_AMIXDOWN_7POINT1", "7point1", HB_AMIXDOWN_7POINT1 }, + { "7.1 (5F/2R/LFE)", "HB_AMIXDOWN_5_2_LFE", "5_2_lfe", HB_AMIXDOWN_5_2_LFE }, +}; +int hb_audio_mixdowns_count = sizeof(hb_audio_mixdowns) / sizeof(hb_mixdown_t); hb_encoder_t hb_video_encoders[] = -{ { "H.264 (x264)", "x264", HB_VCODEC_X264, HB_MUX_MP4|HB_MUX_MKV }, - { "MPEG-4 (FFmpeg)", "ffmpeg4", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MP4|HB_MUX_MKV }, - { "MPEG-2 (FFmpeg)", "ffmpeg2", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MP4|HB_MUX_MKV }, - { "VP3 (Theora)", "theora", HB_VCODEC_THEORA, HB_MUX_MKV } }; -int hb_video_encoders_count = sizeof( hb_video_encoders ) / - sizeof( hb_encoder_t ); +{ + { "H.264 (x264)", "x264", HB_VCODEC_X264, HB_MUX_MP4|HB_MUX_MKV }, + { "MPEG-4 (FFmpeg)", "ffmpeg4", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MP4|HB_MUX_MKV }, + { "MPEG-2 (FFmpeg)", "ffmpeg2", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MP4|HB_MUX_MKV }, + { "VP3 (Theora)", "theora", HB_VCODEC_THEORA, HB_MUX_MKV }, +}; +int hb_video_encoders_count = sizeof(hb_video_encoders) / sizeof(hb_encoder_t); hb_encoder_t hb_audio_encoders[] = { #ifdef __APPLE__ - { "AAC (CoreAudio)", "ca_aac", HB_ACODEC_CA_AAC, HB_MUX_MP4|HB_MUX_MKV }, - { "HE-AAC (CoreAudio)", "ca_haac", HB_ACODEC_CA_HAAC, HB_MUX_MP4|HB_MUX_MKV }, + { "AAC (CoreAudio)", "ca_aac", HB_ACODEC_CA_AAC, HB_MUX_MP4|HB_MUX_MKV }, + { "HE-AAC (CoreAudio)", "ca_haac", HB_ACODEC_CA_HAAC, HB_MUX_MP4|HB_MUX_MKV }, #endif - { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MP4|HB_MUX_MKV }, - { "AAC (ffmpeg)", "ffaac", HB_ACODEC_FFAAC, HB_MUX_MP4|HB_MUX_MKV }, - { "AAC Passthru", "copy:aac", HB_ACODEC_AAC_PASS, HB_MUX_MP4|HB_MUX_MKV }, - { "AC3 (ffmpeg)", "ffac3", HB_ACODEC_AC3, HB_MUX_MP4|HB_MUX_MKV }, - { "AC3 Passthru", "copy:ac3", HB_ACODEC_AC3_PASS, HB_MUX_MP4|HB_MUX_MKV }, - { "DTS Passthru", "copy:dts", HB_ACODEC_DCA_PASS, HB_MUX_MP4|HB_MUX_MKV }, - { "DTS-HD Passthru", "copy:dtshd", HB_ACODEC_DCA_HD_PASS, HB_MUX_MP4|HB_MUX_MKV }, - { "MP3 (lame)", "lame", HB_ACODEC_LAME, HB_MUX_MP4|HB_MUX_MKV }, - { "MP3 Passthru", "copy:mp3", HB_ACODEC_MP3_PASS, HB_MUX_MP4|HB_MUX_MKV }, - { "Vorbis (vorbis)", "vorbis", HB_ACODEC_VORBIS, HB_MUX_MKV }, - { "FLAC (ffmpeg)", "ffflac", HB_ACODEC_FFFLAC, HB_MUX_MKV }, - { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MP4|HB_MUX_MKV } }; -int hb_audio_encoders_count = sizeof( hb_audio_encoders ) / - sizeof( hb_encoder_t ); + { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MP4|HB_MUX_MKV }, + { "AAC (ffmpeg)", "ffaac", HB_ACODEC_FFAAC, HB_MUX_MP4|HB_MUX_MKV }, + { "AAC Passthru", "copy:aac", HB_ACODEC_AAC_PASS, HB_MUX_MP4|HB_MUX_MKV }, + { "AC3 (ffmpeg)", "ffac3", HB_ACODEC_AC3, HB_MUX_MP4|HB_MUX_MKV }, + { "AC3 Passthru", "copy:ac3", HB_ACODEC_AC3_PASS, HB_MUX_MP4|HB_MUX_MKV }, + { "DTS Passthru", "copy:dts", HB_ACODEC_DCA_PASS, HB_MUX_MP4|HB_MUX_MKV }, + { "DTS-HD Passthru", "copy:dtshd", HB_ACODEC_DCA_HD_PASS, HB_MUX_MP4|HB_MUX_MKV }, + { "MP3 (lame)", "lame", HB_ACODEC_LAME, HB_MUX_MP4|HB_MUX_MKV }, + { "MP3 Passthru", "copy:mp3", HB_ACODEC_MP3_PASS, HB_MUX_MP4|HB_MUX_MKV }, + { "Vorbis (vorbis)", "vorbis", HB_ACODEC_VORBIS, HB_MUX_MKV }, + { "FLAC (ffmpeg)", "ffflac", HB_ACODEC_FFFLAC, HB_MUX_MKV }, + { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MP4|HB_MUX_MKV }, +}; +int hb_audio_encoders_count = sizeof(hb_audio_encoders) / sizeof(hb_encoder_t); /* Expose values for PInvoke */ -hb_rate_t* hb_get_video_rates() { return hb_video_rates; } -int hb_get_video_rates_count() { return hb_video_rates_count; } -hb_rate_t* hb_get_audio_rates() { return hb_audio_rates; } -int hb_get_audio_rates_count() { return hb_audio_rates_count; } -int hb_get_audio_rates_default() { return hb_audio_rates_default; } -hb_rate_t* hb_get_audio_bitrates() { return hb_audio_bitrates; } -int hb_get_audio_bitrates_count() { return hb_audio_bitrates_count; } -hb_mixdown_t* hb_get_audio_mixdowns() { return hb_audio_mixdowns; } -int hb_get_audio_mixdowns_count() { return hb_audio_mixdowns_count; } -hb_encoder_t* hb_get_video_encoders() { return hb_video_encoders; } -int hb_get_video_encoders_count() { return hb_video_encoders_count; } -hb_encoder_t* hb_get_audio_encoders() { return hb_audio_encoders; } -int hb_get_audio_encoders_count() { return hb_audio_encoders_count; } +hb_rate_t* hb_get_video_rates() { return hb_video_rates; } +int hb_get_video_rates_count() { return hb_video_rates_count; } +hb_rate_t* hb_get_audio_rates() { return hb_audio_rates; } +int hb_get_audio_rates_count() { return hb_audio_rates_count; } +hb_rate_t* hb_get_audio_bitrates() { return hb_audio_bitrates; } +int hb_get_audio_bitrates_count() { return hb_audio_bitrates_count; } +hb_mixdown_t* hb_get_audio_mixdowns() { return hb_audio_mixdowns; } +int hb_get_audio_mixdowns_count() { return hb_audio_mixdowns_count; } +hb_encoder_t* hb_get_video_encoders() { return hb_video_encoders; } +int hb_get_video_encoders_count() { return hb_video_encoders_count; } +hb_encoder_t* hb_get_audio_encoders() { return hb_audio_encoders; } +int hb_get_audio_encoders_count() { return hb_audio_encoders_count; } + +int hb_mixdown_is_supported(int mixdown, uint32_t codec, uint64_t layout) +{ + return (hb_mixdown_has_codec_support(mixdown, codec) && + hb_mixdown_has_remix_support(mixdown, layout)); +} + +int hb_mixdown_has_codec_support(int mixdown, uint32_t codec) +{ + // Passthru, only "None" mixdown is supported + if (codec & HB_ACODEC_PASS_FLAG) + return (mixdown == HB_AMIXDOWN_NONE); + + // Not passthru, "None" mixdown never supported + if (mixdown == HB_AMIXDOWN_NONE) + return 0; + + switch (codec) + { + case HB_ACODEC_FFFLAC: + case HB_ACODEC_VORBIS: + return (mixdown <= HB_AMIXDOWN_7POINT1); + + case HB_ACODEC_LAME: + case HB_ACODEC_FFAAC: + return (mixdown <= HB_AMIXDOWN_DOLBYPLII); + + case HB_ACODEC_FAAC: + case HB_ACODEC_CA_AAC: + case HB_ACODEC_CA_HAAC: + return ((mixdown <= HB_AMIXDOWN_5POINT1) || + (mixdown == HB_AMIXDOWN_5_2_LFE)); + + default: + return (mixdown <= HB_AMIXDOWN_5POINT1); + } +} + +int hb_mixdown_has_remix_support(int mixdown, uint64_t layout) +{ + switch (mixdown) + { + // stereo + front left/right of center + case HB_AMIXDOWN_5_2_LFE: + return ((layout & AV_CH_FRONT_LEFT_OF_CENTER) && + (layout & AV_CH_FRONT_RIGHT_OF_CENTER) && + (layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO); + + // 7.0 or better + case HB_AMIXDOWN_7POINT1: + return ((layout & AV_CH_LAYOUT_7POINT0) == AV_CH_LAYOUT_7POINT0); + + // 6.0 or better + case HB_AMIXDOWN_6POINT1: + return ((layout & AV_CH_LAYOUT_7POINT0) == AV_CH_LAYOUT_7POINT0 || + (layout & AV_CH_LAYOUT_6POINT0) == AV_CH_LAYOUT_6POINT0 || + (layout & AV_CH_LAYOUT_HEXAGONAL) == AV_CH_LAYOUT_HEXAGONAL); + + // stereo + either of front center, side or back left/right, back center + case HB_AMIXDOWN_5POINT1: + return ((layout & AV_CH_LAYOUT_2_1) == AV_CH_LAYOUT_2_1 || + (layout & AV_CH_LAYOUT_2_2) == AV_CH_LAYOUT_2_2 || + (layout & AV_CH_LAYOUT_QUAD) == AV_CH_LAYOUT_QUAD || + (layout & AV_CH_LAYOUT_SURROUND) == AV_CH_LAYOUT_SURROUND); + + // stereo + either of side or back left/right, back center + // also, allow Dolby Surrounbd output if the input is already Dolby + case HB_AMIXDOWN_DOLBY: + case HB_AMIXDOWN_DOLBYPLII: + return ((layout & AV_CH_LAYOUT_2_1) == AV_CH_LAYOUT_2_1 || + (layout & AV_CH_LAYOUT_2_2) == AV_CH_LAYOUT_2_2 || + (layout & AV_CH_LAYOUT_QUAD) == AV_CH_LAYOUT_QUAD || + (layout == AV_CH_LAYOUT_STEREO_DOWNMIX && + mixdown == HB_AMIXDOWN_DOLBY)); + + // more than 1 channel + case HB_AMIXDOWN_STEREO: + return (av_get_channel_layout_nb_channels(layout) > 1); + + // regular stereo (not Dolby) + case HB_AMIXDOWN_LEFT: + case HB_AMIXDOWN_RIGHT: + return (layout == AV_CH_LAYOUT_STEREO); + + // mono remix always supported + // HB_AMIXDOWN_NONE always supported (for Passthru) + case HB_AMIXDOWN_MONO: + case HB_AMIXDOWN_NONE: + return 1; + + // unknown mixdown, should never happen + default: + return 0; + } +} int hb_mixdown_get_discrete_channel_count(int amixdown) { switch (amixdown) { - case HB_AMIXDOWN_6CH: + case HB_AMIXDOWN_5_2_LFE: + case HB_AMIXDOWN_7POINT1: + return 8; + + case HB_AMIXDOWN_6POINT1: + return 7; + + case HB_AMIXDOWN_5POINT1: return 6; case HB_AMIXDOWN_MONO: + case HB_AMIXDOWN_LEFT: + case HB_AMIXDOWN_RIGHT: return 1; case HB_AMIXDOWN_NONE: @@ -117,6 +265,21 @@ int hb_mixdown_get_discrete_channel_count(int amixdown) } } +int hb_mixdown_get_low_freq_channel_count(int amixdown) +{ + switch (amixdown) + { + case HB_AMIXDOWN_5POINT1: + case HB_AMIXDOWN_6POINT1: + case HB_AMIXDOWN_7POINT1: + case HB_AMIXDOWN_5_2_LFE: + return 1; + + default: + return 0; + } +} + int hb_mixdown_get_mixdown_from_short_name(const char *short_name) { int i; @@ -294,17 +457,15 @@ int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int // Given an input bitrate, find closest match in the set of allowed bitrates int hb_find_closest_audio_bitrate(int bitrate) { - int ii; - int result; - // Check if bitrate mode was disabled - if( bitrate <= 0 ) + if (bitrate <= 0) return bitrate; + int ii, result; // result is highest rate if none found during search. // rate returned will always be <= rate asked for. result = hb_audio_bitrates[0].rate; - for (ii = hb_audio_bitrates_count-1; ii >= 0; ii--) + for (ii = hb_audio_bitrates_count - 1; ii > 0; ii--) { if (bitrate >= hb_audio_bitrates[ii].rate) { @@ -315,259 +476,263 @@ int hb_find_closest_audio_bitrate(int bitrate) return result; } -// Get the bitrate low and high limits for a codec/samplerate/mixdown triplet -// The limits have been empirically determined through testing. Max bitrates -// in table below. Numbers in parenthesis are the target bitrate chosen. -/* -Encoder 1 channel 2 channels 6 channels - -faac -24kHz 86 (128) 173 (256) 460 (768) -48kHz 152 (160) 304 (320) 759 (768) +/* Get the bitrate low and high limits for a codec/samplerate/mixdown triplet. -Vorbis -24kHz 97 (80) 177 (160) 527 (512) -48kHz 241 (224) 465 (448) 783 (768) +Encoder 1.0 channel 2.0 channels 5.1 channels 6.1 channels 7.1 channels +-------------------------------------------------------------------------------------- -Lame -24kHz 146 (768) 138 (768) -48kHz 318 (768) 318 (768) +faac +---- +supported samplerates: 8 - 48 kHz +libfaac/util.c defines the bitrate limits: +MinBitrate() -> 8000 bps (per channel, incl. LFE). +MaxBitrate() -> (6144 * samplerate / 1024) bps (per channel, incl. LFE). +But output bitrates don't go as high as the theoretical maximums: +12 kHz 43 (72) 87 (144) 260 (432) 303 (504) 342 (576) +24 kHz 87 (144) 174 (288) 514 (864) 595 (1008) 669 (1152) +48 kHz 174 (288) 347 (576) 970 (1728) 1138 (2016) 1287 (2304) +Also, faac isn't a great encoder, so you don't want to allow too low a bitrate. +Limits: minimum of 32 Kbps per channel + maximum of 192 Kbps per channel at 32-48 kHz, adjusted for sr_shift + + +ffaac +----- +supported samplerates: 8 - 48 kHz +libavcodec/aacenc.c defines a maximum bitrate: +-> 6144 * samplerate / 1024 bps (per channel, incl. LFE). +But output bitrates don't go as high as the theoretical maximums: +12 kHz 61 (72) 123 (144) +24 kHz 121 (144) 242 (288) +48 kHz 236 (288) 472 (576) +Also, ffaac isn't a great encoder, so you don't want to allow too low a bitrate. +Limits: minimum of 32 Kbps per channel + maximum of 192 Kbps per channel at 32 kHz, adjusted for sr_shift + maximum of 256 Kbps per channel at 44.1-48 kHz, adjusted for sr_shift + +vorbis +------ +supported samplerates: 8 - 48 kHz +lib/modes/setup_*.h provides a range of allowed bitrates for various configurations. +for each samplerate, the highest minimums and lowest maximums are: + 8 kHz Minimum 8 Kbps, maximum 32 Kbps (per channel, incl. LFE). +12 kHz Minimum 14 Kbps, maximum 44 Kbps (per channel, incl. LFE). +16 kHz Minimum 16 Kbps, maximum 86 Kbps (per channel, incl. LFE). +24 kHz Minimum 22 Kbps, maximum 86 Kbps (per channel, incl. LFE). +32 kHz Minimum 26 Kbps, maximum 190 Kbps (per channel, incl. LFE). +48 kHz Minimum 28 Kbps, maximum 240 Kbps (per channel, incl. LFE). +Limits: minimum of 14/22/28 Kbps per channel (8-12, 16-24, 32-48 kHz) + maximum of 32/86/190/240 Kbps per channel (8-12, 16-24, 32, 44.1-48 kHz) + +lame +---- +supported samplerates: 8 - 48 kHz +lame_init_params() allows the following bitrates: +12 kHz Minimum 8 Kbps, maximum 64 Kbps +24 kHz Minimum 8 Kbps, maximum 160 Kbps +48 kHz Minimum 32 Kbps, maximum 320 Kbps +Limits: minimum of 8/8/32 Kbps (8-12, 16-24, 32-48 kHz) + maximum of 64/160/320 Kbps (8-12, 16-24, 32-48 kHz) ffac3 -24kHz 318 (320) 318 (320) 318 (320) -48kHz 636 (640) 636 (640) 636 (640) - -Core Audio AAC (core audio api provides range of allowed bitrates) -24kHz 16-64 32-128 80-320 -32kHz 24-96 48-192 128-448 -48kHz 32-256 64-320 160-768 - -Core Audio HE-AAC (core audio api provides range of allowed bitrates) -32kHz 12-40 24-80 64-192 -48kHz 16-40 32-80 80-192 +----- +supported samplerates: 32 - 48 kHz (< 32 kHz disabled for compatibility reasons) +Dolby's encoder has a min. of 224 Kbps for 5 full-bandwidth channels (5.0, 5.1) +The maximum AC3 bitrate is 640 Kbps +Limits: minimum of 224/5 Kbps per full-bandwidth channel, maximum of 640 Kbps + +ca_aac +------ +supported samplerates: 8 - 48 kHz +Core Audio API provides a range of allowed bitrates: + 8 kHz 8 - 24 16 - 48 40 - 112 48 - 144 56 - 160 +12 kHz 12 - 32 24 - 64 64 - 160 72 - 192 96 - 224 +16 kHz 12 - 48 24 - 96 64 - 224 72 - 288 96 - 320 +24 kHz 16 - 64 32 - 128 80 - 320 96 - 384 112 - 448 +32 kHz 24 - 96 48 - 192 128 - 448 144 - 576 192 - 640 +48 kHz 32 - 256 64 - 320 160 - 768 192 - 960 224 - 960 +Limits: + 8 kHz -> minimum of 8 Kbps and maximum of 24 Kbps per full-bandwidth channel +12 kHz -> minimum of 12 Kbps and maximum of 32 Kbps per full-bandwidth channel +16 kHz -> minimum of 12 Kbps and maximum of 48 Kbps per full-bandwidth channel +24 kHz -> minimum of 16 Kbps and maximum of 64 Kbps per full-bandwidth channel +32 kHz -> minimum of 24 Kbps and maximum of 96 Kbps per full-bandwidth channel +48 kHz -> minimum of 32 Kbps and maximum of 160 Kbps per full-bandwidth channel +48 kHz -> maximum of +96 Kbps for Mono +Note: encCoreAudioInit() will sanitize any mistake made here. + +ca_haac +------- +supported samplerates: 32 - 48 kHz +Core Audio API provides a range of allowed bitrates: +32 kHz 12 - 40 24 - 80 64 - 192 N/A 96 - 256 +48 kHz 16 - 40 32 - 80 80 - 192 N/A 112 - 256 +Limits: minimum of 12 (+ 4 if rate >= 44100) Kbps per full-bandwidth channel + maximum of 40 Kbps per full-bandwidth channel +Note: encCoreAudioInit() will sanitize any mistake made here. */ -void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown, int *low, int *high) +void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown, + int *low, int *high) { - int channels; - - channels = hb_mixdown_get_discrete_channel_count( mixdown ); - if( codec & HB_ACODEC_PASS_FLAG ) + if (codec & HB_ACODEC_PASS_FLAG) { - // Bitrates don't apply to "lossless" audio (Passthru, FLAC), but may apply - // if we fallback to an encoder when the source can't be passed through. + // Bitrates don't apply to passthrough audio, but may apply if we + // fallback to an encoder when the source can't be passed through. *low = hb_audio_bitrates[0].rate; *high = hb_audio_bitrates[hb_audio_bitrates_count-1].rate; return; } - switch( codec ) + + /* samplerate, sr_shift */ + int sr_shift; + samplerate = hb_get_best_samplerate(codec, samplerate, &sr_shift); + + /* LFE, full-bandwidth channels */ + int lfe_count, nchannels; + lfe_count = hb_mixdown_get_low_freq_channel_count(mixdown); + nchannels = hb_mixdown_get_discrete_channel_count(mixdown) - lfe_count; + + switch (codec) { + // Bitrates don't apply to "lossless" audio case HB_ACODEC_FFFLAC: - // Bitrates don't apply to "lossless" audio (Passthru, FLAC) - *high = *low = -1; - break; + *low = *high = -1; + return; case HB_ACODEC_AC3: - *low = 32 * channels; - if (samplerate > 24000) - { - *high = 640; - } - else - { - *high = 320; - } + *low = 224 * nchannels / 5; + *high = 640; break; case HB_ACODEC_CA_AAC: - if (samplerate > 32000) - { - *low = channels * 32; - if (channels == 1) - *high = 256; - if (channels == 2) - *high = 320; - if (channels == 6) - { - *low = 160; - *high = 768; - } - } - else if (samplerate > 24000) - { - *low = channels * 24; - *high = channels * 96; - if (channels == 6) - { - *low = 128; - *high = 448; - } - } - else + { + switch (samplerate) { - *low = channels * 16; - *high = channels * 64; - if (channels == 6) - { - *low = 80; - *high = 320; - } + case 8000: + *low = nchannels * 8; + *high = nchannels * 24; + break; + case 11025: + case 12000: + *low = nchannels * 12; + *high = nchannels * 32; + break; + case 16000: + *low = nchannels * 12; + *high = nchannels * 48; + break; + case 22050: + case 24000: + *low = nchannels * 16; + *high = nchannels * 64; + break; + case 32000: + *low = nchannels * 24; + *high = nchannels * 96; + break; + case 44100: + case 48000: + default: + *low = nchannels * 32; + *high = nchannels * (160 + (96 * (nchannels == 1))); + break; } - break; + } break; case HB_ACODEC_CA_HAAC: - if (samplerate > 32000) - { - *low = channels * 16; - *high = channels * 40; - if (channels == 6) - { - *low = 80; - *high = 192; - } - } - else - { - *low = channels * 12; - *high = channels * 40; - if (channels == 6) - { - *low = 64; - *high = 192; - } - } + *low = nchannels * (12 + (4 * (samplerate >= 44100))); + *high = nchannels * 40; break; case HB_ACODEC_FAAC: - *low = 32 * channels; - if (samplerate > 24000) - { - *high = 160 * channels; - if (*high > 768) - *high = 768; - } - else - { - *high = 96 * channels; - if (*high > 480) - *high = 480; - } + *low = (nchannels + lfe_count) * 32; + *high = (nchannels + lfe_count) * (192 >> sr_shift); break; case HB_ACODEC_FFAAC: - *low = 32 * channels; - if (samplerate > 24000) - { - *high = 160 * channels; - if (*high > 768) - *high = 768; - } - else - { - *high = 96 * channels; - if (*high > 480) - *high = 480; - } + *low = ((nchannels + lfe_count) * 32); + *high = ((nchannels + lfe_count) * + ((192 + (64 * ((samplerate << sr_shift) >= 44100))) + >> sr_shift)); break; - case HB_ACODEC_VORBIS: - *high = channels * 80; - if (samplerate > 24000) - { - if (channels > 2) - { - // Vorbis minimum is around 30kbps/ch for 6ch - // at rates > 24k (32k/44.1k/48k) - *low = 32 * channels; - *high = 128 * channels; - } - else - { - // Allow 24kbps mono and 48kbps stereo at rates > 24k - // (32k/44.1k/48k) - *low = 24 * channels; - if (samplerate > 32000) - *high = channels * 224; - else - *high = channels * 160; - } - } - else - { - *low = channels * 16; - *high = 80 * channels; - } + case HB_ACODEC_LAME: + *low = 8 + (24 * (sr_shift < 1)); + *high = 64 + (96 * (sr_shift < 2)) + (160 * (sr_shift < 1)); break; - case HB_ACODEC_LAME: - *low = hb_audio_bitrates[0].rate; - if (samplerate > 24000) - *high = 320; - else - *high = 160; + case HB_ACODEC_VORBIS: + *low = (nchannels + lfe_count) * (14 + + (8 * (sr_shift < 2)) + + (6 * (sr_shift < 1))); + *high = (nchannels + lfe_count) * (32 + + ( 54 * (sr_shift < 2)) + + (104 * (sr_shift < 1)) + + ( 50 * (samplerate >= 44100))); break; - + default: - *low = hb_audio_bitrates[0].rate; + *low = hb_audio_bitrates[0].rate; *high = hb_audio_bitrates[hb_audio_bitrates_count-1].rate; break; } + // sanitize max. bitrate + if (*high < hb_audio_bitrates[0].rate) + *high = hb_audio_bitrates[0].rate; + if (*high > hb_audio_bitrates[hb_audio_bitrates_count-1].rate) + *high = hb_audio_bitrates[hb_audio_bitrates_count-1].rate; } -// Given an input bitrate, sanitize it. Check low and high limits and -// make sure it is in the set of allowed bitrates. -int hb_get_best_audio_bitrate( uint32_t codec, int bitrate, int samplerate, int mixdown) +// Given an input bitrate, sanitize it. +// Check low and high limits and make sure it is in the set of allowed bitrates. +int hb_get_best_audio_bitrate(uint32_t codec, int bitrate, int samplerate, + int mixdown) { int low, high; - hb_get_audio_bitrate_limits(codec, samplerate, mixdown, &low, &high); if (bitrate > high) bitrate = high; if (bitrate < low) bitrate = low; - bitrate = hb_find_closest_audio_bitrate(bitrate); - return bitrate; + return hb_find_closest_audio_bitrate(bitrate); } // Get the default bitrate for a given codec/samplerate/mixdown triplet. -int hb_get_default_audio_bitrate( uint32_t codec, int samplerate, int mixdown ) +int hb_get_default_audio_bitrate(uint32_t codec, int samplerate, int mixdown) { - int bitrate, channels; - int sr_shift; - - if( codec & HB_ACODEC_PASS_FLAG ) + if (codec & HB_ACODEC_PASS_FLAG) + { return -1; + } - channels = hb_mixdown_get_discrete_channel_count( mixdown ); - - // Min bitrate is established such that we get good quality - // audio as a minimum. - sr_shift = (samplerate <= 24000) ? 1 : 0; + int bitrate, nchannels, sr_shift; + /* full-bandwidth channels, sr_shift */ + nchannels = (hb_mixdown_get_discrete_channel_count(mixdown) - + hb_mixdown_get_low_freq_channel_count(mixdown)); + hb_get_best_samplerate(codec, samplerate, &sr_shift); - switch ( codec ) + switch (codec) { case HB_ACODEC_FFFLAC: - bitrate = -1; - sr_shift = 0; - break; + return -1; + + // 96, 224, 640 Kbps case HB_ACODEC_AC3: - if (channels == 1) - bitrate = 96; - else if (channels <= 2) - bitrate = 224; - else - bitrate = 640; + bitrate = (nchannels * 128) - (32 * (nchannels < 5)); break; + case HB_ACODEC_CA_HAAC: - bitrate = channels * 32; + bitrate = nchannels * 32; break; + default: - bitrate = channels * 80; + bitrate = nchannels * 80; break; } + // sample_rate adjustment bitrate >>= sr_shift; - bitrate = hb_get_best_audio_bitrate( codec, bitrate, samplerate, mixdown ); - return bitrate; + return hb_get_best_audio_bitrate(codec, bitrate, samplerate, mixdown); } // Get limits and hints for the UIs. @@ -577,9 +742,10 @@ int hb_get_default_audio_bitrate( uint32_t codec, int samplerate, int mixdown ) // // direction says whether 'low' limit is highest or lowest // quality (direction 0 == lowest value is worst quality) -void hb_get_audio_quality_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction) +void hb_get_audio_quality_limits(uint32_t codec, float *low, float *high, + float *granularity, int *direction) { - switch( codec ) + switch (codec) { case HB_ACODEC_LAME: *direction = 1; @@ -610,11 +776,10 @@ void hb_get_audio_quality_limits(uint32_t codec, float *low, float *high, float } } -float hb_get_best_audio_quality( uint32_t codec, float quality) +float hb_get_best_audio_quality(uint32_t codec, float quality) { float low, high, granularity; int direction; - hb_get_audio_quality_limits(codec, &low, &high, &granularity, &direction); if (quality > high) quality = high; @@ -654,9 +819,10 @@ float hb_get_default_audio_quality( uint32_t codec ) // // direction says whether 'low' limit is highest or lowest // compression level (direction 0 == lowest value is worst compression level) -void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction) +void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high, + float *granularity, int *direction) { - switch( codec ) + switch (codec) { case HB_ACODEC_FFFLAC: *direction = 0; @@ -680,12 +846,11 @@ void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high, fl } } -float hb_get_best_audio_compression( uint32_t codec, float compression) +float hb_get_best_audio_compression(uint32_t codec, float compression) { float low, high, granularity; int direction; - - hb_get_audio_compression_limits( codec, &low, &high, &granularity, &direction ); + hb_get_audio_compression_limits(codec, &low, &high, &granularity, &direction); if( compression > high ) compression = high; if( compression < low ) @@ -693,72 +858,39 @@ float hb_get_best_audio_compression( uint32_t codec, float compression) return compression; } -float hb_get_default_audio_compression( uint32_t codec ) +float hb_get_default_audio_compression(uint32_t codec) { - float compression; - switch( codec ) + switch (codec) { case HB_ACODEC_FFFLAC: - compression = 5; - break; + return 5.; case HB_ACODEC_LAME: - compression = 2; - break; + return 2.; default: - compression = -1; - break; + return -1.; } - return compression; } int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown) { - int best_mixdown; - + // Passthru, only "None" mixdown is supported if (codec & HB_ACODEC_PASS_FLAG) - { - // Audio passthrough, no mixdown return HB_AMIXDOWN_NONE; - } - else if ((layout & AV_CH_LAYOUT_2_1) == AV_CH_LAYOUT_2_1 || - (layout & AV_CH_LAYOUT_2_2) == AV_CH_LAYOUT_2_2 || - (layout & AV_CH_LAYOUT_QUAD) == AV_CH_LAYOUT_QUAD) - { - // at least 2 front channels and one back or side channel - // allow downmixing or upmixing to 5.1 (yes, we can) - if (codec != HB_ACODEC_LAME && codec != HB_ACODEC_FFAAC) - { - best_mixdown = HB_AMIXDOWN_6CH; - } - else - { - best_mixdown = HB_AMIXDOWN_DOLBYPLII; - } - } - else if (layout == AV_CH_LAYOUT_STEREO_DOWNMIX) - { - // Dolby in, allow Dolby out - best_mixdown = HB_AMIXDOWN_DOLBY; - } - else if (av_get_channel_layout_nb_channels(layout) > 1) - { - // more than one channel, allow Stereo downmix - best_mixdown = HB_AMIXDOWN_STEREO; - } - else - { - // only one channel, not much point in upmixing - best_mixdown = HB_AMIXDOWN_MONO; - } - // return the best that is not greater than the requested mixdown - // HB_INVALID_AMIXDOWN means the caller requested the best available mixdown - if (best_mixdown > mixdown && mixdown != HB_INVALID_AMIXDOWN) - best_mixdown = mixdown; + // caller requested the best available mixdown + if (mixdown == HB_INVALID_AMIXDOWN) + mixdown = hb_audio_mixdowns[hb_audio_mixdowns_count].amixdown; - return best_mixdown; + int ii; + // test all mixdowns until an authorized, supported mixdown is found + // stop before we reach the "worst" non-None mixdown (index == 1) + for (ii = hb_audio_mixdowns_count; ii > 1; ii--) + if (hb_audio_mixdowns[ii].amixdown <= mixdown && + hb_mixdown_is_supported(hb_audio_mixdowns[ii].amixdown, codec, layout)) + break; + return hb_audio_mixdowns[ii].amixdown; } int hb_get_default_mixdown(uint32_t codec, uint64_t layout) @@ -766,10 +898,13 @@ int hb_get_default_mixdown(uint32_t codec, uint64_t layout) int mixdown; switch (codec) { - // the FLAC and AC3 encoders default to the best mixdown up to 6-channel + // the FLAC encoder defaults to the best mixdown up to 7.1 case HB_ACODEC_FFFLAC: + mixdown = HB_AMIXDOWN_7POINT1; + break; + // the AC3 encoder defaults to the best mixdown up to 5.1 case HB_ACODEC_AC3: - mixdown = HB_AMIXDOWN_6CH; + mixdown = HB_AMIXDOWN_5POINT1; break; // other encoders default to the best mixdown up to DPLII default: @@ -780,6 +915,52 @@ int hb_get_default_mixdown(uint32_t codec, uint64_t layout) return hb_get_best_mixdown(codec, layout, mixdown); } +int hb_get_best_samplerate(uint32_t codec, int samplerate, int *sr_shift) +{ + int ii, best_samplerate, samplerate_shift; + if ((samplerate < 32000) && + (codec == HB_ACODEC_CA_HAAC || codec == HB_ACODEC_AC3)) + { + // ca_haac can't do samplerates < 32 kHz + // AC-3 < 32 kHz suffers from poor hardware compatibility + best_samplerate = 32000; + samplerate_shift = 0; + } + else + { + best_samplerate = samplerate; + for (ii = hb_audio_rates_count - 1; ii >= 0; ii--) + { + // valid samplerate + if (best_samplerate == hb_audio_rates[ii].rate) + break; + + // samplerate is higher than the next valid samplerate, + // or lower than the lowest valid samplerate + if (best_samplerate > hb_audio_rates[ii].rate || ii == 0) + { + best_samplerate = hb_audio_rates[ii].rate; + break; + } + } + /* sr_shift: 0 -> 48000, 44100, 32000 Hz + * 1 -> 24000, 22050, 16000 Hz + * 2 -> 12000, 11025, 8000 Hz + * + * also, since samplerates are sanitized downwards: + * + * (samplerate < 32000) implies (samplerate <= 24000) + */ + samplerate_shift = ((best_samplerate < 16000) ? 2 : + (best_samplerate < 32000) ? 1 : 0); + } + if (sr_shift != NULL) + { + *sr_shift = samplerate_shift; + } + return best_samplerate; +} + /********************************************************************** * hb_reduce ********************************************************************** diff --git a/libhb/common.h b/libhb/common.h index 1650f8002..77898cef3 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -197,7 +197,11 @@ int hb_get_video_encoders_count(); hb_encoder_t* hb_get_audio_encoders(); int hb_get_audio_encoders_count(); +int hb_mixdown_is_supported(int mixdown, uint32_t codec, uint64_t layout); +int hb_mixdown_has_codec_support(int mixdown, uint32_t codec); +int hb_mixdown_has_remix_support(int mixdown, uint64_t layout); int hb_mixdown_get_discrete_channel_count(int amixdown); +int hb_mixdown_get_low_freq_channel_count(int amixdown); int hb_mixdown_get_mixdown_from_short_name(const char *short_name); const char* hb_mixdown_get_short_name_from_mixdown(int amixdown); @@ -206,6 +210,7 @@ void hb_autopassthru_print_settings( hb_job_t * job ); int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int muxer ); int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown); int hb_get_default_mixdown(uint32_t codec, uint64_t layout); +int hb_get_best_samplerate(uint32_t codec, int samplerate, int *sr_shift); int hb_find_closest_audio_bitrate(int bitrate); void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown, int *low, int *high); int hb_get_best_audio_bitrate( uint32_t codec, int bitrate, int samplerate, int mixdown); @@ -438,10 +443,15 @@ struct hb_audio_config_s HB_INVALID_AMIXDOWN = -1, HB_AMIXDOWN_NONE = 0, HB_AMIXDOWN_MONO, + HB_AMIXDOWN_LEFT, + HB_AMIXDOWN_RIGHT, HB_AMIXDOWN_STEREO, HB_AMIXDOWN_DOLBY, HB_AMIXDOWN_DOLBYPLII, - HB_AMIXDOWN_6CH, + HB_AMIXDOWN_5POINT1, + HB_AMIXDOWN_6POINT1, + HB_AMIXDOWN_7POINT1, + HB_AMIXDOWN_5_2_LFE, } mixdown; /* Audio mixdown */ int track; /* Output track number */ uint32_t codec; /* Output audio codec */ diff --git a/libhb/encfaac.c b/libhb/encfaac.c index 675881e8e..c6a3f8a16 100644 --- a/libhb/encfaac.c +++ b/libhb/encfaac.c @@ -40,21 +40,6 @@ hb_work_object_t hb_encfaac = encfaacClose }; -static const int valid_rates[] = -{ - 22050, 24000, 32000, 44100, 48000, 0 -}; - -static int find_samplerate( int rate ) -{ - int i; - - for ( i = 0; valid_rates[i] && rate > valid_rates[i]; ++i ) - { - } - return i; -} - /*********************************************************************** * hb_work_encfaac_init *********************************************************************** @@ -75,28 +60,6 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job ) /* pass the number of channels used into the private work data */ pv->out_discrete_channels = hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown); - /* if the sample rate is 'auto' and that has given us an invalid output */ - /* rate, map it to the next highest output rate or 48K if above the highest. */ - int rate_index = find_samplerate(audio->config.out.samplerate); - if ( audio->config.out.samplerate != valid_rates[rate_index] ) - { - int rate = valid_rates[valid_rates[rate_index]? rate_index : rate_index - 1]; - hb_log( "encfaac changing output samplerate from %d to %d", - audio->config.out.samplerate, rate ); - audio->config.out.samplerate = rate; - - /* if the new rate is over the max bandwidth per channel limit */ - /* lower the bandwidth. */ - double bw = audio->config.out.bitrate * 1000 / pv->out_discrete_channels; - if ( bw > (double)rate * (6144./1024.) ) - { - int newbr = (double)rate * (6.144/1024.) * pv->out_discrete_channels; - hb_log( "encfaac changing output bitrate from %d to %d", - audio->config.out.bitrate, newbr ); - audio->config.out.bitrate = newbr; - } - } - 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 ) ); @@ -110,7 +73,7 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job ) cfg->aacObjectType = LOW; cfg->allowMidside = 1; - // channel remapping, LFE + /* channel configuration & remapping */ uint64_t layout; int *remap_table; layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, NULL); @@ -123,7 +86,33 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job ) pv->out_discrete_channels * sizeof(int)); free(remap_table); } - cfg->useLfe = !!(layout & AV_CH_LOW_FREQUENCY); + switch (audio->config.out.mixdown) + { + case HB_AMIXDOWN_7POINT1: + cfg->channelConfiguration = 0; + cfg->numFrontChannels = 3; + cfg->numSideChannels = 2; + cfg->numBackChannels = 2; + cfg->numLFEChannels = 1; + break; + + case HB_AMIXDOWN_6POINT1: + cfg->channelConfiguration = 0; + cfg->numFrontChannels = 3; + cfg->numSideChannels = 0; + cfg->numBackChannels = 3; + cfg->numLFEChannels = 1; + break; + + case HB_AMIXDOWN_5_2_LFE: + cfg->channelConfiguration = 7; + break; + + default: + cfg->channelConfiguration = + hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown); + break; + } cfg->useTns = 0; cfg->bitRate = audio->config.out.bitrate * 1000 / pv->out_discrete_channels; /* Per channel */ diff --git a/libhb/encvorbis.c b/libhb/encvorbis.c index a5325ef6d..4bd36b43a 100644 --- a/libhb/encvorbis.c +++ b/libhb/encvorbis.c @@ -72,18 +72,6 @@ int encvorbisInit(hb_work_object_t *w, hb_job_t *job) if (audio->config.out.bitrate > 0) { - /* 28kbps/channel seems to be the minimum for 6ch vorbis. */ - int min_bitrate = 28 * pv->out_discrete_channels; - 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", - audio->config.out.bitrate, pv->out_discrete_channels); - hb_log("encvorbis: Resetting bitrate to %d kbps", min_bitrate); - /* Naughty! We shouldn't modify the audio from here. */ - audio->config.out.bitrate = min_bitrate; - } - if (vorbis_encode_setup_managed(&pv->vi, pv->out_discrete_channels, audio->config.out.samplerate, -1, audio->config.out.bitrate * 1000, -1)) diff --git a/libhb/hb.c b/libhb/hb.c index ed074f93d..12377a8b5 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -221,6 +221,8 @@ uint64_t hb_ff_mixdown_xlat(int hb_mixdown, int *downmix_mode) break; case HB_AMIXDOWN_MONO: + case HB_AMIXDOWN_LEFT: + case HB_AMIXDOWN_RIGHT: ff_layout = AV_CH_LAYOUT_MONO; break; @@ -238,13 +240,27 @@ uint64_t hb_ff_mixdown_xlat(int hb_mixdown, int *downmix_mode) ff_layout = AV_CH_LAYOUT_STEREO; break; - case HB_AMIXDOWN_6CH: + case HB_AMIXDOWN_5POINT1: ff_layout = AV_CH_LAYOUT_5POINT1; break; + case HB_AMIXDOWN_6POINT1: + ff_layout = AV_CH_LAYOUT_6POINT1; + break; + + case HB_AMIXDOWN_7POINT1: + ff_layout = AV_CH_LAYOUT_7POINT1; + break; + + case HB_AMIXDOWN_5_2_LFE: + ff_layout = (AV_CH_LAYOUT_5POINT1_BACK| + AV_CH_FRONT_LEFT_OF_CENTER| + AV_CH_FRONT_RIGHT_OF_CENTER); + break; + default: ff_layout = AV_CH_LAYOUT_STEREO; - hb_log("unrecognized channel layout"); + hb_log("hb_ff_mixdown_xlat: unsupported mixdown %d", hb_mixdown); break; } if (downmix_mode != NULL) diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index 2203193a1..d21e4b767 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -295,7 +295,7 @@ static int MP4Init( hb_mux_object_t * m ) bsmod = 0; freq = audio->config.out.samplerate; bitrate = audio->config.out.bitrate * 1000; - switch( audio->config.out.mixdown ) + switch (audio->config.out.mixdown) { case HB_AMIXDOWN_MONO: acmod = 1; @@ -309,13 +309,13 @@ static int MP4Init( hb_mux_object_t * m ) lfeon = 0; break; - case HB_AMIXDOWN_6CH: + case HB_AMIXDOWN_5POINT1: acmod = 7; lfeon = 1; break; default: - hb_log(" MP4Init: bad mixdown" ); + hb_log("MP4Init: bad mixdown"); acmod = 2; lfeon = 0; break; diff --git a/libhb/work.c b/libhb/work.c index 141ec4b3b..9dffb5f46 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -405,14 +405,14 @@ void hb_display_job_info( hb_job_t * job ) else if( subtitle->source == SRTSUB ) { /* For SRT, print offset and charset too */ - hb_log( " * subtitle track %i, %s (track %d, id 0x%x) Text [SRT] -> Passthrough%s, offset: %"PRId64", charset: %s", + hb_log( " * subtitle track %d, %s (track %d, id 0x%x) Text [SRT] -> Passthrough%s, offset: %"PRId64", charset: %s", subtitle->out_track, subtitle->lang, subtitle->track, subtitle->id, subtitle->config.default_track ? ", Default" : "", subtitle->config.offset, subtitle->config.src_codeset ); } else { - hb_log( " * subtitle track %i, %s (track %d, id 0x%x) %s [%s] -> %s%s%s", + hb_log( " * subtitle track %d, %s (track %d, id 0x%x) %s [%s] -> %s%s%s", subtitle->out_track, subtitle->lang, subtitle->track, subtitle->id, subtitle->format == PICTURESUB ? "Picture" : "Text", hb_subsource_name( subtitle->source ), @@ -782,36 +782,15 @@ static void do_job( hb_job_t * job ) free(audio); continue; } - if (!(audio->config.out.codec & HB_ACODEC_PASS_FLAG)) - { - if (audio->config.out.samplerate < 0) - { - // if not specified, set to same as input - audio->config.out.samplerate = audio->config.in.samplerate; - } - if (audio->config.out.samplerate > 48000) - { - hb_log("Sample rate %d not supported. Downsampling to 48kHz for track %d", - audio->config.out.samplerate, audio->config.out.track); - audio->config.out.samplerate = 48000; - } - else if (audio->config.out.samplerate < 32000 && - audio->config.out.codec == HB_ACODEC_CA_HAAC) - { - // Core Audio HE-AAC doesn't support samplerates < 32 kHz - hb_log("Sample rate %d not supported (ca_haac). Using 32kHz for track %d", - audio->config.out.samplerate, audio->config.out.track); - audio->config.out.samplerate = 32000; - } - } /* Adjust output track number, in case we removed one. * Output tracks sadly still need to be in sequential order. * Note: out.track starts at 1, i starts at 0 */ audio->config.out.track = ++i; } - int best_mixdown = 0; - int best_bitrate = 0; + int best_mixdown = 0; + int best_bitrate = 0; + int best_samplerate = 0; for (i = 0; i < hb_list_count(title->list_audio); i++) { @@ -831,6 +810,31 @@ static void do_job( hb_job_t * job ) if (audio->config.out.codec == HB_ACODEC_VORBIS) audio->priv.config.vorbis.language = audio->config.lang.simple; + /* sense-check the requested samplerate */ + if (audio->config.out.samplerate < 0) + { + // if not specified, set to same as input + audio->config.out.samplerate = audio->config.in.samplerate; + } + best_samplerate = + hb_get_best_samplerate(audio->config.out.codec, + audio->config.out.samplerate, NULL); + if (best_samplerate != audio->config.out.samplerate) + { + int ii; + for (ii = 0; ii < hb_audio_rates_count; ii++) + { + if (best_samplerate == hb_audio_rates[ii].rate) + { + hb_log("work: sanitizing track %d unsupported samplerate %d Hz to %s kHz", + audio->config.out.track, audio->config.out.samplerate, + hb_audio_rates[ii].string); + break; + } + } + audio->config.out.samplerate = best_samplerate; + } + /* sense-check the requested mixdown */ if (audio->config.out.mixdown <= HB_AMIXDOWN_NONE) { @@ -842,7 +846,7 @@ static void do_job( hb_job_t * job ) { if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) { - hb_log("work: mixdown not specified, track %i setting mixdown %s", + hb_log("work: mixdown not specified, track %d setting mixdown %s", audio->config.out.track, hb_audio_mixdowns[j].human_readable_name); break; @@ -851,10 +855,10 @@ static void do_job( hb_job_t * job ) } else { - best_mixdown = hb_get_best_mixdown(audio->config.out.codec, - audio->config.in.channel_layout, - audio->config.out.mixdown); - + best_mixdown = + hb_get_best_mixdown(audio->config.out.codec, + audio->config.in.channel_layout, + audio->config.out.mixdown); if (audio->config.out.mixdown != best_mixdown) { int prev_mix_idx = 0, best_mix_idx = 0; @@ -870,7 +874,7 @@ static void do_job( hb_job_t * job ) } } /* log the output mixdown */ - hb_log("work: sanitizing track %i mixdown %s to %s", + hb_log("work: sanitizing track %d mixdown %s to %s", audio->config.out.track, hb_audio_mixdowns[prev_mix_idx].human_readable_name, hb_audio_mixdowns[best_mix_idx].human_readable_name); @@ -942,14 +946,13 @@ static void do_job( hb_job_t * job ) if (audio->config.out.bitrate <= 0) { /* Bitrate not specified, set the default bitrate */ - audio->config.out.bitrate = + audio->config.out.bitrate = hb_get_default_audio_bitrate(audio->config.out.codec, audio->config.out.samplerate, audio->config.out.mixdown); - if (audio->config.out.bitrate > 0) { - hb_log("work: bitrate not specified, track %d setting bitrate %d", + hb_log("work: bitrate not specified, track %d setting bitrate %d Kbps", audio->config.out.track, audio->config.out.bitrate); } @@ -961,12 +964,11 @@ static void do_job( hb_job_t * job ) audio->config.out.bitrate, audio->config.out.samplerate, audio->config.out.mixdown); - if (best_bitrate > 0 && best_bitrate != audio->config.out.bitrate) { /* log the output bitrate */ - hb_log("work: sanitizing track %d bitrate %d to %d", + hb_log("work: sanitizing track %d bitrate %d to %d Kbps", audio->config.out.track, audio->config.out.bitrate, best_bitrate); } |