diff options
author | Rodeo <[email protected]> | 2012-05-27 13:38:41 +0000 |
---|---|---|
committer | Rodeo <[email protected]> | 2012-05-27 13:38:41 +0000 |
commit | f2ffde5fff6540a84bca511a67ad7468c25aab81 (patch) | |
tree | 1026ba45c33da4d752b50fa9a11d4eff4269e46a | |
parent | c906e05b28bae440471dd2a816627b9852eed3e8 (diff) |
decdca: attempt to fix Dolby Surround and Pro Logic II mixdown. We were doing it wrong in some cases.
This means Dolby Pro Logic II is now only available for sources with at least L, R, C, Ls, Rs channels (as well as any additional channels), due to some libdca limitations. This will eventually go away when we use our own downmixing for all sources.
Further cleanup to follow.
Also cleans up usage of audio->config.in.flags (was audio->config.flags.*).
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4705 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r-- | libhb/common.c | 62 | ||||
-rw-r--r-- | libhb/common.h | 83 | ||||
-rw-r--r-- | libhb/deca52.c | 7 | ||||
-rw-r--r-- | libhb/decdca.c | 72 | ||||
-rw-r--r-- | libhb/muxmp4.c | 4 | ||||
-rw-r--r-- | libhb/scan.c | 4 | ||||
-rw-r--r-- | libhb/stream.c | 6 |
7 files changed, 139 insertions, 99 deletions
diff --git a/libhb/common.c b/libhb/common.c index 23c6ea21e..0bc48a842 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -705,41 +705,33 @@ int hb_get_best_mixdown( uint32_t codec, int layout, int mixdown ) } switch (layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK) { - // stereo input or something not handled below - default: - case HB_INPUT_CH_LAYOUT_STEREO: - // mono gets mixed up to stereo & more than stereo gets mixed down - best_mixdown = HB_AMIXDOWN_STEREO; - break; - // mono input case HB_INPUT_CH_LAYOUT_MONO: - // everything else passes through best_mixdown = HB_AMIXDOWN_MONO; break; - // dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input - // the A52 flags don't allow for a way to distinguish between DPL1 and + // Dolby Pro Logic (a.k.a. Dolby Surround), 4.0 channels (matrix-encoded) + // The A52 flags don't allow for a way to distinguish between DPL1 and // DPL2 on a DVD so we always assume a DPL1 source for A52_DOLBY. case HB_INPUT_CH_LAYOUT_DOLBY: - best_mixdown = HB_AMIXDOWN_DOLBY; - break; - - // 4 channel discrete + // 3 or 4 discrete channels + // case HB_INPUT_CH_LAYOUT_3F: // FIXME: can it be downmixed to Dolby? + // case HB_INPUT_CH_LAYOUT_2F1R: // FIXME: can it be downmixed to Dolby? case HB_INPUT_CH_LAYOUT_2F2R: case HB_INPUT_CH_LAYOUT_3F1R: // a52dec and libdca can't upmix to 6ch, // so we must downmix these. - best_mixdown = HB_AMIXDOWN_DOLBYPLII; + // libdca only supports DPLII if the source is 3F2R to begin with + best_mixdown = HB_AMIXDOWN_DOLBY; break; - // 5, 6, 7, or 8 channel discrete + // 5 to 8 discrete channels case HB_INPUT_CH_LAYOUT_4F2R: case HB_INPUT_CH_LAYOUT_3F4R: case HB_INPUT_CH_LAYOUT_3F2R: - if ( ! ( layout & HB_INPUT_CH_LAYOUT_HAS_LFE ) ) + if (!(layout & HB_INPUT_CH_LAYOUT_HAS_LFE)) { - // we don't do 5 channel discrete so mixdown to DPLII + // we don't do 5-channel discrete // a52dec and libdca can't upmix to 6ch, // so we must downmix this. best_mixdown = HB_AMIXDOWN_DOLBYPLII; @@ -759,6 +751,12 @@ int hb_get_best_mixdown( uint32_t codec, int layout, int mixdown ) } } break; + + // stereo input or something not handled above + default: + // mono gets mixed up to stereo & more than stereo gets mixed down + best_mixdown = HB_AMIXDOWN_STEREO; + break; } // return the best that is not greater than the requested mixdown // 0 means the caller requested the best available mixdown @@ -1608,30 +1606,36 @@ hb_audio_t *hb_audio_copy(const hb_audio_t *src) *********************************************************************/ void hb_audio_config_init(hb_audio_config_t * audiocfg) { - /* 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->in.channel_map = NULL; + /* Set read-only paramaters to invalid values */ + audiocfg->in.codec = 0; + audiocfg->in.codec_param = 0; + audiocfg->in.reg_desc = 0; + audiocfg->in.stream_type = 0; + audiocfg->in.substream_type = 0; audiocfg->in.version = 0; + audiocfg->in.flags = 0; audiocfg->in.mode = 0; - audiocfg->flags.ac3 = 0; + audiocfg->in.samplerate = -1; + audiocfg->in.samples_per_frame = -1; + audiocfg->in.bitrate = -1; + audiocfg->in.channel_layout = -1; + audiocfg->in.channel_map = NULL; audiocfg->lang.description[0] = 0; audiocfg->lang.simple[0] = 0; audiocfg->lang.iso639_2[0] = 0; - /* Initalize some sensable defaults */ + /* Initalize some sensible defaults */ audiocfg->in.track = audiocfg->out.track = 0; - audiocfg->out.codec = HB_ACODEC_FAAC; + audiocfg->out.codec = hb_audio_encoders[0].encoder; + audiocfg->out.samplerate = -1; + audiocfg->out.samples_per_frame = -1; audiocfg->out.bitrate = -1; audiocfg->out.quality = HB_INVALID_AUDIO_QUALITY; audiocfg->out.compression_level = -1; - audiocfg->out.samplerate = -1; audiocfg->out.mixdown = -1; audiocfg->out.dynamic_range_compression = 0; + audiocfg->out.gain = 0; audiocfg->out.name = NULL; - } /********************************************************************** diff --git a/libhb/common.h b/libhb/common.h index ab1a0c169..ac486b4a5 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -433,12 +433,12 @@ struct hb_job_s // 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 +#define HB_AMIXDOWN_DOLBY 0x040000A2 +// DCA_FORMAT handled directly in decdca.c // 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 +#define HB_AMIXDOWN_DOLBYPLII 0x080004A2 +// DCA_FORMAT handled directly in decdca.c // A52_FORMAT of A52_DOLBY | A52_USE_DPLII = 74 = 0x4A // discrete channel count of 2 #define HB_AMIXDOWN_6CH 0x10089176 @@ -486,55 +486,44 @@ 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 samples_per_frame; /* Number of samples per frame */ - int bitrate; /* Output bitrate (kbps) */ - float quality; /* Output quality */ - float compression_level; /* Output compression level */ - 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 */ - double gain; /* Gain in dB. negative is quieter */ - char * name; /* Output track name */ + int track; /* Output track number */ + uint32_t codec; /* Output audio codec */ + int samplerate; /* Output sample rate (Hz) */ + int samples_per_frame; /* Number of samples per frame */ + int bitrate; /* Output bitrate (Kbps) */ + float quality; /* Output quality (encoder-specific) */ + float compression_level; /* Output compression level (encoder-specific) */ + int mixdown; /* The mixdown used for this audio track (see HB_AMIXDOWN_*) */ + double dynamic_range_compression; /* Amount of DRC applied to this track */ + double gain; /* Gain (in dB), negative is quieter */ + char * name; /* Output track name */ } out; /* Input */ struct { - int track; /* Input track number */ - PRIVATE uint32_t codec; /* Input audio codec */ - PRIVATE uint32_t reg_desc; /* registration descriptor of source */ - PRIVATE uint32_t stream_type; /* stream type from source stream */ - PRIVATE uint32_t substream_type; /* substream for multiplexed streams */ - PRIVATE uint32_t codec_param; /* per-codec config info */ + int track; /* Input track number */ + PRIVATE uint32_t codec; /* Input audio codec */ + PRIVATE uint32_t codec_param; /* Per-codec config info */ + PRIVATE uint32_t reg_desc; /* Registration descriptor of source */ + PRIVATE uint32_t stream_type; /* Stream type from source stream */ + PRIVATE uint32_t substream_type; /* Substream type for multiplexed streams */ PRIVATE uint32_t version; /* Bitsream version */ - PRIVATE uint32_t mode; /* Bitstream mode, codec dependent encoding */ + PRIVATE uint32_t flags; /* Bitstream flags, codec-specific */ + PRIVATE uint32_t mode; /* Bitstream mode, codec-specific */ PRIVATE int samplerate; /* Input sample rate (Hz) */ PRIVATE int samples_per_frame; /* Number of samples per frame */ - 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 */ - PRIVATE hb_chan_map_t * channel_map; /* source channel map, set by the audio decoder */ + PRIVATE int bitrate; /* Input bitrate (bps) */ + PRIVATE int channel_layout; /* Source channel layout, set by the audio decoder */ + PRIVATE hb_chan_map_t * channel_map; /* Source channel map, set by the audio decoder */ } 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; -#define AUDIO_F_DOLBY (1 << 31) /* set if source uses Dolby Surround */ - struct { PRIVATE char description[1024]; PRIVATE char simple[1024]; PRIVATE char iso639_2[4]; - PRIVATE uint8_t type; /* normal, visually impared, directors */ + PRIVATE uint8_t type; /* normal, visually impaired, director's commentary */ } lang; }; @@ -799,15 +788,15 @@ struct hb_state_s typedef struct hb_work_info_s { - const char *name; - int profile; - int level; - int bitrate; - int rate; - int rate_base; - int flags; - int version; - int mode; + const char * name; + int profile; + int level; + int bitrate; + int rate; + int rate_base; + uint32_t version; + uint32_t flags; + uint32_t mode; union { struct { // info only valid for video decoders int width; diff --git a/libhb/deca52.c b/libhb/deca52.c index 09eb88101..f0befdd01 100644 --- a/libhb/deca52.c +++ b/libhb/deca52.c @@ -418,11 +418,6 @@ static int deca52BSInfo( hb_work_object_t *w, const hb_buffer_t *b, info->mode = raw & 0x7; /* bsmod is the following 3 bits */ info->samples_per_frame = 1536; - if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY ) - { - info->flags |= AUDIO_F_DOLBY; - } - switch( flags & A52_CHANNEL_MASK ) { /* mono sources */ @@ -436,7 +431,7 @@ static int deca52BSInfo( hb_work_object_t *w, const hb_buffer_t *b, case A52_STEREO: info->channel_layout = HB_INPUT_CH_LAYOUT_STEREO; break; - /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */ + /* Dolby Pro Logic (a.k.a. Dolby Surround), 4.0 channels (matrix-encoded) */ case A52_DOLBY: info->channel_layout = HB_INPUT_CH_LAYOUT_DOLBY; break; diff --git a/libhb/decdca.c b/libhb/decdca.c index 49fb3ecae..a459dcd23 100644 --- a/libhb/decdca.c +++ b/libhb/decdca.c @@ -76,17 +76,66 @@ static int decdcaInit( hb_work_object_t * w, hb_job_t * job ) pv->list = hb_list_init(); pv->state = dca_init( 0 ); + pv->level = 1.0; + + /* Decide what format we want out of libdca; + * work.c has already done some of this deduction for us in do_job(). + * Dolby Surround and Pro Logic II are a bit tricky. */ + int layout = ( audio->config.in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK ); + switch( audio->config.out.mixdown ) + { + case HB_AMIXDOWN_DOLBYPLII: + { + if( layout == HB_INPUT_CH_LAYOUT_3F2R ) + { + // Dolby Pro Logic II output is supported + pv->flags_out = ( DCA_3F2R | DCA_OUT_DPLII ); + } + else if( layout == HB_INPUT_CH_LAYOUT_3F1R ) + { + // Dolby Surround output and DCA_3F1R downmix are supported + pv->flags_out = ( DCA_3F1R | DCA_OUT_DPLI ); + } + else if( layout > HB_INPUT_CH_LAYOUT_DOLBY ) + { + // Dolby Surround output is supported, but DCA_3F1R downmix isn't + pv->flags_out = DCA_DOLBY; + } + else + { + // Dolby Surround output not supported OR + // Dolby Surround input just gets passed through as is + pv->flags_out = DCA_STEREO; + } + } break; - /* Decide what format we want out of libdca - work.c has already done some of this deduction for us in do_job() */ + case HB_AMIXDOWN_DOLBY: + { + if( layout == HB_INPUT_CH_LAYOUT_3F2R || layout == HB_INPUT_CH_LAYOUT_3F1R ) + { + // Dolby Surround output and DCA_3F1R downmix are supported + pv->flags_out = ( DCA_3F1R | DCA_OUT_DPLI ); + } + else if( layout > HB_INPUT_CH_LAYOUT_DOLBY ) + { + // Dolby Surround output is supported, but DCA_3F1R downmix isn't + pv->flags_out = DCA_DOLBY; + } + else + { + // Dolby Surround output not supported OR + // Dolby Surround input just gets passed through as is + pv->flags_out = DCA_STEREO; + } + } break; - pv->flags_out = HB_AMIXDOWN_GET_DCA_FORMAT(audio->config.out.mixdown); + default: + pv->flags_out = HB_AMIXDOWN_GET_DCA_FORMAT( audio->config.out.mixdown ); + break; + } /* 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(audio->config.out.mixdown); - - pv->level = 1.0; + pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT( audio->config.out.mixdown ); return 0; } @@ -315,11 +364,6 @@ static int decdcaBSInfo( hb_work_object_t *w, const hb_buffer_t *b, info->flags = flags; info->samples_per_frame = frame_length; - if ( ( flags & DCA_CHANNEL_MASK) == DCA_DOLBY ) - { - info->flags |= AUDIO_F_DOLBY; - } - switch( flags & DCA_CHANNEL_MASK ) { /* mono sources */ @@ -333,6 +377,10 @@ static int decdcaBSInfo( hb_work_object_t *w, const hb_buffer_t *b, case DCA_STEREO_TOTAL: info->channel_layout = HB_INPUT_CH_LAYOUT_STEREO; break; + /* Dolby Pro Logic (a.k.a. Dolby Surround), 4.0 channels (matrix-encoded) */ + case DCA_DOLBY: + info->channel_layout = HB_INPUT_CH_LAYOUT_DOLBY; + break; /* 3F/2R input */ case DCA_3F2R: info->channel_layout = HB_INPUT_CH_LAYOUT_3F2R; diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index cad1d3944..df55db7fd 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -282,8 +282,8 @@ static int MP4Init( hb_mux_object_t * m ) if ( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) { bsmod = audio->config.in.mode; - acmod = audio->config.flags.ac3 & 0x7; - lfeon = (audio->config.flags.ac3 & A52_LFE) ? 1 : 0; + acmod = audio->config.in.flags & 0x7; + lfeon = ( audio->config.in.flags & A52_LFE ) ? 1 : 0; freq = audio->config.in.samplerate; bitrate = audio->config.in.bitrate; } diff --git a/libhb/scan.c b/libhb/scan.c index 1f222ac7a..30d609d23 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -1065,11 +1065,11 @@ static void LookForAudio( hb_title_t * title, hb_buffer_t * b ) audio->config.in.channel_layout = info.channel_layout; audio->config.in.channel_map = info.channel_map; audio->config.in.version = info.version; + audio->config.in.flags = info.flags; audio->config.in.mode = info.mode; - audio->config.flags.ac3 = info.flags; // update the audio description string based on the info we found - if ( audio->config.flags.ac3 & AUDIO_F_DOLBY ) + if( audio->config.in.channel_layout == HB_INPUT_CH_LAYOUT_DOLBY ) { strcat( audio->config.lang.description, " (Dolby Surround)" ); } diff --git a/libhb/stream.c b/libhb/stream.c index eb2a42e6f..26de66ee5 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -2039,7 +2039,11 @@ static void set_audio_description( sizeof( audio->config.lang.description ), "%s (%s)", audio->config.lang.simple, codec_name ); - if ( audio->config.in.channel_layout ) + if( audio->config.in.channel_layout == HB_INPUT_CH_LAYOUT_DOLBY ) + { + strcat( audio->config.lang.description, " (Dolby Surround)" ); + } + else if( audio->config.in.channel_layout ) { int layout = audio->config.in.channel_layout; char *desc = audio->config.lang.description + |