diff options
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/common.c | 206 | ||||
-rw-r--r-- | libhb/common.h | 13 | ||||
-rw-r--r-- | libhb/encavcodecaudio.c | 4 | ||||
-rw-r--r-- | libhb/module.defs | 4 | ||||
-rw-r--r-- | libhb/muxavformat.c | 17 | ||||
-rw-r--r-- | libhb/work.c | 5 |
6 files changed, 187 insertions, 62 deletions
diff --git a/libhb/common.c b/libhb/common.c index c75e4e564..50b596a98 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -31,6 +31,8 @@ #include <windows.h> #endif +static int mixdown_get_opus_coupled_stream_count(int mixdown); + /********************************************************************** * Global variables *********************************************************************/ @@ -63,6 +65,7 @@ enum HB_GID_ACODEC_MP3_PASS, HB_GID_ACODEC_TRUEHD_PASS, HB_GID_ACODEC_VORBIS, + HB_GID_ACODEC_OPUS, HB_GID_MUX_MKV, HB_GID_MUX_MP4, }; @@ -324,6 +327,7 @@ hb_encoder_internal_t hb_audio_encoders[] = { { "FLAC 16-bit", "flac16", "FLAC 16-bit (libavcodec)", HB_ACODEC_FFFLAC, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_FLAC, }, { { "FLAC 24-bit", "flac24", "FLAC 24-bit (libavcodec)", HB_ACODEC_FFFLAC24, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_FLAC, }, { { "FLAC Passthru", "copy:flac", "FLAC Passthru", HB_ACODEC_FLAC_PASS, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_FLAC_PASS, }, + { { "Opus", "opus", "Opus (libopus)", HB_ACODEC_OPUS, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_OPUS, }, { { "Auto Passthru", "copy", "Auto Passthru", HB_ACODEC_AUTO_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AUTO_PASS, }, }; int hb_audio_encoders_count = sizeof(hb_audio_encoders) / sizeof(hb_audio_encoders[0]); @@ -361,6 +365,9 @@ static int hb_audio_encoder_is_enabled(int encoder) case HB_ACODEC_FFFLAC24: return avcodec_find_encoder(AV_CODEC_ID_FLAC) != NULL; + case HB_ACODEC_OPUS: + return avcodec_find_encoder(AV_CODEC_ID_OPUS) != NULL; + // the following encoders are always enabled case HB_ACODEC_LAME: case HB_ACODEC_VORBIS: @@ -742,56 +749,56 @@ int hb_video_framerate_get_close(hb_rational_t *framerate, double thresh) return result; } -int hb_audio_samplerate_get_best(uint32_t codec, int samplerate, int *sr_shift) +int hb_audio_samplerate_is_supported(int samplerate, uint32_t codec) { - int best_samplerate; - if (samplerate < 32000 && (codec == HB_ACODEC_AC3 || - codec == HB_ACODEC_FFEAC3 || - codec == HB_ACODEC_CA_HAAC)) - { - // ca_haac can't do samplerates < 32 kHz - // libav's E-AC-3 encoder can't do samplerates < 32 kHz - // AC-3 < 32 kHz suffers from poor hardware compatibility - best_samplerate = 32000; - } - else if (samplerate < 16000 && codec == HB_ACODEC_FDK_HAAC) - { - // fdk_haac can't do samplerates < 16 kHz - best_samplerate = 16000; - } - else + switch (codec) { - best_samplerate = hb_audio_rates_first_item->rate; - const hb_rate_t *audio_samplerate = NULL; - while ((audio_samplerate = hb_audio_samplerate_get_next(audio_samplerate)) != NULL) - { - if (samplerate == audio_samplerate->rate) - { - // valid samplerate - best_samplerate = audio_samplerate->rate; - break; - } - if (samplerate > audio_samplerate->rate) + case HB_ACODEC_AC3: + case HB_ACODEC_FFEAC3: + case HB_ACODEC_CA_HAAC: + // ca_haac can't do samplerates < 32 kHz + // libav's E-AC-3 encoder can't do samplerates < 32 kHz + // AC-3 < 32 kHz suffers from poor hardware compatibility + if (samplerate < 32000) + return 0; + else + return 1; + case HB_ACODEC_FDK_HAAC: + // fdk_haac can't do samplerates < 16 kHz + if (samplerate < 16000) + return 0; + else + return 1; + case HB_ACODEC_OPUS: + switch (samplerate) { - // samplerates are sanitized downwards - best_samplerate = audio_samplerate->rate; + // Opus only supports samplerates 8kHz, 12kHz, 16kHz, + // 24kHz, 48kHz + case 8000: + case 12000: + case 16000: + case 24000: + case 48000: + return 1; + default: + return 0; } - } - } - if (sr_shift != NULL) - { - /* 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) - */ - *sr_shift = ((best_samplerate < 16000) ? 2 : - (best_samplerate < 32000) ? 1 : 0); + default: + return 1; } - return best_samplerate; +} + +int hb_audio_samplerate_get_sr_shift(int samplerate) +{ + /* 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) + */ + return ((samplerate < 16000) ? 2 : (samplerate < 32000) ? 1 : 0); } int hb_audio_samplerate_get_from_name(const char *name) @@ -813,7 +820,7 @@ int hb_audio_samplerate_get_from_name(const char *name) if (i >= hb_audio_rates_first_item->rate && i <= hb_audio_rates_last_item ->rate) { - return hb_audio_samplerate_get_best(0, i, NULL); + return hb_audio_samplerate_find_closest(i, HB_ACODEC_INVALID); } fail: @@ -848,6 +855,44 @@ const hb_rate_t* hb_audio_samplerate_get_next(const hb_rate_t *last) return ((hb_rate_internal_t*)last)->next; } +const hb_rate_t* hb_audio_samplerate_get_next_for_codec(const hb_rate_t *last, + uint32_t codec) +{ + while ((last = hb_audio_samplerate_get_next(last)) != NULL) + if (hb_audio_samplerate_is_supported(last->rate, codec)) + return last; + + // None found or end of list + return NULL; +} + +int hb_audio_samplerate_find_closest(int samplerate, uint32_t codec) +{ + const hb_rate_t * rate, * prev, * next; + + rate = prev = next = hb_audio_samplerate_get_next_for_codec(NULL, codec); + while (rate != NULL && next->rate < samplerate) + { + rate = hb_audio_samplerate_get_next_for_codec(rate, codec); + if (rate != NULL) + { + prev = next; + next = rate; + } + } + + int delta_prev = samplerate - prev->rate; + int delta_next = next->rate - samplerate; + if (delta_prev <= delta_next) + { + return prev->rate; + } + else + { + return next->rate; + } +} + // Given an input bitrate, find closest match in the set of allowed bitrates static int hb_audio_bitrate_find_closest(int bitrate) { @@ -894,11 +939,11 @@ int hb_audio_bitrate_get_default(uint32_t codec, int samplerate, int mixdown) if ((codec & HB_ACODEC_PASS_FLAG) || !(codec & HB_ACODEC_MASK)) goto fail; - int bitrate, nchannels, sr_shift; + int bitrate, nchannels, nlfe, sr_shift; /* full-bandwidth channels, sr_shift */ - nchannels = (hb_mixdown_get_discrete_channel_count(mixdown) - - hb_mixdown_get_low_freq_channel_count(mixdown)); - hb_audio_samplerate_get_best(codec, samplerate, &sr_shift); + nlfe = hb_mixdown_get_low_freq_channel_count(mixdown); + nchannels = hb_mixdown_get_discrete_channel_count(mixdown) - nlfe; + sr_shift = hb_audio_samplerate_get_sr_shift(samplerate); switch (codec) { @@ -924,6 +969,14 @@ int hb_audio_bitrate_get_default(uint32_t codec, int samplerate, int mixdown) bitrate = nchannels * 32; break; + case HB_ACODEC_OPUS: + { + int coupled = mixdown_get_opus_coupled_stream_count(mixdown); + int uncoupled = nchannels + nlfe - 2 * coupled; + + bitrate = coupled * 96 + uncoupled * 64; + } break; + default: bitrate = nchannels * 80; break; @@ -1070,7 +1123,8 @@ void hb_audio_bitrate_get_limits(uint32_t codec, int samplerate, int mixdown, /* samplerate, sr_shift */ int sr_shift; - samplerate = hb_audio_samplerate_get_best(codec, samplerate, &sr_shift); + samplerate = hb_audio_samplerate_find_closest(samplerate, codec); + sr_shift = hb_audio_samplerate_get_sr_shift(samplerate); /* LFE, full-bandwidth channels */ int lfe_count, nchannels; @@ -1174,6 +1228,11 @@ void hb_audio_bitrate_get_limits(uint32_t codec, int samplerate, int mixdown, ( 50 * (samplerate >= 44100))); break; + case HB_ACODEC_OPUS: + *low = (nchannels + lfe_count) * 6; + *high = (nchannels + lfe_count) * 256; + break; + // Bitrates don't apply to passthrough audio, but may apply if we // fall back to an encoder when the source can't be passed through. default: @@ -1473,6 +1532,13 @@ void hb_audio_quality_get_limits(uint32_t codec, float *low, float *high, *high = 127.; break; + case HB_ACODEC_OPUS: + *direction = 0; + *granularity = 1.; + *low = 0.; + *high = 10.; + break; + default: *direction = 0; *granularity = 1.; @@ -1513,6 +1579,9 @@ float hb_audio_quality_get_default(uint32_t codec) case HB_ACODEC_CA_AAC: return 91.; + case HB_ACODEC_OPUS: + return 10.; + default: return HB_INVALID_AUDIO_QUALITY; } @@ -1658,6 +1727,34 @@ const hb_dither_t* hb_audio_dither_get_next(const hb_dither_t *last) return ((hb_dither_internal_t*)last)->next; } +static int mixdown_get_opus_coupled_stream_count(int mixdown) +{ + switch (mixdown) + { + case HB_AMIXDOWN_7POINT1: + case HB_AMIXDOWN_6POINT1: + return 3; + + case HB_AMIXDOWN_5POINT1: + return 2; + + case HB_AMIXDOWN_MONO: + case HB_AMIXDOWN_LEFT: + case HB_AMIXDOWN_RIGHT: + return 0; + + case HB_AMIXDOWN_NONE: + case HB_INVALID_AMIXDOWN: + case HB_AMIXDOWN_5_2_LFE: + // The 5F/2R/LFE configuration is currently not supported by Opus, + // so don't set coupled streams. + return 0; + + default: + return 1; + } +} + int hb_mixdown_is_supported(int mixdown, uint32_t codec, uint64_t layout) { return (hb_mixdown_has_codec_support(mixdown, codec) && @@ -1679,6 +1776,7 @@ int hb_mixdown_has_codec_support(int mixdown, uint32_t codec) case HB_ACODEC_VORBIS: case HB_ACODEC_FFFLAC: case HB_ACODEC_FFFLAC24: + case HB_ACODEC_OPUS: return (mixdown <= HB_AMIXDOWN_7POINT1); case HB_ACODEC_LAME: @@ -1831,6 +1929,7 @@ int hb_mixdown_get_default(uint32_t codec, uint64_t layout) // the FLAC encoder defaults to the best mixdown up to 7.1 case HB_ACODEC_FFFLAC: case HB_ACODEC_FFFLAC24: + case HB_ACODEC_OPUS: mixdown = HB_AMIXDOWN_7POINT1; break; @@ -2289,9 +2388,8 @@ void hb_autopassthru_apply_settings(hb_job_t *job) if (audio->config.out.samplerate <= 0) audio->config.out.samplerate = audio->config.in.samplerate; audio->config.out.samplerate = - hb_audio_samplerate_get_best(audio->config.out.codec, - audio->config.out.samplerate, - NULL); + hb_audio_samplerate_find_closest( + audio->config.out.samplerate, audio->config.out.codec); int quality_not_allowed = hb_audio_quality_get_default(audio->config.out.codec) == HB_INVALID_AUDIO_QUALITY; diff --git a/libhb/common.h b/libhb/common.h index 92cc1dadf..ae05f2726 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -341,10 +341,16 @@ const hb_rate_t* hb_video_framerate_get_next(const hb_rate_t *last); int hb_video_framerate_get_close(hb_rational_t *framerate, double thresh); -int hb_audio_samplerate_get_best(uint32_t codec, int samplerate, int *sr_shift); +int hb_audio_samplerate_is_supported(int samplerate, + uint32_t codec); +int hb_audio_samplerate_find_closest(int samplerate, + uint32_t codec); +int hb_audio_samplerate_get_sr_shift(int samplerate); int hb_audio_samplerate_get_from_name(const char *name); const char* hb_audio_samplerate_get_name(int samplerate); const hb_rate_t* hb_audio_samplerate_get_next(const hb_rate_t *last); +const hb_rate_t* hb_audio_samplerate_get_next_for_codec(const hb_rate_t *last, + uint32_t codec); int hb_audio_bitrate_get_best(uint32_t codec, int bitrate, int samplerate, int mixdown); int hb_audio_bitrate_get_default(uint32_t codec, int samplerate, int mixdown); @@ -659,7 +665,7 @@ struct hb_job_s /* Audio starts here */ /* Audio Codecs: Update win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/NativeConstants.cs when changing these consts */ #define HB_ACODEC_INVALID 0x00000000 -#define HB_ACODEC_MASK 0x03FFFF00 +#define HB_ACODEC_MASK 0x07FFFF00 #define HB_ACODEC_LAME 0x00000200 #define HB_ACODEC_VORBIS 0x00000400 #define HB_ACODEC_AC3 0x00000800 @@ -677,7 +683,8 @@ struct hb_job_s #define HB_ACODEC_FDK_HAAC 0x00800000 #define HB_ACODEC_FFEAC3 0x01000000 #define HB_ACODEC_FFTRUEHD 0x02000000 -#define HB_ACODEC_FF_MASK 0x03FF2800 +#define HB_ACODEC_OPUS 0x04000000 +#define HB_ACODEC_FF_MASK 0x07FF2800 #define HB_ACODEC_PASS_FLAG 0x40000000 #define HB_ACODEC_PASS_MASK (HB_ACODEC_AC3 | HB_ACODEC_DCA | HB_ACODEC_DCA_HD | HB_ACODEC_FFAAC | HB_ACODEC_FFEAC3 | HB_ACODEC_FFFLAC | HB_ACODEC_MP3 | HB_ACODEC_FFTRUEHD) #define HB_ACODEC_AUTO_PASS (HB_ACODEC_PASS_FLAG | HB_ACODEC_PASS_MASK) diff --git a/libhb/encavcodecaudio.c b/libhb/encavcodecaudio.c index 544ee385a..73d44a25c 100644 --- a/libhb/encavcodecaudio.c +++ b/libhb/encavcodecaudio.c @@ -125,6 +125,10 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job) codec_name = "libmp3lame"; break; + case HB_ACODEC_OPUS: + codec_name = "libopus"; + break; + default: hb_error("encavcodecaInit: unsupported codec (0x%x)", audio->config.out.codec); diff --git a/libhb/module.defs b/libhb/module.defs index ca80e56fa..8ea828bfa 100644 --- a/libhb/module.defs +++ b/libhb/module.defs @@ -1,7 +1,7 @@ __deps__ := A52DEC BZIP2 LIBVPX FFMPEG FONTCONFIG FREETYPE LAME LIBASS LIBDCA \ LIBDVDREAD LIBDVDNAV LIBICONV LIBSAMPLERATE LIBTHEORA LIBVORBIS LIBOGG \ LIBXML2 PTHREADW32 X264 X265 ZLIB LIBBLURAY FDKAAC LIBMFX LIBGNURX JANSSON \ - HARFBUZZ + HARFBUZZ LIBOPUS $(eval $(call import.MODULE.defs,LIBHB,libhb,$(__deps__))) $(eval $(call import.GCC,LIBHB)) @@ -124,7 +124,7 @@ LIBHB.lib = $(LIBHB.build/)hb.lib LIBHB.dll.libs = $(foreach n, \ ass avcodec avformat avfilter avutil avresample dvdnav dvdread fontconfig \ freetype mp3lame samplerate swscale vpx theora vorbis vorbisenc ogg \ - x264 xml2 bluray jansson harfbuzz, \ + x264 xml2 bluray jansson harfbuzz opus, \ $(CONTRIB.build/)lib/lib$(n).a ) ifeq (1,$(FEATURE.fdk_aac)) diff --git a/libhb/muxavformat.c b/libhb/muxavformat.c index b7533d4dc..47762721c 100644 --- a/libhb/muxavformat.c +++ b/libhb/muxavformat.c @@ -485,6 +485,23 @@ static int avformatInit( hb_mux_object_t * m ) size += ogg_headers[jj]->bytes; } } break; + case HB_ACODEC_OPUS: + track->st->codec->codec_id = AV_CODEC_ID_OPUS; + + if (audio->priv.config.extradata.length) + { + priv_size = audio->priv.config.extradata.length; + priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (priv_data == NULL) + { + hb_error("OPUS extradata: malloc failure"); + goto error; + } + memcpy(priv_data, + audio->priv.config.extradata.bytes, + audio->priv.config.extradata.length); + } + break; case HB_ACODEC_FFFLAC: case HB_ACODEC_FFFLAC24: track->st->codec->codec_id = AV_CODEC_ID_FLAC; diff --git a/libhb/work.c b/libhb/work.c index afb866394..a2290cc8b 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -967,9 +967,8 @@ static int sanitize_audio(hb_job_t *job) audio->config.out.samplerate = audio->config.in.samplerate; } best_samplerate = - hb_audio_samplerate_get_best(audio->config.out.codec, - audio->config.out.samplerate, - NULL); + hb_audio_samplerate_find_closest(audio->config.out.samplerate, + audio->config.out.codec); if (best_samplerate != audio->config.out.samplerate) { hb_log("work: sanitizing track %d unsupported samplerate %d Hz to %s kHz", |