summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorRodeo <[email protected]>2013-05-30 13:57:37 +0000
committerRodeo <[email protected]>2013-05-30 13:57:37 +0000
commit93117add4ed41f9f87d1da16ca339b2efad6767d (patch)
tree755030aca2bd309d9a47f6748adc70a7ff4e839f /libhb
parentbf0fe59e97a4fc22b0800191407cdeb758ed20fa (diff)
Don't expose rate, mixdown, dither and encoder arrays to the UIs.
- instead, make these lists available through enumerators: --> hb_*_get_next(<type> *last); - this should give us more flexibility to populate the lists at runtime, using the implementation(s) of our choice, whether they use arrays or not, without requiring UI modifications - use consistent naming for getters --> hb_get_best_foo() becomes hb_foo_get_best(), and so on - hb_*_get_from_name() and hb_*_ sanitize_name() sanitize the requested value to a supported one if it's unavailable - adds an additional, passthru-specific fallback mechanism - adds a list of video containers git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@5526 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r--libhb/common.c1850
-rw-r--r--libhb/common.h210
-rw-r--r--libhb/encavcodec.c8
-rw-r--r--libhb/scan.c7
-rw-r--r--libhb/work.c205
5 files changed, 1454 insertions, 826 deletions
diff --git a/libhb/common.c b/libhb/common.c
index 95c9f921d..1d02af536 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -19,6 +19,8 @@
/**********************************************************************
* Global variables
*********************************************************************/
+static hb_error_handler_t *error_handler = NULL;
+
hb_rate_t hb_video_rates[] =
{
{ "5", 5400000 },
@@ -81,8 +83,6 @@ hb_rate_t hb_audio_bitrates[] =
};
int hb_audio_bitrates_count = sizeof(hb_audio_bitrates) / sizeof(hb_rate_t);
-static hb_error_handler_t *error_handler = NULL;
-
hb_dither_t hb_audio_dithers[] =
{
{ "default", "auto", AV_RESAMPLE_DITHER_NONE - 1, },
@@ -112,10 +112,10 @@ 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 },
+ { "H.264 (x264)", "x264", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "MPEG-4 (FFmpeg)", "ffmpeg4", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "MPEG-2 (FFmpeg)", "ffmpeg2", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "VP3 (Theora)", "theora", HB_VCODEC_THEORA, HB_MUX_MASK_MKV },
};
int hb_video_encoders_count = sizeof(hb_video_encoders) / sizeof(hb_encoder_t);
@@ -123,566 +123,420 @@ 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_MASK_MP4|HB_MUX_MASK_MKV },
+ { "HE-AAC (CoreAudio)", "ca_haac", HB_ACODEC_CA_HAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
#endif
- { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MP4|HB_MUX_MKV },
+ { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
#ifdef USE_FDK_AAC
- { "AAC (FDK)", "fdk_aac", HB_ACODEC_FDK_AAC, HB_MUX_MP4|HB_MUX_MKV },
- { "HE-AAC (FDK)", "fdk_haac", HB_ACODEC_FDK_HAAC, HB_MUX_MP4|HB_MUX_MKV },
+ { "AAC (FDK)", "fdk_aac", HB_ACODEC_FDK_AAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "HE-AAC (FDK)", "fdk_haac", HB_ACODEC_FDK_HAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
#endif
- { "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 },
- { "FLAC (24-bit)", "ffflac24", HB_ACODEC_FFFLAC24, HB_MUX_MKV },
- { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MP4|HB_MUX_MKV },
+ { "AAC (ffmpeg)", "ffaac", HB_ACODEC_FFAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "AAC Passthru", "copy:aac", HB_ACODEC_AAC_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "AC3 (ffmpeg)", "ffac3", HB_ACODEC_AC3, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "AC3 Passthru", "copy:ac3", HB_ACODEC_AC3_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "DTS Passthru", "copy:dts", HB_ACODEC_DCA_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "DTS-HD Passthru", "copy:dtshd", HB_ACODEC_DCA_HD_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "MP3 (lame)", "lame", HB_ACODEC_LAME, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "MP3 Passthru", "copy:mp3", HB_ACODEC_MP3_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
+ { "Vorbis (vorbis)", "vorbis", HB_ACODEC_VORBIS, HB_MUX_MASK_MKV },
+ { "FLAC (ffmpeg)", "ffflac", HB_ACODEC_FFFLAC, HB_MUX_MASK_MKV },
+ { "FLAC (24-bit)", "ffflac24", HB_ACODEC_FFFLAC24, HB_MUX_MASK_MKV },
+ { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_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; }
-hb_rate_t* hb_get_audio_bitrates() { return hb_audio_bitrates; }
-int hb_get_audio_bitrates_count() { return hb_audio_bitrates_count; }
-hb_dither_t* hb_get_audio_dithers() { return hb_audio_dithers; }
-int hb_get_audio_dithers_count() { return hb_audio_dithers_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_audio_dither_get_default()
+// note: for each container, the muxer nearer the top is the default
+hb_container_t hb_containers[] =
{
- // "auto"
- return hb_audio_dithers[0].method;
-}
+ { "MPEG-4 (mp4v2)", "mp4v2", "mp4", HB_MUX_MP4V2, },
+ { "Matroska (libmkv)", "libmkv", "mkv", HB_MUX_LIBMKV, },
+};
+int hb_containers_count = sizeof(hb_containers) / sizeof(hb_container_t);
-int hb_audio_dither_get_default_method()
+int hb_video_framerate_get_from_name(const char *name)
{
- /*
- * input could be s16 (possibly already dithered) converted to flt, so
- * let's use a "low-risk" dither algorithm (standard triangular).
- */
- return AV_RESAMPLE_DITHER_TRIANGULAR;
-}
+ if (name == NULL || *name == '\0')
+ goto fail;
-int hb_audio_dither_is_supported(uint32_t codec)
-{
- // encoder's input sample format must be s16(p)
- switch (codec)
+ // TODO: implement something more flexible
+ if (!strcasecmp(name, "23.976 (NTSC Film)"))
{
- case HB_ACODEC_FFFLAC:
- case HB_ACODEC_FDK_AAC:
- case HB_ACODEC_FDK_HAAC:
- return 1;
- default:
- return 0;
+ return 1126125;
+ }
+ if (!strcasecmp(name, "25 (PAL Film/Video)"))
+ {
+ return 1080000;
+ }
+ if (!strcasecmp(name, "29.97 (NTSC Video)"))
+ {
+ return 900900;
}
-}
-const char* hb_audio_dither_get_description(int method)
-{
int i;
- for (i = 0; i < hb_audio_dithers_count; i++)
+ for (i = 0; i < hb_video_rates_count; i++)
{
- if (hb_audio_dithers[i].method == method)
+ if (!strcasecmp(hb_video_rates[i].name, name))
{
- return hb_audio_dithers[i].description;
+ return hb_video_rates[i].rate;
}
}
- return "";
-}
-
-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));
+fail:
+ return -1;
}
-int hb_mixdown_has_codec_support(int mixdown, uint32_t codec)
+const char* hb_video_framerate_get_name(int framerate)
{
- // 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;
+ if (framerate > hb_video_rates[0].rate ||
+ framerate < hb_video_rates[hb_video_rates_count - 1].rate)
+ goto fail;
- switch (codec)
+ int i;
+ for (i = 0; i < hb_video_rates_count; i++)
{
- case HB_ACODEC_VORBIS:
- case HB_ACODEC_FFFLAC:
- case HB_ACODEC_FFFLAC24:
- 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);
+ if (hb_video_rates[i].rate == framerate)
+ {
+ return hb_video_rates[i].name;
+ }
}
+
+fail:
+ return NULL;
}
-int hb_mixdown_has_remix_support(int mixdown, uint64_t layout)
+const char* hb_video_framerate_sanitize_name(const char *name)
{
- 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;
- }
+ return hb_video_framerate_get_name(hb_video_framerate_get_from_name(name));
}
-int hb_mixdown_get_discrete_channel_count(int amixdown)
+const hb_rate_t* hb_video_framerate_get_next(const hb_rate_t *last)
{
- switch (amixdown)
+ if (last == NULL)
{
- 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:
- return 0;
-
- default:
- return 2;
+ return &hb_video_rates[0];
}
-}
-
-int hb_mixdown_get_low_freq_channel_count(int amixdown)
-{
- switch (amixdown)
+ if (last < &hb_video_rates[0] ||
+ last >= &hb_video_rates[hb_video_rates_count - 1])
{
- case HB_AMIXDOWN_5POINT1:
- case HB_AMIXDOWN_6POINT1:
- case HB_AMIXDOWN_7POINT1:
- case HB_AMIXDOWN_5_2_LFE:
- return 1;
-
- default:
- return 0;
+ return NULL;
}
+ return last + 1;
}
-int hb_mixdown_get_mixdown_from_short_name(const char *short_name)
+int hb_audio_samplerate_get_best(uint32_t codec, int samplerate, int *sr_shift)
{
- int i;
- for (i = 0; i < hb_audio_mixdowns_count; i++)
+ int ii, best_samplerate, samplerate_shift;
+ if ((samplerate < 32000) &&
+ (codec == HB_ACODEC_CA_HAAC || codec == HB_ACODEC_AC3))
{
- if (!strcmp(hb_audio_mixdowns[i].short_name, short_name))
- {
- return hb_audio_mixdowns[i].amixdown;
- }
+ // ca_haac can't do samplerates < 32 kHz
+ // AC-3 < 32 kHz suffers from poor hardware compatibility
+ best_samplerate = 32000;
+ samplerate_shift = 0;
}
- return 0;
-}
-
-const char* hb_mixdown_get_short_name_from_mixdown(int amixdown)
-{
- int i;
- for (i = 0; i < hb_audio_mixdowns_count; i++)
+ else if (samplerate < 16000 && codec == HB_ACODEC_FDK_HAAC)
{
- if (hb_audio_mixdowns[i].amixdown == amixdown)
- {
- return hb_audio_mixdowns[i].short_name;
- }
+ // fdk_haac can't do samplerates < 16 kHz
+ best_samplerate = 16000;
+ samplerate_shift = 1;
}
- return "";
-}
-
-void hb_autopassthru_apply_settings( hb_job_t * job )
-{
- int i, j, already_printed;
- hb_audio_t * audio;
- for( i = 0, already_printed = 0; i < hb_list_count( job->list_audio ); )
+ else
{
- audio = hb_list_item( job->list_audio, i );
- if( audio->config.out.codec == HB_ACODEC_AUTO_PASS )
+ best_samplerate = samplerate;
+ for (ii = hb_audio_rates_count - 1; ii >= 0; ii--)
{
- if( !already_printed )
- hb_autopassthru_print_settings( job );
- already_printed = 1;
- audio->config.out.codec = hb_autopassthru_get_encoder( audio->config.in.codec,
- job->acodec_copy_mask,
- job->acodec_fallback,
- job->mux );
- if( !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) &&
- !( audio->config.out.codec & HB_ACODEC_MASK ) )
- {
- hb_log( "Auto Passthru: passthru not possible and no valid fallback specified, dropping track %d",
- audio->config.out.track );
- hb_list_rem( job->list_audio, audio );
- hb_audio_close( &audio );
- continue;
- }
- audio->config.out.samplerate = audio->config.in.samplerate;
- if( !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) )
- {
- if( audio->config.out.codec == job->acodec_fallback )
- {
- hb_log( "Auto Passthru: passthru not possible for track %d, using fallback",
- audio->config.out.track );
- }
- else
- {
- hb_log( "Auto Passthru: passthru and fallback not possible for track %d, using default encoder",
- audio->config.out.track );
- }
- audio->config.out.mixdown = hb_get_default_mixdown( audio->config.out.codec,
- audio->config.in.channel_layout );
- audio->config.out.bitrate = hb_get_default_audio_bitrate( audio->config.out.codec,
- audio->config.out.samplerate,
- audio->config.out.mixdown );
- audio->config.out.compression_level = hb_get_default_audio_compression( audio->config.out.codec );
- }
- else
+ // 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)
{
- for( j = 0; j < hb_audio_encoders_count; j++ )
- {
- if( hb_audio_encoders[j].encoder == audio->config.out.codec )
- {
- hb_log( "Auto Passthru: using %s for track %d",
- hb_audio_encoders[j].human_readable_name,
- audio->config.out.track );
- break;
- }
- }
+ best_samplerate = hb_audio_rates[ii].rate;
+ break;
}
}
- /* 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;
+ /* 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;
}
-void hb_autopassthru_print_settings( hb_job_t * job )
+int hb_audio_samplerate_get_from_name(const char *name)
{
- int i, codec_len;
- char *mask = NULL, *tmp;
- const char *fallback = NULL;
- for( i = 0; i < hb_audio_encoders_count; i++ )
+ if (name == NULL || *name == '\0')
+ goto fail;
+
+ // TODO: implement something more flexible
+ int i = atoi(name);
+ if (i >= hb_audio_rates[0].rate &&
+ i <= hb_audio_rates[hb_audio_rates_count - 1].rate)
{
- if( ( hb_audio_encoders[i].encoder & HB_ACODEC_PASS_FLAG ) &&
- ( hb_audio_encoders[i].encoder != HB_ACODEC_AUTO_PASS ) &&
- ( hb_audio_encoders[i].encoder & job->acodec_copy_mask ) )
- {
- if( mask )
- {
- tmp = hb_strncat_dup( mask, ", ", 2 );
- if( tmp )
- {
- free( mask );
- mask = tmp;
- }
- }
- // passthru name without " Passthru"
- codec_len = strlen( hb_audio_encoders[i].human_readable_name ) - 9;
- tmp = hb_strncat_dup( mask, hb_audio_encoders[i].human_readable_name, codec_len );
- if( tmp )
- {
- free( mask );
- mask = tmp;
- }
- }
- else if( !( hb_audio_encoders[i].encoder & HB_ACODEC_PASS_FLAG ) &&
- ( hb_audio_encoders[i].encoder == job->acodec_fallback ) )
+ return i;
+ }
+
+ for (i = 0; i < hb_audio_rates_count; i++)
+ {
+ if (!strcasecmp(hb_audio_rates[i].name, name))
{
- fallback = hb_audio_encoders[i].human_readable_name;
+ return hb_audio_rates[i].rate;
}
}
- if( !mask )
- hb_log( "Auto Passthru: no codecs allowed" );
- else
- hb_log( "Auto Passthru: allowed codecs are %s", mask );
- if( !fallback )
- hb_log( "Auto Passthru: no valid fallback specified" );
- else
- hb_log( "Auto Passthru: fallback is %s", fallback );
+
+fail:
+ return -1;
}
-int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int muxer )
+const char* hb_audio_samplerate_get_name(int samplerate)
{
+ if (samplerate < hb_audio_rates[0].rate ||
+ samplerate > hb_audio_rates[hb_audio_rates_count - 1].rate)
+ goto fail;
+
int i;
- int out_codec = ( copy_mask & in_codec ) | HB_ACODEC_PASS_FLAG;
- // sanitize fallback encoder and selected passthru
- // note: invalid fallbacks are caught in hb_autopassthru_apply_settings
- for( i = 0; i < hb_audio_encoders_count; i++ )
+ for (i = 0; i < hb_audio_rates_count; i++)
{
- if( ( hb_audio_encoders[i].encoder == fallback ) &&
- !( hb_audio_encoders[i].muxers & muxer ) )
+ if (hb_audio_rates[i].rate == samplerate)
{
- // fallback not possible with current muxer
- // use the default audio encoder instead
- fallback = hb_get_default_audio_encoder(muxer);
- break;
+ return hb_audio_rates[i].name;
}
}
- for( i = 0; i < hb_audio_encoders_count; i++ )
- {
- if( ( hb_audio_encoders[i].encoder == out_codec ) &&
- !( hb_audio_encoders[i].muxers & muxer ) )
- {
- // selected passthru not possible with current muxer
- out_codec = fallback;
- break;
- }
- }
- if( !( out_codec & HB_ACODEC_PASS_MASK ) )
- return fallback;
- return out_codec;
+
+fail:
+ return NULL;
}
-int hb_get_default_audio_encoder(int muxer)
+const hb_rate_t* hb_audio_samplerate_get_next(const hb_rate_t *last)
{
-#ifndef __APPLE__
- if (muxer == HB_MUX_MKV)
+ if (last == NULL)
{
- return HB_ACODEC_LAME;
+ return &hb_audio_rates[0];
}
-#endif
- return hb_audio_encoders[0].encoder;
+ if (last < &hb_audio_rates[0] ||
+ last >= &hb_audio_rates[hb_audio_rates_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
}
// Given an input bitrate, find closest match in the set of allowed bitrates
-int hb_find_closest_audio_bitrate(int bitrate)
+static int hb_audio_bitrate_find_closest(int bitrate)
{
// Check if bitrate mode was disabled
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--)
+ int i, result = hb_audio_bitrates[0].rate;
+ for (i = hb_audio_bitrates_count - 1; i > 0; i--)
{
- if (bitrate >= hb_audio_bitrates[ii].rate)
+ if (bitrate >= hb_audio_bitrates[i].rate)
{
- result = hb_audio_bitrates[ii].rate;
+ result = hb_audio_bitrates[i].rate;
break;
}
}
return result;
}
-/* Get the bitrate low and high limits for a codec/samplerate/mixdown triplet.
+// Given an input bitrate, sanitize it.
+// Check low and high limits and make sure it is in the set of allowed bitrates.
+int hb_audio_bitrate_get_best(uint32_t codec, int bitrate, int samplerate,
+ int mixdown)
+{
+ int low, high;
+ hb_audio_bitrate_get_limits(codec, samplerate, mixdown, &low, &high);
+ if (bitrate > high)
+ bitrate = high;
+ if (bitrate < low)
+ bitrate = low;
+ return hb_audio_bitrate_find_closest(bitrate);
+}
-Encoder 1.0 channel 2.0 channels 5.1 channels 6.1 channels 7.1 channels
---------------------------------------------------------------------------------------
-
-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
------
-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 Kbps per full-bandwidth channel (<= 32 kHz)
- minimum of 16 Kbps per full-bandwidth channel ( > 32 kHz)
- maximum of 40 Kbps per full-bandwidth channel
-Note: encCoreAudioInit() will sanitize any mistake made here.
-
-fdk_aac
--------
-supported samplerates: 8 - 48 kHz
-libfdk limits the bitrate to the following values:
- 8 kHz 48 96 240
-12 kHz 72 144 360
-16 kHz 96 192 480
-24 kHz 144 288 720
-32 kHz 192 384 960
-48 kHz 288 576 1440
-Limits: minimum of samplerate * 2/3 Kbps per full-bandwidth channel (see ca_aac)
- maximum of samplerate * 6.0 Kbps per full-bandwidth channel
-
-fdk_haac
---------
-supported samplerates: 16 - 48 kHz
-libfdk limits the bitrate to the following values:
-16 kHz 8 - 48 16 - 96 45 - 199
-24 kHz 8 - 63 16 - 127 45 - 266
-32 kHz 8 - 63 16 - 127 45 - 266
-48 kHz 12 - 63 16 - 127 50 - 266
-Limits: minimum of 12 Kbps per full-bandwidth channel (<= 32 kHz) (see ca_haac)
- minimum of 16 Kbps per full-bandwidth channel ( > 32 kHz) (see ca_haac)
- maximum of 48, 96 or 192 Kbps (1.0, 2.0, 5.1) (<= 16 kHz)
- maximum of 64, 128 or 256 Kbps (1.0, 2.0, 5.1) ( > 16 kHz)
-*/
-
-void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown,
- int *low, int *high)
+// Get the default bitrate for a given codec/samplerate/mixdown triplet.
+int hb_audio_bitrate_get_default(uint32_t codec, int samplerate, int mixdown)
{
- if (codec & HB_ACODEC_PASS_FLAG)
+ if ((codec & HB_ACODEC_PASS_FLAG) || !(codec & HB_ACODEC_MASK))
+ goto fail;
+
+ 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_audio_samplerate_get_best(codec, samplerate, &sr_shift);
+
+ switch (codec)
{
- // 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;
+ case HB_ACODEC_FFFLAC:
+ case HB_ACODEC_FFFLAC24:
+ goto fail;
+
+ // 96, 224, 640 Kbps
+ case HB_ACODEC_AC3:
+ bitrate = (nchannels * 128) - (32 * (nchannels < 5));
+ break;
+
+ case HB_ACODEC_CA_HAAC:
+ case HB_ACODEC_FDK_HAAC:
+ bitrate = nchannels * 32;
+ break;
+
+ default:
+ bitrate = nchannels * 80;
+ break;
}
+ // sample_rate adjustment
+ bitrate >>= sr_shift;
+ return hb_audio_bitrate_get_best(codec, bitrate, samplerate, mixdown);
+
+fail:
+ return -1;
+}
+/* Get the bitrate low and high limits for a codec/samplerate/mixdown triplet.
+ *
+ * Encoder 1.0 channel 2.0 channels 5.1 channels 6.1 channels 7.1 channels
+ * --------------------------------------------------------------------------------------
+ *
+ * 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
+ * -----
+ * 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 Kbps per full-bandwidth channel (<= 32 kHz)
+ * minimum of 16 Kbps per full-bandwidth channel ( > 32 kHz)
+ * maximum of 40 Kbps per full-bandwidth channel
+ * Note: encCoreAudioInit() will sanitize any mistake made here.
+ *
+ * fdk_aac
+ * -------
+ * supported samplerates: 8 - 48 kHz
+ * libfdk limits the bitrate to the following values:
+ * 8 kHz 48 96 240
+ * 12 kHz 72 144 360
+ * 16 kHz 96 192 480
+ * 24 kHz 144 288 720
+ * 32 kHz 192 384 960
+ * 48 kHz 288 576 1440
+ * Limits: minimum of samplerate * 2/3 Kbps per full-bandwidth channel (see ca_aac)
+ * maximum of samplerate * 6.0 Kbps per full-bandwidth channel
+ *
+ * fdk_haac
+ * --------
+ * supported samplerates: 16 - 48 kHz
+ * libfdk limits the bitrate to the following values:
+ * 16 kHz 8 - 48 16 - 96 45 - 199
+ * 24 kHz 8 - 63 16 - 127 45 - 266
+ * 32 kHz 8 - 63 16 - 127 45 - 266
+ * 48 kHz 12 - 63 16 - 127 50 - 266
+ * Limits: minimum of 12 Kbps per full-bandwidth channel (<= 32 kHz) (see ca_haac)
+ * minimum of 16 Kbps per full-bandwidth channel ( > 32 kHz) (see ca_haac)
+ * maximum of 48, 96 or 192 Kbps (1.0, 2.0, 5.1) (<= 16 kHz)
+ * maximum of 64, 128 or 256 Kbps (1.0, 2.0, 5.1) ( > 16 kHz)
+ */
+void hb_audio_bitrate_get_limits(uint32_t codec, int samplerate, int mixdown,
+ int *low, int *high)
+{
/* samplerate, sr_shift */
int sr_shift;
- samplerate = hb_get_best_samplerate(codec, samplerate, &sr_shift);
+ samplerate = hb_audio_samplerate_get_best(codec, samplerate, &sr_shift);
/* LFE, full-bandwidth channels */
int lfe_count, nchannels;
@@ -710,32 +564,37 @@ void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown,
*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:
*low = nchannels * (12 + (4 * (samplerate >= 44100)));
@@ -781,69 +640,33 @@ void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown,
( 50 * (samplerate >= 44100)));
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:
*low = hb_audio_bitrates[0].rate;
- *high = hb_audio_bitrates[hb_audio_bitrates_count-1].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)
-{
- int low, high;
- hb_get_audio_bitrate_limits(codec, samplerate, mixdown, &low, &high);
- if (bitrate > high)
- bitrate = high;
- if (bitrate < low)
- bitrate = low;
- return hb_find_closest_audio_bitrate(bitrate);
+ if (*high > hb_audio_bitrates[hb_audio_bitrates_count - 1].rate)
+ *high = hb_audio_bitrates[hb_audio_bitrates_count - 1].rate;
}
-// Get the default bitrate for a given codec/samplerate/mixdown triplet.
-int hb_get_default_audio_bitrate(uint32_t codec, int samplerate, int mixdown)
+const hb_rate_t* hb_audio_bitrate_get_next(const hb_rate_t *last)
{
- if (codec & HB_ACODEC_PASS_FLAG)
+ if (last == NULL)
{
- return -1;
+ return &hb_audio_bitrates[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)
+ if (last < &hb_audio_bitrates[0] ||
+ last >= &hb_audio_bitrates[hb_audio_bitrates_count - 1])
{
- case HB_ACODEC_FFFLAC:
- case HB_ACODEC_FFFLAC24:
- return -1;
-
- // 96, 224, 640 Kbps
- case HB_ACODEC_AC3:
- bitrate = (nchannels * 128) - (32 * (nchannels < 5));
- break;
-
- case HB_ACODEC_CA_HAAC:
- case HB_ACODEC_FDK_HAAC:
- bitrate = nchannels * 32;
- break;
-
- default:
- bitrate = nchannels * 80;
- break;
+ return NULL;
}
- // sample_rate adjustment
- bitrate >>= sr_shift;
- return hb_get_best_audio_bitrate(codec, bitrate, samplerate, mixdown);
+ return last + 1;
}
// Get limits and hints for the UIs.
@@ -851,47 +674,47 @@ int hb_get_default_audio_bitrate(uint32_t codec, int samplerate, int mixdown)
// granularity sets the minimum step increments that should be used
// (it's ok to round up to some nice multiple if you like)
//
-// direction says whether 'low' limit is highest or lowest
+// 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,
+void hb_audio_quality_get_limits(uint32_t codec, float *low, float *high,
float *granularity, int *direction)
{
switch (codec)
{
case HB_ACODEC_LAME:
- *direction = 1;
+ *direction = 1;
*granularity = 0.5;
- *low = 0.;
- *high = 10.0;
+ *low = 0.;
+ *high = 10.;
break;
case HB_ACODEC_VORBIS:
- *direction = 0;
+ *direction = 0;
*granularity = 0.5;
- *low = -2.0;
- *high = 10.0;
+ *low = -2.;
+ *high = 10.;
break;
case HB_ACODEC_CA_AAC:
- *direction = 0;
- *granularity = 9;
- *low = 1.;
- *high = 127.0;
+ *direction = 0;
+ *granularity = 9.;
+ *low = 1.;
+ *high = 127.;
break;
default:
- *direction = 0;
- *granularity = 1;
+ *direction = 0;
+ *granularity = 1.;
*low = *high = HB_INVALID_AUDIO_QUALITY;
break;
}
}
-float hb_get_best_audio_quality(uint32_t codec, float quality)
+float hb_audio_quality_get_best(uint32_t codec, float quality)
{
- float low, high, granularity;
int direction;
- hb_get_audio_quality_limits(codec, &low, &high, &granularity, &direction);
+ float low, high, granularity;
+ hb_audio_quality_get_limits(codec, &low, &high, &granularity, &direction);
if (quality > high)
quality = high;
if (quality < low)
@@ -899,28 +722,22 @@ float hb_get_best_audio_quality(uint32_t codec, float quality)
return quality;
}
-float hb_get_default_audio_quality( uint32_t codec )
+float hb_audio_quality_get_default(uint32_t codec)
{
- float quality;
- switch( codec )
+ switch (codec)
{
case HB_ACODEC_LAME:
- quality = 2.;
- break;
+ return 2.;
case HB_ACODEC_VORBIS:
- quality = 5.;
- break;
+ return 5.;
case HB_ACODEC_CA_AAC:
- quality = 91.;
- break;
+ return 91.;
default:
- quality = HB_INVALID_AUDIO_QUALITY;
- break;
+ return HB_INVALID_AUDIO_QUALITY;
}
- return quality;
}
// Get limits and hints for the UIs.
@@ -928,41 +745,41 @@ float hb_get_default_audio_quality( uint32_t codec )
// granularity sets the minimum step increments that should be used
// (it's ok to round up to some nice multiple if you like)
//
-// direction says whether 'low' limit is highest or lowest
+// 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,
+void hb_audio_compression_get_limits(uint32_t codec, float *low, float *high,
float *granularity, int *direction)
{
switch (codec)
{
case HB_ACODEC_FFFLAC:
case HB_ACODEC_FFFLAC24:
- *direction = 0;
- *granularity = 1;
- *high = 12;
- *low = 0;
+ *direction = 0;
+ *granularity = 1.;
+ *high = 12.;
+ *low = 0.;
break;
-
+
case HB_ACODEC_LAME:
- *direction = 1;
- *granularity = 1;
- *high = 9;
- *low = 0;
+ *direction = 1;
+ *granularity = 1.;
+ *high = 9.;
+ *low = 0.;
break;
-
+
default:
- *direction = 0;
- *granularity = 1;
- *low = *high = -1;
+ *direction = 0;
+ *granularity = 1.;
+ *low = *high = -1.;
break;
}
}
-float hb_get_best_audio_compression(uint32_t codec, float compression)
+float hb_audio_compression_get_best(uint32_t codec, float compression)
{
- float low, high, granularity;
int direction;
- hb_get_audio_compression_limits(codec, &low, &high, &granularity, &direction);
+ float low, high, granularity;
+ hb_audio_compression_get_limits(codec, &low, &high, &granularity, &direction);
if( compression > high )
compression = high;
if( compression < low )
@@ -970,7 +787,7 @@ float hb_get_best_audio_compression(uint32_t codec, float compression)
return compression;
}
-float hb_get_default_audio_compression(uint32_t codec)
+float hb_audio_compression_get_default(uint32_t codec)
{
switch (codec)
{
@@ -986,7 +803,226 @@ float hb_get_default_audio_compression(uint32_t codec)
}
}
-int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown)
+int hb_audio_dither_get_default()
+{
+ // "auto"
+ return hb_audio_dithers[0].method;
+}
+
+int hb_audio_dither_get_default_method()
+{
+ /*
+ * input could be s16 (possibly already dithered) converted to flt, so
+ * let's use a "low-risk" dither algorithm (standard triangular).
+ */
+ return AV_RESAMPLE_DITHER_TRIANGULAR;
+}
+
+int hb_audio_dither_is_supported(uint32_t codec)
+{
+ // encoder's input sample format must be s16(p)
+ switch (codec)
+ {
+ case HB_ACODEC_FFFLAC:
+ case HB_ACODEC_FDK_AAC:
+ case HB_ACODEC_FDK_HAAC:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+int hb_audio_dither_get_from_name(const char *name)
+{
+ if (name == NULL || *name == '\0')
+ goto fail;
+
+ int i;
+ for ( i = 0; i < hb_audio_dithers_count; i++)
+ {
+ if (!strcasecmp(hb_audio_dithers[i].short_name, name))
+ {
+ return hb_audio_dithers[i].method;
+ }
+ }
+
+fail:
+ return hb_audio_dither_get_default();
+}
+
+const char* hb_audio_dither_get_description(int method)
+{
+ if (method < hb_audio_dithers[0].method ||
+ method > hb_audio_dithers[hb_audio_dithers_count - 1].method)
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_audio_dithers_count; i++)
+ {
+ if (hb_audio_dithers[i].method == method)
+ {
+ return hb_audio_dithers[i].description;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const hb_dither_t* hb_audio_dither_get_next(const hb_dither_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_audio_dithers[0];
+ }
+ if (last < &hb_audio_dithers[0] ||
+ last >= &hb_audio_dithers[hb_audio_dithers_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
+}
+
+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_VORBIS:
+ case HB_ACODEC_FFFLAC:
+ case HB_ACODEC_FFFLAC24:
+ 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_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:
+ return 0;
+
+ default:
+ return 2;
+ }
+}
+
+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_best(uint32_t codec, uint64_t layout, int mixdown)
{
// Passthru, only "None" mixdown is supported
if (codec & HB_ACODEC_PASS_FLAG)
@@ -996,17 +1032,17 @@ int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown)
if (mixdown == HB_INVALID_AMIXDOWN)
mixdown = hb_audio_mixdowns[hb_audio_mixdowns_count - 1].amixdown;
- 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 - 1; ii > 1; ii--)
- if (hb_audio_mixdowns[ii].amixdown <= mixdown &&
- hb_mixdown_is_supported(hb_audio_mixdowns[ii].amixdown, codec, layout))
+ int i;
+ for (i = hb_audio_mixdowns_count - 1; i > 1; i--)
+ if (hb_audio_mixdowns[i].amixdown <= mixdown &&
+ hb_mixdown_is_supported(hb_audio_mixdowns[i].amixdown, codec, layout))
break;
- return hb_audio_mixdowns[ii].amixdown;
+ return hb_audio_mixdowns[i].amixdown;
}
-int hb_get_default_mixdown(uint32_t codec, uint64_t layout)
+int hb_mixdown_get_default(uint32_t codec, uint64_t layout)
{
int mixdown;
switch (codec)
@@ -1016,69 +1052,641 @@ int hb_get_default_mixdown(uint32_t codec, uint64_t layout)
case HB_ACODEC_FFFLAC24:
mixdown = HB_AMIXDOWN_7POINT1;
break;
+
// the AC3 encoder defaults to the best mixdown up to 5.1
case HB_ACODEC_AC3:
mixdown = HB_AMIXDOWN_5POINT1;
break;
+
// other encoders default to the best mixdown up to DPLII
default:
mixdown = HB_AMIXDOWN_DOLBYPLII;
break;
}
+
// return the best available mixdown up to the selected default
- return hb_get_best_mixdown(codec, layout, mixdown);
+ return hb_mixdown_get_best(codec, layout, mixdown);
}
-int hb_get_best_samplerate(uint32_t codec, int samplerate, int *sr_shift)
+int hb_mixdown_get_from_name(const char *name)
{
- int ii, best_samplerate, samplerate_shift;
- if ((samplerate < 32000) &&
- (codec == HB_ACODEC_CA_HAAC || codec == HB_ACODEC_AC3))
+ if (name == NULL || *name == '\0')
+ goto fail;
+
+ // TODO: implement something more flexible
+ if (!strcasecmp(name, "AC3 Passthru") ||
+ !strcasecmp(name, "DTS Passthru") ||
+ !strcasecmp(name, "DTS-HD Passthru"))
{
- // ca_haac can't do samplerates < 32 kHz
- // AC-3 < 32 kHz suffers from poor hardware compatibility
- best_samplerate = 32000;
- samplerate_shift = 0;
+ return HB_AMIXDOWN_NONE;
}
- else if (samplerate < 16000 && codec == HB_ACODEC_FDK_HAAC)
+ if (!strcasecmp(name, "6-channel discrete"))
{
- // fdk_haac can't do samplerates < 16 kHz
- best_samplerate = 16000;
- samplerate_shift = 1;
+ return HB_AMIXDOWN_5POINT1;
}
- else
+
+ int i;
+ for (i = 0; i < hb_audio_mixdowns_count; i++)
{
- best_samplerate = samplerate;
- for (ii = hb_audio_rates_count - 1; ii >= 0; ii--)
+ if (!strcasecmp(hb_audio_mixdowns[i].name, name) ||
+ !strcasecmp(hb_audio_mixdowns[i].short_name, name))
{
- // valid samplerate
- if (best_samplerate == hb_audio_rates[ii].rate)
- break;
+ return hb_audio_mixdowns[i].amixdown;
+ }
+ }
- // 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)
+fail:
+ return -1;
+}
+
+const char* hb_mixdown_get_name(int mixdown)
+{
+ if (mixdown < hb_audio_mixdowns[0].amixdown ||
+ mixdown > hb_audio_mixdowns[hb_audio_mixdowns_count - 1].amixdown)
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_audio_mixdowns_count; i++)
+ {
+ if (hb_audio_mixdowns[i].amixdown == mixdown)
+ {
+ return hb_audio_mixdowns[i].name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_mixdown_get_short_name(int mixdown)
+{
+ if (mixdown < hb_audio_mixdowns[0].amixdown ||
+ mixdown > hb_audio_mixdowns[hb_audio_mixdowns_count - 1].amixdown)
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_audio_mixdowns_count; i++)
+ {
+ if (hb_audio_mixdowns[i].amixdown == mixdown)
+ {
+ return hb_audio_mixdowns[i].short_name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_mixdown_sanitize_name(const char *name)
+{
+ return hb_mixdown_get_name(hb_mixdown_get_from_name(name));
+}
+
+const hb_mixdown_t* hb_mixdown_get_next(const hb_mixdown_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_audio_mixdowns[0];
+ }
+ if (last < &hb_audio_mixdowns[0] ||
+ last >= &hb_audio_mixdowns[hb_audio_mixdowns_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
+}
+
+int hb_video_encoder_get_default(int muxer)
+{
+ if (!(muxer & HB_MUX_MASK))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_video_encoders_count; i++)
+ {
+ if (hb_video_encoders[i].muxers & muxer)
+ {
+ return hb_video_encoders[i].codec;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+int hb_video_encoder_get_from_name(const char *name)
+{
+ if (name == NULL || *name == '\0')
+ goto fail;
+
+ // TODO: implement something more flexible
+ if (!strcasecmp(name, "XviD") ||
+ !strcasecmp(name, "FFmpeg"))
+ {
+ return HB_VCODEC_FFMPEG_MPEG4;
+ }
+
+ int i;
+ for (i = 0; i < hb_video_encoders_count; i++)
+ {
+ if (!strcasecmp(hb_video_encoders[i].name, name) ||
+ !strcasecmp(hb_video_encoders[i].short_name, name))
+ {
+ return hb_video_encoders[i].codec;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+const char* hb_video_encoder_get_name(int encoder)
+{
+ if (!(encoder & HB_VCODEC_MASK))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_video_encoders_count; i++)
+ {
+ if (hb_video_encoders[i].codec == encoder)
+ {
+ return hb_video_encoders[i].name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_video_encoder_get_short_name(int encoder)
+{
+ if (!(encoder & HB_VCODEC_MASK))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_video_encoders_count; i++)
+ {
+ if (hb_video_encoders[i].codec == encoder)
+ {
+ return hb_video_encoders[i].short_name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_video_encoder_sanitize_name(const char *name)
+{
+ return hb_video_encoder_get_name(hb_video_encoder_get_from_name(name));
+}
+
+const hb_encoder_t* hb_video_encoder_get_next(const hb_encoder_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_video_encoders[0];
+ }
+ if (last < &hb_video_encoders[0] ||
+ last >= &hb_video_encoders[hb_video_encoders_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
+}
+
+// for a valid passthru, return the matching encoder for that codec (if any),
+// else return -1 (i.e. drop the track)
+int hb_audio_encoder_get_fallback_for_passthru(int passthru)
+{
+ // TODO: implement something more flexible
+ switch (passthru)
+ {
+ case HB_ACODEC_AAC_PASS:
+#ifdef __APPLE__
+ return HB_ACODEC_CA_AAC;
+#else
+ return HB_ACODEC_FAAC;
+#endif
+
+ case HB_ACODEC_AC3_PASS:
+ return HB_ACODEC_AC3;
+
+ case HB_ACODEC_MP3_PASS:
+ return HB_ACODEC_LAME;
+
+ // passthru tracks are often the second audio from the same source track
+ // if we don't have an encoder matching the passthru codec, return -1
+ // dropping the track, as well as ensuring that there is at least one
+ // audio track in the output is then up to the UIs
+ default:
+ return -1;
+ }
+}
+
+int hb_audio_encoder_get_default(int muxer)
+{
+ if (!(muxer & HB_MUX_MASK))
+ goto fail;
+
+#ifndef __APPLE__
+ if (muxer == HB_MUX_MKV)
+ {
+ return HB_ACODEC_LAME;
+ }
+#endif
+
+ int i;
+ for (i = 0; i < hb_audio_encoders_count; i++)
+ {
+ // default encoder should not be passthru
+ if ((hb_audio_encoders[i].muxers & muxer) &&
+ (hb_audio_encoders[i].codec & HB_ACODEC_PASS_FLAG) == 0)
+ {
+ return hb_audio_encoders[i].codec;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+int hb_audio_encoder_get_from_name(const char *name)
+{
+ if (name == NULL || *name == '\0')
+ goto fail;
+
+ // TODO: implement something more flexible
+ if (!strcasecmp(name, "AC3"))
+ {
+ return HB_ACODEC_AC3;
+ }
+ // libfdk fallback, use Core Audio if available, else FAAC
+#ifndef USE_FDK_AAC
+#ifdef __APPLE__
+#define AAC_ENC HB_ACODEC_CA_AAC
+#define HAAC_ENC HB_ACODEC_CA_HAAC
+#else
+#define AAC_ENC HB_ACODEC_FAAC
+#define HAAC_ENC HB_ACODEC_FAAC
+#endif
+ if (!strcasecmp(name, "AAC (FDK)") || !strcasecmp(name, "fdk_aac"))
+ {
+ return AAC_ENC;
+ }
+ if (!strcasecmp(name, "HE-AAC (FDK)") || !strcasecmp(name, "fdk_haac"))
+ {
+ return HAAC_ENC;
+ }
+#undef AAC_ENC
+#undef HAAC_ENC
+#endif
+
+ int i;
+ for (i = 0; i < hb_audio_encoders_count; i++)
+ {
+ if (!strcasecmp(hb_audio_encoders[i].name, name) ||
+ !strcasecmp(hb_audio_encoders[i].short_name, name))
+ {
+ return hb_audio_encoders[i].codec;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+const char* hb_audio_encoder_get_name(int encoder)
+{
+ if (!(encoder & HB_ACODEC_ANY))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_audio_encoders_count; i++)
+ {
+ if (hb_audio_encoders[i].codec == encoder)
+ {
+ return hb_audio_encoders[i].name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_audio_encoder_get_short_name(int encoder)
+{
+ if (!(encoder & HB_ACODEC_ANY))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_audio_encoders_count; i++)
+ {
+ if (hb_audio_encoders[i].codec == encoder)
+ {
+ return hb_audio_encoders[i].short_name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_audio_encoder_sanitize_name(const char *name)
+{
+ return hb_audio_encoder_get_name(hb_audio_encoder_get_from_name(name));
+}
+
+const hb_encoder_t* hb_audio_encoder_get_next(const hb_encoder_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_audio_encoders[0];
+ }
+ if (last < &hb_audio_encoders[0] ||
+ last >= &hb_audio_encoders[hb_audio_encoders_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
+}
+
+void hb_autopassthru_apply_settings(hb_job_t *job)
+{
+ hb_audio_t *audio;
+ int i, already_printed;
+ for (i = already_printed = 0; i < hb_list_count(job->list_audio);)
+ {
+ audio = hb_list_item(job->list_audio, i);
+ if (audio->config.out.codec == HB_ACODEC_AUTO_PASS)
+ {
+ if (!already_printed)
+ hb_autopassthru_print_settings(job);
+ already_printed = 1;
+ audio->config.out.codec = hb_autopassthru_get_encoder(audio->config.in.codec,
+ job->acodec_copy_mask,
+ job->acodec_fallback,
+ job->mux);
+ if (!(audio->config.out.codec & HB_ACODEC_PASS_FLAG) &&
+ !(audio->config.out.codec & HB_ACODEC_MASK))
{
- best_samplerate = hb_audio_rates[ii].rate;
- break;
+ hb_log("Auto Passthru: passthru not possible and no valid fallback specified, dropping track %d",
+ audio->config.out.track );
+ hb_list_rem(job->list_audio, audio);
+ hb_audio_close(&audio);
+ continue;
+ }
+ audio->config.out.samplerate = audio->config.in.samplerate;
+ if (!(audio->config.out.codec & HB_ACODEC_PASS_FLAG))
+ {
+ if (audio->config.out.codec == job->acodec_fallback)
+ {
+ hb_log("Auto Passthru: passthru not possible for track %d, using fallback",
+ audio->config.out.track);
+ }
+ else
+ {
+ hb_log("Auto Passthru: passthru and fallback not possible for track %d, using default encoder",
+ audio->config.out.track);
+ }
+ audio->config.out.mixdown =
+ hb_mixdown_get_default(audio->config.out.codec,
+ audio->config.in.channel_layout);
+ audio->config.out.bitrate =
+ hb_audio_bitrate_get_default(audio->config.out.codec,
+ audio->config.out.samplerate,
+ audio->config.out.mixdown );
+ audio->config.out.compression_level =
+ hb_audio_compression_get_default(audio->config.out.codec);
+ }
+ else
+ {
+ const hb_encoder_t *audio_encoder = NULL;
+ while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL)
+ {
+ if (audio_encoder->codec == audio->config.out.codec)
+ {
+ hb_log("Auto Passthru: using %s for track %d",
+ audio_encoder->name,
+ audio->config.out.track);
+ 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);
+ /* 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;
}
- if (sr_shift != NULL)
+}
+
+void hb_autopassthru_print_settings(hb_job_t *job)
+{
+ char *mask = NULL, *tmp;
+ const char *fallback = NULL;
+ const hb_encoder_t *audio_encoder = NULL;
+ while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL)
{
- *sr_shift = samplerate_shift;
+ if ((audio_encoder->codec & HB_ACODEC_PASS_FLAG) &&
+ (audio_encoder->codec != HB_ACODEC_AUTO_PASS) &&
+ (audio_encoder->codec & job->acodec_copy_mask))
+ {
+ if (mask != NULL)
+ {
+ tmp = hb_strncat_dup(mask, ", ", 2);
+ if (tmp != NULL)
+ {
+ free(mask);
+ mask = tmp;
+ }
+ }
+ // passthru name without " Passthru"
+ tmp = hb_strncat_dup(mask, audio_encoder->name,
+ strlen(audio_encoder->name) - 9);
+ if (tmp != NULL)
+ {
+ free(mask);
+ mask = tmp;
+ }
+ }
+ else if ((audio_encoder->codec & HB_ACODEC_PASS_FLAG) == 0 &&
+ (audio_encoder->codec == job->acodec_fallback))
+ {
+ fallback = audio_encoder->name;
+ }
}
- return best_samplerate;
+ if (mask == NULL)
+ hb_log("Auto Passthru: no codecs allowed");
+ else
+ hb_log("Auto Passthru: allowed codecs are %s", mask);
+ if (fallback == NULL)
+ hb_log("Auto Passthru: no valid fallback specified");
+ else
+ hb_log("Auto Passthru: fallback is %s", fallback);
+}
+
+int hb_autopassthru_get_encoder(int in_codec, int copy_mask, int fallback,
+ int muxer)
+{
+ int i = 0;
+ const hb_encoder_t *audio_encoder = NULL;
+ int out_codec = (copy_mask & in_codec) | HB_ACODEC_PASS_FLAG;
+ // sanitize fallback encoder and selected passthru
+ // note: invalid fallbacks are caught in hb_autopassthru_apply_settings
+ while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL)
+ {
+ if (audio_encoder->codec == out_codec)
+ {
+ i++;
+ if (!(audio_encoder->muxers & muxer))
+ out_codec = 0;
+ }
+ else if (audio_encoder->codec == fallback)
+ {
+ i++;
+ if (!(audio_encoder->muxers & muxer))
+ fallback = hb_audio_encoder_get_default(muxer);
+ }
+ if (i > 1)
+ {
+ break;
+ }
+ }
+ return (out_codec & HB_ACODEC_PASS_MASK) ? out_codec : fallback;
+}
+
+int hb_container_get_from_name(const char *name)
+{
+ if (name == NULL || *name == '\0')
+ goto fail;
+
+ // TODO: implement something more flexible
+ if (!strcasecmp(name, "m4v"))
+ {
+ // old CLI alternate short name for "mp4"
+ return HB_MUX_MP4;
+ }
+ if (!strcasecmp(name, "MP4 file"))
+ {
+ return HB_MUX_MP4;
+ }
+ if (!strcasecmp(name, "MKV file"))
+ {
+ return HB_MUX_MKV;
+ }
+
+ int i;
+ for (i = 0; i < hb_containers_count; i++)
+ {
+ if (!strcasecmp(hb_containers[i].name, name) ||
+ !strcasecmp(hb_containers[i].short_name, name) ||
+ !strcasecmp(hb_containers[i].default_extension, name))
+ {
+ return hb_containers[i].format;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+int hb_container_get_from_extension(const char *extension)
+{
+ if (extension == NULL || *extension == '\0')
+ goto fail;
+
+ // TODO: implement something more flexible
+ if (!strcasecmp(extension, "m4v"))
+ {
+ return HB_MUX_MP4;
+ }
+
+ int i;
+ for (i = 0; i < hb_containers_count; i++)
+ {
+ if (!strcasecmp(hb_containers[i].default_extension, extension))
+ {
+ return hb_containers[i].format;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+const char* hb_container_get_name(int format)
+{
+ if (!(format & HB_MUX_MASK))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_containers_count; i++)
+ {
+ if (hb_containers[i].format == format)
+ {
+ return hb_containers[i].name;
+ }
+
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_container_get_short_name(int format)
+{
+ if (!(format & HB_MUX_MASK))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_containers_count; i++)
+ {
+ if (hb_containers[i].format == format)
+ {
+ return hb_containers[i].short_name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_container_get_default_extension(int format)
+{
+ if (!(format & HB_MUX_MASK))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_containers_count; i++)
+ {
+ if (hb_containers[i].format == format)
+ {
+ return hb_containers[i].default_extension;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_container_sanitize_name(const char *name)
+{
+ return hb_container_get_name(hb_container_get_from_name(name));
+}
+
+const hb_container_t* hb_container_get_next(const hb_container_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_containers[0];
+ }
+ if (last < &hb_containers[0] ||
+ last >= &hb_containers[hb_containers_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
}
/**********************************************************************
@@ -2336,7 +2944,7 @@ void hb_audio_config_init(hb_audio_config_t * audiocfg)
/* Initalize some sensible defaults */
audiocfg->in.track = audiocfg->out.track = 0;
- audiocfg->out.codec = hb_audio_encoders[0].encoder;
+ audiocfg->out.codec = hb_audio_encoders[0].codec;
audiocfg->out.samplerate = -1;
audiocfg->out.samples_per_frame = -1;
audiocfg->out.bitrate = -1;
@@ -2970,9 +3578,9 @@ void hb_attachment_close( hb_attachment_t **attachment )
* hb_yuv2rgb
**********************************************************************
* Converts a YCrCb pixel to an RGB pixel.
- *
+ *
* This conversion is lossy (due to rounding and clamping).
- *
+ *
* Algorithm:
* http://en.wikipedia.org/w/index.php?title=YCbCr&oldid=361987695#Technical_details
*********************************************************************/
@@ -3004,9 +3612,9 @@ int hb_yuv2rgb(int yuv)
* hb_rgb2yuv
**********************************************************************
* Converts an RGB pixel to a YCrCb pixel.
- *
+ *
* This conversion is lossy (due to rounding and clamping).
- *
+ *
* Algorithm:
* http://en.wikipedia.org/w/index.php?title=YCbCr&oldid=361987695#Technical_details
*********************************************************************/
diff --git a/libhb/common.h b/libhb/common.h
index 2951def5d..58d102c9a 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -73,6 +73,7 @@ typedef struct hb_rate_s hb_rate_t;
typedef struct hb_dither_s hb_dither_t;
typedef struct hb_mixdown_s hb_mixdown_t;
typedef struct hb_encoder_s hb_encoder_t;
+typedef struct hb_container_s hb_container_t;
typedef struct hb_job_s hb_job_t;
typedef struct hb_title_set_s hb_title_set_t;
typedef struct hb_title_s hb_title_t;
@@ -171,7 +172,7 @@ void hb_chapter_set_title(hb_chapter_t *chapter, const char *title);
struct hb_rate_s
{
- const char *string;
+ const char *name;
int rate;
};
@@ -184,7 +185,7 @@ struct hb_dither_s
struct hb_mixdown_s
{
- const char *human_readable_name;
+ const char *name;
const char *internal_name;
const char *short_name;
int amixdown;
@@ -192,10 +193,18 @@ struct hb_mixdown_s
struct hb_encoder_s
{
- const char *human_readable_name; // note: used in presets
- const char *short_name; // note: used in CLI
- int encoder; // HB_*CODEC_* define
- int muxers; // supported muxers
+ const char *name; // note: used in presets
+ const char *short_name; // note: used in CLI
+ int codec; // HB_*CODEC_* define
+ int muxers; // supported muxers
+};
+
+struct hb_container_s
+{
+ const char *name;
+ const char *short_name;
+ const char *default_extension;
+ int format;
};
struct hb_subtitle_config_s
@@ -210,77 +219,115 @@ struct hb_subtitle_config_s
int64_t offset;
};
-#define HB_VIDEO_RATE_BASE 27000000
-
-extern hb_rate_t hb_video_rates[];
-extern int hb_video_rates_count;
-extern hb_rate_t hb_audio_rates[];
-extern int hb_audio_rates_count;
-extern int hb_audio_rates_default;
-extern hb_rate_t hb_audio_bitrates[];
-extern int hb_audio_bitrates_count;
-extern hb_dither_t hb_audio_dithers[];
-extern int hb_audio_dithers_count;
-extern hb_mixdown_t hb_audio_mixdowns[];
-extern int hb_audio_mixdowns_count;
-extern hb_encoder_t hb_video_encoders[];
-extern int hb_video_encoders_count;
-extern hb_encoder_t hb_audio_encoders[];
-extern int hb_audio_encoders_count;
-
-/* Expose values for PInvoke */
-hb_rate_t* hb_get_video_rates();
-int hb_get_video_rates_count();
-hb_rate_t* hb_get_audio_rates();
-int hb_get_audio_rates_count();
-int hb_get_audio_rates_default();
-hb_rate_t* hb_get_audio_bitrates();
-int hb_get_audio_bitrates_count();
-hb_dither_t* hb_get_audio_dithers();
-int hb_get_audio_dithers_count();
-hb_mixdown_t* hb_get_audio_mixdowns();
-int hb_get_audio_mixdowns_count();
-hb_encoder_t* hb_get_video_encoders();
-int hb_get_video_encoders_count();
-hb_encoder_t* hb_get_audio_encoders();
-int hb_get_audio_encoders_count();
-
-int hb_audio_dither_get_default();
-int hb_audio_dither_get_default_method();
-int hb_audio_dither_is_supported(uint32_t codec);
-const char* hb_audio_dither_get_description(int method);
-
-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);
+/*******************************************************************************
+ * Lists of rates, mixdowns, encoders etc.
+ *******************************************************************************
+ *
+ * Use hb_*_get_next() to get the next list item (use NULL to get the first).
+ *
+ * Use hb_*_get_from_name() to get the value corresponding to a name.
+ * The name can be either the short or full name.
+ * Legacy names are sanitized to currently-supported values whenever possible.
+ * Returns -1 if no value could be found.
+ *
+ * Use hb_*_get_name() and hb_*_get_short_name() to get the corresponding value.
+ * Returns NULL if the value is invalid.
+ *
+ * hb_*_sanitize_name() are convenience functions for use when dealing
+ * with full names (e.g. to translate legacy values while loading a preset).
+ *
+ * Names are case-insensitive; libhb will ensure that the lists do not contain
+ * more than one entry with the same name.
+ *
+ * Use hb_*_get_limits() to get the minimum/maximum for lists with numerically
+ * ordered values.
+ *
+ * Use hb_*_get_best() to sanitize a value based on other relevant parameters.
+ *
+ * Use hb_*_get_default() to get the default based on other relevant parameters.
+ *
+ */
+
+int hb_video_framerate_get_from_name(const char *name);
+const char* hb_video_framerate_get_name(int framerate);
+const char* hb_video_framerate_sanitize_name(const char *name);
+const hb_rate_t* hb_video_framerate_get_next(const hb_rate_t *last);
+
+int hb_audio_samplerate_get_best(uint32_t codec, int samplerate, int *sr_shift);
+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);
+
+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);
+void hb_audio_bitrate_get_limits(uint32_t codec, int samplerate, int mixdown, int *low, int *high);
+const hb_rate_t* hb_audio_bitrate_get_next(const hb_rate_t *last);
+
+void hb_audio_quality_get_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction);
+float hb_audio_quality_get_best(uint32_t codec, float quality);
+float hb_audio_quality_get_default(uint32_t codec);
+
+void hb_audio_compression_get_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction);
+float hb_audio_compression_get_best(uint32_t codec, float compression);
+float hb_audio_compression_get_default(uint32_t codec);
+
+int hb_audio_dither_get_default();
+int hb_audio_dither_get_default_method(); // default method, if enabled && supported
+int hb_audio_dither_is_supported(uint32_t codec);
+int hb_audio_dither_get_from_name(const char *name);
+const char* hb_audio_dither_get_description(int method);
+const hb_dither_t* hb_audio_dither_get_next(const hb_dither_t *last);
+
+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 mixdown);
+int hb_mixdown_get_low_freq_channel_count(int mixdown);
+int hb_mixdown_get_best(uint32_t codec, uint64_t layout, int mixdown);
+int hb_mixdown_get_default(uint32_t codec, uint64_t layout);
+int hb_mixdown_get_from_name(const char *name);
+const char* hb_mixdown_get_name(int mixdown);
+const char* hb_mixdown_get_short_name(int mixdown);
+const char* hb_mixdown_sanitize_name(const char *name);
+const hb_mixdown_t* hb_mixdown_get_next(const hb_mixdown_t *last);
+
+int hb_video_encoder_get_default(int muxer);
+int hb_video_encoder_get_from_name(const char *name);
+const char* hb_video_encoder_get_name(int encoder);
+const char* hb_video_encoder_get_short_name(int encoder);
+const char* hb_video_encoder_sanitize_name(const char *name);
+const hb_encoder_t* hb_video_encoder_get_next(const hb_encoder_t *last);
+
+/*
+ * hb_audio_encoder_get_fallback_for_passthru() will sanitize a passthru codec
+ * to the matching audio encoder (if any is available).
+ *
+ * hb_audio_encoder_get_from_name(), hb_audio_encoder_sanitize_name() will
+ * sanitize legacy encoder names, but won't convert passthru to an encoder.
+ */
+int hb_audio_encoder_get_fallback_for_passthru(int passthru);
+int hb_audio_encoder_get_default(int muxer);
+int hb_audio_encoder_get_from_name(const char *name);
+const char* hb_audio_encoder_get_name(int encoder);
+const char* hb_audio_encoder_get_short_name(int encoder);
+const char* hb_audio_encoder_sanitize_name(const char *name);
+const hb_encoder_t* hb_audio_encoder_get_next(const hb_encoder_t *last);
+/*
+ * Not typically used by the UIs
+ * (set hb_job_t.acodec_copy_mask, hb_job_t.acodec_fallback instead).
+ */
void hb_autopassthru_apply_settings(hb_job_t *job);
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_default_audio_encoder(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);
-int hb_get_default_audio_bitrate(uint32_t codec, int samplerate, int mixdown);
-
-void hb_get_audio_quality_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction);
-float hb_get_best_audio_quality(uint32_t codec, float quality);
-float hb_get_default_audio_quality(uint32_t codec);
-
-void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction);
-float hb_get_best_audio_compression(uint32_t codec, float compression);
-float hb_get_default_audio_compression(uint32_t codec);
+int hb_container_get_from_name(const char *name);
+int hb_container_get_from_extension(const char *extension); // not really a container name
+const char* hb_container_get_name(int format);
+const char* hb_container_get_short_name(int format);
+const char* hb_container_get_default_extension(int format);
+const char* hb_container_sanitize_name(const char *name);
+const hb_container_t* hb_container_get_next(const hb_container_t *last);
struct hb_title_set_s
{
@@ -408,12 +455,19 @@ struct hb_job_s
hb_metadata_t * metadata;
- /* Muxer settings
- mux: output file format
- file: file path */
-#define HB_MUX_MASK 0xFF0000
-#define HB_MUX_MP4 0x010000
-#define HB_MUX_MKV 0x200000
+ /*
+ * Muxer settings
+ * mux: output file format
+ * file: file path
+ */
+#define HB_MUX_MASK 0xFF0000
+#define HB_MUX_MP4V2 0x010000
+#define HB_MUX_MASK_MP4 0x0F0000
+#define HB_MUX_LIBMKV 0x100000
+#define HB_MUX_MASK_MKV 0xF00000
+// default MP4 and MKV muxers
+#define HB_MUX_MP4 HB_MUX_MP4V2
+#define HB_MUX_MKV HB_MUX_LIBMKV
int mux;
char * file;
diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c
index b232dae81..dcb19da34 100644
--- a/libhb/encavcodec.c
+++ b/libhb/encavcodec.c
@@ -117,12 +117,12 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job )
// to fps.den.
if (fps.num == 27000000)
{
- int ii;
- for (ii = 0; ii < hb_video_rates_count; ii++)
+ const hb_rate_t *video_framerate = NULL;
+ while ((video_framerate = hb_video_framerate_get_next(video_framerate)) != NULL)
{
- if (abs(fps.den - hb_video_rates[ii].rate) < 10)
+ if (abs(fps.den - video_framerate->rate) < 10)
{
- fps.den = hb_video_rates[ii].rate;
+ fps.den = video_framerate->rate;
break;
}
}
diff --git a/libhb/scan.c b/libhb/scan.c
index c83326d4d..0d7dde7ff 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -820,11 +820,12 @@ skip_preview:
// if the frame rate is very close to one of our "common" framerates,
// assume it actually is said frame rate; e.g. some 24000/1001 sources
// may have a rate_base of 1126124 (instead of 1126125)
- for( i = 0; i < hb_video_rates_count; i++ )
+ const hb_rate_t *video_framerate = NULL;
+ while ((video_framerate = hb_video_framerate_get_next(video_framerate)) != NULL)
{
- if( is_close_to( vid_info.rate_base, hb_video_rates[i].rate, 100 ) )
+ if (is_close_to(vid_info.rate_base, video_framerate->rate, 100))
{
- vid_info.rate_base = hb_video_rates[i].rate;
+ vid_info.rate_base = video_framerate->rate;
break;
}
}
diff --git a/libhb/work.c b/libhb/work.c
index 72d758eed..1e05c9db7 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -149,12 +149,12 @@ hb_work_object_t* hb_codec_encoder(int codec)
* Displays job parameters in the debug log.
* @param job Handle work hb_job_t.
*/
-void hb_display_job_info( hb_job_t * job )
+void hb_display_job_info(hb_job_t *job)
{
- hb_title_t * title = job->title;
- hb_audio_t * audio;
- hb_subtitle_t * subtitle;
- int i, j;
+ int i;
+ hb_title_t *title = job->title;
+ hb_audio_t *audio;
+ hb_subtitle_t *subtitle;
hb_log("job configuration:");
hb_log( " * source");
@@ -206,26 +206,19 @@ void hb_display_job_info( hb_job_t * job )
hb_log( " + %s", job->file );
- switch( job->mux )
+ hb_log(" + container: %s", hb_container_get_name(job->mux));
+ switch (job->mux)
{
- case HB_MUX_MP4:
- hb_log(" + container: MPEG-4 (.mp4 and .m4v)");
-
- if( job->ipod_atom )
- hb_log( " + compatibility atom for iPod 5G");
-
- if( job->largeFileSize )
- hb_log( " + 64-bit formatting");
-
- if( job->mp4_optimize )
- hb_log( " + optimized for progressive web downloads");
-
- if( job->color_matrix_code )
- hb_log( " + custom color matrix: %s", job->color_matrix_code == 1 ? "ITU Bt.601 (SD)" : job->color_matrix_code == 2 ? "ITU Bt.709 (HD)" : "Custom" );
+ case HB_MUX_MP4V2:
+ if (job->largeFileSize)
+ hb_log(" + 64-bit chunk offsets");
+ if (job->mp4_optimize)
+ hb_log(" + optimized for HTTP streaming (fast start)");
+ if (job->ipod_atom)
+ hb_log(" + compatibility atom for iPod 5G");
break;
- case HB_MUX_MKV:
- hb_log(" + container: Matroska (.mkv)");
+ default:
break;
}
@@ -295,14 +288,7 @@ void hb_display_job_info( hb_job_t * job )
if( !job->indepth_scan )
{
/* Video encoder */
- for( i = 0; i < hb_video_encoders_count; i++ )
- {
- if( hb_video_encoders[i].encoder == job->vcodec )
- {
- hb_log( " + encoder: %s", hb_video_encoders[i].human_readable_name );
- break;
- }
- }
+ hb_log(" + encoder: %s", hb_video_encoder_get_name(job->vcodec));
if( job->x264_preset && *job->x264_preset &&
job->vcodec == HB_VCODEC_X264 )
@@ -346,6 +332,18 @@ void hb_display_job_info( hb_job_t * job )
hb_log( " subq=2 (if originally greater than 2, else subq unchanged)" );
}
}
+
+ if (job->color_matrix_code && (job->vcodec == HB_VCODEC_X264 ||
+ job->mux == HB_MUX_MP4V2))
+ {
+ // color matrix is set:
+ // 1) at the stream level (x264 only),
+ // 2) at the container level (mp4v2 only)
+ hb_log(" + custom color matrix: %s",
+ job->color_matrix_code == 1 ? "ITU Bt.601 (NTSC)" :
+ job->color_matrix_code == 2 ? "ITU Bt.601 (PAL)" :
+ job->color_matrix_code == 3 ? "ITU Bt.709 (HD)" : "Custom");
+ }
}
if( job->indepth_scan )
@@ -413,25 +411,13 @@ void hb_display_job_info( hb_job_t * job )
if( audio->config.out.codec & HB_ACODEC_PASS_FLAG )
{
- for( j = 0; j < hb_audio_encoders_count; j++ )
- {
- if( hb_audio_encoders[j].encoder == audio->config.out.codec )
- {
- hb_log( " + %s", hb_audio_encoders[j].human_readable_name );
- break;
- }
- }
+ hb_log(" + %s",
+ hb_audio_encoder_get_name(audio->config.out.codec));
}
else
{
- for( j = 0; j < hb_audio_mixdowns_count; j++ )
- {
- if( hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown )
- {
- hb_log( " + mixdown: %s", hb_audio_mixdowns[j].human_readable_name );
- break;
- }
- }
+ hb_log(" + mixdown: %s",
+ hb_mixdown_get_name(audio->config.out.mixdown));
if( audio->config.out.normalize_mix_level != 0 )
{
hb_log( " + normalized mixing levels" );
@@ -449,22 +435,27 @@ void hb_display_job_info( hb_job_t * job )
hb_log(" + dither: %s",
hb_audio_dither_get_description(audio->config.out.dither_method));
}
- for( j = 0; j < hb_audio_encoders_count; j++ )
+ hb_log(" + encoder: %s",
+ hb_audio_encoder_get_name(audio->config.out.codec));
+ if (audio->config.out.bitrate > 0)
{
- if( hb_audio_encoders[j].encoder == audio->config.out.codec )
- {
- hb_log( " + encoder: %s", hb_audio_encoders[j].human_readable_name );
- if( audio->config.out.bitrate > 0 )
- hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate );
- else if( audio->config.out.quality != HB_INVALID_AUDIO_QUALITY )
- hb_log( " + quality: %.2f, samplerate: %d Hz", audio->config.out.quality, audio->config.out.samplerate );
- else if( audio->config.out.samplerate > 0 )
- hb_log( " + samplerate: %d Hz", audio->config.out.samplerate );
- if( audio->config.out.compression_level >= 0 )
- hb_log( " + compression level: %.2f",
- audio->config.out.compression_level );
- break;
- }
+ hb_log(" + bitrate: %d kbps, samplerate: %d Hz",
+ audio->config.out.bitrate, audio->config.out.samplerate);
+ }
+ else if (audio->config.out.quality != HB_INVALID_AUDIO_QUALITY)
+ {
+ hb_log(" + quality: %.2f, samplerate: %d Hz",
+ audio->config.out.quality, audio->config.out.samplerate);
+ }
+ else if (audio->config.out.samplerate > 0)
+ {
+ hb_log(" + samplerate: %d Hz",
+ audio->config.out.samplerate);
+ }
+ if (audio->config.out.compression_level >= 0)
+ {
+ hb_log(" + compression level: %.2f",
+ audio->config.out.compression_level);
}
}
}
@@ -494,24 +485,24 @@ void correct_framerate( hb_job_t * job )
* Closes threads and frees fifos.
* @param job Handle work hb_job_t.
*/
-static void do_job( hb_job_t * job )
+static void do_job(hb_job_t *job)
{
- hb_title_t * title;
- int i, j;
- hb_work_object_t * w;
- hb_work_object_t * sync;
- hb_work_object_t * muxer;
+ int i;
+ hb_title_t *title;
+ hb_interjob_t *interjob;
+ hb_work_object_t *w;
+ hb_work_object_t *sync;
+ hb_work_object_t *muxer;
hb_work_object_t *reader = hb_get_work(WORK_READER);
- hb_interjob_t * interjob;
-
- hb_audio_t * audio;
- hb_subtitle_t * subtitle;
- unsigned int subtitle_highest = 0;
- unsigned int subtitle_lowest = 0;
- unsigned int subtitle_lowest_id = 0;
- unsigned int subtitle_forced_id = 0;
+
+ hb_audio_t *audio;
+ hb_subtitle_t *subtitle;
+ unsigned int subtitle_highest = 0;
+ unsigned int subtitle_lowest = 0;
+ unsigned int subtitle_lowest_id = 0;
+ unsigned int subtitle_forced_id = 0;
unsigned int subtitle_forced_hits = 0;
- unsigned int subtitle_hit = 0;
+ unsigned int subtitle_hit = 0;
title = job->title;
interjob = hb_interjob_get( job->h );
@@ -797,21 +788,14 @@ static void do_job( hb_job_t * job )
audio->config.out.samplerate = audio->config.in.samplerate;
}
best_samplerate =
- hb_get_best_samplerate(audio->config.out.codec,
- audio->config.out.samplerate, NULL);
+ hb_audio_samplerate_get_best(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;
- }
- }
+ hb_log("work: sanitizing track %d unsupported samplerate %d Hz to %s kHz",
+ audio->config.out.track, audio->config.out.samplerate,
+ hb_audio_samplerate_get_name(best_samplerate));
audio->config.out.samplerate = best_samplerate;
}
@@ -820,44 +804,25 @@ static void do_job( hb_job_t * job )
{
/* Mixdown not specified, set the default mixdown */
audio->config.out.mixdown =
- hb_get_default_mixdown(audio->config.out.codec,
+ hb_mixdown_get_default(audio->config.out.codec,
audio->config.in.channel_layout);
- for (j = 0; j < hb_audio_mixdowns_count; j++)
- {
- if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown)
- {
- hb_log("work: mixdown not specified, track %d setting mixdown %s",
- audio->config.out.track,
- hb_audio_mixdowns[j].human_readable_name);
- break;
- }
- }
+ hb_log("work: mixdown not specified, track %d setting mixdown %s",
+ audio->config.out.track,
+ hb_mixdown_get_name(audio->config.out.mixdown));
}
else
{
best_mixdown =
- hb_get_best_mixdown(audio->config.out.codec,
+ hb_mixdown_get_best(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;
- for (j = 0; j < hb_audio_mixdowns_count; j++)
- {
- if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown)
- {
- prev_mix_idx = j;
- }
- else if (hb_audio_mixdowns[j].amixdown == best_mixdown)
- {
- best_mix_idx = j;
- }
- }
/* log the output mixdown */
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);
+ hb_mixdown_get_name(audio->config.out.mixdown),
+ hb_mixdown_get_name(best_mixdown));
audio->config.out.mixdown = best_mixdown;
}
}
@@ -866,7 +831,7 @@ static void do_job( hb_job_t * job )
if (audio->config.out.compression_level < 0)
{
audio->config.out.compression_level =
- hb_get_default_audio_compression(audio->config.out.codec);
+ hb_audio_compression_get_default(audio->config.out.codec);
if (audio->config.out.compression_level >= 0)
{
hb_log("work: compression level not specified, track %d setting compression level %.2f",
@@ -877,7 +842,7 @@ static void do_job( hb_job_t * job )
else
{
float best_compression =
- hb_get_best_audio_compression(audio->config.out.codec,
+ hb_audio_compression_get_best(audio->config.out.codec,
audio->config.out.compression_level);
if (best_compression != audio->config.out.compression_level)
{
@@ -901,7 +866,7 @@ static void do_job( hb_job_t * job )
if (audio->config.out.quality != HB_INVALID_AUDIO_QUALITY)
{
float best_quality =
- hb_get_best_audio_quality(audio->config.out.codec,
+ hb_audio_quality_get_best(audio->config.out.codec,
audio->config.out.quality);
if (best_quality != audio->config.out.quality)
{
@@ -927,7 +892,7 @@ static void do_job( hb_job_t * job )
{
/* Bitrate not specified, set the default bitrate */
audio->config.out.bitrate =
- hb_get_default_audio_bitrate(audio->config.out.codec,
+ hb_audio_bitrate_get_default(audio->config.out.codec,
audio->config.out.samplerate,
audio->config.out.mixdown);
if (audio->config.out.bitrate > 0)
@@ -940,7 +905,7 @@ static void do_job( hb_job_t * job )
else
{
best_bitrate =
- hb_get_best_audio_bitrate(audio->config.out.codec,
+ hb_audio_bitrate_get_best(audio->config.out.codec,
audio->config.out.bitrate,
audio->config.out.samplerate,
audio->config.out.mixdown);