diff options
-rw-r--r-- | libhb/common.c | 148 | ||||
-rw-r--r-- | libhb/common.h | 214 | ||||
-rw-r--r-- | libhb/deca52.c | 11 | ||||
-rw-r--r-- | libhb/decdca.c | 5 | ||||
-rw-r--r-- | libhb/dvd.c | 23 | ||||
-rw-r--r-- | libhb/encfaac.c | 14 | ||||
-rw-r--r-- | libhb/enclame.c | 12 | ||||
-rw-r--r-- | libhb/encvorbis.c | 14 | ||||
-rw-r--r-- | libhb/hb.c | 49 | ||||
-rw-r--r-- | libhb/muxavi.c | 26 | ||||
-rw-r--r-- | libhb/muxcommon.c | 6 | ||||
-rw-r--r-- | libhb/muxmkv.c | 38 | ||||
-rw-r--r-- | libhb/muxmp4.c | 48 | ||||
-rw-r--r-- | libhb/muxogm.c | 26 | ||||
-rw-r--r-- | libhb/reader.c | 2 | ||||
-rw-r--r-- | libhb/scan.c | 123 | ||||
-rwxr-xr-x | libhb/stream.c | 84 | ||||
-rw-r--r-- | libhb/sync.c | 73 | ||||
-rw-r--r-- | libhb/work.c | 220 |
19 files changed, 615 insertions, 521 deletions
diff --git a/libhb/common.c b/libhb/common.c index d802f41a5..247d15ec6 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -7,6 +7,7 @@ #include <stdarg.h> #include <time.h> #include <sys/time.h> +#include <assert.h> #include "common.h" @@ -43,9 +44,7 @@ hb_mixdown_t hb_audio_mixdowns[] = { "Stereo", "HB_AMIXDOWN_STEREO", "stereo", HB_AMIXDOWN_STEREO }, { "Dolby Surround", "HB_AMIXDOWN_DOLBY", "dpl1", HB_AMIXDOWN_DOLBY }, { "Dolby Pro Logic II", "HB_AMIXDOWN_DOLBYPLII", "dpl2", HB_AMIXDOWN_DOLBYPLII }, - { "6-channel discrete", "HB_AMIXDOWN_6CH", "6ch", HB_AMIXDOWN_6CH }, - { "AC-3 Pass-through", "HB_AMIXDOWN_AC3", "ac-3", HB_AMIXDOWN_AC3 }, - { "Dolby Pro Logic II + AC-3", "HB_AMIXDOWN_DOLBYPLII_AC3", "dpl2+ac3", HB_AMIXDOWN_DOLBYPLII_AC3 }, + { "6-channel discrete", "HB_AMIXDOWN_6CH", "6ch", HB_AMIXDOWN_6CH } }; int hb_audio_mixdowns_count = sizeof( hb_audio_mixdowns ) / sizeof( hb_mixdown_t ); @@ -115,7 +114,7 @@ void hb_fix_aspect( hb_job_t * job, int keep ) if ( title->height == 0 || title->width == 0 || title->aspect == 0 ) { hb_log( "hb_fix_aspect: incomplete info for title %d: " - "height = %d, width = %d, aspect = %d", + "height = %d, width = %d, aspect = %d", title->height, title->width, title->aspect ); return; } @@ -202,23 +201,6 @@ int hb_calc_bitrate( hb_job_t * job, int size ) return 0; } - /* How many audio samples we put in each frame */ - switch( job->acodec ) - { - case HB_ACODEC_FAAC: - case HB_ACODEC_VORBIS: - samples_per_frame = 1024; - break; - case HB_ACODEC_LAME: - samples_per_frame = 1152; - break; - case HB_ACODEC_AC3: - samples_per_frame = 1536; - break; - default: - return 0; - } - /* Get the duration in seconds */ length = 0; for( i = job->chapter_start; i <= job->chapter_end; i++ ) @@ -232,19 +214,37 @@ int hb_calc_bitrate( hb_job_t * job, int size ) /* Video overhead */ avail -= length * job->vrate * overhead / job->vrate_base; - for( i = 0; job->audios[i] >= 0; i++ ) + for( i = 0; i < hb_list_count(job->list_audio); i++ ) { /* Audio data */ int abitrate; - if( job->acodec & HB_ACODEC_AC3 || - job->audio_mixdowns[i] == HB_AMIXDOWN_AC3) + audio = hb_list_item( job->list_audio, i); + + /* How many audio samples we put in each frame */ + switch( audio->config.out.codec ) + { + case HB_ACODEC_FAAC: + case HB_ACODEC_VORBIS: + samples_per_frame = 1024; + break; + case HB_ACODEC_LAME: + samples_per_frame = 1152; + break; + case HB_ACODEC_AC3: + samples_per_frame = 1536; + break; + default: + return 0; + } + + if( audio->config.out.codec == HB_ACODEC_AC3 || + audio->config.out.codec == HB_ACODEC_DCA) { /* - * For AC-3 we take the bitrate from the input audio + * For pass through we take the bitrate from the input audio * bitrate as we are simply passing it through. */ - audio = hb_list_item( title->list_audio, job->audios[i] ); - abitrate = audio->bitrate / 8; + abitrate = audio->config.in.bitrate / 8; } else { @@ -252,12 +252,12 @@ int hb_calc_bitrate( hb_job_t * job, int size ) * Where we are transcoding the audio we use the destination * bitrate. */ - abitrate = job->abitrate * 1000 / 8; + abitrate = audio->config.out.bitrate * 1000 / 8; } avail -= length * abitrate; /* Audio overhead */ - avail -= length * job->arate * overhead / samples_per_frame; + avail -= length * audio->config.out.samplerate * overhead / samples_per_frame; } if( avail < 0 ) @@ -654,3 +654,93 @@ void hb_filter_close( hb_filter_object_t ** _f ) *_f = NULL; } +/********************************************************************** + * hb_audio_copy + ********************************************************************** + * + *********************************************************************/ +hb_audio_t *hb_audio_copy(const hb_audio_t *src) +{ + hb_audio_t *audio = calloc(1, sizeof(*audio)); + memcpy(audio, src, sizeof(*audio)); + return audio; +} + +/********************************************************************** + * hb_audio_new + ********************************************************************** + * + *********************************************************************/ +void hb_audio_config_init(hb_audio_config_t * audiocfg) +{ + assert(audiocfg != NULL); + + /* Set read only paramaters to invalid values */ + audiocfg->in.codec = 0xDEADBEEF; + audiocfg->in.bitrate = -1; + audiocfg->in.samplerate = -1; + audiocfg->in.channel_layout = 0; + audiocfg->flags.ac3 = 0; + audiocfg->lang.description[0] = 0; + audiocfg->lang.simple[0] = 0; + audiocfg->lang.iso639_2[0] = 0; + + /* Initalize some sensable defaults */ + audiocfg->in.track = audiocfg->out.track = 0; + audiocfg->out.codec = HB_ACODEC_FAAC; + audiocfg->out.bitrate = 128; + audiocfg->out.samplerate = 44100; + audiocfg->out.mixdown = HB_AMIXDOWN_DOLBYPLII; + audiocfg->out.dynamic_range_compression = 0; +} + +/********************************************************************** + * hb_audio_add + ********************************************************************** + * + *********************************************************************/ +int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg) +{ + assert(job != NULL); + assert(audiocfg != NULL); + + hb_title_t *title = job->title; + hb_audio_t *audio; + + audio = hb_audio_copy( hb_list_item( title->list_audio, audiocfg->in.track ) ); + if( audio == NULL ) + { + /* We fail! */ + return 0; + } + + if( (audiocfg->in.bitrate != -1) && (audiocfg->in.codec != 0xDEADBEEF) ) + { + /* This most likely means the client didn't call hb_audio_config_init + * 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. + */ + audio->config.out.track = hb_list_count(job->list_audio) + 1; + audio->config.out.codec = audiocfg->out.codec; + audio->config.out.samplerate = audiocfg->out.samplerate; + audio->config.out.bitrate = audiocfg->out.bitrate; + audio->config.out.mixdown = audiocfg->out.mixdown; + audio->config.out.dynamic_range_compression = audiocfg->out.dynamic_range_compression; + + hb_list_add(job->list_audio, audio); + return 1; +} + +hb_audio_config_t * hb_list_audio_config_item(hb_list_t * list, int i) +{ + assert(list != NULL); + + hb_audio_t *audio = hb_list_item(list, i); + + return &(audio->config); +} diff --git a/libhb/common.h b/libhb/common.h index 4758d9c8d..1eef164e6 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -39,6 +39,7 @@ typedef struct hb_job_s hb_job_t; typedef struct hb_title_s hb_title_t; typedef struct hb_chapter_s hb_chapter_t; typedef struct hb_audio_s hb_audio_t; +typedef struct hb_audio_config_s hb_audio_config_t; typedef struct hb_subtitle_s hb_subtitle_t; typedef struct hb_state_s hb_state_t; typedef union hb_esconfig_u hb_esconfig_t; @@ -53,6 +54,9 @@ typedef struct hb_lock_s hb_lock_t; #include "ports.h" #ifdef __LIBHB__ #include "internal.h" +#define PRIVATE +#else +#define PRIVATE const #endif hb_list_t * hb_list_init(); @@ -70,6 +74,11 @@ void hb_fix_aspect( hb_job_t * job, int keep ); int hb_calc_bitrate( hb_job_t *, int size ); +hb_audio_t *hb_audio_copy(const hb_audio_t *src); +void hb_audio_config_init(hb_audio_config_t * audiocfg); +int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg); +hb_audio_config_t * hb_list_audio_config_item(hb_list_t * list, int i); + struct hb_rate_s { char * string; @@ -175,76 +184,8 @@ struct hb_job_s int areBframes; int vfr; - /* Audio tracks: - audios: Indexes in hb_title_t's audios list, starting from 0. - -1 indicates the end of the list - audio_mixdowns: The mixdown to be used for each audio track in audios[] */ - -/* define some masks, used to extract the various information from the HB_AMIXDOWN_XXXX values */ -#define HB_AMIXDOWN_DCA_FORMAT_MASK 0x00FFF000 -#define HB_AMIXDOWN_A52_FORMAT_MASK 0x00000FF0 -#define HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK 0x0000000F - -/* define the HB_AMIXDOWN_XXXX values */ - -#define HB_AMIXDOWN_MONO 0x01000001 -// DCA_FORMAT of DCA_MONO = 0 = 0x000 -// A52_FORMAT of A52_MONO = 1 = 0x01 -// discrete channel count of 1 - -#define HB_AMIXDOWN_STEREO 0x02002022 -// DCA_FORMAT of DCA_STEREO = 2 = 0x002 -// A52_FORMAT of A52_STEREO = 2 = 0x02 -// discrete channel count of 2 - -#define HB_AMIXDOWN_DOLBY 0x042070A2 -// DCA_FORMAT of DCA_3F1R | DCA_OUT_DPLI = 519 = 0x207 -// A52_FORMAT of A52_DOLBY = 10 = 0x0A -// discrete channel count of 2 - -#define HB_AMIXDOWN_DOLBYPLII 0x084094A2 -// DCA_FORMAT of DCA_3F2R | DCA_OUT_DPLII = 1033 = 0x409 -// A52_FORMAT of A52_DOLBY | A52_USE_DPLII = 74 = 0x4A -// discrete channel count of 2 - -#define HB_AMIXDOWN_6CH 0x10089176 -// DCA_FORMAT of DCA_3F2R | DCA_LFE = 137 = 0x089 -// A52_FORMAT of A52_3F2R | A52_LFE = 23 = 0x17 -// discrete channel count of 6 - -#define HB_AMIXDOWN_AC3 0x20000000 - -#define HB_AMIXDOWN_DOLBYPLII_AC3 0x404094A2 -// DCA_FORMAT of DCA_3F2R | DCA_OUT_DPLII = 1033 = 0x409 -// A52_FORMAT of A52_DOLBY | A52_USE_DPLII = 74 = 0x4A -// discrete channel count of 2 - -/* define some macros to extract the various information from the HB_AMIXDOWN_XXXX values */ -#define HB_AMIXDOWN_GET_DCA_FORMAT( a ) ( ( a & HB_AMIXDOWN_DCA_FORMAT_MASK ) >> 12 ) -#define HB_AMIXDOWN_GET_A52_FORMAT( a ) ( ( a & HB_AMIXDOWN_A52_FORMAT_MASK ) >> 4 ) -#define HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT( a ) ( ( a & HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK ) ) - - int audios[8]; - int audio_mixdowns[8]; - - /* Audio settings: - acodec: output codec - abitrate: output bitrate (kbps) - arate: output samplerate (Hz) - HB_ACODEC_AC3 means pass-through, then abitrate and arate are - ignored */ -#define HB_ACODEC_MASK 0x00FF00 -#define HB_ACODEC_FAAC 0x000100 -#define HB_ACODEC_LAME 0x000200 -#define HB_ACODEC_VORBIS 0x000400 -#define HB_ACODEC_AC3 0x000800 -#define HB_ACODEC_MPGA 0x001000 -#define HB_ACODEC_LPCM 0x002000 -#define HB_ACODEC_DCA 0x004000 - int acodec; - int abitrate; - int arate; - float dynamic_range_compression; + /* List of audio settings. */ + hb_list_t * list_audio; /* Subtitle settings: subtitle: index in hb_title_t's subtitles list, starting @@ -300,22 +241,49 @@ struct hb_job_s #endif }; -struct hb_audio_s -{ - int id; - char lang[1024]; - char lang_simple[1024]; - char iso639_2[4]; - int codec; - int rate; - int bitrate; - - /* ac3flags is only set when the source audio format is HB_ACODEC_AC3 */ - int ac3flags; +/* Audio starts here */ +/* Audio Codecs */ +#define HB_ACODEC_MASK 0x00FF00 +#define HB_ACODEC_FAAC 0x000100 +#define HB_ACODEC_LAME 0x000200 +#define HB_ACODEC_VORBIS 0x000400 +#define HB_ACODEC_AC3 0x000800 +#define HB_ACODEC_MPGA 0x001000 +#define HB_ACODEC_LPCM 0x002000 +#define HB_ACODEC_DCA 0x004000 - /* dcaflags is only set when the source audio format is HB_ACODEC_DCA */ - int dcaflags; +/* Audio Mixdown */ +/* define some masks, used to extract the various information from the HB_AMIXDOWN_XXXX values */ +#define HB_AMIXDOWN_DCA_FORMAT_MASK 0x00FFF000 +#define HB_AMIXDOWN_A52_FORMAT_MASK 0x00000FF0 +#define HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK 0x0000000F +/* define the HB_AMIXDOWN_XXXX values */ +#define HB_AMIXDOWN_MONO 0x01000001 +// DCA_FORMAT of DCA_MONO = 0 = 0x000 +// A52_FORMAT of A52_MONO = 1 = 0x01 +// discrete channel count of 1 +#define HB_AMIXDOWN_STEREO 0x02002022 +// DCA_FORMAT of DCA_STEREO = 2 = 0x002 +// A52_FORMAT of A52_STEREO = 2 = 0x02 +// discrete channel count of 2 +#define HB_AMIXDOWN_DOLBY 0x042070A2 +// DCA_FORMAT of DCA_3F1R | DCA_OUT_DPLI = 519 = 0x207 +// A52_FORMAT of A52_DOLBY = 10 = 0x0A +// discrete channel count of 2 +#define HB_AMIXDOWN_DOLBYPLII 0x084094A2 +// DCA_FORMAT of DCA_3F2R | DCA_OUT_DPLII = 1033 = 0x409 +// A52_FORMAT of A52_DOLBY | A52_USE_DPLII = 74 = 0x4A +// discrete channel count of 2 +#define HB_AMIXDOWN_6CH 0x10089176 +// DCA_FORMAT of DCA_3F2R | DCA_LFE = 137 = 0x089 +// A52_FORMAT of A52_3F2R | A52_LFE = 23 = 0x17 +// discrete channel count of 6 +/* define some macros to extract the various information from the HB_AMIXDOWN_XXXX values */ +#define HB_AMIXDOWN_GET_DCA_FORMAT( a ) ( ( a & HB_AMIXDOWN_DCA_FORMAT_MASK ) >> 12 ) +#define HB_AMIXDOWN_GET_A52_FORMAT( a ) ( ( a & HB_AMIXDOWN_A52_FORMAT_MASK ) >> 4 ) +#define HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT( a ) ( ( a & HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK ) ) +/* Input Channel Layout */ /* define some masks, used to extract the various information from the HB_AMIXDOWN_XXXX values */ #define HB_INPUT_CH_LAYOUT_DISCRETE_FRONT_MASK 0x00F0000 #define HB_INPUT_CH_LAYOUT_DISCRETE_REAR_MASK 0x000F000 @@ -323,7 +291,6 @@ struct hb_audio_s #define HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK 0xFFFF0FF #define HB_INPUT_CH_LAYOUT_ENCODED_FRONT_MASK 0x00000F0 #define HB_INPUT_CH_LAYOUT_ENCODED_REAR_MASK 0x000000F - /* define the input channel layouts used to describe the channel layout of this audio */ #define HB_INPUT_CH_LAYOUT_MONO 0x0110010 #define HB_INPUT_CH_LAYOUT_STEREO 0x0220020 @@ -335,7 +302,6 @@ struct hb_audio_s #define HB_INPUT_CH_LAYOUT_3F2R 0x0832032 #define HB_INPUT_CH_LAYOUT_4F2R 0x0942042 #define HB_INPUT_CH_LAYOUT_HAS_LFE 0x0000100 - /* define some macros to extract the various information from the HB_AMIXDOWN_XXXX values */ #define HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT( a ) ( ( a & HB_INPUT_CH_LAYOUT_DISCRETE_FRONT_MASK ) >> 16 ) #define HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT( a ) ( ( a & HB_INPUT_CH_LAYOUT_DISCRETE_REAR_MASK ) >> 12 ) @@ -344,24 +310,68 @@ struct hb_audio_s #define HB_INPUT_CH_LAYOUT_GET_ENCODED_FRONT_COUNT( a ) ( ( a & HB_INPUT_CH_LAYOUT_ENCODED_FRONT_MASK ) >> 4 ) #define HB_INPUT_CH_LAYOUT_GET_ENCODED_REAR_COUNT( a ) ( ( a & HB_INPUT_CH_LAYOUT_ENCODED_REAR_MASK ) ) - /* input_channel_layout is the channel layout of this audio */ - /* this is used to provide a common way of describing the source audio */ - int input_channel_layout; +struct hb_audio_config_s +{ + /* Output */ + struct + { + int track; /* Output track number */ + uint32_t codec; /* Output audio codec. + * HB_ACODEC_AC3 means pass-through, then bitrate and samplerate + * are ignored. + */ + int samplerate; /* Output sample rate (Hz) */ + int bitrate; /* Output bitrate (kbps) */ + int mixdown; /* The mixdown format to be used for this audio track (see HB_AMIXDOWN_*) */ + double dynamic_range_compression; /* Amount of DRC that gets applied to this track */ + } out; + + /* Input */ + struct + { + int track; /* Input track number */ + PRIVATE uint32_t codec; /* Input audio codec */ + PRIVATE int samplerate; /* Input sample rate (Hz) */ + PRIVATE int bitrate; /* Input bitrate (kbps) */ + PRIVATE int channel_layout; + /* channel_layout is the channel layout of this audio this is used to + * provide a common way of describing the source audio + */ + } in; + + /* Misc. */ + union + { + PRIVATE int ac3; /* flags.ac3 is only set when the source audio format is HB_ACODEC_AC3 */ + PRIVATE int dca; /* flags.dca is only set when the source audio format is HB_ACODEC_DCA */ + } flags; + + struct + { + PRIVATE char description[1024]; + PRIVATE char simple[1024]; + PRIVATE char iso639_2[4]; + } lang; +}; #ifdef __LIBHB__ - /* Internal data */ - hb_fifo_t * fifo_in; /* AC3/MPEG/LPCM ES */ - hb_fifo_t * fifo_raw; /* Raw audio */ - hb_fifo_t * fifo_sync; /* Resampled, synced raw audio */ - hb_fifo_t * fifo_out; /* MP3/AAC/Vorbis ES */ +struct hb_audio_s +{ + int id; - hb_esconfig_t config; - hb_mux_data_t * mux_data; + hb_audio_config_t config; - /* amixdown is the mixdown format to be used for this audio track */ - int amixdown; -#endif + struct { + hb_fifo_t * fifo_in; /* AC3/MPEG/LPCM ES */ + hb_fifo_t * fifo_raw; /* Raw audio */ + hb_fifo_t * fifo_sync; /* Resampled, synced raw audio */ + hb_fifo_t * fifo_out; /* MP3/AAC/Vorbis ES */ + + hb_esconfig_t config; + hb_mux_data_t * mux_data; + } priv; }; +#endif struct hb_chapter_s { @@ -506,10 +516,8 @@ struct hb_work_object_s hb_fifo_t * fifo_out; hb_esconfig_t * config; - /* amixdown is the mixdown format to be used if the work object is an audio track */ - int amixdown; - /* source_acodec is the source audio codec if the work object is an audio track */ - int source_acodec; + /* Pointer hb_audio_t so we have access to the info in the audio worker threads. */ + hb_audio_t *audio; hb_work_private_t * private_data; diff --git a/libhb/deca52.c b/libhb/deca52.c index e38ce9c82..421c97346 100644 --- a/libhb/deca52.c +++ b/libhb/deca52.c @@ -88,6 +88,7 @@ static sample_t dynrng_call (sample_t c, void *data) int deca52Init( hb_work_object_t * w, hb_job_t * job ) { hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) ); + hb_audio_t * audio = w->audio; w->private_data = pv; pv->job = job; @@ -98,14 +99,14 @@ int deca52Init( hb_work_object_t * w, hb_job_t * job ) /* Decide what format we want out of a52dec work.c has already done some of this deduction for us in do_job() */ - pv->flags_out = HB_AMIXDOWN_GET_A52_FORMAT(w->amixdown); + pv->flags_out = HB_AMIXDOWN_GET_A52_FORMAT(audio->config.out.mixdown); /* pass the number of channels used into the private work data */ /* will only be actually used if we're not doing AC3 passthru */ - pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown); + pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); pv->level = 32768.0; - pv->dynamic_range_compression = job->dynamic_range_compression; + pv->dynamic_range_compression = audio->config.out.dynamic_range_compression; pv->next_expected_pts = 0; pv->sequence = 0; @@ -168,6 +169,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; hb_buffer_t * buf; + hb_audio_t * audio = w->audio; int i, j, k; uint64_t pts, pos; @@ -219,8 +221,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) } /* AC3 passthrough: don't decode the AC3 frame */ - if( pv->job->acodec & HB_ACODEC_AC3 || - w->amixdown == HB_AMIXDOWN_AC3 ) + if( audio->config.out.codec == HB_ACODEC_AC3 ) { buf = hb_buffer_init( pv->size ); memcpy( buf->data, pv->frame, pv->size ); diff --git a/libhb/decdca.c b/libhb/decdca.c index d84a6ca45..ec6dedd87 100644 --- a/libhb/decdca.c +++ b/libhb/decdca.c @@ -61,6 +61,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w ); int decdcaInit( hb_work_object_t * w, hb_job_t * job ) { hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) ); + hb_audio_t * audio = w->audio; w->private_data = pv; pv->job = job; @@ -71,11 +72,11 @@ int decdcaInit( hb_work_object_t * w, hb_job_t * job ) /* Decide what format we want out of libdca work.c has already done some of this deduction for us in do_job() */ - pv->flags_out = HB_AMIXDOWN_GET_DCA_FORMAT(w->amixdown); + pv->flags_out = HB_AMIXDOWN_GET_DCA_FORMAT(audio->config.out.mixdown); /* pass the number of channels used into the private work data */ /* will only be actually used if we're not doing AC3 passthru */ - pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown); + pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); pv->level = 32768.0; diff --git a/libhb/dvd.c b/libhb/dvd.c index 1c4eb60d3..3c78e2cbd 100644 --- a/libhb/dvd.c +++ b/libhb/dvd.c @@ -257,28 +257,28 @@ hb_title_t * hb_dvd_title_scan( hb_dvd_t * d, int t ) { case 0x00: audio->id = ( ( 0x80 + position ) << 8 ) | 0xbd; - audio->codec = HB_ACODEC_AC3; + audio->config.in.codec = HB_ACODEC_AC3; break; case 0x02: case 0x03: audio->id = 0xc0 + position; - audio->codec = HB_ACODEC_MPGA; + audio->config.in.codec = HB_ACODEC_MPGA; break; case 0x04: audio->id = ( ( 0xa0 + position ) << 8 ) | 0xbd; - audio->codec = HB_ACODEC_LPCM; + audio->config.in.codec = HB_ACODEC_LPCM; break; case 0x06: audio->id = ( ( 0x88 + position ) << 8 ) | 0xbd; - audio->codec = HB_ACODEC_DCA; + audio->config.in.codec = HB_ACODEC_DCA; break; default: audio->id = 0; - audio->codec = 0; + audio->config.in.codec = 0; hb_log( "scan: unknown audio codec (%x)", audio_format ); break; @@ -308,19 +308,20 @@ hb_title_t * hb_dvd_title_scan( hb_dvd_t * d, int t ) lang = lang_for_code( vts->vtsi_mat->vts_audio_attr[i].lang_code ); - snprintf( audio->lang, sizeof( audio->lang ), "%s (%s)", + snprintf( audio->config.lang.description, sizeof( audio->config.lang.description ), "%s (%s)", strlen(lang->native_name) ? lang->native_name : lang->eng_name, - audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec == - HB_ACODEC_DCA ? "DTS" : ( audio->codec == + audio->config.in.codec == HB_ACODEC_AC3 ? "AC3" : ( audio->config.in.codec == + HB_ACODEC_DCA ? "DTS" : ( audio->config.in.codec == HB_ACODEC_MPGA ? "MPEG" : "LPCM" ) ) ); - snprintf( audio->lang_simple, sizeof( audio->lang_simple ), "%s", + snprintf( audio->config.lang.simple, sizeof( audio->config.lang.simple ), "%s", strlen(lang->native_name) ? lang->native_name : lang->eng_name ); - snprintf( audio->iso639_2, sizeof( audio->iso639_2 ), "%s", + snprintf( audio->config.lang.iso639_2, sizeof( audio->config.lang.iso639_2 ), "%s", lang->iso639_2); hb_log( "scan: id=%x, lang=%s, 3cc=%s", audio->id, - audio->lang, audio->iso639_2 ); + audio->config.lang.description, audio->config.lang.iso639_2 ); + audio->config.in.track = i; hb_list_add( title->list_audio, audio ); } diff --git a/libhb/encfaac.c b/libhb/encfaac.c index b54b79934..7303a3faa 100644 --- a/libhb/encfaac.c +++ b/libhb/encfaac.c @@ -45,6 +45,7 @@ hb_work_object_t hb_encfaac = int encfaacInit( hb_work_object_t * w, hb_job_t * job ) { hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) ); + hb_audio_t * audio = w->audio; faacEncConfigurationPtr cfg; uint8_t * bytes; unsigned long length; @@ -54,9 +55,9 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job ) pv->job = job; /* pass the number of channels used into the private work data */ - pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown); + pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); - pv->faac = faacEncOpen( job->arate, pv->out_discrete_channels, &pv->input_samples, + pv->faac = faacEncOpen( audio->config.out.samplerate, pv->out_discrete_channels, &pv->input_samples, &pv->output_bytes ); pv->buf = malloc( pv->input_samples * sizeof( float ) ); @@ -74,12 +75,12 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job ) } cfg->useTns = 0; - cfg->bitRate = job->abitrate * 1000 / pv->out_discrete_channels; /* Per channel */ + cfg->bitRate = audio->config.out.bitrate * 1000 / pv->out_discrete_channels; /* Per channel */ cfg->bandWidth = 0; cfg->outputFormat = 0; cfg->inputFormat = FAAC_INPUT_FLOAT; - if (w->amixdown == HB_AMIXDOWN_6CH && w->source_acodec == HB_ACODEC_AC3) + if (audio->config.out.mixdown == HB_AMIXDOWN_6CH && audio->config.in.codec == HB_ACODEC_AC3) { /* we are preserving 5.1 AC-3 audio into 6-channel AAC, and need to re-map the output of deca52 into our own mapping - the mapping @@ -140,6 +141,7 @@ void encfaacClose( hb_work_object_t * w ) static hb_buffer_t * Encode( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; + hb_audio_t * audio = w->audio; hb_buffer_t * buf; uint64_t pts, pos; @@ -153,8 +155,8 @@ static hb_buffer_t * Encode( hb_work_object_t * w ) &pts, &pos ); buf = hb_buffer_init( pv->output_bytes ); - buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / pv->job->arate; - buf->stop = buf->start + 90000 * pv->input_samples / pv->job->arate / pv->out_discrete_channels; + buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate; + buf->stop = buf->start + 90000 * pv->input_samples / audio->config.out.samplerate / pv->out_discrete_channels; buf->size = faacEncEncode( pv->faac, (int32_t *) pv->buf, pv->input_samples, buf->data, pv->output_bytes ); buf->frametype = HB_FRAME_AUDIO; diff --git a/libhb/enclame.c b/libhb/enclame.c index 35b35ff50..6b31a11d1 100644 --- a/libhb/enclame.c +++ b/libhb/enclame.c @@ -39,6 +39,7 @@ struct hb_work_private_s int enclameInit( hb_work_object_t * w, hb_job_t * job ) { hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) ); + hb_audio_t * audio = w->audio; w->private_data = pv; pv->job = job; @@ -46,9 +47,9 @@ int enclameInit( hb_work_object_t * w, hb_job_t * job ) hb_log( "enclame: opening libmp3lame" ); pv->lame = lame_init(); - lame_set_brate( pv->lame, job->abitrate ); - lame_set_in_samplerate( pv->lame, job->arate ); - lame_set_out_samplerate( pv->lame, job->arate ); + lame_set_brate( pv->lame, audio->config.out.bitrate ); + lame_set_in_samplerate( pv->lame, audio->config.out.samplerate ); + lame_set_out_samplerate( pv->lame, audio->config.out.samplerate ); lame_init_params( pv->lame ); pv->input_samples = 1152 * 2; @@ -85,6 +86,7 @@ void enclameClose( hb_work_object_t * w ) static hb_buffer_t * Encode( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; + hb_audio_t * audio = w->audio; hb_buffer_t * buf; int16_t samples_s16[1152 * 2]; uint64_t pts, pos; @@ -104,8 +106,8 @@ static hb_buffer_t * Encode( hb_work_object_t * w ) } buf = hb_buffer_init( pv->output_bytes ); - buf->start = pts + 90000 * pos / 2 / sizeof( float ) / pv->job->arate; - buf->stop = buf->start + 90000 * 1152 / pv->job->arate; + buf->start = pts + 90000 * pos / 2 / sizeof( float ) / audio->config.out.samplerate; + buf->stop = buf->start + 90000 * 1152 / audio->config.out.samplerate; buf->size = lame_encode_buffer_interleaved( pv->lame, samples_s16, 1152, buf->data, LAME_MAXMP3BUFFER ); buf->frametype = HB_FRAME_AUDIO; diff --git a/libhb/encvorbis.c b/libhb/encvorbis.c index b94366e09..136096a15 100644 --- a/libhb/encvorbis.c +++ b/libhb/encvorbis.c @@ -44,13 +44,14 @@ struct hb_work_private_s int encvorbisInit( hb_work_object_t * w, hb_job_t * job ) { + hb_audio_t * audio = w->audio; int i; ogg_packet header[3]; struct ovectl_ratemanage2_arg ctl_rate_arg; hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) ); w->private_data = pv; - pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown); + pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); pv->job = job; @@ -58,17 +59,18 @@ int encvorbisInit( hb_work_object_t * w, hb_job_t * job ) /* 28kbps/channel seems to be the minimum for 6ch vorbis. */ int min_bitrate = 28 * pv->out_discrete_channels; - if (pv->out_discrete_channels > 2 && job->abitrate < min_bitrate) + if (pv->out_discrete_channels > 2 && audio->config.out.bitrate < min_bitrate) { - hb_log( "encvorbis: Selected bitrate (%d kbps) too low for %d channel audio.", job->abitrate, pv->out_discrete_channels); + hb_log( "encvorbis: Selected bitrate (%d kbps) too low for %d channel audio.", audio->config.out.bitrate, pv->out_discrete_channels); hb_log( "encvorbis: Resetting bitrate to %d kbps", min_bitrate); - job->abitrate = min_bitrate; + /* Naughty! We shouldn't modify the audio from here. */ + audio->config.out.bitrate = min_bitrate; } /* init */ vorbis_info_init( &pv->vi ); if( vorbis_encode_setup_managed( &pv->vi, pv->out_discrete_channels, - job->arate, -1, 1000 * job->abitrate, -1 ) ) + audio->config.out.samplerate, -1, 1000 * audio->config.out.bitrate, -1 ) ) { hb_error( "encvorbis: vorbis_encode_setup_managed failed.\n" ); *job->die = 1; @@ -80,7 +82,7 @@ int encvorbisInit( hb_work_object_t * w, hb_job_t * job ) hb_log( "encvorbis: vorbis_encode_ctl( ratemanage2_get ) failed" ); } - ctl_rate_arg.bitrate_average_kbps = job->abitrate; + ctl_rate_arg.bitrate_average_kbps = audio->config.out.bitrate; ctl_rate_arg.management_active = 1; if( vorbis_encode_ctl( &pv->vi, OV_ECTL_RATEMANAGE2_SET, &ctl_rate_arg ) || diff --git a/libhb/hb.c b/libhb/hb.c index fd3cd45ea..5f176f1ae 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -453,7 +453,7 @@ int hb_detect_comb( hb_buffer_t * buf, int width, int height, int color_equal, i cc_1 = 0; cc_2 = 0; int offset = 0; - + for( k = 0; k < 3; k++ ) { /* One pas for Y, one pass for Cb, one pass for Cr */ @@ -476,14 +476,14 @@ int hb_detect_comb( hb_buffer_t * buf, int width, int height, int color_equal, i so it's width*height + (width / 2) * (height / 2) */ offset *= 5/4; } - + /* Look at one horizontal line at a time */ block = width; - + for( j = 0; j < block; ++j ) { off = 0; - + for( n = 0; n < ( height - 4 ); n = n + 2 ) { /* Look at groups of 4 sequential horizontal lines */ @@ -491,29 +491,29 @@ int hb_detect_comb( hb_buffer_t * buf, int width, int height, int color_equal, i s2 = ( ( buf->data + offset )[ off + j + block ] & 0xff ); s3 = ( ( buf->data + offset )[ off + j + 2 * block ] & 0xff ); s4 = ( ( buf->data + offset )[ off + j + 3 * block ] & 0xff ); - + /* Note if the 1st and 2nd lines are more different in color than the 1st and 3rd lines are similar in color.*/ - if ( ( abs( s1 - s3 ) < color_equal ) && + if ( ( abs( s1 - s3 ) < color_equal ) && ( abs( s1 - s2 ) > color_diff ) ) ++cc_1; - + /* Note if the 2nd and 3rd lines are more different in color than the 2nd and 4th lines are similar in color.*/ if ( ( abs( s2 - s4 ) < color_equal ) && ( abs( s2 - s3 ) > color_diff) ) ++cc_2; - + /* Now move down 2 horizontal lines before starting over.*/ off += 2 * block; } } - + // compare results /* The final metric seems to be doing some kind of bits per pixel style calculation to decide whether or not enough lines showed alternating colors for the frame size. */ cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) ); - + /* If the plane's cc score meets the threshold, flag it as combed. */ flag[k] = 0; if ( cc[k] > threshold ) @@ -521,13 +521,13 @@ int hb_detect_comb( hb_buffer_t * buf, int width, int height, int color_equal, i flag[k] = 1; } } - + #if 0 /* Debugging info */ // if(flag) hb_log("flags: %i/%i/%i | cc0: %i | cc1: %i | cc2: %i", flag[0], flag[1], flag[2], cc[0], cc[1], cc[2]); #endif - + /* When more than one plane shows combing, tell the caller. */ if (flag[0] || flag[1] || flag[2] ) { @@ -834,7 +834,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) hb_job_t * job_copy; hb_title_t * title, * title_copy; hb_chapter_t * chapter, * chapter_copy; - hb_audio_t * audio, * audio_copy; + hb_audio_t * audio; hb_subtitle_t * subtitle, * subtitle_copy; int i; char audio_lang[4]; @@ -859,17 +859,11 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) /* Do nothing about audio during first pass */ if( job->pass == 0 || job->pass == 2 ) { - for( i = 0; i < 8; i++ ) + for( i = 0; i < hb_list_count(job->list_audio); i++ ) { - if( job->audios[i] < 0 ) - { - break; - } - if( ( audio = hb_list_item( title->list_audio, job->audios[i] ) ) ) + if( ( audio = hb_list_item( job->list_audio, i ) ) ) { - audio_copy = malloc( sizeof( hb_audio_t ) ); - memcpy( audio_copy, audio, sizeof( hb_audio_t ) ); - hb_list_add( title_copy->list_audio, audio_copy ); + hb_list_add( title_copy->list_audio, hb_audio_copy(audio) ); } } } @@ -900,15 +894,11 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) /* * Find the first audio language that is being encoded */ - for( i = 0; i < 8; i++ ) + for( i = 0; i < hb_list_count(job->list_audio); i++ ) { - if( job->audios[i] < 0 ) - { - break; - } - if( ( audio = hb_list_item( title->list_audio, job->audios[i] ) ) ) + if( ( audio = hb_list_item( job->list_audio, i ) ) ) { - strncpy(audio_lang, audio->iso639_2, sizeof(audio_lang)); + strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang)); break; } } @@ -1035,6 +1025,7 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) memcpy( job_copy, job, sizeof( hb_job_t ) ); title_copy->job = job_copy; job_copy->title = title_copy; + job_copy->list_audio = title_copy->list_audio; job_copy->file = strdup( job->file ); job_copy->h = h; job_copy->pause = h->pause_lock; diff --git a/libhb/muxavi.c b/libhb/muxavi.c index 0370c8858..632f24640 100644 --- a/libhb/muxavi.c +++ b/libhb/muxavi.c @@ -281,7 +281,7 @@ static int AVIInit( hb_mux_object_t * m ) hb_mux_data_t * mux_data; int audio_count = hb_list_count( title->list_audio ); - int is_ac3 = ( job->acodec & HB_ACODEC_AC3 ); + int is_ac3 = 0; int hdrl_bytes; int i; @@ -346,8 +346,10 @@ static int AVIInit( hb_mux_object_t * m ) { audio = hb_list_item( title->list_audio, i ); + is_ac3 = (audio->config.out.codec == HB_ACODEC_AC3); + mux_data = calloc( sizeof( hb_mux_data_t ), 1 ); - audio->mux_data = mux_data; + audio->priv.mux_data = mux_data; #define h mux_data->header #define f mux_data->format.a.f @@ -358,8 +360,8 @@ static int AVIInit( hb_mux_object_t * m ) h.Type = FOURCC( "auds" ); h.InitialFrames = 1; h.Scale = 1; - h.Rate = is_ac3 ? ( audio->bitrate / 8 ) : - ( job->abitrate * 1000 / 8 ); + h.Rate = is_ac3 ? ( audio->config.in.bitrate / 8 ) : + ( audio->config.out.bitrate * 1000 / 8 ); h.Quality = 0xFFFFFFFF; h.SampleSize = 1; @@ -369,16 +371,16 @@ static int AVIInit( hb_mux_object_t * m ) { f.BytesCount = sizeof( hb_wave_formatex_t ) - 8; f.FormatTag = 0x2000; - f.Channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->input_channel_layout); - f.SamplesPerSec = audio->rate; + f.Channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout); + f.SamplesPerSec = audio->config.in.samplerate; } else { f.BytesCount = sizeof( hb_wave_formatex_t ) + sizeof( hb_wave_mp3_t ) - 8; f.FormatTag = 0x55; - f.Channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(job->audio_mixdowns[i]); - f.SamplesPerSec = job->arate; + f.Channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); + f.SamplesPerSec = audio->config.out.samplerate; } f.AvgBytesPerSec = h.Rate; f.BlockAlign = 1; @@ -391,7 +393,7 @@ static int AVIInit( hb_mux_object_t * m ) f.Size = sizeof( hb_wave_mp3_t ); m.Id = 1; m.Flags = 2; - m.BlockSize = 1152 * f.AvgBytesPerSec / job->arate; + m.BlockSize = 1152 * f.AvgBytesPerSec / audio->config.out.samplerate; m.FramesPerBlock = 1; m.CodecDelay = 1393; } @@ -439,7 +441,7 @@ static int AVIInit( hb_mux_object_t * m ) char fourcc[4] = "00wb"; audio = hb_list_item( title->list_audio, i ); - mux_data = audio->mux_data; + mux_data = audio->priv.mux_data; fourcc[1] = '1' + i; /* This is fine as we don't allow more than 8 tracks */ @@ -513,9 +515,9 @@ static int AVIMux( hb_mux_object_t * m, hb_mux_data_t * mux_data, { audio = hb_list_item( title->list_audio, i ); fseek( m->file, 264 + i * - ( 102 + ( ( job->acodec & HB_ACODEC_AC3 ) ? 0 : + ( 102 + ( ( audio->config.out.codec == HB_ACODEC_AC3 ) ? 0 : sizeof( hb_wave_mp3_t ) ) ), SEEK_SET ); - WriteInt32( m->file, audio->mux_data->header.Length ); + WriteInt32( m->file, audio->priv.mux_data->header.Length ); } /* movi size */ diff --git a/libhb/muxcommon.c b/libhb/muxcommon.c index d6a8270da..c4f3a8941 100644 --- a/libhb/muxcommon.c +++ b/libhb/muxcommon.c @@ -98,7 +98,7 @@ static void MuxerFunc( void * _mux ) for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - if( !hb_fifo_size( audio->fifo_out ) ) + if( !hb_fifo_size( audio->priv.fifo_out ) ) { ready = 0; break; @@ -131,8 +131,8 @@ static void MuxerFunc( void * _mux ) { audio = hb_list_item( title->list_audio, i ); track = calloc( sizeof( hb_track_t ), 1 ); - track->fifo = audio->fifo_out; - track->mux_data = audio->mux_data; + track->fifo = audio->priv.fifo_out; + track->mux_data = audio->priv.mux_data; hb_list_add( list, track ); } diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c index 6ed6a6dec..76fc48b6f 100644 --- a/libhb/muxmkv.c +++ b/libhb/muxmkv.c @@ -29,6 +29,7 @@ struct hb_mux_data_s mk_Track * track; uint64_t prev_chapter_tc; uint16_t current_chapter; + int codec; }; /********************************************************************** @@ -158,9 +159,11 @@ static int MKVInit( hb_mux_object_t * m ) { audio = hb_list_item( title->list_audio, i ); mux_data = malloc( sizeof( hb_mux_data_t ) ); - audio->mux_data = mux_data; + audio->priv.mux_data = mux_data; - switch (job->acodec) + mux_data->codec = audio->config.out.codec; + + switch (audio->config.out.codec) { case HB_ACODEC_AC3: track->codecPrivate = NULL; @@ -180,8 +183,8 @@ static int MKVInit( hb_mux_object_t * m ) uint64_t header_sizes[3]; for (i = 0; i < 3; ++i) { - ogg_headers[i] = (ogg_packet *)audio->config.vorbis.headers[i]; - ogg_headers[i]->packet = (unsigned char *)&audio->config.vorbis.headers[i] + sizeof( ogg_packet ); + ogg_headers[i] = (ogg_packet *)audio->priv.config.vorbis.headers[i]; + ogg_headers[i]->packet = (unsigned char *)&audio->priv.config.vorbis.headers[i] + sizeof( ogg_packet ); header_sizes[i] = ogg_headers[i]->bytes; } track->codecPrivate = mk_laceXiph(header_sizes, 2, &cp_size); @@ -195,22 +198,13 @@ static int MKVInit( hb_mux_object_t * m ) } break; case HB_ACODEC_FAAC: - if( job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 ) - { - track->codecPrivate = NULL; - track->codecPrivateSize = 0; - track->codecID = MK_ACODEC_AC3; - } - else - { - track->codecPrivate = audio->config.aac.bytes; - track->codecPrivateSize = audio->config.aac.length; - track->codecID = MK_ACODEC_AAC; - } + track->codecPrivate = audio->priv.config.aac.bytes; + track->codecPrivateSize = audio->priv.config.aac.length; + track->codecID = MK_ACODEC_AAC; break; default: *job->die = 1; - hb_error("muxmkv: Unknown audio codec: %x", job->acodec); + hb_error("muxmkv: Unknown audio codec: %x", audio->config.out.codec); return 0; } @@ -221,12 +215,12 @@ static int MKVInit( hb_mux_object_t * m ) } track->flagEnabled = 1; track->trackType = MK_TRACK_AUDIO; - track->language = audio->iso639_2; - track->extra.audio.samplingFreq = (float)job->arate; - track->extra.audio.channels = (job->acodec == HB_ACODEC_AC3 || job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 ) ? HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->input_channel_layout) : HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown); + track->language = audio->config.lang.iso639_2; + track->extra.audio.samplingFreq = (float)audio->config.out.samplerate; + track->extra.audio.channels = (audio->config.out.codec == HB_ACODEC_AC3 ) ? HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout) : HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); // track->defaultDuration = job->arate * 1000; mux_data->track = mk_createTrack(m->file, track); - if (job->acodec == HB_ACODEC_VORBIS && track->codecPrivate != NULL) + if (audio->config.out.codec == HB_ACODEC_VORBIS && track->codecPrivate != NULL) free(track->codecPrivate); } @@ -308,7 +302,7 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data, { /* Audio */ timecode = buf->start * TIMECODE_SCALE; - if (job->acodec == HB_ACODEC_VORBIS) + if (mux_data->codec == HB_ACODEC_VORBIS) { /* ughhh, vorbis is a pain :( */ op = (ogg_packet *)buf->data; diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index d4681c614..59c228f70 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -27,6 +27,11 @@ struct hb_mux_object_s MP4TrackId chapter_track; int current_chapter; uint64_t chapter_duration; + + /* Sample rate of the first audio track. + * Used for the timescale + */ + int samplerate; }; struct hb_mux_data_s @@ -137,6 +142,10 @@ static int MP4Init( hb_mux_object_t * m ) /* Flags for enabling/disabling tracks in an MP4. */ typedef enum { TRACK_DISABLED = 0x0, TRACK_ENABLED = 0x1, TRACK_IN_MOVIE = 0x2, TRACK_IN_PREVIEW = 0x4, TRACK_IN_POSTER = 0x8} track_header_flags; + /* Need the sample rate of the first audio track to use as the timescale. */ + audio = hb_list_item(title->list_audio, 0); + m->samplerate = audio->config.out.samplerate; + audio = NULL; /* Create an empty mp4 file */ if (job->largeFileSize) @@ -166,7 +175,7 @@ static int MP4Init( hb_mux_object_t * m ) synchronization issues (audio not playing at the correct speed). To workaround this, we use the audio samplerate as the timescale */ - if (!(MP4SetTimeScale( m->file, job->arate ))) + if (!(MP4SetTimeScale( m->file, m->samplerate ))) { hb_error("muxmp4.c: MP4SetTimeScale failed!"); *job->die = 1; @@ -183,7 +192,7 @@ static int MP4Init( hb_mux_object_t * m ) return 0; } - mux_data->track = MP4AddH264VideoTrack( m->file, job->arate, + mux_data->track = MP4AddH264VideoTrack( m->file, m->samplerate, MP4_INVALID_DURATION, job->width, job->height, job->config.h264.sps[1], /* AVCProfileIndication */ job->config.h264.sps[2], /* profile_compat */ @@ -211,7 +220,7 @@ static int MP4Init( hb_mux_object_t * m ) *job->die = 1; return 0; } - mux_data->track = MP4AddVideoTrack( m->file, job->arate, + mux_data->track = MP4AddVideoTrack( m->file, m->samplerate, MP4_INVALID_DURATION, job->width, job->height, MP4_MPEG4_VIDEO_TYPE ); if (mux_data->track == MP4_INVALID_TRACK_ID) @@ -261,14 +270,13 @@ static int MP4Init( hb_mux_object_t * m ) audio = hb_list_item( title->list_audio, i ); mux_data = malloc( sizeof( hb_mux_data_t ) ); - audio->mux_data = mux_data; + audio->priv.mux_data = mux_data; - if( job->acodec & HB_ACODEC_AC3 || - job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 ) + if( audio->config.out.codec == HB_ACODEC_AC3 ) { mux_data->track = MP4AddAC3AudioTrack( m->file, - job->arate, 1536, MP4_MPEG4_AUDIO_TYPE ); + m->samplerate, 1536, MP4_MPEG4_AUDIO_TYPE ); MP4SetTrackBytesProperty( m->file, mux_data->track, "udta.name.value", @@ -276,7 +284,7 @@ static int MP4Init( hb_mux_object_t * m ) } else { mux_data->track = MP4AddAudioTrack( m->file, - job->arate, 1024, MP4_MPEG4_AUDIO_TYPE ); + m->samplerate, 1024, MP4_MPEG4_AUDIO_TYPE ); MP4SetTrackBytesProperty( m->file, mux_data->track, "udta.name.value", @@ -285,18 +293,18 @@ static int MP4Init( hb_mux_object_t * m ) MP4SetAudioProfileLevel( m->file, 0x0F ); MP4SetTrackESConfiguration( m->file, mux_data->track, - audio->config.aac.bytes, audio->config.aac.length ); + audio->priv.config.aac.bytes, audio->priv.config.aac.length ); /* Set the correct number of channels for this track */ - reserved2[9] = (u_int8_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown); + reserved2[9] = (u_int8_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); MP4SetTrackBytesProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.reserved2", reserved2, sizeof(reserved2)); } /* Set the language for this track */ /* The language is stored as 5-bit text - 0x60 */ - language_code = audio->iso639_2[0] - 0x60; language_code <<= 5; - language_code |= audio->iso639_2[1] - 0x60; language_code <<= 5; - language_code |= audio->iso639_2[2] - 0x60; + language_code = audio->config.lang.iso639_2[0] - 0x60; language_code <<= 5; + language_code |= audio->config.lang.iso639_2[1] - 0x60; language_code <<= 5; + language_code |= audio->config.lang.iso639_2[2] - 0x60; MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.mdhd.language", language_code); @@ -372,7 +380,7 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, if ( job->areBframes ) { - duration += buf->renderOffset * job->arate / 90000; + duration += buf->renderOffset * m->samplerate / 90000; } sample = MP4GenerateChapterSample( m, duration ); @@ -396,8 +404,8 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, /* Because we use the audio samplerate as the timescale, we have to use potentially variable durations so the video doesn't go out of sync */ - int64_t bias = ( buf->start * job->arate / 90000 ) - m->sum_dur; - duration = ( buf->stop - buf->start ) * job->arate / 90000 + bias; + int64_t bias = ( buf->start * m->samplerate / 90000 ) - m->sum_dur; + duration = ( buf->stop - buf->start ) * m->samplerate / 90000 + bias; if ( duration <= 0 ) { /* We got an illegal mp4/h264 duration. This shouldn't @@ -406,14 +414,14 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, try to fix the error so that the file will still be playable. */ hb_log("MP4Mux: illegal duration %lld, bias %lld, start %lld (%lld)," "stop %lld (%lld), sum_dur %lld", - duration, bias, buf->start * job->arate / 90000, buf->start, - buf->stop * job->arate / 90000, buf->stop, m->sum_dur ); + duration, bias, buf->start * m->samplerate / 90000, buf->start, + buf->stop * m->samplerate / 90000, buf->stop, m->sum_dur ); /* we don't know when the next frame starts so we can't pick a valid duration for this one so we pick something "short" (roughly 1/3 of an NTSC frame time) and rely on the bias calc for the next frame to correct things (a duration underestimate just results in a large bias on the next frame). */ - duration = 1000 * job->arate / 90000; + duration = 1000 * m->samplerate / 90000; } m->sum_dur += duration; } @@ -436,7 +444,7 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, duration, ((mux_data->track != 1) || (job->areBframes==0) || - (job->vcodec != HB_VCODEC_X264)) ? 0 : ( buf->renderOffset * job->arate / 90000), + (job->vcodec != HB_VCODEC_X264)) ? 0 : ( buf->renderOffset * m->samplerate / 90000), ((buf->frametype & HB_FRAME_KEY) != 0) ) ) { hb_error("Failed to write to output file, disk full?"); diff --git a/libhb/muxogm.c b/libhb/muxogm.c index 433122448..a7b72d510 100644 --- a/libhb/muxogm.c +++ b/libhb/muxogm.c @@ -135,9 +135,9 @@ static int OGMInit( hb_mux_object_t * m ) { audio = hb_list_item( title->list_audio, i ); mux_data = malloc( sizeof( hb_mux_data_t ) ); - mux_data->codec = job->acodec; + mux_data->codec = audio->config.out.codec; mux_data->i_packet_no = 0; - audio->mux_data = mux_data; + audio->priv.mux_data = mux_data; ogg_stream_init( &mux_data->os, i + 1 ); } @@ -200,9 +200,9 @@ static int OGMInit( hb_mux_object_t * m ) for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - mux_data = audio->mux_data; + mux_data = audio->priv.mux_data; memset( &h, 0, sizeof( ogg_stream_header_t ) ); - switch( job->acodec ) + switch( audio->config.out.codec ) { case HB_ACODEC_LAME: { @@ -212,7 +212,7 @@ static int OGMInit( hb_mux_object_t * m ) SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1); SetQWLE( &h.i_time_unit, 0 ); - SetQWLE( &h.i_samples_per_unit, job->arate ); + SetQWLE( &h.i_samples_per_unit, audio->config.out.samplerate ); SetDWLE( &h.i_default_len, 1 ); SetDWLE( &h.i_buffer_size, 30 * 1024 ); SetWLE ( &h.i_bits_per_sample, 0 ); @@ -220,7 +220,7 @@ static int OGMInit( hb_mux_object_t * m ) SetDWLE( &h.header.audio.i_channels, 2 ); SetDWLE( &h.header.audio.i_block_align, 0 ); SetDWLE( &h.header.audio.i_avgbytespersec, - job->abitrate / 8 ); + audio->config.out.bitrate / 8 ); op.packet = (unsigned char*) &h; op.bytes = sizeof( ogg_stream_header_t ); @@ -233,9 +233,9 @@ static int OGMInit( hb_mux_object_t * m ) } case HB_ACODEC_VORBIS: { - memcpy( &op, audio->config.vorbis.headers[0], + memcpy( &op, audio->priv.config.vorbis.headers[0], sizeof( ogg_packet ) ); - op.packet = audio->config.vorbis.headers[0] + + op.packet = audio->priv.config.vorbis.headers[0] + sizeof( ogg_packet ); ogg_stream_packetin( &mux_data->os, &op ); break; @@ -275,16 +275,16 @@ static int OGMInit( hb_mux_object_t * m ) for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - if( job->acodec == HB_ACODEC_VORBIS ) + if( audio->config.out.codec == HB_ACODEC_VORBIS ) { int j; - mux_data = audio->mux_data; + mux_data = audio->priv.mux_data; for( j = 1; j < 3; j++ ) { - memcpy( &op, audio->config.vorbis.headers[j], + memcpy( &op, audio->priv.config.vorbis.headers[j], sizeof( ogg_packet ) ); - op.packet = audio->config.vorbis.headers[j] + + op.packet = audio->priv.config.vorbis.headers[j] + sizeof( ogg_packet ); ogg_stream_packetin( &mux_data->os, &op ); @@ -387,7 +387,7 @@ static int OGMEnd( hb_mux_object_t * m ) for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - mux_data = audio->mux_data; + mux_data = audio->priv.mux_data; if( OGMFlush( m, mux_data ) < 0 ) { return -1; diff --git a/libhb/reader.c b/libhb/reader.c index db1c7af72..823dfbe84 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -358,7 +358,7 @@ static hb_fifo_t ** GetFifoForId( hb_job_t * job, int id ) audio = hb_list_item( title->list_audio, i ); if( id == audio->id ) { - fifos[n++] = audio->fifo_in; + fifos[n++] = audio->priv.fifo_in; } } diff --git a/libhb/scan.c b/libhb/scan.c index 4aee25bc7..6c97920da 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -147,8 +147,8 @@ static void ScanFunc( void * _data ) for( j = 0; j < hb_list_count( title->list_audio ); ) { audio = hb_list_item( title->list_audio, j ); - if( audio->codec == HB_ACODEC_AC3 && - !audio->bitrate ) + if( audio->config.in.codec == HB_ACODEC_AC3 && + !audio->config.in.bitrate ) { hb_list_rem( title->list_audio, audio ); free( audio ); @@ -162,11 +162,11 @@ static void ScanFunc( void * _data ) for( j = 0; j < hb_list_count( title->list_audio ); ) { audio = hb_list_item( title->list_audio, j ); - if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) && - !audio->bitrate ) + if( ( audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA ) && + !audio->config.in.bitrate ) { hb_log( "scan: removing audio with codec of 0x%x because of no bitrate", - audio->codec ); + audio->config.in.codec ); hb_list_rem( title->list_audio, audio ); free( audio ); continue; @@ -188,9 +188,9 @@ static void ScanFunc( void * _data ) for( j = 0; j < hb_list_count( title->list_audio ); j++ ) { audio = hb_list_item( title->list_audio, j ); - if( audio->codec == HB_ACODEC_LPCM || audio->codec == HB_ACODEC_MPGA ) + if( audio->config.in.codec == HB_ACODEC_LPCM || audio->config.in.codec == HB_ACODEC_MPGA ) { - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO; } } @@ -247,12 +247,7 @@ static void ScanFunc( void * _data ) job->vrate = title->rate; job->vrate_base = title->rate_base; - job->audios[0] = 0; - job->audios[1] = -1; - - job->acodec = HB_ACODEC_FAAC; - job->abitrate = 128; - job->arate = 44100; + job->list_audio = hb_list_init(); job->subtitle = -1; @@ -451,14 +446,14 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title ) } buf_raw = hb_list_item( list_raw, 0 ); - + /* Check preview for interlacing artifacts */ if( hb_detect_comb( buf_raw, title->width, title->height, 10, 30, 9 ) ) { hb_log("Interlacing detected in preview frame %i", i); interlaced_preview_count++; } - + hb_get_tempory_filename( data->h, filename, "%x%d", (intptr_t)title, i ); @@ -584,7 +579,7 @@ static void LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b ) { audio = hb_list_item( title->list_audio, i ); /* check if we have an AC3 or DCA which we recognise */ - if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) && + if( ( audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA ) && audio->id == b->id ) { break; @@ -599,7 +594,7 @@ static void LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b ) return; } - if( audio->bitrate ) + if( audio->config.in.bitrate ) { /* Already done for this track */ return; @@ -608,78 +603,77 @@ static void LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b ) for( i = 0; i < b->size - 7; i++ ) { - if ( audio->codec == HB_ACODEC_AC3 ) + if ( audio->config.in.codec == HB_ACODEC_AC3 ) { /* check for a52 */ if( a52_syncinfo( &b->data[i], &flags, &rate, &bitrate ) ) { hb_log( "scan: AC3, rate=%dHz, bitrate=%d", rate, bitrate ); - audio->rate = rate; - audio->bitrate = bitrate; + audio->config.in.samplerate = rate; + audio->config.in.bitrate = bitrate; switch( flags & A52_CHANNEL_MASK ) { /* mono sources */ case A52_MONO: case A52_CHANNEL1: case A52_CHANNEL2: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_MONO; break; /* stereo input */ case A52_CHANNEL: case A52_STEREO: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO; break; /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */ case A52_DOLBY: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_DOLBY; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_DOLBY; break; /* 3F/2R input */ case A52_3F2R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F2R; break; /* 3F/1R input */ case A52_3F1R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F1R; break; /* other inputs */ case A52_3F: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F; break; case A52_2F1R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F1R; break; case A52_2F2R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F2R; break; /* unknown */ default: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO; } /* add in our own LFE flag if the source has LFE */ if (flags & A52_LFE) { - audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE; + audio->config.in.channel_layout = audio->config.in.channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE; } /* store the AC3 flags for future reference - This enables us to find out if we had a stereo or Dolby source later on */ - audio->config.a52.ac3flags = flags; - - /* store the ac3 flags in the public ac3flags property too, so we can access it from the GUI */ - audio->ac3flags = audio->config.a52.ac3flags; + * This enables us to find out if we had a stereo or Dolby source later on + * Store the ac3 flags in the public ac3flags property too, so we can access it from the GUI + */ + audio->config.flags.ac3 = audio->priv.config.a52.ac3flags = flags; /* XXX */ if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY ) { - sprintf( audio->lang + strlen( audio->lang ), + sprintf( audio->config.lang.description + strlen( audio->config.lang.description ), " (Dolby Surround)" ); } else { - sprintf( audio->lang + strlen( audio->lang ), + sprintf( audio->config.lang.description + strlen( audio->config.lang.description ), " (%d.%d ch)", - HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) + - HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout), - HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout)); + HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->config.in.channel_layout) + + HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->config.in.channel_layout), + HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->config.in.channel_layout)); } break; @@ -687,7 +681,7 @@ static void LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b ) } } - else if ( audio->codec == HB_ACODEC_DCA ) + else if ( audio->config.in.codec == HB_ACODEC_DCA ) { hb_log( "scan: checking for DCA syncinfo" ); @@ -697,70 +691,69 @@ static void LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b ) if( dca_syncinfo( state, &b->data[i], &flags, &rate, &bitrate, &frame_length ) ) { hb_log( "scan: DCA, rate=%dHz, bitrate=%d", rate, bitrate ); - audio->rate = rate; - audio->bitrate = bitrate; + audio->config.in.samplerate = rate; + audio->config.in.bitrate = bitrate; switch( flags & DCA_CHANNEL_MASK ) { /* mono sources */ case DCA_MONO: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_MONO; break; /* stereo input */ case DCA_CHANNEL: case DCA_STEREO: case DCA_STEREO_SUMDIFF: case DCA_STEREO_TOTAL: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO; break; /* 3F/2R input */ case DCA_3F2R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F2R; break; /* 3F/1R input */ case DCA_3F1R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F1R; break; /* other inputs */ case DCA_3F: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F; break; case DCA_2F1R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F1R; break; case DCA_2F2R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F2R; break; case DCA_4F2R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_4F2R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_4F2R; break; /* unknown */ default: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO; } /* add in our own LFE flag if the source has LFE */ if (flags & DCA_LFE) { - audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE; + audio->config.in.channel_layout = audio->config.in.channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE; } /* store the DCA flags for future reference - This enables us to find out if we had a stereo or Dolby source later on */ - audio->config.dca.dcaflags = flags; - - /* store the dca flags in the public dcaflags property too, so we can access it from the GUI */ - audio->dcaflags = audio->config.dca.dcaflags; + * This enables us to find out if we had a stereo or Dolby source later on + * store the dca flags in the public dcaflags property too, so we can access it from the GUI + */ + audio->config.flags.dca = audio->priv.config.dca.dcaflags = flags; /* XXX */ if ( (flags & DCA_CHANNEL_MASK) == DCA_DOLBY ) { - sprintf( audio->lang + strlen( audio->lang ), + sprintf( audio->config.lang.description + strlen( audio->config.lang.description ), " (Dolby Surround)" ); } else { - sprintf( audio->lang + strlen( audio->lang ), + sprintf( audio->config.lang.description + strlen( audio->config.lang.description ), " (%d.%d ch)", - HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) + - HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout), - HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout)); + HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->config.in.channel_layout) + + HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->config.in.channel_layout), + HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->config.in.channel_layout)); } break; @@ -778,8 +771,8 @@ static int AllAC3AndDCAOK( hb_title_t * title ) for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) && - !audio->bitrate ) + if( ( audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA ) && + !audio->config.in.bitrate ) { return 0; } diff --git a/libhb/stream.c b/libhb/stream.c index e376c6903..fe2c962c0 100755 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -340,7 +340,7 @@ void hb_stream_close( hb_stream_t ** _d ) if ( stream->frames ) { hb_log( "stream: %d good frames, %d errors (%.0f%%)", stream->frames, - stream->errors, (double)stream->errors * 100. / + stream->errors, (double)stream->errors * 100. / (double)stream->frames ); } /* @@ -444,7 +444,7 @@ hb_title_t * hb_stream_title_scan(hb_stream_t *stream) for (i=0; i < stream->ts_number_audio_pids; i++) { hb_audio_t *audio = hb_ts_stream_set_audio_id_and_codec(stream, i); - if (audio->codec) + if (audio->config.in.codec) hb_list_add( aTitle->list_audio, audio ); else { @@ -773,7 +773,7 @@ static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream, if (buf[3] == 0xbd) { audio->id = 0x80bd | (aud_pid_index << 8); - audio->codec = HB_ACODEC_AC3; + audio->config.in.codec = HB_ACODEC_AC3; hb_log("transport stream pid 0x%x (type 0x%x) is AC-3 audio id 0x%x", stream->ts_audio_pids[aud_pid_index], stream->ts_audio_stream_type[1 + aud_pid_index], @@ -784,7 +784,7 @@ static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream, else if ((buf[3] & 0xe0) == 0xc0) { audio->id = buf[3] | aud_pid_index; - audio->codec = HB_ACODEC_MPGA; + audio->config.in.codec = HB_ACODEC_MPGA; hb_log("transport stream pid 0x%x (type 0x%x) is MPEG audio id 0x%x", stream->ts_audio_pids[aud_pid_index], stream->ts_audio_stream_type[1 + aud_pid_index], @@ -794,7 +794,7 @@ static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream, } } fseeko(stream->file_handle, cur_pos, SEEK_SET); - if (! audio->codec) + if (! audio->config.in.codec) { hb_log("transport stream pid 0x%x (type 0x%x) isn't audio", stream->ts_audio_pids[aud_pid_index], @@ -811,7 +811,7 @@ static void add_audio_to_title(hb_title_t *title, int id) switch ( id >> 12 ) { case 0x0: - audio->codec = HB_ACODEC_MPGA; + audio->config.in.codec = HB_ACODEC_MPGA; hb_log("add_audio_to_title: added MPEG audio stream 0x%x", id); break; case 0x2: @@ -819,11 +819,11 @@ static void add_audio_to_title(hb_title_t *title, int id) free( audio ); return; case 0x8: - audio->codec = HB_ACODEC_AC3; + audio->config.in.codec = HB_ACODEC_AC3; hb_log("add_audio_to_title: added AC3 audio stream 0x%x", id); break; case 0xa: - audio->codec = HB_ACODEC_LPCM; + audio->config.in.codec = HB_ACODEC_LPCM; hb_log("add_audio_to_title: added LPCM audio stream 0x%x", id); break; default: @@ -913,12 +913,12 @@ void hb_stream_update_audio(hb_stream_t *stream, hb_audio_t *audio) } lang = lang_for_code(stream->a52_info[i].lang_code); - if (!audio->rate) - audio->rate = stream->a52_info[i].rate; - if (!audio->bitrate) - audio->bitrate = stream->a52_info[i].bitrate; - if (!audio->config.a52.ac3flags) - audio->config.a52.ac3flags = audio->ac3flags = stream->a52_info[i].flags; + if (!audio->config.in.samplerate) + audio->config.in.samplerate = stream->a52_info[i].rate; + if (!audio->config.in.bitrate) + audio->config.in.bitrate = stream->a52_info[i].bitrate; + if (!audio->priv.config.a52.ac3flags) + audio->priv.config.a52.ac3flags = audio->config.flags.ac3 = stream->a52_info[i].flags; } else @@ -927,74 +927,74 @@ void hb_stream_update_audio(hb_stream_t *stream, hb_audio_t *audio) lang = lang_for_code(0x0000); } - if (!audio->input_channel_layout) + if (!audio->config.in.channel_layout) { - switch( audio->ac3flags & A52_CHANNEL_MASK ) + switch( audio->config.flags.ac3 & A52_CHANNEL_MASK ) { /* mono sources */ case A52_MONO: case A52_CHANNEL1: case A52_CHANNEL2: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_MONO; break; /* stereo input */ case A52_CHANNEL: case A52_STEREO: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO; break; /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */ case A52_DOLBY: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_DOLBY; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_DOLBY; break; /* 3F/2R input */ case A52_3F2R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F2R; break; /* 3F/1R input */ case A52_3F1R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F1R; break; /* other inputs */ case A52_3F: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F; break; case A52_2F1R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F1R; break; case A52_2F2R: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F2R; break; /* unknown */ default: - audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO; + audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO; } /* add in our own LFE flag if the source has LFE */ - if (audio->ac3flags & A52_LFE) + if (audio->config.flags.ac3 & A52_LFE) { - audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE; + audio->config.in.channel_layout = audio->config.in.channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE; } } - snprintf( audio->lang, sizeof( audio->lang ), "%s (%s)", strlen(lang->native_name) ? lang->native_name : lang->eng_name, - audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec == HB_ACODEC_MPGA ? "MPEG" : ( audio->codec == HB_ACODEC_DCA ? "DTS" : "LPCM" ) ) ); - snprintf( audio->lang_simple, sizeof( audio->lang_simple ), "%s", strlen(lang->native_name) ? lang->native_name : lang->eng_name ); - snprintf( audio->iso639_2, sizeof( audio->iso639_2 ), "%s", lang->iso639_2); + snprintf( audio->config.lang.description, sizeof( audio->config.lang.description ), "%s (%s)", strlen(lang->native_name) ? lang->native_name : lang->eng_name, + audio->config.in.codec == HB_ACODEC_AC3 ? "AC3" : ( audio->config.in.codec == HB_ACODEC_MPGA ? "MPEG" : ( audio->config.in.codec == HB_ACODEC_DCA ? "DTS" : "LPCM" ) ) ); + snprintf( audio->config.lang.simple, sizeof( audio->config.lang.simple ), "%s", strlen(lang->native_name) ? lang->native_name : lang->eng_name ); + snprintf( audio->config.lang.iso639_2, sizeof( audio->config.lang.iso639_2 ), "%s", lang->iso639_2); - if ( (audio->ac3flags & A52_CHANNEL_MASK) == A52_DOLBY ) { - sprintf( audio->lang + strlen( audio->lang ), + if ( (audio->config.flags.ac3 & A52_CHANNEL_MASK) == A52_DOLBY ) { + sprintf( audio->config.lang.description + strlen( audio->config.lang.description ), " (Dolby Surround)" ); } else { - sprintf( audio->lang + strlen( audio->lang ), + sprintf( audio->config.lang.description + strlen( audio->config.lang.description ), " (%d.%d ch)", - HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) + - HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout), - HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout)); + HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->config.in.channel_layout) + + HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->config.in.channel_layout), + HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->config.in.channel_layout)); } hb_log( "stream: audio %x: lang %s, rate %d, bitrate %d, " - "flags = 0x%x", audio->id, audio->lang, audio->rate, - audio->bitrate, audio->ac3flags ); + "flags = 0x%x", audio->id, audio->config.lang.description, audio->config.in.samplerate, + audio->config.in.bitrate, audio->config.flags.ac3 ); } @@ -1879,7 +1879,7 @@ static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf ) // remember the pcr across calls to this routine stream->ts_lastpcr = pcr; } - + if ( pcr == -1 ) { // don't accumulate data until we get a pcr @@ -1903,7 +1903,7 @@ static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf ) // so ignore the rest. continue; } - if ( !start && (stream->ts_streamcont[curstream] != -1) && + if ( !start && (stream->ts_streamcont[curstream] != -1) && (continuity != ( (stream->ts_streamcont[curstream] + 1) & 0xf ) ) ) { ts_err( stream, curstream, "continuity error: got %d expected %d", @@ -1933,7 +1933,7 @@ static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf ) stream->ts_skipbad[curstream] = 0; } - // If we don't have video yet, check to see if this is an + // If we don't have video yet, check to see if this is an // i_frame (group of picture start) if ( curstream == 0 ) { diff --git a/libhb/sync.c b/libhb/sync.c index 2a4818af3..5b4891bb6 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -130,6 +130,7 @@ void syncClose( hb_work_object_t * w ) hb_work_private_t * pv = w->private_data; hb_job_t * job = pv->job; hb_title_t * title = job->title; + hb_audio_t * audio = NULL; int i; @@ -144,8 +145,8 @@ void syncClose( hb_work_object_t * w ) pv->sync_audio[i].start_silence) / 90), i ); } - if( job->acodec & HB_ACODEC_AC3 || - job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 ) + audio = hb_list_item( title->list_audio, i ); + if( audio->config.out.codec == HB_ACODEC_AC3 ) { free( pv->sync_audio[i].ac3_buf ); } @@ -207,8 +208,7 @@ static void InitAudio( hb_work_object_t * w, int i ) sync = &pv->sync_audio[i]; sync->audio = hb_list_item( title->list_audio, i ); - if( job->acodec & HB_ACODEC_AC3 || - job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 ) + if( sync->audio->config.out.codec == HB_ACODEC_AC3 ) { /* Have a silent AC-3 frame ready in case we have to fill a gap */ @@ -219,9 +219,9 @@ static void InitAudio( hb_work_object_t * w, int i ) codec = avcodec_find_encoder( CODEC_ID_AC3 ); c = avcodec_alloc_context(); - c->bit_rate = sync->audio->bitrate; - c->sample_rate = sync->audio->rate; - c->channels = 2; + c->bit_rate = sync->audio->config.in.bitrate; + c->sample_rate = sync->audio->config.in.samplerate; + c->channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( sync->audio->config.in.channel_layout ); if( avcodec_open( c, codec ) < 0 ) { @@ -231,8 +231,8 @@ static void InitAudio( hb_work_object_t * w, int i ) zeros = calloc( AC3_SAMPLES_PER_FRAME * sizeof( short ) * c->channels, 1 ); - sync->ac3_size = sync->audio->bitrate * AC3_SAMPLES_PER_FRAME / - sync->audio->rate / 8; + sync->ac3_size = sync->audio->config.in.bitrate * AC3_SAMPLES_PER_FRAME / + sync->audio->config.in.samplerate / 8; sync->ac3_buf = malloc( sync->ac3_size ); if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size, @@ -249,7 +249,7 @@ static void InitAudio( hb_work_object_t * w, int i ) { /* Initialize libsamplerate */ int error; - sync->state = src_new( SRC_LINEAR, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown), &error ); + sync->state = src_new( SRC_LINEAR, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->config.out.mixdown), &error ); sync->data.end_of_input = 0; } } @@ -432,9 +432,9 @@ static int SyncVideo( hb_work_object_t * w ) * Subtitle is on for less than three seconds, extend * the time that it is displayed to make it easier * to read. Make it 3 seconds or until the next - * subtitle is displayed. + * subtitle is displayed. * - * This is in response to Indochine which only + * This is in response to Indochine which only * displays subs for 1 second - too fast to read. */ sub->stop = sub->start + ( 3 * 90000 ); @@ -558,22 +558,22 @@ static void OutputAudioFrame( hb_job_t *job, hb_audio_t *audio, hb_buffer_t *buf { int64_t start = sync->next_start; int64_t duration = buf->stop - buf->start; - if (duration <= 0 || - duration > ( 90000 * AC3_SAMPLES_PER_FRAME ) / audio->rate ) + if (duration <= 0 || + duration > ( 90000 * AC3_SAMPLES_PER_FRAME ) / audio->config.out.samplerate ) { hb_log("sync: audio %d weird duration %lld, start %lld, stop %lld, next %lld", i, duration, buf->start, buf->stop, sync->next_pts); if ( duration <= 0 ) { - duration = ( 90000 * AC3_SAMPLES_PER_FRAME ) / audio->rate; + duration = ( 90000 * AC3_SAMPLES_PER_FRAME ) / audio->config.out.samplerate; buf->stop = buf->start + duration; } } sync->next_pts += duration; if( /* audio->rate == job->arate || This should work but doesn't */ - job->acodec & HB_ACODEC_AC3 || - job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 ) + audio->config.out.codec == HB_ACODEC_AC3 || + audio->config.out.codec == HB_ACODEC_DCA ) { /* * If we don't have to do sample rate conversion or this audio is AC3 @@ -586,11 +586,11 @@ static void OutputAudioFrame( hb_job_t *job, hb_audio_t *audio, hb_buffer_t *buf /* Not pass-thru - do sample rate conversion */ int count_in, count_out; hb_buffer_t * buf_raw = buf; - int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) * + int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) * sizeof( float ); count_in = buf_raw->size / channel_count; - count_out = ( buf_raw->stop - buf_raw->start ) * job->arate / 90000; + count_out = ( buf_raw->stop - buf_raw->start ) * audio->config.out.samplerate / 90000; sync->data.input_frames = count_in; sync->data.output_frames = count_out; @@ -630,19 +630,18 @@ static void SyncAudio( hb_work_object_t * w, int i ) hb_fifo_t * fifo; int rate; - if( job->acodec & HB_ACODEC_AC3 || - job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 ) + if( audio->config.out.codec == HB_ACODEC_AC3 ) { - fifo = audio->fifo_out; - rate = audio->rate; + fifo = audio->priv.fifo_out; + rate = audio->config.in.samplerate; } else { - fifo = audio->fifo_sync; - rate = job->arate; + fifo = audio->priv.fifo_sync; + rate = audio->config.out.samplerate; } - while( !hb_fifo_is_full( fifo ) && ( buf = hb_fifo_see( audio->fifo_raw ) ) ) + while( !hb_fifo_is_full( fifo ) && ( buf = hb_fifo_see( audio->priv.fifo_raw ) ) ) { if ( sync->next_pts - buf->start > 500 ) { @@ -656,7 +655,7 @@ static void SyncAudio( hb_work_object_t * w, int i ) sync->first_drop = buf->start; } ++sync->drop_count; - buf = hb_fifo_get( audio->fifo_raw ); + buf = hb_fifo_get( audio->priv.fifo_raw ); hb_buffer_close( &buf ); continue; } @@ -711,13 +710,13 @@ static void SyncAudio( hb_work_object_t * w, int i ) * audio stream and are ready to inject the next input frame into * the output stream. */ - buf = hb_fifo_get( audio->fifo_raw ); + buf = hb_fifo_get( audio->priv.fifo_raw ); OutputAudioFrame( job, audio, buf, sync, fifo, i ); } if( NeedSilence( w, audio, i ) ) { - InsertSilence( w, i, (90000 * AC3_SAMPLES_PER_FRAME) / sync->audio->rate ); + InsertSilence( w, i, (90000 * AC3_SAMPLES_PER_FRAME) / sync->audio->config.out.samplerate ); } } @@ -727,10 +726,10 @@ static int NeedSilence( hb_work_object_t * w, hb_audio_t * audio, int i ) hb_job_t * job = pv->job; hb_sync_audio_t * sync = &pv->sync_audio[i]; - if( hb_fifo_size( audio->fifo_in ) || - hb_fifo_size( audio->fifo_raw ) || - hb_fifo_size( audio->fifo_sync ) || - hb_fifo_size( audio->fifo_out ) ) + if( hb_fifo_size( audio->priv.fifo_in ) || + hb_fifo_size( audio->priv.fifo_raw ) || + hb_fifo_size( audio->priv.fifo_sync ) || + hb_fifo_size( audio->priv.fifo_out ) ) { /* We have some audio, we are fine */ return 0; @@ -759,22 +758,22 @@ static void InsertSilence( hb_work_object_t * w, int i, int64_t duration ) hb_sync_audio_t *sync = &pv->sync_audio[i]; hb_buffer_t *buf; - if( job->acodec & HB_ACODEC_AC3 || job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 ) + if( sync->audio->config.out.codec == HB_ACODEC_AC3 ) { buf = hb_buffer_init( sync->ac3_size ); buf->start = sync->next_pts; buf->stop = buf->start + duration; memcpy( buf->data, sync->ac3_buf, buf->size ); - OutputAudioFrame( job, sync->audio, buf, sync, sync->audio->fifo_out, i ); + OutputAudioFrame( job, sync->audio, buf, sync, sync->audio->priv.fifo_out, i ); } else { buf = hb_buffer_init( duration * sizeof( float ) * - HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown) ); + HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->config.out.mixdown) ); buf->start = sync->next_pts; buf->stop = buf->start + duration; memset( buf->data, 0, buf->size ); - OutputAudioFrame( job, sync->audio, buf, sync, sync->audio->fifo_sync, i ); + OutputAudioFrame( job, sync->audio, buf, sync, sync->audio->priv.fifo_sync, i ); } } diff --git a/libhb/work.c b/libhb/work.c index 9ebc33bf6..e867a2bfe 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -337,57 +337,55 @@ static void do_job( hb_job_t * job, int cpu_count ) } } - if( job->audio_mixdowns[0] == HB_AMIXDOWN_AC3 || job->audio_mixdowns[1] == HB_AMIXDOWN_AC3 ) - { - /* Hard set correct sample rate for AC3 when libhb - mistakenly thinks the audio codec is AAC */ - job->arate = 48000; - } - - if( job->acodec & HB_ACODEC_AC3 ) - { - hb_log( " + audio AC3 passthrough" ); - - /* Hard set correct sample rate for AC3 */ - job->arate = 48000; - } - else - { - hb_log( " + audio %d kbps, %d Hz", job->abitrate, job->arate ); - hb_log( " + encoder %s", ( job->acodec & HB_ACODEC_FAAC ) ? - "faac" : ( ( job->acodec & HB_ACODEC_LAME ) ? "lame" : - "vorbis" ) ); - } - - if ( job->dynamic_range_compression > 1 ) - hb_log(" + dynamic range compression: %f", job->dynamic_range_compression); - - /* if we are doing AC3 passthru (at the codec level, not pass-through), - * then remove any non-AC3 audios from the job */ + /* if we are doing passthru, and the input codec is not the same as the output + * codec, then remove this audio from the job */ /* otherwise, Bad Things will happen */ for( i = 0; i < hb_list_count( title->list_audio ); ) { audio = hb_list_item( title->list_audio, i ); - if( ( job->acodec & HB_ACODEC_AC3 ) && ( audio->codec != HB_ACODEC_AC3 ) ) + if( ( ( audio->config.out.codec == HB_ACODEC_AC3 ) && ( audio->config.in.codec != HB_ACODEC_AC3 ) ) || + ( ( audio->config.out.codec == HB_ACODEC_DCA ) && ( audio->config.in.codec != HB_ACODEC_DCA ) ) ) { + hb_log( "Passthru requested and input codec is not the same as output codec for track %d", + audio->config.out.track ); hb_list_rem( title->list_audio, audio ); free( audio ); continue; } - i++; + /* Adjust output track number, in case we removed one. + * Output tracks sadly still need to be in sequential order. + */ + audio->config.out.track = i++; } for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - hb_log( " + %x, %s", audio->id, audio->lang ); + hb_log( " + audio track %d", audio->config.out.track ); + hb_log( " + input track %d", audio->config.in.track ); + if( (audio->config.out.codec == HB_ACODEC_AC3) || (audio->config.out.codec == HB_ACODEC_DCA) ) + { + hb_log( " + %s passthrough", (audio->config.out.codec == HB_ACODEC_AC3) ? + "AC3" : "DCA" ); + } + else + { + hb_log( " + audio %d kbps, %d Hz", audio->config.out.bitrate, audio->config.out.samplerate ); + hb_log( " + encoder %s", ( audio->config.out.codec == HB_ACODEC_FAAC ) ? + "faac" : ( ( audio->config.out.codec == HB_ACODEC_LAME ) ? "lame" : + "vorbis" ) ); + if ( audio->config.out.dynamic_range_compression > 1 ) + hb_log(" + dynamic range compression: %f", audio->config.out.dynamic_range_compression); + } + + hb_log( " + %x, %s", audio->id, audio->config.lang.description ); /* sense-check the current mixdown options */ /* log the requested mixdown */ for (j = 0; j < hb_audio_mixdowns_count; j++) { - if (hb_audio_mixdowns[j].amixdown == job->audio_mixdowns[i]) { - hb_log( " + Requested mixdown: %s (%s)", hb_audio_mixdowns[j].human_readable_name, hb_audio_mixdowns[j].internal_name ); + if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) { + hb_log( " + Requested mixdown: %s (%s)", hb_audio_mixdowns[j].human_readable_name, hb_audio_mixdowns[j].internal_name ); break; } } @@ -396,33 +394,22 @@ static void do_job( hb_job_t * job, int cpu_count ) /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now, but this may change in the future, so they are separated for flexibility */ - int audioCodecsSupportMono = ((audio->codec == HB_ACODEC_AC3 || - audio->codec == HB_ACODEC_DCA) && (job->acodec == HB_ACODEC_FAAC || job->acodec == HB_ACODEC_VORBIS)); - int audioCodecsSupport6Ch = ((audio->codec == HB_ACODEC_AC3 || - audio->codec == HB_ACODEC_DCA) && (job->acodec == HB_ACODEC_FAAC || job->acodec == HB_ACODEC_VORBIS)); + int audioCodecsSupportMono = ( (audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA) && + (audio->config.out.codec == HB_ACODEC_FAAC || audio->config.out.codec == HB_ACODEC_VORBIS) ); + int audioCodecsSupport6Ch = ( (audio->config.in.codec == HB_ACODEC_AC3 || audio->config.in.codec == HB_ACODEC_DCA) && + (audio->config.out.codec == HB_ACODEC_FAAC || audio->config.out.codec == HB_ACODEC_VORBIS)); - if( audio->codec != HB_ACODEC_AC3 && job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 ) - { - /* - * Sanity check that we haven't asked for AC3 from a non AC3 track - drop this track - * to stereo to avoid a crash later. - */ - job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO; - } - - if( job->audio_mixdowns[i] != HB_AMIXDOWN_AC3 ) - { /* find out what the format of our source audio is */ - switch (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK) { + switch (audio->config.in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK) { /* mono sources */ case HB_INPUT_CH_LAYOUT_MONO: /* regardless of what stereo mixdown we've requested, a mono source always get mixed down to mono if we can, and mixed up to stereo if we can't */ - if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) { - job->audio_mixdowns[i] = HB_AMIXDOWN_MONO; + if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) { + audio->config.out.mixdown = HB_AMIXDOWN_MONO; } else { - job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO; + audio->config.out.mixdown = HB_AMIXDOWN_STEREO; } break; @@ -430,11 +417,11 @@ static void do_job( hb_job_t * job, int cpu_count ) case HB_INPUT_CH_LAYOUT_STEREO: /* if we've requested a mono mixdown, and it is supported, then do the mix */ /* use stereo if not supported */ - if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) { - job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO; + if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) { + audio->config.out.mixdown = HB_AMIXDOWN_STEREO; /* otherwise, preserve stereo regardless of if we requested something higher */ - } else if (job->audio_mixdowns[i] > HB_AMIXDOWN_STEREO) { - job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO; + } else if (audio->config.out.mixdown > HB_AMIXDOWN_STEREO) { + audio->config.out.mixdown = HB_AMIXDOWN_STEREO; } break; @@ -444,12 +431,12 @@ static void do_job( hb_job_t * job, int cpu_count ) case HB_INPUT_CH_LAYOUT_DOLBY: /* if we've requested a mono mixdown, and it is supported, then do the mix */ /* preserve dolby if not supported */ - if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) { - job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBY; + if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) { + audio->config.out.mixdown = HB_AMIXDOWN_DOLBY; /* otherwise, preserve dolby even if we requested something higher */ /* a stereo mixdown will still be honoured here */ - } else if (job->audio_mixdowns[i] > HB_AMIXDOWN_DOLBY) { - job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBY; + } else if (audio->config.out.mixdown > HB_AMIXDOWN_DOLBY) { + audio->config.out.mixdown = HB_AMIXDOWN_DOLBY; } break; @@ -457,21 +444,21 @@ static void do_job( hb_job_t * job, int cpu_count ) case HB_INPUT_CH_LAYOUT_3F2R: /* if we've requested a mono mixdown, and it is supported, then do the mix */ /* use dpl2 if not supported */ - if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) { - job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBYPLII; + if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) { + audio->config.out.mixdown = HB_AMIXDOWN_DOLBYPLII; } else { /* check if we have 3F2R input and also have an LFE - i.e. we have a 5.1 source) */ - if (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE) { + if (audio->config.in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE) { /* we have a 5.1 source */ /* if we requested 6ch, but our audio format doesn't support it, then mix to DPLII instead */ - if (job->audio_mixdowns[i] == HB_AMIXDOWN_6CH && audioCodecsSupport6Ch == 0) { - job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBYPLII; + if (audio->config.out.mixdown == HB_AMIXDOWN_6CH && audioCodecsSupport6Ch == 0) { + audio->config.out.mixdown = HB_AMIXDOWN_DOLBYPLII; } } else { /* we have a 5.0 source, so we can't do 6ch conversion default to DPL II instead */ - if (job->audio_mixdowns[i] > HB_AMIXDOWN_DOLBYPLII) { - job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBYPLII; + if (audio->config.out.mixdown > HB_AMIXDOWN_DOLBYPLII) { + audio->config.out.mixdown = HB_AMIXDOWN_DOLBYPLII; } } } @@ -482,13 +469,13 @@ static void do_job( hb_job_t * job, int cpu_count ) case HB_INPUT_CH_LAYOUT_3F1R: /* if we've requested a mono mixdown, and it is supported, then do the mix */ /* use dpl1 if not supported */ - if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) { - job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBY; + if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 0) { + audio->config.out.mixdown = HB_AMIXDOWN_DOLBY; } else { /* we have a 4.0 or 4.1 source, so we can't do DPLII or 6ch conversion default to DPL I instead */ - if (job->audio_mixdowns[i] > HB_AMIXDOWN_DOLBY) { - job->audio_mixdowns[i] = HB_AMIXDOWN_DOLBY; + if (audio->config.out.mixdown > HB_AMIXDOWN_DOLBY) { + audio->config.out.mixdown = HB_AMIXDOWN_DOLBY; } } /* all other mixdowns will have been preserved here */ @@ -496,41 +483,37 @@ static void do_job( hb_job_t * job, int cpu_count ) default: /* if we've requested a mono mixdown, and it is supported, then do the mix */ - if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) { - job->audio_mixdowns[i] = HB_AMIXDOWN_MONO; + if (audio->config.out.mixdown == HB_AMIXDOWN_MONO && audioCodecsSupportMono == 1) { + audio->config.out.mixdown = HB_AMIXDOWN_MONO; /* mix everything else down to stereo */ } else { - job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO; + audio->config.out.mixdown = HB_AMIXDOWN_STEREO; } } - } /* log the output mixdown */ for (j = 0; j < hb_audio_mixdowns_count; j++) { - if (hb_audio_mixdowns[j].amixdown == job->audio_mixdowns[i]) { - hb_log( " + Actual mixdown: %s (%s)", hb_audio_mixdowns[j].human_readable_name, hb_audio_mixdowns[j].internal_name ); + if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) { + hb_log( " + Actual mixdown: %s (%s)", hb_audio_mixdowns[j].human_readable_name, hb_audio_mixdowns[j].internal_name ); break; } } - /* we now know we have a valid mixdown for the input source and the audio output format */ - /* remember the mixdown for this track */ - audio->amixdown = job->audio_mixdowns[i]; - - audio->config.vorbis.language = audio->lang_simple; + if (audio->config.out.codec == HB_ACODEC_VORBIS) + audio->priv.config.vorbis.language = audio->config.lang.simple; /* set up the audio work structures */ - audio->fifo_in = hb_fifo_init( 2048 ); - audio->fifo_raw = hb_fifo_init( FIFO_CPU_MULT * cpu_count ); - audio->fifo_sync = hb_fifo_init( FIFO_CPU_MULT * cpu_count ); - audio->fifo_out = hb_fifo_init( FIFO_CPU_MULT * cpu_count ); + audio->priv.fifo_in = hb_fifo_init( 2048 ); + audio->priv.fifo_raw = hb_fifo_init( FIFO_CPU_MULT * cpu_count ); + audio->priv.fifo_sync = hb_fifo_init( FIFO_CPU_MULT * cpu_count ); + audio->priv.fifo_out = hb_fifo_init( FIFO_CPU_MULT * cpu_count ); /* * Audio Decoder Thread */ - switch( audio->codec ) + switch( audio->config.in.codec ) { case HB_ACODEC_AC3: w = getWork( WORK_DECA52 ); @@ -544,12 +527,16 @@ static void do_job( hb_job_t * job, int cpu_count ) case HB_ACODEC_LPCM: w = getWork( WORK_DECLPCM ); break; + default: + /* Invalid input codec */ + hb_error("Invalid input codec: %d", audio->config.in.codec); + *job->die = 1; + goto cleanup; } - w->fifo_in = audio->fifo_in; - w->fifo_out = audio->fifo_raw; - w->config = &audio->config; - w->amixdown = audio->amixdown; - w->source_acodec = audio->codec; + w->fifo_in = audio->priv.fifo_in; + w->fifo_out = audio->priv.fifo_raw; + w->config = &audio->priv.config; + w->audio = audio; /* FIXME: This feels really hackish, anything better? */ audio_w = calloc( sizeof( hb_work_object_t ), 1 ); @@ -560,10 +547,8 @@ static void do_job( hb_job_t * job, int cpu_count ) /* * Audio Encoder Thread */ - if( job->audio_mixdowns[i] != HB_AMIXDOWN_AC3 ) + switch( audio->config.out.codec ) { - switch( job->acodec ) - { case HB_ACODEC_FAAC: w = getWork( WORK_ENCFAAC ); break; @@ -573,20 +558,25 @@ static void do_job( hb_job_t * job, int cpu_count ) case HB_ACODEC_VORBIS: w = getWork( WORK_ENCVORBIS ); break; - } + case HB_ACODEC_AC3: + break; + case HB_ACODEC_DCA: /* These are all invalid output codecs. */ + default: + hb_error("Invalid audio codec: %#x", audio->config.out.codec); + w = NULL; + *job->die = 1; + goto cleanup; } - if( job->acodec != HB_ACODEC_AC3 && - job->audio_mixdowns[i] != HB_AMIXDOWN_AC3) + if( audio->config.out.codec != HB_ACODEC_AC3 ) { /* * Add the encoder thread if not doing AC-3 pass through */ - w->fifo_in = audio->fifo_sync; - w->fifo_out = audio->fifo_out; - w->config = &audio->config; - w->amixdown = audio->amixdown; - w->source_acodec = audio->codec; + w->fifo_in = audio->priv.fifo_sync; + w->fifo_out = audio->priv.fifo_out; + w->config = &audio->priv.config; + w->audio = audio; /* FIXME: This feels really hackish, anything better? */ audio_w = calloc( sizeof( hb_work_object_t ), 1 ); @@ -640,12 +630,16 @@ static void do_job( hb_job_t * job, int cpu_count ) w->close( w ); job->done = 1; +cleanup: /* Close work objects */ while( ( w = hb_list_item( job->list_work, 0 ) ) ) { hb_list_rem( job->list_work, w ); - hb_thread_close( &w->thread ); - w->close( w ); + if( w != NULL && w->thread != NULL ) + { + hb_thread_close( &w->thread ); + w->close( w ); + } /* FIXME: This feels really hackish, anything better? */ if ( w->id == WORK_DECA52 || @@ -663,8 +657,10 @@ static void do_job( hb_job_t * job, int cpu_count ) hb_list_close( &job->list_work ); /* Stop read & write threads */ - hb_thread_close( &job->reader ); - hb_thread_close( &job->muxer ); + if( job->reader != NULL ) + hb_thread_close( &job->reader ); + if( job->muxer != NULL ) + hb_thread_close( &job->muxer ); /* Close fifos */ hb_fifo_close( &job->fifo_mpeg2 ); @@ -684,10 +680,14 @@ static void do_job( hb_job_t * job, int cpu_count ) for( i = 0; i < hb_list_count( title->list_audio ); i++ ) { audio = hb_list_item( title->list_audio, i ); - hb_fifo_close( &audio->fifo_in ); - hb_fifo_close( &audio->fifo_raw ); - hb_fifo_close( &audio->fifo_sync ); - hb_fifo_close( &audio->fifo_out ); + if( audio->priv.fifo_in != NULL ) + hb_fifo_close( &audio->priv.fifo_in ); + if( audio->priv.fifo_raw != NULL ) + hb_fifo_close( &audio->priv.fifo_raw ); + if( audio->priv.fifo_sync != NULL ) + hb_fifo_close( &audio->priv.fifo_sync ); + if( audio->priv.fifo_out != NULL ) + hb_fifo_close( &audio->priv.fifo_out ); } if( job->indepth_scan ) |