diff options
author | jstebbins <[email protected]> | 2010-10-04 23:16:57 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2010-10-04 23:16:57 +0000 |
commit | afffc15c0fec6680f6a612c729d184d92fbc809c (patch) | |
tree | 84266ecb82c48e371039feac8527f06573e57dc4 /libhb | |
parent | e10652943a245468659a3ed0dfed452ccd12ae0c (diff) |
Add ac3 encoding
Uses ffmpeg's ac3 encoder.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3570 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/common.c | 12 | ||||
-rw-r--r-- | libhb/common.h | 26 | ||||
-rw-r--r-- | libhb/deca52.c | 2 | ||||
-rw-r--r-- | libhb/decavcodec.c | 51 | ||||
-rw-r--r-- | libhb/decdca.c | 2 | ||||
-rw-r--r-- | libhb/encac3.c | 257 | ||||
-rw-r--r-- | libhb/hb.c | 2 | ||||
-rw-r--r-- | libhb/internal.h | 1 | ||||
-rw-r--r-- | libhb/muxmkv.c | 6 | ||||
-rw-r--r-- | libhb/muxmp4.c | 216 | ||||
-rw-r--r-- | libhb/sync.c | 16 | ||||
-rw-r--r-- | libhb/work.c | 44 |
12 files changed, 494 insertions, 141 deletions
diff --git a/libhb/common.c b/libhb/common.c index 35417cb6c..0c9ac629e 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -34,7 +34,7 @@ hb_rate_t hb_audio_bitrates[] = { "64", 64 }, { "80", 80 }, { "96", 96 }, { "112", 112 }, { "128", 128 }, { "160", 160 }, { "192", 192 }, { "224", 224 }, { "256", 256 }, { "320", 320 }, { "384", 384 }, { "448", 448 }, - { "768", 768 } }; + { "512", 512 }, { "576", 576 }, { "640", 640 }, { "768", 768 } }; int hb_audio_bitrates_count = sizeof( hb_audio_bitrates ) / sizeof( hb_rate_t ); int hb_audio_bitrates_default = 8; /* 128 kbps */ @@ -255,6 +255,8 @@ int hb_calc_bitrate( hb_job_t * job, int size ) case HB_ACODEC_LAME: samples_per_frame = 1152; break; + case HB_ACODEC_AC3_PASS: + case HB_ACODEC_DCA_PASS: case HB_ACODEC_AC3: case HB_ACODEC_DCA: samples_per_frame = 1536; @@ -263,8 +265,8 @@ int hb_calc_bitrate( hb_job_t * job, int size ) return 0; } - if( audio->config.out.codec == HB_ACODEC_AC3 || - audio->config.out.codec == HB_ACODEC_DCA) + if( audio->config.out.codec == HB_ACODEC_AC3_PASS || + audio->config.out.codec == HB_ACODEC_DCA_PASS) { /* * For pass through we take the bitrate from the input audio @@ -904,7 +906,8 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg) */ audio->config.out.track = hb_list_count(job->list_audio) + 1; audio->config.out.codec = audiocfg->out.codec; - if( audiocfg->out.codec == audio->config.in.codec ) + if( (audiocfg->out.codec & HB_ACODEC_MASK) == audio->config.in.codec && + (audiocfg->out.codec & HB_ACODEC_PASS_FLAG ) ) { /* Pass-through, copy from input. */ audio->config.out.samplerate = audio->config.in.samplerate; @@ -915,6 +918,7 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg) else { /* Non pass-through, use what is given. */ + audio->config.out.codec &= ~HB_ACODEC_PASS_FLAG; audio->config.out.samplerate = audiocfg->out.samplerate; audio->config.out.bitrate = audiocfg->out.bitrate; audio->config.out.dynamic_range_compression = audiocfg->out.dynamic_range_compression; diff --git a/libhb/common.h b/libhb/common.h index bba48350c..fcb4d4d04 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -307,16 +307,21 @@ struct hb_job_s /* 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 -#define HB_ACODEC_FFMPEG 0x008000 -#define HB_ACODEC_CA_AAC 0x010000 +#define HB_ACODEC_MASK 0x000FFF00 +#define HB_ACODEC_FAAC 0x00000100 +#define HB_ACODEC_LAME 0x00000200 +#define HB_ACODEC_VORBIS 0x00000400 +#define HB_ACODEC_AC3 0x00000800 +#define HB_ACODEC_MPGA 0x00001000 +#define HB_ACODEC_LPCM 0x00002000 +#define HB_ACODEC_DCA 0x00004000 +#define HB_ACODEC_FFMPEG 0x00008000 +#define HB_ACODEC_CA_AAC 0x00010000 +#define HB_ACODEC_PASS_FLAG 0x40000000 +#define HB_ACODEC_PASS_MASK (HB_ACODEC_AC3 | HB_ACODEC_DCA) +#define HB_ACODEC_AC3_PASS (HB_ACODEC_AC3 | HB_ACODEC_PASS_FLAG) +#define HB_ACODEC_DCA_PASS (HB_ACODEC_DCA | HB_ACODEC_PASS_FLAG) +#define HB_ACODEC_ANY (HB_ACODEC_MASK | HB_ACODEC_PASS_FLAG) /* Audio Mixdown */ /* define some masks, used to extract the various information from the HB_AMIXDOWN_XXXX values */ @@ -771,6 +776,7 @@ extern hb_work_object_t hb_enclame; extern hb_work_object_t hb_encvorbis; extern hb_work_object_t hb_muxer; extern hb_work_object_t hb_encca_aac; +extern hb_work_object_t hb_encac3; #define FILTER_OK 0 #define FILTER_DELAY 1 diff --git a/libhb/deca52.c b/libhb/deca52.c index 785bf6aef..0958a9139 100644 --- a/libhb/deca52.c +++ b/libhb/deca52.c @@ -259,7 +259,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) double frame_dur = (6. * 256. * 90000.) / pv->rate; /* AC3 passthrough: don't decode the AC3 frame */ - if( audio->config.out.codec == HB_ACODEC_AC3 ) + if( audio->config.out.codec == HB_ACODEC_AC3_PASS ) { buf = hb_buffer_init( size ); memcpy( buf->data, pv->frame, size ); diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index abf7ed179..bbdd4d668 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -111,6 +111,7 @@ struct hb_work_private_s struct SwsContext *sws_context; // if we have to rescale or convert color space hb_downmix_t *downmix; hb_sample_t *downmix_buffer; + hb_chan_map_t *out_map; }; static void decodeAudio( hb_audio_t * audio, hb_work_private_t *pv, uint8_t *data, int size ); @@ -203,13 +204,25 @@ static int decavcodecInit( hb_work_object_t * w, hb_job_t * job ) pv->context = avcodec_alloc_context(); hb_avcodec_open( pv->context, codec ); - if ( w->audio != NULL && - hb_need_downmix( w->audio->config.in.channel_layout, - w->audio->config.out.mixdown) ) + if ( w->audio != NULL ) { - pv->downmix = hb_downmix_init(w->audio->config.in.channel_layout, - w->audio->config.out.mixdown); - hb_downmix_set_chan_map( pv->downmix, &hb_smpte_chan_map, &hb_qt_chan_map ); + if ( w->audio->config.out.codec == HB_ACODEC_AC3 ) + { + // ffmpegs audio encoder expect an smpte chan map as input. + // So we need to map the decoders output to smpte. + pv->out_map = &hb_smpte_chan_map; + } + else + { + pv->out_map = &hb_qt_chan_map; + } + if ( hb_need_downmix( w->audio->config.in.channel_layout, + w->audio->config.out.mixdown) ) + { + pv->downmix = hb_downmix_init(w->audio->config.in.channel_layout, + w->audio->config.out.mixdown); + hb_downmix_set_chan_map( pv->downmix, &hb_smpte_chan_map, pv->out_map ); + } } return 0; @@ -1129,13 +1142,25 @@ static int decavcodecviInit( hb_work_object_t * w, hb_job_t * job ) pv->pts_next = -1; pv->pts = -1; - if ( w->audio != NULL && - hb_need_downmix( w->audio->config.in.channel_layout, - w->audio->config.out.mixdown) ) + if ( w->audio != NULL ) { - pv->downmix = hb_downmix_init(w->audio->config.in.channel_layout, - w->audio->config.out.mixdown); - hb_downmix_set_chan_map( pv->downmix, &hb_smpte_chan_map, &hb_qt_chan_map ); + if ( w->audio->config.out.codec == HB_ACODEC_AC3 ) + { + // ffmpegs audio encoder expect an smpte chan map as input. + // So we need to map the decoders output to smpte. + pv->out_map = &hb_smpte_chan_map; + } + else + { + pv->out_map = &hb_qt_chan_map; + } + if ( hb_need_downmix( w->audio->config.in.channel_layout, + w->audio->config.out.mixdown) ) + { + pv->downmix = hb_downmix_init(w->audio->config.in.channel_layout, + w->audio->config.out.mixdown); + hb_downmix_set_chan_map( pv->downmix, &hb_smpte_chan_map, pv->out_map ); + } } return 0; @@ -1308,7 +1333,7 @@ static void decodeAudio( hb_audio_t * audio, hb_work_private_t *pv, uint8_t *dat fl32[i] = buffer[i]; } int n_ch_samples = nsamples / context->channels; - hb_layout_remap( &hb_smpte_chan_map, &hb_qt_chan_map, + hb_layout_remap( &hb_smpte_chan_map, pv->out_map, audio->config.in.channel_layout, fl32, n_ch_samples ); } diff --git a/libhb/decdca.c b/libhb/decdca.c index 89c2b1c17..ea4cb560c 100644 --- a/libhb/decdca.c +++ b/libhb/decdca.c @@ -231,7 +231,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) double frame_dur = (double)(pv->frame_length & ~0xFF) / (double)pv->rate * 90000.; /* DCA passthrough: don't decode the DCA frame */ - if( audio->config.out.codec == HB_ACODEC_DCA ) + if( audio->config.out.codec == HB_ACODEC_DCA_PASS ) { buf = hb_buffer_init( pv->size ); memcpy( buf->data, pv->frame, pv->size ); diff --git a/libhb/encac3.c b/libhb/encac3.c new file mode 100644 index 000000000..5c45b9800 --- /dev/null +++ b/libhb/encac3.c @@ -0,0 +1,257 @@ +/* $Id: encac3.c,v 1.23 2005/10/13 23:47:06 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.fr/>. + It may be used under the terms of the GNU General Public License. */ + +#include "hb.h" +#include "hbffmpeg.h" +#include "downmix.h" + +struct hb_work_private_s +{ + hb_job_t * job; + AVCodecContext * context; + + int out_discrete_channels; + unsigned long input_samples; + unsigned long output_bytes; + hb_list_t * list; + uint8_t * buf; + int16_t * samples; +}; + +int encac3Init( hb_work_object_t *, hb_job_t * ); +int encac3Work( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** ); +void encac3Close( hb_work_object_t * ); + +#define AC3_SAMPLES_PER_FRAME 1536 +#define AC3_MAX_CODED_FRAME_SIZE 3840 + +hb_work_object_t hb_encac3 = +{ + WORK_ENCAC3, + "AC-3 encoder (libavcodec)", + encac3Init, + encac3Work, + encac3Close +}; + +int encac3Init( hb_work_object_t * w, hb_job_t * job ) +{ + AVCodec * codec; + AVCodecContext * context; + hb_audio_t * audio = w->audio; + + hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) ); + w->private_data = pv; + + pv->job = job; + + pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown); + pv->input_samples = AC3_SAMPLES_PER_FRAME * pv->out_discrete_channels; + pv->output_bytes = AC3_MAX_CODED_FRAME_SIZE; + + pv->buf = malloc( pv->input_samples * sizeof( float ) ); + pv->samples = malloc( pv->input_samples * sizeof( int16_t ) ); + + codec = avcodec_find_encoder( CODEC_ID_AC3 ); + if( !codec ) + { + hb_log( "encac3Init: avcodec_find_encoder " + "failed" ); + } + context = avcodec_alloc_context(); + + context->channel_layout = CH_LAYOUT_STEREO; + switch( audio->config.out.mixdown ) + { + case HB_AMIXDOWN_MONO: + context->channel_layout = CH_LAYOUT_MONO; + break; + + case HB_AMIXDOWN_STEREO: + case HB_AMIXDOWN_DOLBY: + case HB_AMIXDOWN_DOLBYPLII: + context->channel_layout = CH_LAYOUT_STEREO; + break; + + case HB_AMIXDOWN_6CH: + context->channel_layout = CH_LAYOUT_5POINT0|CH_LOW_FREQUENCY; + break; + + default: + hb_log(" encac3Init: bad mixdown" ); + break; + } + + context->bit_rate = audio->config.out.bitrate * 1000; + context->sample_rate = audio->config.out.samplerate; + context->channels = pv->out_discrete_channels; + + if( hb_avcodec_open( context, codec ) ) + { + hb_log( "encac3Init: avcodec_open failed" ); + } + pv->context = context; + + pv->list = hb_list_init(); + + return 0; +} + +/*********************************************************************** + * Close + *********************************************************************** + * + **********************************************************************/ +void encac3Close( hb_work_object_t * w ) +{ + hb_work_private_t * pv = w->private_data; + + if ( pv ) + { + if( pv->context ) + { + hb_deep_log( 2, "encac3: closing libavcodec" ); + if ( pv->context->codec ) + avcodec_flush_buffers( pv->context ); + hb_avcodec_close( pv->context ); + } + + if ( pv->buf ) + { + free( pv->buf ); + pv->buf = NULL; + } + + if ( pv->samples ) + { + free( pv->samples ); + pv->samples = NULL; + } + + if ( pv->list ) + hb_list_empty( &pv->list ); + + free( pv ); + w->private_data = NULL; + } +} + +static hb_buffer_t * Encode( hb_work_object_t * w ) +{ + hb_work_private_t * pv = w->private_data; + uint64_t pts, pos; + hb_audio_t * audio = w->audio; + hb_buffer_t * buf; + int ii; + + if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) ) + { + return NULL; + } + + hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ), + &pts, &pos); + + hb_chan_map_t *map = NULL; + if ( audio->config.in.codec == HB_ACODEC_AC3 ) + { + map = &hb_ac3_chan_map; + } + else if ( audio->config.in.codec == HB_ACODEC_DCA ) + { + map = &hb_qt_chan_map; + } + if ( map ) + { + int layout; + switch (audio->config.out.mixdown) + { + case HB_AMIXDOWN_MONO: + layout = HB_INPUT_CH_LAYOUT_MONO; + break; + case HB_AMIXDOWN_STEREO: + case HB_AMIXDOWN_DOLBY: + case HB_AMIXDOWN_DOLBYPLII: + layout = HB_INPUT_CH_LAYOUT_STEREO; + break; + case HB_AMIXDOWN_6CH: + default: + layout = HB_INPUT_CH_LAYOUT_3F2R | HB_INPUT_CH_LAYOUT_HAS_LFE; + break; + } + hb_layout_remap( map, &hb_smpte_chan_map, layout, + (float*)pv->buf, AC3_SAMPLES_PER_FRAME); + } + + for (ii = 0; ii < pv->input_samples; ii++) + { + pv->samples[ii] = (int16_t)((float*)pv->buf)[ii]; + } + + buf = hb_buffer_init( pv->output_bytes ); + buf->size = avcodec_encode_audio( pv->context, buf->data, buf->alloc, + pv->samples ); + + buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate; + buf->stop = buf->start + 90000 * AC3_SAMPLES_PER_FRAME / audio->config.out.samplerate; + + buf->frametype = HB_FRAME_AUDIO; + + if ( !buf->size ) + { + hb_buffer_close( &buf ); + return Encode( w ); + } + else if (buf->size < 0) + { + hb_log( "encac3: avcodec_encode_audio failed" ); + hb_buffer_close( &buf ); + return NULL; + } + + return buf; +} + +/*********************************************************************** + * Work + *********************************************************************** + * + **********************************************************************/ +int encac3Work( hb_work_object_t * w, hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out ) +{ + hb_work_private_t * pv = w->private_data; + hb_buffer_t * in = *buf_in, * buf; + + if ( in->size <= 0 ) + { + /* EOF on input - send it downstream & say we're done */ + *buf_out = in; + *buf_in = NULL; + return HB_WORK_DONE; + } + + if ( pv->context == NULL || pv->context->codec == NULL ) + { + // No encoder context. Nothing we can do. + return HB_WORK_OK; + } + + hb_list_add( pv->list, in ); + *buf_in = NULL; + + *buf_out = buf = Encode( w ); + + while ( buf ) + { + buf->next = Encode( w ); + buf = buf->next; + } + + return HB_WORK_OK; +} + + diff --git a/libhb/hb.c b/libhb/hb.c index fcb4a55df..f7489c162 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -346,6 +346,7 @@ hb_handle_t * hb_init( int verbose, int update_check ) #ifdef __APPLE__ hb_register( &hb_encca_aac ); #endif + hb_register( &hb_encac3 ); return h; } @@ -450,6 +451,7 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) #ifdef __APPLE__ hb_register( &hb_encca_aac ); #endif + hb_register( &hb_encac3 ); return h; } diff --git a/libhb/internal.h b/libhb/internal.h index 30bf022d5..b6fbd1ddb 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -355,6 +355,7 @@ enum WORK_ENCLAME, WORK_ENCVORBIS, WORK_ENC_CA_AAC, + WORK_ENCAC3, WORK_MUX }; diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c index aa320e9aa..073b39f45 100644 --- a/libhb/muxmkv.c +++ b/libhb/muxmkv.c @@ -167,11 +167,13 @@ static int MKVInit( hb_mux_object_t * m ) switch (audio->config.out.codec) { case HB_ACODEC_DCA: + case HB_ACODEC_DCA_PASS: track->codecPrivate = NULL; track->codecPrivateSize = 0; track->codecID = MK_ACODEC_DTS; break; case HB_ACODEC_AC3: + case HB_ACODEC_AC3_PASS: track->codecPrivate = NULL; track->codecPrivateSize = 0; track->codecID = MK_ACODEC_AC3; @@ -228,8 +230,8 @@ static int MKVInit( hb_mux_object_t * m ) track->trackType = MK_TRACK_AUDIO; track->language = audio->config.lang.iso639_2; track->extra.audio.samplingFreq = (float)audio->config.out.samplerate; - if (audio->config.out.codec == HB_ACODEC_AC3 || - audio->config.out.codec == HB_ACODEC_DCA) + if (audio->config.out.codec == HB_ACODEC_AC3_PASS || + audio->config.out.codec == HB_ACODEC_DCA_PASS) { track->extra.audio.channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout); } diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index bc523f836..5225ea523 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -63,6 +63,14 @@ static int MP4TuneTrackDurationPerChunk( hb_mux_object_t* m, MP4TrackId trackId return 1; } +static const uint16_t ac3_sample_rate_tab[3] = { 48000, 44100, 32000 }; +/* possible bitrates */ +static const uint16_t ac3_bitrate_tab[19] = { + 32, 40, 48, 56, 64, 80, 96, 112, 128, + 160, 192, 224, 256, 320, 384, 448, 512, 576, 640 +}; + + /********************************************************************** * MP4Init ********************************************************************** @@ -225,106 +233,142 @@ static int MP4Init( hb_mux_object_t * m ) mux_data = calloc(1, sizeof( hb_mux_data_t ) ); audio->priv.mux_data = mux_data; - if( audio->config.out.codec == HB_ACODEC_AC3 ) + if( audio->config.out.codec == HB_ACODEC_AC3_PASS ) { - uint8_t fscod = 0; uint8_t bsid = audio->config.in.version; uint8_t bsmod = audio->config.in.mode; uint8_t acmod = audio->config.flags.ac3 & 0x7; uint8_t lfeon = (audio->config.flags.ac3 & A52_LFE) ? 1 : 0; uint8_t bit_rate_code = 0; + int ii, jj; + int freq = audio->config.in.samplerate; + int bitrate = audio->config.in.bitrate; + int sr_shift, sr_code; - /* - * Rewrite AC3 information into correct format for dac3 atom - */ - switch( audio->config.in.samplerate ) + for (ii = 0; ii < 3; ii++) { - case 48000: - fscod = 0; - break; - case 44100: - fscod = 1; - break; - case 32000: - fscod = 2; - break; - default: - /* - * Error value, tells decoder to not decode this audio. - */ - fscod = 3; - break; + for (jj = 0; jj < 3; jj++) + { + if ((ac3_sample_rate_tab[jj] >> ii) == freq) + { + break; + } + } } + if ( ii >= 3 ) + { + hb_error("Unknown AC3 samplerate"); + ii = jj = 0; + } + sr_shift = ii; + sr_code = jj; + for (ii = 0; ii < 19; ii++) + { + if ((ac3_bitrate_tab[ii] >> sr_shift)*1000 == bitrate) + break; + } + if ( ii >= 19 ) + { + hb_error("Unknown AC3 bitrate"); + ii = 0; + } + bit_rate_code = ii; + + mux_data->track = MP4AddAC3AudioTrack( + m->file, + audio->config.in.samplerate, + sr_code, + bsid, + bsmod, + acmod, + lfeon, + bit_rate_code); + + /* Tune track chunk duration */ + MP4TuneTrackDurationPerChunk( m, mux_data->track ); - switch( audio->config.in.bitrate ) + if (audio->config.out.name == NULL) { + MP4SetTrackBytesProperty( + m->file, mux_data->track, + "udta.name.value", + (const uint8_t*)"Surround", strlen("Surround")); + } + else { + MP4SetTrackBytesProperty( + m->file, mux_data->track, + "udta.name.value", + (const uint8_t*)(audio->config.out.name), + strlen(audio->config.out.name)); + } + } + else if( audio->config.out.codec == HB_ACODEC_AC3 ) + { + uint8_t bsid = 8; + uint8_t bsmod = 0; + uint8_t acmod = 2; + uint8_t lfeon = 0; + uint8_t bit_rate_code = 0; + int ii, jj; + int freq = audio->config.out.samplerate; + int bitrate = audio->config.out.bitrate; + int sr_shift, sr_code; + + for (ii = 0; ii < 3; ii++) + { + for (jj = 0; jj < 3; jj++) + { + if ((ac3_sample_rate_tab[jj] >> ii) == freq) + { + break; + } + } + } + if ( ii >= 3 ) + { + hb_error("Unknown AC3 samplerate"); + ii = jj = 0; + } + sr_shift = ii; + sr_code = jj; + bsid = 8 + ii; + for (ii = 0; ii < 19; ii++) + { + if ((ac3_bitrate_tab[ii] >> sr_shift)*1000 == bitrate) + break; + } + if ( ii >= 19 ) { - case 32000: - bit_rate_code = 0; - break; - case 40000: - bit_rate_code = 1; - break; - case 48000: - bit_rate_code = 2; - break; - case 56000: - bit_rate_code = 3; - break; - case 64000: - bit_rate_code = 4; - break; - case 80000: - bit_rate_code = 5; - break; - case 96000: - bit_rate_code = 6; - break; - case 112000: - bit_rate_code = 7; - break; - case 128000: - bit_rate_code = 8; - break; - case 160000: - bit_rate_code = 9; - break; - case 192000: - bit_rate_code = 10; - break; - case 224000: - bit_rate_code = 11; - break; - case 256000: - bit_rate_code = 12; - break; - case 320000: - bit_rate_code = 13; - break; - case 384000: - bit_rate_code = 14; - break; - case 448000: - bit_rate_code = 15; - break; - case 512000: - bit_rate_code = 16; - break; - case 576000: - bit_rate_code = 17; - break; - case 640000: - bit_rate_code = 18; - break; - default: hb_error("Unknown AC3 bitrate"); - bit_rate_code = 0; - break; + ii = 0; + } + bit_rate_code = ii; + + switch( audio->config.out.mixdown ) + { + case HB_AMIXDOWN_MONO: + acmod = 1; + break; + + case HB_AMIXDOWN_STEREO: + case HB_AMIXDOWN_DOLBY: + case HB_AMIXDOWN_DOLBYPLII: + acmod = 2; + break; + + case HB_AMIXDOWN_6CH: + acmod = 7; + lfeon = 1; + break; + + default: + hb_log(" MP4Init: bad mixdown" ); + break; } mux_data->track = MP4AddAC3AudioTrack( m->file, audio->config.out.samplerate, - fscod, + sr_code, bsid, bsmod, acmod, @@ -347,8 +391,10 @@ static int MP4Init( hb_mux_object_t * m ) (const uint8_t*)(audio->config.out.name), strlen(audio->config.out.name)); } - } else if( audio->config.out.codec == HB_ACODEC_FAAC || - audio->config.out.codec == HB_ACODEC_CA_AAC ) { + } + else if( audio->config.out.codec == HB_ACODEC_FAAC || + audio->config.out.codec == HB_ACODEC_CA_AAC ) + { mux_data->track = MP4AddAudioTrack( m->file, audio->config.out.samplerate, 1024, MP4_MPEG4_AUDIO_TYPE ); diff --git a/libhb/sync.c b/libhb/sync.c index 58628f316..acc782e4a 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -898,7 +898,7 @@ void syncAudioClose( hb_work_object_t * w ) hb_work_private_t * pv = w->private_data; hb_sync_audio_t * sync = &pv->type.audio; - if( w->audio->config.out.codec == HB_ACODEC_AC3 ) + if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS ) { free( sync->ac3_buf ); } @@ -1073,7 +1073,7 @@ static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in, * Or in the case of DCA, skip some frames from the * other streams. */ - if( w->audio->config.out.codec == HB_ACODEC_DCA ) + if( w->audio->config.out.codec == HB_ACODEC_DCA_PASS ) { hb_log( "sync: audio gap %d ms. Skipping frames. Audio %d" " start %"PRId64", next %"PRId64, @@ -1131,8 +1131,8 @@ static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i ) w->audio = hb_list_item( title->list_audio, i ); w->fifo_in = w->audio->priv.fifo_raw; - if( w->audio->config.out.codec == HB_ACODEC_AC3 || - w->audio->config.out.codec == HB_ACODEC_DCA ) + if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS || + w->audio->config.out.codec == HB_ACODEC_DCA_PASS ) { w->fifo_out = w->audio->priv.fifo_out; } @@ -1141,7 +1141,7 @@ static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i ) w->fifo_out = w->audio->priv.fifo_sync; } - if( w->audio->config.out.codec == HB_ACODEC_AC3 ) + if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS ) { /* Have a silent AC-3 frame ready in case we have to fill a gap */ @@ -1199,8 +1199,8 @@ static hb_buffer_t * OutputAudioFrame( hb_audio_t *audio, hb_buffer_t *buf, sync->next_pts += duration; if( audio->config.in.samplerate == audio->config.out.samplerate || - audio->config.out.codec == HB_ACODEC_AC3 || - audio->config.out.codec == HB_ACODEC_DCA ) + audio->config.out.codec == HB_ACODEC_AC3_PASS || + audio->config.out.codec == HB_ACODEC_DCA_PASS ) { /* * If we don't have to do sample rate conversion or this audio is @@ -1271,7 +1271,7 @@ static void InsertSilence( hb_work_object_t * w, int64_t duration ) while ( --frame_count >= 0 ) { - if( w->audio->config.out.codec == HB_ACODEC_AC3 ) + if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS ) { buf = hb_buffer_init( sync->ac3_size ); buf->start = sync->next_pts; diff --git a/libhb/work.c b/libhb/work.c index 3c3346d19..b7dda2736 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -128,7 +128,8 @@ hb_work_object_t * hb_codec_encoder( int codec ) case HB_ACODEC_FAAC: return hb_get_work( WORK_ENCFAAC ); case HB_ACODEC_LAME: return hb_get_work( WORK_ENCLAME ); case HB_ACODEC_VORBIS: return hb_get_work( WORK_ENCVORBIS ); - case HB_ACODEC_CA_AAC: return hb_get_work( WORK_ENC_CA_AAC ); + case HB_ACODEC_CA_AAC: return hb_get_work( WORK_ENC_CA_AAC ); + case HB_ACODEC_AC3: return hb_get_work( WORK_ENCAC3 ); } return NULL; } @@ -344,7 +345,7 @@ 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_AC3) && (audio->config.out.codec != HB_ACODEC_DCA) ) + if( (audio->config.out.codec != HB_ACODEC_AC3_PASS) && (audio->config.out.codec != HB_ACODEC_DCA_PASS) ) { for (j = 0; j < hb_audio_mixdowns_count; j++) { @@ -355,22 +356,24 @@ void hb_display_job_info( hb_job_t * job ) } } - if ( audio->config.out.dynamic_range_compression && (audio->config.out.codec != HB_ACODEC_AC3) && (audio->config.out.codec != HB_ACODEC_DCA)) + if ( audio->config.out.dynamic_range_compression && (audio->config.out.codec != HB_ACODEC_AC3_PASS) && (audio->config.out.codec != HB_ACODEC_DCA_PASS)) { hb_log(" + dynamic range compression: %f", audio->config.out.dynamic_range_compression); } - if( (audio->config.out.codec == HB_ACODEC_AC3) || (audio->config.out.codec == HB_ACODEC_DCA) ) + if( (audio->config.out.codec == HB_ACODEC_AC3_PASS) || (audio->config.out.codec == HB_ACODEC_DCA_PASS) ) { - hb_log( " + %s passthrough", (audio->config.out.codec == HB_ACODEC_AC3) ? + hb_log( " + %s passthrough", (audio->config.out.codec == HB_ACODEC_AC3_PASS) ? "AC3" : "DCA" ); } 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" : "vorbis" ) ) ); + 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_AC3 ) ? "ffac3" : + "vorbis" ) ) ) ); hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate ); } } @@ -513,8 +516,8 @@ static void do_job( hb_job_t * job, int cpu_count ) 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_AC3 ) && ( audio->config.in.codec != HB_ACODEC_AC3 ) ) || - ( ( audio->config.out.codec == HB_ACODEC_DCA ) && ( audio->config.in.codec != HB_ACODEC_DCA ) ) ) + if( ( ( audio->config.out.codec == HB_ACODEC_AC3_PASS ) && ( audio->config.in.codec != HB_ACODEC_AC3 ) ) || + ( ( audio->config.out.codec == HB_ACODEC_DCA_PASS ) && ( 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 ); @@ -522,14 +525,21 @@ static void do_job( hb_job_t * job, int cpu_count ) free( audio ); continue; } - if( audio->config.out.codec != HB_ACODEC_AC3 && - audio->config.out.codec != HB_ACODEC_DCA && + if( audio->config.out.codec != HB_ACODEC_AC3_PASS && + audio->config.out.codec != HB_ACODEC_DCA_PASS && audio->config.out.samplerate > 48000 ) { hb_log( "Sample rate %d not supported. Down-sampling to 48kHz.", audio->config.out.samplerate ); audio->config.out.samplerate = 48000; } + if( audio->config.out.codec == HB_ACODEC_AC3 && + audio->config.out.bitrate > 640 ) + { + hb_log( "Bitrate %d not supported. Reducing to 640Kbps.", + audio->config.out.bitrate ); + audio->config.out.bitrate = 640; + } if ( audio->config.in.codec == HB_ACODEC_FFMPEG ) { if ( aud_id_uses[audio->id] ) @@ -570,8 +580,8 @@ static void do_job( hb_job_t * job, int cpu_count ) /* sense-check the requested mixdown */ if( audio->config.out.mixdown == 0 && - audio->config.out.codec != HB_ACODEC_AC3 && - audio->config.out.codec != HB_ACODEC_DCA ) + audio->config.out.codec != HB_ACODEC_AC3_PASS && + audio->config.out.codec != HB_ACODEC_DCA_PASS ) { /* * Mixdown wasn't specified and this is not pass-through, @@ -863,8 +873,8 @@ static void do_job( hb_job_t * job, int cpu_count ) /* * Audio Encoder Thread */ - if( audio->config.out.codec != HB_ACODEC_AC3 && - audio->config.out.codec != HB_ACODEC_DCA ) + if( audio->config.out.codec != HB_ACODEC_AC3_PASS && + audio->config.out.codec != HB_ACODEC_DCA_PASS ) { /* * Add the encoder thread if not doing AC-3 pass through |