summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authormaurj <[email protected]>2007-04-11 15:23:57 +0000
committermaurj <[email protected]>2007-04-11 15:23:57 +0000
commitddc7ac09960746920ae8e48ac6f38a61c9f56d47 (patch)
tree0ad40c6da4ff1ef22f33f6b6543171f346643029 /libhb
parent1ce785c8d342834c33ee09e63315c5997782f919 (diff)
Added libhb and CLI support for Dolby Pro Logic II 5.0 matrix encoding. *NOT YET ADDED TO THE GUI*. Handbrake now uses a more general "audio mixdown" concept. For each audio track to be converted you specify a mixdown. These are defined in common.h.
This checkin only allows you to specify one mixdown for all tracks in the CLI, although everything is in place internally to specify a different mixdown per track. In the CLI, the "-6 --surround" option has been repurposed as a "-6 --mixdown" option, with a string parameter of mono/stereo/dpl1/dpl2/6ch. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@494 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r--libhb/common.c9
-rw-r--r--libhb/common.h83
-rw-r--r--libhb/deca52.c32
-rw-r--r--libhb/encfaac.c16
-rw-r--r--libhb/encvorbis.c16
-rw-r--r--libhb/internal.h14
-rw-r--r--libhb/muxavi.c2
-rw-r--r--libhb/scan.c61
-rw-r--r--libhb/sync.c12
-rw-r--r--libhb/work.c187
10 files changed, 300 insertions, 132 deletions
diff --git a/libhb/common.c b/libhb/common.c
index 560a839e6..d0dcef877 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -36,6 +36,15 @@ int hb_audio_bitrates_count = sizeof( hb_audio_bitrates ) /
sizeof( hb_rate_t );
int hb_audio_bitrates_default = 8; /* 128 kbps */
+hb_mixdown_t hb_audio_mixdowns[] =
+{ { "Mono", "HB_AMIXDOWN_MONO", HB_AMIXDOWN_MONO },
+ { "Stereo", "HB_AMIXDOWN_STEREO", HB_AMIXDOWN_STEREO },
+ { "Dolby Surround", "HB_AMIXDOWN_DOLBY", HB_AMIXDOWN_DOLBY },
+ { "Dolby Pro Logic II", "HB_AMIXDOWN_DOLBYPLII", HB_AMIXDOWN_DOLBYPLII },
+ { "6-channel discrete", "HB_AMIXDOWN_6CH", HB_AMIXDOWN_6CH } };
+int hb_audio_mixdowns_count = sizeof( hb_audio_mixdowns ) /
+ sizeof( hb_mixdown_t );
+
/**********************************************************************
* hb_reduce
**********************************************************************
diff --git a/libhb/common.h b/libhb/common.h
index d09c2d279..4934063e5 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -31,6 +31,7 @@
typedef struct hb_handle_s hb_handle_t;
typedef struct hb_list_s hb_list_t;
typedef struct hb_rate_s hb_rate_t;
+typedef struct hb_mixdown_s hb_mixdown_t;
typedef struct hb_job_s hb_job_t;
typedef struct hb_title_s hb_title_t;
typedef struct hb_chapter_s hb_chapter_t;
@@ -70,17 +71,26 @@ struct hb_rate_s
int rate;
};
+struct hb_mixdown_s
+{
+ char * human_readable_name;
+ char * internal_name;
+ int amixdown;
+};
+
#define HB_ASPECT_BASE 9
#define HB_VIDEO_RATE_BASE 27000000
-extern hb_rate_t hb_video_rates[];
-extern int hb_video_rates_count;
-extern hb_rate_t hb_audio_rates[];
-extern int hb_audio_rates_count;
-extern int hb_audio_rates_default;
-extern hb_rate_t hb_audio_bitrates[];
-extern int hb_audio_bitrates_count;
-extern int hb_audio_bitrates_default;
+extern hb_rate_t hb_video_rates[];
+extern int hb_video_rates_count;
+extern hb_rate_t hb_audio_rates[];
+extern int hb_audio_rates_count;
+extern int hb_audio_rates_default;
+extern hb_rate_t hb_audio_bitrates[];
+extern int hb_audio_bitrates_count;
+extern int hb_audio_bitrates_default;
+extern hb_mixdown_t hb_audio_mixdowns[];
+extern int hb_audio_mixdowns_count;
/******************************************************************************
* hb_job_t: settings to be filled by the UI
@@ -151,10 +161,36 @@ struct hb_job_s
int areBframes;
/* Audio tracks:
- audios: Indexes in hb_title_t's audios list, starting from 0.
- -1 indicates the end of the list
- surround: 1 if 5.1 should be preserved for AAC, 0 otherwise */
+ 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_A52_FORMAT_MASK 0x00FF0000
+#define HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK 0x0000F000
+#define HB_AMIXDOWN_FRONT_CHANNEL_COUNT_MASK 0x00000F00
+#define HB_AMIXDOWN_REAR_CHANNEL_COUNT_MASK 0x000000F0
+#define HB_AMIXDOWN_LFE_CHANNEL_COUNT_MASK 0x0000000F
+/* define the HB_AMIXDOWN_XXXX values */
+#define HB_AMIXDOWN_MONO 0x01011100 // A52_FORMAT of A52_MONO = 1 = 0x01
+#define HB_AMIXDOWN_STEREO 0x02022200 // A52_FORMAT of A52_STEREO = 2 = 0x02
+#define HB_AMIXDOWN_DOLBY 0x040A2310 // A52_FORMAT of A52_DOLBY = 10 = 0x0A
+#define HB_AMIXDOWN_DOLBYPLII 0x084A2320 // A52_FORMAT of A52_DOLBY | A52_USE_DPLII = 74 = 0x4A
+#define HB_AMIXDOWN_6CH 0x10176321 // A52_FORMAT of A52_3F2R | A52_LFE = 23 = 0x17
+/* define some macros to extract the various information from the HB_AMIXDOWN_XXXX values */
+#define HB_AMIXDOWN_GET_A52_FORMAT( a ) ( ( a & HB_AMIXDOWN_A52_FORMAT_MASK ) >> 16 )
+#define HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT( a ) ( ( a & HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK ) >> 12 )
+#define HB_AMIXDOWN_GET_FRONT_CHANNEL_COUNT( a ) ( ( a & HB_AMIXDOWN_FRONT_CHANNEL_COUNT_MASK ) >> 8 )
+#define HB_AMIXDOWN_GET_REAR_CHANNEL_COUNT( a ) ( ( a & HB_AMIXDOWN_REAR_CHANNEL_COUNT_MASK ) >> 4 )
+#define HB_AMIXDOWN_GET_LFE_CHANNEL_COUNT( a ) ( ( a & HB_AMIXDOWN_LFE_CHANNEL_COUNT_MASK ) )
+#define HB_AMIXDOWN_GET_NORMAL_CHANNEL_COUNT( a ) ( (( a & HB_AMIXDOWN_FRONT_CHANNEL_COUNT_MASK ) >> 8) + (( a & HB_AMIXDOWN_REAR_CHANNEL_COUNT_MASK ) >> 4) )
int audios[8];
+ int audio_mixdowns[8];
+
+ /* this "surround" property will be removed shortly,
+ as soon as the AMIXDOWN code has been integrated into the Mac GUI
+ it's still included here to avoid breaking the Mac GUI short-term
+ however, it won't be applied in deca52.c etc. any more */
int surround;
/* Audio settings:
@@ -225,14 +261,16 @@ struct hb_audio_s
int codec;
int rate;
int bitrate;
- /* channels: The # of normal channels in the last used audio
- lfechannels: The # of lfe channels in the last used audio
- channelsused: The # of channels we will actually use for this job -
- calculated based on surround, channels and lfechannels
- in work.c */
- int channels;
- int lfechannels;
- int channelsused;
+ /* src_discrete_front_channels: The # of discrete front channels in the source audio
+ src_discrete_rear_channels: The # of discrete rear channels in the source audio
+ src_discrete_lfe_channels: The # of discrete lfe channels in the source audio
+ src_encoded_front_channels: The # of front channels encoded into the source audio
+ src_encoded_rear_channels: The # of rear channels encoded into the source audio */
+ int src_discrete_front_channels;
+ int src_discrete_rear_channels;
+ int src_discrete_lfe_channels;
+ int src_encoded_front_channels;
+ int src_encoded_rear_channels;
#ifdef __LIBHB__
/* Internal data */
@@ -243,6 +281,10 @@ struct hb_audio_s
hb_esconfig_t config;
hb_mux_data_t * mux_data;
+
+ /* amixdown is the mixdown format to be used for this audio track */
+ int amixdown;
+
#endif
};
@@ -381,6 +423,9 @@ 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;
+
hb_work_private_t * private_data;
hb_thread_t * thread;
diff --git a/libhb/deca52.c b/libhb/deca52.c
index 0664584c9..5b5f080bc 100644
--- a/libhb/deca52.c
+++ b/libhb/deca52.c
@@ -29,7 +29,7 @@ struct hb_work_private_s
hb_list_t * list;
- int channelsused;
+ int out_discrete_channels;
};
@@ -69,27 +69,11 @@ 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() */
- if (w->config->a52.channelsused == 6) {
- /* we're going to be encoding to a 6ch-supporting format,
- and have turned on the "preserve 5.1" flag */
- pv->flags_out = A52_3F2R | A52_LFE;
- } else if (w->config->a52.channelsused == 1) {
- /* we're going to be encoding to a 1ch-supporting format,
- so mix down to a mono track */
- pv->flags_out = A52_MONO;
- } else if (w->config->a52.channelsused == 2 && w->config->a52.channels == 5 && w->config->a52.lfechannels == 1) {
- /* we are mixing a 5.1 source down to stereo, so use dolby surround */
- pv->flags_out = A52_DOLBY;
- } else if (w->config->a52.channelsused == 2 && ((w->config->a52.ac3flags & A52_CHANNEL_MASK) == A52_DOLBY)) {
- /* we have a dolby stereo surround source, so preserve it */
- pv->flags_out = A52_DOLBY;
- } else {
- /* mix everything else down to plain stereo */
- pv->flags_out = A52_STEREO;
- }
+ pv->flags_out = HB_AMIXDOWN_GET_A52_FORMAT(w->amixdown);
/* pass the number of channels used into the private work data */
- pv->channelsused = w->config->a52.channelsused;
+ /* 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->level = 32768.0;
@@ -206,7 +190,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
a52_frame( pv->state, pv->frame, &pv->flags_out, &pv->level, 0 );
/* 6 blocks per frame, 256 samples per block, channelsused channels */
- buf = hb_buffer_init( 6 * 256 * pv->channelsused * sizeof( float ) );
+ buf = hb_buffer_init( 6 * 256 * pv->out_discrete_channels * sizeof( float ) );
buf->start = pts + ( pos / pv->size ) * 6 * 256 * 90000 / pv->rate;
buf->stop = buf->start + 6 * 256 * 90000 / pv->rate;
@@ -217,14 +201,14 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
a52_block( pv->state );
samples_in = a52_samples( pv->state );
- samples_out = ((float *) buf->data) + 256 * pv->channelsused * i;
+ samples_out = ((float *) buf->data) + 256 * pv->out_discrete_channels * i;
/* Interleave */
for( j = 0; j < 256; j++ )
{
- for ( k = 0; k < pv->channelsused; k++ )
+ for ( k = 0; k < pv->out_discrete_channels; k++ )
{
- samples_out[(pv->channelsused*j)+k] = samples_in[(256*k)+j]; // DJA
+ samples_out[(pv->out_discrete_channels*j)+k] = samples_in[(256*k)+j]; // DJA
}
}
}
diff --git a/libhb/encfaac.c b/libhb/encfaac.c
index 7ed9853d7..d46e8aedd 100644
--- a/libhb/encfaac.c
+++ b/libhb/encfaac.c
@@ -20,7 +20,7 @@ struct hb_work_private_s
hb_list_t * list;
int64_t pts;
- int channelsused;
+ int out_discrete_channels;
};
@@ -54,9 +54,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->channelsused = w->config->aac.channelsused;
+ pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown);
- pv->faac = faacEncOpen( job->arate, pv->channelsused, &pv->input_samples,
+ pv->faac = faacEncOpen( job->arate, pv->out_discrete_channels, &pv->input_samples,
&pv->output_bytes );
pv->buf = malloc( pv->input_samples * sizeof( float ) );
@@ -65,7 +65,7 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job )
cfg->aacObjectType = LOW;
cfg->allowMidside = 1;
- if (pv->channelsused == 6) {
+ if (pv->out_discrete_channels == 6) {
/* we are preserving 5.1 audio into 6-channel AAC,
so indicate that we have an lfe channel */
cfg->useLfe = 1;
@@ -74,12 +74,12 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job )
}
cfg->useTns = 0;
- cfg->bitRate = job->abitrate * 1000 / pv->channelsused; /* Per channel */
+ cfg->bitRate = job->abitrate * 1000 / pv->out_discrete_channels; /* Per channel */
cfg->bandWidth = 0;
cfg->outputFormat = 0;
cfg->inputFormat = FAAC_INPUT_FLOAT;
- if (pv->channelsused == 6) {
+ if (pv->out_discrete_channels == 6) {
/* we are preserving 5.1 audio into 6-channel AAC, and need to
re-map the output of deca52 into our own mapping - the mapping
below is the default mapping expected by QuickTime */
@@ -147,8 +147,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->channelsused / sizeof( float ) / pv->job->arate;
- buf->stop = buf->start + 90000 * pv->input_samples / pv->job->arate / pv->channelsused;
+ 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->size = faacEncEncode( pv->faac, (int32_t *) pv->buf,
pv->input_samples, buf->data, pv->output_bytes );
buf->key = 1;
diff --git a/libhb/encvorbis.c b/libhb/encvorbis.c
index 169cb938f..df91e14e8 100644
--- a/libhb/encvorbis.c
+++ b/libhb/encvorbis.c
@@ -37,7 +37,7 @@ struct hb_work_private_s
uint64_t pts;
hb_list_t * list;
- int channelsused;
+ int out_discrete_channels;
int channel_map[6];
};
@@ -48,7 +48,7 @@ int encvorbisInit( hb_work_object_t * w, hb_job_t * job )
hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
w->private_data = pv;
- pv->channelsused = w->config->vorbis.channelsused;
+ pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown);
pv->job = job;
@@ -56,7 +56,7 @@ int encvorbisInit( hb_work_object_t * w, hb_job_t * job )
/* init */
vorbis_info_init( &pv->vi );
- if( vorbis_encode_setup_managed( &pv->vi, pv->channelsused,
+ if( vorbis_encode_setup_managed( &pv->vi, pv->out_discrete_channels,
job->arate, -1, 1000 * job->abitrate, -1 ) ||
vorbis_encode_ctl( &pv->vi, OV_ECTL_RATEMANAGE_AVG, NULL ) ||
vorbis_encode_setup_init( &pv->vi ) )
@@ -84,12 +84,12 @@ int encvorbisInit( hb_work_object_t * w, hb_job_t * job )
header[i].packet, header[i].bytes );
}
- pv->input_samples = pv->channelsused * OGGVORBIS_FRAME_SIZE;
+ pv->input_samples = pv->out_discrete_channels * OGGVORBIS_FRAME_SIZE;
pv->buf = malloc( pv->input_samples * sizeof( float ) );
pv->list = hb_list_init();
- switch (pv->channelsused) {
+ switch (pv->out_discrete_channels) {
case 1:
pv->channel_map[0] = 0;
break;
@@ -102,7 +102,7 @@ int encvorbisInit( hb_work_object_t * w, hb_job_t * job )
pv->channel_map[5] = 3;
break;
default:
- hb_log("encvorbis.c: Unable to correctly proccess %d channels, assuming stereo.", pv->channelsused);
+ hb_log("encvorbis.c: Unable to correctly proccess %d channels, assuming stereo.", pv->out_discrete_channels);
case 2:
// Assume stereo
pv->channel_map[0] = 0;
@@ -199,9 +199,9 @@ static hb_buffer_t * Encode( hb_work_object_t * w )
buffer = vorbis_analysis_buffer( &pv->vd, OGGVORBIS_FRAME_SIZE );
for( i = 0; i < OGGVORBIS_FRAME_SIZE; i++ )
{
- for( j = 0; j < pv->channelsused; j++)
+ for( j = 0; j < pv->out_discrete_channels; j++)
{
- buffer[j][i] = ((float *) pv->buf)[(pv->channelsused * i + pv->channel_map[j])] / 32768.f;
+ buffer[j][i] = ((float *) pv->buf)[(pv->out_discrete_channels * i + pv->channel_map[j])] / 32768.f;
}
}
vorbis_analysis_wrote( &pv->vd, OGGVORBIS_FRAME_SIZE );
diff --git a/libhb/internal.h b/libhb/internal.h
index 577ad3032..bc6f5063c 100644
--- a/libhb/internal.h
+++ b/libhb/internal.h
@@ -119,6 +119,7 @@ void hb_dvd_close( hb_dvd_t ** );
#define HB_CONFIG_MAX_SIZE 8192
union hb_esconfig_u
{
+
struct
{
uint8_t bytes[HB_CONFIG_MAX_SIZE];
@@ -137,29 +138,20 @@ union hb_esconfig_u
{
uint8_t bytes[HB_CONFIG_MAX_SIZE];
int length;
- /* Total channels actually used for this audio track */
- int channelsused;
- int lfechannels;
} aac;
struct
{
uint8_t headers[3][HB_CONFIG_MAX_SIZE];
- int channelsused;
char *language;
} vorbis;
struct
{
- /* indicates the number of normal channels the source audio has */
- int channels;
- /* indicates the number of lfe channels the source audio has */
- int lfechannels;
- /* ac3flags: stores the flags from the AC3 source, as found in scan.c */
+ /* ac3flags stores the flags from the AC3 source, as found in scan.c */
int ac3flags;
- /* Total channels actually used for this audio track */
- int channelsused;
} a52;
+
};
enum
diff --git a/libhb/muxavi.c b/libhb/muxavi.c
index 8746a3cdd..214393d68 100644
--- a/libhb/muxavi.c
+++ b/libhb/muxavi.c
@@ -369,7 +369,7 @@ static int AVIInit( hb_mux_object_t * m )
{
f.BytesCount = sizeof( hb_wave_formatex_t ) - 8;
f.FormatTag = 0x2000;
- f.Channels = audio->channels;
+ f.Channels = 2;
f.SamplesPerSec = audio->rate;
}
else
diff --git a/libhb/scan.c b/libhb/scan.c
index e969a4380..9e9f9542a 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -468,39 +468,76 @@ static void LookForAC3( hb_title_t * title, hb_buffer_t * b )
case A52_MONO:
case A52_CHANNEL1:
case A52_CHANNEL2:
- audio->channels = 1;
+ audio->src_discrete_front_channels = 1;
+ audio->src_discrete_rear_channels = 0;
+ audio->src_encoded_front_channels = 1;
+ audio->src_encoded_rear_channels = 0;
break;
case A52_STEREO:
- case A52_DOLBY:
case A52_CHANNEL:
- audio->channels = 2;
+ audio->src_discrete_front_channels = 2;
+ audio->src_discrete_rear_channels = 0;
+ audio->src_encoded_front_channels = 2;
+ audio->src_encoded_rear_channels = 0;
+ break;
+ case A52_DOLBY:
+ audio->src_discrete_front_channels = 2;
+ audio->src_discrete_rear_channels = 0;
+ audio->src_encoded_front_channels = 3;
+ audio->src_encoded_rear_channels = 1;
break;
case A52_3F:
+ audio->src_discrete_front_channels = 3;
+ audio->src_discrete_rear_channels = 0;
+ audio->src_encoded_front_channels = 3;
+ audio->src_encoded_rear_channels = 0;
+ break;
case A52_2F1R:
- audio->channels = 3;
+ audio->src_discrete_front_channels = 2;
+ audio->src_discrete_rear_channels = 1;
+ audio->src_encoded_front_channels = 2;
+ audio->src_encoded_rear_channels = 1;
break;
case A52_3F1R:
- case A52_2F2R:
- audio->channels = 4;
+ audio->src_discrete_front_channels = 3;
+ audio->src_discrete_rear_channels = 1;
+ audio->src_encoded_front_channels = 3;
+ audio->src_encoded_rear_channels = 1;
+ break;
+ case A52_2F2R:
+ audio->src_discrete_front_channels = 2;
+ audio->src_discrete_rear_channels = 2;
+ audio->src_encoded_front_channels = 2;
+ audio->src_encoded_rear_channels = 2;
break;
case A52_3F2R:
- audio->channels = 5;
+ audio->src_discrete_front_channels = 3;
+ audio->src_discrete_rear_channels = 2;
+ audio->src_encoded_front_channels = 3;
+ audio->src_encoded_rear_channels = 2;
break;
}
if (flags & A52_LFE) {
- audio->lfechannels = 1;
+ audio->src_discrete_lfe_channels = 1;
} else {
- audio->lfechannels = 0;
+ audio->src_discrete_lfe_channels = 0;
}
- /* store the AC3 tags for future reference
+ /* 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;
/* XXX */
- sprintf( audio->lang + strlen( audio->lang ),
- " (%d.%d ch)", audio->channels, audio->lfechannels );
+ if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY ) {
+ sprintf( audio->lang + strlen( audio->lang ),
+ " (Dolby Surround)" );
+ } else {
+ sprintf( audio->lang + strlen( audio->lang ),
+ " (%d.%d ch)",
+ audio->src_discrete_front_channels + audio->src_discrete_rear_channels, audio->src_discrete_lfe_channels );
+ }
+
break;
}
}
diff --git a/libhb/sync.c b/libhb/sync.c
index b8f49fd01..79423b70c 100644
--- a/libhb/sync.c
+++ b/libhb/sync.c
@@ -196,7 +196,7 @@ static void InitAudio( hb_work_object_t * w, int i )
c->bit_rate = sync->audio->bitrate;
c->sample_rate = sync->audio->rate;
- c->channels = sync->audio->channels;
+ c->channels = 2;
if( avcodec_open( c, codec ) < 0 )
{
@@ -224,7 +224,7 @@ static void InitAudio( hb_work_object_t * w, int i )
{
/* Initialize libsamplerate */
int error;
- sync->state = src_new( SRC_LINEAR, sync->audio->channelsused, &error );
+ sync->state = src_new( SRC_LINEAR, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown), &error );
sync->data.end_of_input = 0;
}
}
@@ -502,7 +502,7 @@ static void SyncAudio( hb_work_object_t * w, int i )
int count_in, count_out;
- count_in = buf_raw->size / audio->channelsused / sizeof( float );
+ count_in = buf_raw->size / HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) / sizeof( float );
count_out = ( buf_raw->stop - buf_raw->start ) * job->arate / 90000;
if( buf->start < pts_expected - 1500 )
count_out--;
@@ -516,7 +516,7 @@ static void SyncAudio( hb_work_object_t * w, int i )
sync->data.src_ratio = (double) sync->data.output_frames /
(double) sync->data.input_frames;
- buf = hb_buffer_init( sync->data.output_frames * audio->channelsused *
+ buf = hb_buffer_init( sync->data.output_frames * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) *
sizeof( float ) );
sync->data.data_out = (float *) buf->data;
if( src_process( sync->state, &sync->data ) )
@@ -526,7 +526,7 @@ static void SyncAudio( hb_work_object_t * w, int i )
}
hb_buffer_close( &buf_raw );
- buf->size = sync->data.output_frames_gen * audio->channelsused * sizeof( float );
+ buf->size = sync->data.output_frames_gen * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) * sizeof( float );
/* Set dates for resampled data */
buf->start = start;
@@ -609,7 +609,7 @@ static void InsertSilence( hb_work_object_t * w, int i )
}
else
{
- buf = hb_buffer_init( sync->audio->channelsused * job->arate / 20 *
+ buf = hb_buffer_init( HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown) * job->arate / 20 *
sizeof( float ) );
buf->start = sync->count_frames * 90000 / job->arate;
buf->stop = buf->start + 90000 / 20;
diff --git a/libhb/work.c b/libhb/work.c
index 0a9392187..1ab422a66 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -5,6 +5,7 @@
It may be used under the terms of the GNU General Public License. */
#include "hb.h"
+#include "a52dec/a52.h"
typedef struct
{
@@ -89,7 +90,7 @@ static hb_work_object_t * getWork( int id )
static void do_job( hb_job_t * job, int cpu_count )
{
hb_title_t * title;
- int i;
+ int i, j;
hb_work_object_t * w;
/* FIXME: This feels really hackish, anything better? */
@@ -218,7 +219,144 @@ static void do_job( hb_job_t * job, int cpu_count )
{
audio = hb_list_item( title->list_audio, i );
hb_log( " + %x, %s", audio->id, audio->lang );
+
+ /* 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 );
+ break;
+ }
+ }
+
+ if(audio->codec != HB_ACODEC_AC3) {
+
+ /* assume a stereo input and output for non-AC3 audio input (LPCM, MP2),
+ regardless of the mixdown passed to us */
+ job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO;
+
+ } else {
+
+ /* sense-check the AC3 mixdown */
+
+ /* audioCodecSupportsMono and audioCodecSupports6Ch are the same for now,
+ but this may change in the future, so they are separated for flexibility */
+ int audioCodecSupportsMono = (job->acodec == HB_ACODEC_FAAC);
+ int audioCodecSupports6Ch = (job->acodec == HB_ACODEC_FAAC);
+
+ /* find out what the format of our source AC3 audio is */
+ switch (audio->config.a52.ac3flags & A52_CHANNEL_MASK) {
+
+ /* mono sources */
+ case A52_MONO:
+ case A52_CHANNEL1:
+ case A52_CHANNEL2:
+ /* 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 && audioCodecSupportsMono == 1) {
+ job->audio_mixdowns[i] = HB_AMIXDOWN_MONO;
+ } else {
+ job->audio_mixdowns[i] = HB_AMIXDOWN_STEREO;
+ }
+ break;
+
+ /* stereo input */
+ case A52_CHANNEL:
+ case A52_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 && audioCodecSupportsMono == 0) {
+ job->audio_mixdowns[i] = 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;
+ }
+ 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 DPL2 on a DVD,
+ so we always assume a DPL1 source for A52_DOLBY */
+ case A52_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 && audioCodecSupportsMono == 0) {
+ job->audio_mixdowns[i] = 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;
+ }
+ break;
+
+ /* 3F/2R input */
+ case A52_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 && audioCodecSupportsMono == 0) {
+ job->audio_mixdowns[i] = 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->config.a52.ac3flags & A52_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 && audioCodecSupports6Ch == 0) {
+ job->audio_mixdowns[i] = 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;
+ }
+ }
+ }
+ /* all other mixdowns will have been preserved here */
+ break;
+
+ /* 3F/1R input */
+ case A52_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 && audioCodecSupportsMono == 0) {
+ job->audio_mixdowns[i] = 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;
+ }
+ }
+ /* all other mixdowns will have been preserved here */
+ break;
+
+ default:
+ /* if we've requested a mono mixdown, and it is supported, then do the mix */
+ if (job->audio_mixdowns[i] == HB_AMIXDOWN_MONO && audioCodecSupportsMono == 1) {
+ job->audio_mixdowns[i] = HB_AMIXDOWN_MONO;
+ /* mix everything else down to stereo */
+ } else {
+ job->audio_mixdowns[i] = 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 );
+ 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;
+ /* set up the audio work structures */
audio->fifo_in = hb_fifo_init( 2048 );
audio->fifo_raw = hb_fifo_init( 8 );
audio->fifo_sync = hb_fifo_init( 8 );
@@ -239,6 +377,7 @@ static void do_job( hb_job_t * job, int cpu_count )
w->fifo_in = audio->fifo_in;
w->fifo_out = audio->fifo_raw;
w->config = &audio->config;
+ w->amixdown = audio->amixdown;
/* FIXME: This feels really hackish, anything better? */
audio_w = calloc( sizeof( hb_work_object_t ), 1 );
@@ -258,11 +397,13 @@ static void do_job( hb_job_t * job, int cpu_count )
w = getWork( WORK_ENCVORBIS );
break;
}
+
if( job->acodec != HB_ACODEC_AC3 )
{
w->fifo_in = audio->fifo_sync;
w->fifo_out = audio->fifo_out;
w->config = &audio->config;
+ w->amixdown = audio->amixdown;
/* FIXME: This feels really hackish, anything better? */
audio_w = calloc( sizeof( hb_work_object_t ), 1 );
@@ -270,48 +411,8 @@ static void do_job( hb_job_t * job, int cpu_count )
hb_list_add( job->list_work, audio_w );
}
-
- /* store this audio's channel counts in the audio struct */
-
- /* we will only end up with a channelsused value other than 2
- if we are encoding to AAC or OGM. All other audio encodings will get
- a stereo mix. */
-
- if (audio->channels == 5 && audio->lfechannels == 1) {
- /* we have a 5.1 AC-3 source soundtrack */
- if ((job->acodec == HB_ACODEC_FAAC || job->acodec == HB_ACODEC_VORBIS) && job->surround) {
- /* we're going to be encoding to a 6ch-supporting format,
- and have turned on the "preserve 5.1" flag */
- audio->channelsused = 6;
- } else {
- /* mix 5.1 down to Dolby Digital (2-channel) */
- audio->channelsused = 2;
- }
- } else if (audio->channels == 1 && audio->lfechannels == 0) {
- /* we have a 1.0 mono AC-3 source soundtrack */
- if (job->acodec == HB_ACODEC_FAAC || job->acodec == HB_ACODEC_VORBIS) {
- /* we're going to be encoding to a 1ch-supporting format,
- so mix down to a mono track */
- audio->channelsused = 1;
- } else {
- /* mix up the mono track to stereo */
- audio->channelsused = 2;
- }
- } else {
- /* mix everything else down to stereo */
- /* dolby pro-logic will be preserved in deca52.c if necessary
- by referring to the value of audio->config->a52.ac3flags */
- audio->channelsused = 2;
- }
-
- /* remember the number of source channels, so that deca52.c knows what source we had */
- audio->config.a52.channels = audio->channels;
- audio->config.a52.lfechannels = audio->lfechannels;
-
- /* pass round the number of channels we actually used */
- audio->config.aac.channelsused = audio->config.a52.channelsused = audio->config.vorbis.channelsused = audio->channelsused;
- audio->config.vorbis.language = audio->lang_simple;
-
+
+
}
/* Init read & write threads */