summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
Diffstat (limited to 'libhb')
-rw-r--r--libhb/common.c150
-rw-r--r--libhb/common.h19
-rw-r--r--libhb/work.c107
3 files changed, 209 insertions, 67 deletions
diff --git a/libhb/common.c b/libhb/common.c
index db2fac551..f320ff2c1 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -41,15 +41,43 @@ int hb_audio_bitrates_count = sizeof( hb_audio_bitrates ) /
static hb_error_handler_t *error_handler = NULL;
hb_mixdown_t hb_audio_mixdowns[] =
-{ { "Mono", "HB_AMIXDOWN_MONO", "mono", HB_AMIXDOWN_MONO },
+{ { "None", "HB_AMIXDOWN_NONE", "none", HB_AMIXDOWN_NONE },
+ { "Mono", "HB_AMIXDOWN_MONO", "mono", HB_AMIXDOWN_MONO },
{ "Stereo", "HB_AMIXDOWN_STEREO", "stereo", HB_AMIXDOWN_STEREO },
{ "Dolby Surround", "HB_AMIXDOWN_DOLBY", "dpl1", HB_AMIXDOWN_DOLBY },
{ "Dolby Pro Logic II", "HB_AMIXDOWN_DOLBYPLII", "dpl2", HB_AMIXDOWN_DOLBYPLII },
- { "6-channel discrete", "HB_AMIXDOWN_6CH", "6ch", HB_AMIXDOWN_6CH }
-};
+ { "6-channel discrete", "HB_AMIXDOWN_6CH", "6ch", HB_AMIXDOWN_6CH } };
int hb_audio_mixdowns_count = sizeof( hb_audio_mixdowns ) /
sizeof( hb_mixdown_t );
+hb_encoder_t hb_video_encoders[] =
+{ { "H.264 (x264)", "x264", HB_VCODEC_X264, HB_MUX_MP4|HB_MUX_MKV },
+ { "MPEG-4 (FFmpeg)", "ffmpeg4", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MP4|HB_MUX_MKV },
+ { "MPEG-2 (FFmpeg)", "ffmpeg2", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MP4|HB_MUX_MKV },
+ { "VP3 (Theora)", "theora", HB_VCODEC_THEORA, HB_MUX_MKV } };
+int hb_video_encoders_count = sizeof( hb_video_encoders ) /
+ sizeof( hb_encoder_t );
+
+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 },
+#endif
+ { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MP4|HB_MUX_MKV },
+ { "AAC (ffmpeg)", "ffaac", HB_ACODEC_FFAAC, HB_MUX_MP4|HB_MUX_MKV },
+ { "AAC Passthru", "copy:aac", HB_ACODEC_AAC_PASS, HB_MUX_MP4|HB_MUX_MKV },
+ { "AC3 (ffmpeg)", "ffac3", HB_ACODEC_AC3, HB_MUX_MP4|HB_MUX_MKV },
+ { "AC3 Passthru", "copy:ac3", HB_ACODEC_AC3_PASS, HB_MUX_MP4|HB_MUX_MKV },
+ { "DTS Passthru", "copy:dts", HB_ACODEC_DCA_PASS, HB_MUX_MP4|HB_MUX_MKV },
+ { "DTS-HD Passthru", "copy:dtshd", HB_ACODEC_DCA_HD_PASS, HB_MUX_MP4|HB_MUX_MKV },
+ { "MP3 (lame)", "lame", HB_ACODEC_LAME, HB_MUX_MP4|HB_MUX_MKV },
+ { "MP3 Passthru", "copy:mp3", HB_ACODEC_MP3_PASS, HB_MUX_MP4|HB_MUX_MKV },
+ { "Vorbis (vorbis)", "vorbis", HB_ACODEC_VORBIS, HB_MUX_MKV },
+ { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MP4|HB_MUX_MKV } };
+int hb_audio_encoders_count = sizeof( hb_audio_encoders ) /
+ sizeof( hb_encoder_t );
+
int hb_mixdown_get_mixdown_from_short_name( const char * short_name )
{
int i;
@@ -76,6 +104,106 @@ const char * hb_mixdown_get_short_name_from_mixdown( int amixdown )
return "";
}
+void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title )
+{
+ int i, j;
+ hb_audio_t * audio;
+ for( i = 0; i < hb_list_count( title->list_audio ); )
+ {
+ audio = hb_list_item( title->list_audio, i );
+ if( audio->config.out.codec == HB_ACODEC_AUTO_PASS )
+ {
+ 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( title->list_audio, audio );
+ free( 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 );
+ }
+ else
+ {
+ 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;
+ }
+ }
+ }
+ }
+ /* Adjust output track number, in case we removed one.
+ * Output tracks sadly still need to be in sequential order.
+ * Note: out.track starts at 1, i starts at 0 */
+ audio->config.out.track = ++i;
+ }
+}
+
+int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int muxer )
+{
+ 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 work.c
+ for( i = 0; i < hb_audio_encoders_count; i++ )
+ {
+ if( ( hb_audio_encoders[i].encoder == fallback ) &&
+ !( hb_audio_encoders[i].muxers & muxer ) )
+ {
+ // fallback not possible with current muxer
+ // use the default audio encoder instead
+#ifndef __APPLE__
+ if( muxer == HB_MUX_MKV )
+ // Lame is the default for MKV
+ fallback = HB_ACODEC_LAME;
+ else
+#endif // Core Audio or faac
+ fallback = hb_audio_encoders[0].encoder;
+ break;
+ }
+ }
+ 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;
+}
+
// Given an input bitrate, find closest match in the set of allowed bitrates
int hb_find_closest_audio_bitrate(int bitrate)
{
@@ -338,7 +466,7 @@ int hb_get_best_mixdown( uint32_t codec, int layout, int mixdown )
if (codec & HB_ACODEC_PASS_FLAG)
{
// Audio pass-thru. No mixdown.
- return 0;
+ return HB_AMIXDOWN_NONE;
}
switch (layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK)
{
@@ -1226,24 +1354,24 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg)
if( (audiocfg->in.bitrate != -1) && (audiocfg->in.codec != 0xDEADBEEF) )
{
/* This most likely means the client didn't call hb_audio_config_init
- * so bail.
- */
+ * so bail. */
return 0;
}
/* Really shouldn't ignore the passed out track, but there is currently no
- * way to handle duplicates or out-of-order track numbers.
- */
+ * way to handle duplicates or out-of-order track numbers. */
audio->config.out.track = hb_list_count(job->list_audio) + 1;
audio->config.out.codec = audiocfg->out.codec;
- if( (audiocfg->out.codec & HB_ACODEC_MASK) == (audio->config.in.codec & HB_ACODEC_MASK) &&
- (audiocfg->out.codec & HB_ACODEC_PASS_FLAG ) )
+ if((audiocfg->out.codec & HB_ACODEC_PASS_FLAG) &&
+ ((audiocfg->out.codec == HB_ACODEC_AUTO_PASS) ||
+ (audiocfg->out.codec & audio->config.in.codec & HB_ACODEC_PASS_MASK)))
{
/* Pass-through, copy from input. */
audio->config.out.samplerate = audio->config.in.samplerate;
audio->config.out.bitrate = audio->config.in.bitrate;
- audio->config.out.dynamic_range_compression = 0;
audio->config.out.mixdown = 0;
+ audio->config.out.dynamic_range_compression = 0;
+ audio->config.out.gain = 0;
}
else
{
diff --git a/libhb/common.h b/libhb/common.h
index d6024aac5..41272b93f 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -56,6 +56,7 @@ typedef struct hb_handle_s hb_handle_t;
typedef struct hb_list_s hb_list_t;
typedef struct hb_rate_s hb_rate_t;
typedef struct hb_mixdown_s hb_mixdown_t;
+typedef struct hb_encoder_s hb_encoder_t;
typedef struct hb_job_s hb_job_t;
typedef struct hb_title_s hb_title_t;
typedef struct hb_chapter_s hb_chapter_t;
@@ -126,6 +127,14 @@ struct hb_mixdown_s
int amixdown;
};
+struct hb_encoder_s
+{
+ char * human_readable_name; // note: used in presets
+ char * short_name; // note: used in CLI
+ int encoder; // HB_*CODEC_* define
+ int muxers; // supported muxers
+};
+
struct hb_subtitle_config_s
{
enum subdest { RENDERSUB, PASSTHRUSUB } dest;
@@ -149,8 +158,14 @@ extern hb_rate_t hb_audio_bitrates[];
extern int hb_audio_bitrates_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;
int hb_mixdown_get_mixdown_from_short_name( const char * short_name );
const char * hb_mixdown_get_short_name_from_mixdown( int amixdown );
+void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title );
+int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int muxer );
int hb_get_best_mixdown( uint32_t codec, int layout, int mixdown );
int hb_get_default_mixdown( uint32_t codec, int layout );
int hb_find_closest_audio_bitrate(int bitrate);
@@ -250,6 +265,8 @@ struct hb_job_s
/* List of audio settings. */
hb_list_t * list_audio;
+ int acodec_copy_mask; // Auto Passthru allowed codecs
+ int acodec_fallback; // Auto Passthru fallback encoder
/* Subtitles */
hb_list_t * list_subtitle;
@@ -328,6 +345,7 @@ struct hb_job_s
#define HB_ACODEC_FF_MASK 0x000f0000
#define HB_ACODEC_PASS_FLAG 0x40000000
#define HB_ACODEC_PASS_MASK (HB_ACODEC_MP3 | HB_ACODEC_FFAAC | HB_ACODEC_DCA_HD | HB_ACODEC_AC3 | HB_ACODEC_DCA)
+#define HB_ACODEC_AUTO_PASS (HB_ACODEC_PASS_MASK | HB_ACODEC_PASS_FLAG)
#define HB_ACODEC_MP3_PASS (HB_ACODEC_MP3 | HB_ACODEC_PASS_FLAG)
#define HB_ACODEC_AAC_PASS (HB_ACODEC_FFAAC | HB_ACODEC_PASS_FLAG)
#define HB_ACODEC_AC3_PASS (HB_ACODEC_AC3 | HB_ACODEC_PASS_FLAG)
@@ -346,6 +364,7 @@ struct hb_job_s
#define HB_AMIXDOWN_A52_FORMAT_MASK 0x00000FF0
#define HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK 0x0000000F
/* define the HB_AMIXDOWN_XXXX values */
+#define HB_AMIXDOWN_NONE 0x00000000
#define HB_AMIXDOWN_MONO 0x01000001
// DCA_FORMAT of DCA_MONO = 0 = 0x000
// A52_FORMAT of A52_MONO = 1 = 0x01
diff --git a/libhb/work.c b/libhb/work.c
index 86f453ef1..c9e5ee205 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -279,28 +279,18 @@ void hb_display_job_info( hb_job_t * job )
if( !job->indepth_scan )
{
/* Video encoder */
- switch( job->vcodec )
+ for( i = 0; i < hb_video_encoders_count; i++ )
{
- case HB_VCODEC_FFMPEG_MPEG4:
- hb_log( " + encoder: FFmpeg MPEG-4" );
- break;
-
- case HB_VCODEC_FFMPEG_MPEG2:
- hb_log( " + encoder: FFmpeg MPEG-2" );
- break;
-
- case HB_VCODEC_X264:
- hb_log( " + encoder: x264" );
- break;
-
- case HB_VCODEC_THEORA:
- hb_log( " + encoder: Theora" );
+ if( hb_video_encoders[i].encoder == job->vcodec )
+ {
+ hb_log( " + encoder: %s", hb_video_encoders[i].human_readable_name );
break;
+ }
}
- if ( job->advanced_opts && *job->advanced_opts &&
- ( ( job->vcodec & HB_VCODEC_FFMPEG_MASK ) ||
- job->vcodec == HB_VCODEC_X264 ) )
+ if( job->advanced_opts && *job->advanced_opts &&
+ ( ( job->vcodec & HB_VCODEC_FFMPEG_MASK ) ||
+ ( job->vcodec == HB_VCODEC_X264 ) ) )
{
hb_log( " + options: %s", job->advanced_opts);
}
@@ -360,46 +350,44 @@ void hb_display_job_info( hb_job_t * job )
hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.in.bitrate / 1000, audio->config.in.samplerate );
}
- if( !(audio->config.out.codec & HB_ACODEC_PASS_FLAG) )
+ if( audio->config.out.codec & HB_ACODEC_PASS_FLAG )
{
- for (j = 0; j < hb_audio_mixdowns_count; j++)
+ for( j = 0; j < hb_audio_encoders_count; j++ )
{
- if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) {
+ if( hb_audio_encoders[j].encoder == audio->config.out.codec )
+ {
+ hb_log( " + %s", hb_audio_encoders[j].human_readable_name );
+ break;
+ }
+ }
+ }
+ 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;
}
}
- if ( audio->config.out.gain != 0.0 )
+ if( audio->config.out.gain != 0.0 )
{
hb_log( " + gain: %.fdB", audio->config.out.gain );
}
- }
-
- if ( audio->config.out.dynamic_range_compression && (audio->config.in.codec == HB_ACODEC_AC3) && (audio->config.out.codec != HB_ACODEC_AC3_PASS) )
- {
- hb_log(" + dynamic range compression: %f", audio->config.out.dynamic_range_compression);
- }
-
- if( audio->config.out.codec & HB_ACODEC_PASS_FLAG )
- {
- hb_log( " + %s passthrough",
- (audio->config.out.codec == HB_ACODEC_MP3_PASS) ? "MP3" :
- (audio->config.out.codec == HB_ACODEC_AAC_PASS) ? "AAC" :
- (audio->config.out.codec == HB_ACODEC_AC3_PASS) ? "AC3" :
- (audio->config.out.codec == HB_ACODEC_DCA_PASS) ? "DTS" :
- "DTS-HD");
- }
- else
- {
- hb_log( " + encoder: %s",
- ( audio->config.out.codec == HB_ACODEC_FAAC ) ? "faac" :
- ( ( audio->config.out.codec == HB_ACODEC_LAME ) ? "lame" :
- ( ( audio->config.out.codec == HB_ACODEC_CA_AAC ) ? "ca_aac" :
- ( ( audio->config.out.codec == HB_ACODEC_CA_HAAC ) ? "ca_haac" :
- ( ( audio->config.out.codec == HB_ACODEC_FFAAC ) ? "ffaac" :
- ( ( audio->config.out.codec == HB_ACODEC_AC3 ) ? "ffac3" :
- "vorbis" ) ) ) ) ) );
- hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate );
+ if( ( audio->config.out.dynamic_range_compression != 0.0 ) && ( audio->config.in.codec == HB_ACODEC_AC3 ) )
+ {
+ hb_log( " + dynamic range compression: %f", audio->config.out.dynamic_range_compression );
+ }
+ for( j = 0; j < hb_audio_encoders_count; j++ )
+ {
+ if( hb_audio_encoders[j].encoder == audio->config.out.codec )
+ {
+ hb_log( " + encoder: %s", hb_audio_encoders[j].human_readable_name );
+ hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate );
+ break;
+ }
+ }
}
}
}
@@ -530,16 +518,23 @@ static void do_job( hb_job_t * job )
*/
if( !job->indepth_scan )
{
- // if we are doing passthru, and the input codec is not the same as the output
- // codec, then remove this audio from the job. If we're not doing passthru and
- // the input codec is the 'internal' ffmpeg codec, make sure that only one
- // audio references that audio stream since the codec context is specific to
- // the audio id & multiple copies of the same stream will garble the audio
- // or cause aborts.
+ // apply Auto Passthru settings
+ hb_autopassthru_apply_settings( job, title );
+ // sanitize audio settings
for( i = 0; i < hb_list_count( title->list_audio ); )
{
audio = hb_list_item( title->list_audio, i );
- if( ( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) &&
+ if( audio->config.out.codec == HB_ACODEC_AUTO_PASS )
+ {
+ // Auto Passthru should have been handled above
+ // remove track to avoid a crash
+ hb_log( "Auto Passthru error, dropping track %d",
+ audio->config.out.track );
+ hb_list_rem( title->list_audio, audio );
+ free( audio );
+ continue;
+ }
+ if( ( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) &&
!( audio->config.in.codec & audio->config.out.codec & HB_ACODEC_PASS_MASK ) )
{
hb_log( "Passthru requested and input codec is not the same as output codec for track %d, dropping track",