summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorRodeo <[email protected]>2012-11-21 18:29:34 +0000
committerRodeo <[email protected]>2012-11-21 18:29:34 +0000
commit282ddc84776683667e417a62186be57b97be3eab (patch)
treefa4f2bd306b5eb06aa28af2bbe507a3f9b8b091b /libhb
parent8612b1b6ab0a60a9b9cca384ca62f8a12d3cbb5b (diff)
Improve support for planar audio.
- encavcodecaudio: use libavresample directly (instead of via the hb_audio_resample wrapper), and add support for planar output - hb_audio_resample: add support for planar input - hb_audio_remap: add support for planar input - deca52: output planar float samples (no re-interleaving) git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@5073 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r--libhb/audio_remap.c129
-rw-r--r--libhb/audio_remap.h8
-rw-r--r--libhb/audio_resample.c83
-rw-r--r--libhb/audio_resample.h8
-rw-r--r--libhb/deca52.c92
-rw-r--r--libhb/decavcodec.c4
-rw-r--r--libhb/declpcm.c4
-rw-r--r--libhb/encavcodecaudio.c152
-rw-r--r--libhb/platform/macosx/encca_aac.c3
9 files changed, 311 insertions, 172 deletions
diff --git a/libhb/audio_remap.c b/libhb/audio_remap.c
index 6daaee9fb..afc9c3209 100644
--- a/libhb/audio_remap.c
+++ b/libhb/audio_remap.c
@@ -81,32 +81,100 @@ hb_chan_map_t hb_aac_chan_map =
}
};
-static void remap_planar(uint8_t *tmp_buf, uint8_t *samples, int nsamples,
- int nchannels, int sample_size, int *remap_table)
+static void remap_planar(uint8_t **samples, int nsamples,
+ int nchannels, int *remap_table)
{
- int ii, stride = nsamples * sample_size;
- memcpy(tmp_buf, samples, nchannels * stride);
+ int ii;
+ uint8_t *tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
+ memcpy(tmp_buf, samples, nchannels * sizeof(uint8_t*));
for (ii = 0; ii < nchannels; ii++)
{
- memcpy(samples + (ii * stride),
- tmp_buf + (remap_table[ii] * stride), stride);
+ samples[ii] = tmp_buf[remap_table[ii]];
}
}
-static void remap_interleaved(uint8_t *tmp_buf, uint8_t *samples, int nsamples,
- int nchannels, int sample_size, int *remap_table)
+static void remap_u8_interleaved(uint8_t **samples, int nsamples,
+ int nchannels, int *remap_table)
{
- int ii, jj, stride = nchannels * sample_size;
- memcpy(tmp_buf, samples, nsamples * stride);
+ int ii, jj;
+ uint8_t *samples_u8 = (*samples);
+ uint8_t tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
for (ii = 0; ii < nsamples; ii++)
{
+ memcpy(tmp_buf, samples_u8, nchannels * sizeof(uint8_t));
for (jj = 0; jj < nchannels; jj++)
{
- memcpy(samples + (jj * sample_size),
- tmp_buf + (remap_table[jj] * sample_size), sample_size);
+ samples_u8[jj] = tmp_buf[remap_table[jj]];
}
- samples += stride;
- tmp_buf += stride;
+ samples_u8 += nchannels;
+ }
+}
+
+static void remap_s16_interleaved(uint8_t **samples, int nsamples,
+ int nchannels, int *remap_table)
+{
+ int ii, jj;
+ int16_t *samples_s16 = (int16_t*)(*samples);
+ int16_t tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
+ for (ii = 0; ii < nsamples; ii++)
+ {
+ memcpy(tmp_buf, samples_s16, nchannels * sizeof(int16_t));
+ for (jj = 0; jj < nchannels; jj++)
+ {
+ samples_s16[jj] = tmp_buf[remap_table[jj]];
+ }
+ samples_s16 += nchannels;
+ }
+}
+
+static void remap_s32_interleaved(uint8_t **samples, int nsamples,
+ int nchannels, int *remap_table)
+{
+ int ii, jj;
+ int32_t *samples_s32 = (int32_t*)(*samples);
+ int32_t tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
+ for (ii = 0; ii < nsamples; ii++)
+ {
+ memcpy(tmp_buf, samples_s32, nchannels * sizeof(int32_t));
+ for (jj = 0; jj < nchannels; jj++)
+ {
+ samples_s32[jj] = tmp_buf[remap_table[jj]];
+ }
+ samples_s32 += nchannels;
+ }
+}
+
+static void remap_flt_interleaved(uint8_t **samples, int nsamples,
+ int nchannels, int *remap_table)
+{
+ int ii, jj;
+ float *samples_flt = (float*)(*samples);
+ float tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
+ for (ii = 0; ii < nsamples; ii++)
+ {
+ memcpy(tmp_buf, samples_flt, nchannels * sizeof(float));
+ for (jj = 0; jj < nchannels; jj++)
+ {
+ samples_flt[jj] = tmp_buf[remap_table[jj]];
+ }
+ samples_flt += nchannels;
+ }
+}
+
+static void remap_dbl_interleaved(uint8_t **samples, int nsamples,
+ int nchannels, int *remap_table)
+{
+ int ii, jj;
+ double *samples_dbl = (double*)(*samples);
+ double tmp_buf[HB_AUDIO_REMAP_MAX_CHANNELS];
+ for (ii = 0; ii < nsamples; ii++)
+ {
+ memcpy(tmp_buf, samples_dbl, nchannels * sizeof(double));
+ for (jj = 0; jj < nchannels; jj++)
+ {
+ samples_dbl[jj] = tmp_buf[remap_table[jj]];
+ }
+ samples_dbl += nchannels;
}
}
@@ -133,11 +201,23 @@ hb_audio_remap_t* hb_audio_remap_init(enum AVSampleFormat sample_fmt,
break;
case AV_SAMPLE_FMT_U8:
+ remap->remap = &remap_u8_interleaved;
+ break;
+
case AV_SAMPLE_FMT_S16:
+ remap->remap = &remap_s16_interleaved;
+ break;
+
case AV_SAMPLE_FMT_S32:
+ remap->remap = &remap_s32_interleaved;
+ break;
+
case AV_SAMPLE_FMT_FLT:
+ remap->remap = &remap_flt_interleaved;
+ break;
+
case AV_SAMPLE_FMT_DBL:
- remap->remap = &remap_interleaved;
+ remap->remap = &remap_dbl_interleaved;
break;
default:
@@ -145,7 +225,6 @@ hb_audio_remap_t* hb_audio_remap_init(enum AVSampleFormat sample_fmt,
av_get_sample_fmt_name(sample_fmt));
goto fail;
}
- remap->sample_size = av_get_bytes_per_sample(sample_fmt);
// input/output channel order
if (channel_map_in == NULL || channel_map_out == NULL)
@@ -156,14 +235,6 @@ hb_audio_remap_t* hb_audio_remap_init(enum AVSampleFormat sample_fmt,
remap->channel_map_in = channel_map_in;
remap->channel_map_out = channel_map_out;
- // temp buffer - we don't know the required size yet
- remap->buf = hb_buffer_init(0);
- if (remap->buf == NULL)
- {
- hb_error("hb_audio_remap_init: failed to allocate remap->buf");
- goto fail;
- }
-
// remap can't be done until the channel layout has been set
remap->remap_needed = 0;
@@ -215,21 +286,15 @@ void hb_audio_remap_free(hb_audio_remap_t *remap)
{
if (remap != NULL)
{
- if (remap->buf != NULL)
- hb_buffer_close(&remap->buf);
free(remap);
}
}
-void hb_audio_remap(hb_audio_remap_t *remap, uint8_t *samples, int nsamples)
+void hb_audio_remap(hb_audio_remap_t *remap, uint8_t **samples, int nsamples)
{
if (remap != NULL && remap->remap_needed)
{
- // make sure our temp buffer can hold a copy of all samples
- hb_buffer_realloc(remap->buf, nsamples * remap->sample_size *
- remap->nchannels);
- remap->remap(remap->buf->data, samples, nsamples, remap->nchannels,
- remap->sample_size, remap->table);
+ remap->remap(samples, nsamples, remap->nchannels, remap->table);
}
}
diff --git a/libhb/audio_remap.h b/libhb/audio_remap.h
index a776fe57b..0bdd23bb7 100644
--- a/libhb/audio_remap.h
+++ b/libhb/audio_remap.h
@@ -40,15 +40,13 @@ typedef struct
typedef struct
{
int nchannels;
- int sample_size;
int remap_needed;
- hb_buffer_t *buf;
hb_chan_map_t *channel_map_in;
hb_chan_map_t *channel_map_out;
int table[HB_AUDIO_REMAP_MAX_CHANNELS];
- void (*remap)(uint8_t *tmp_buf, uint8_t *samples, int nsamples,
- int nchannels, int sample_size, int *remap_table);
+ void (*remap)(uint8_t **samples, int nsamples,
+ int nchannels, int *remap_table);
} hb_audio_remap_t;
/*
@@ -88,7 +86,7 @@ void hb_audio_remap_free(hb_audio_remap_t *remap);
*
* The remap parameter can be NULL (no remapping).
*/
-void hb_audio_remap(hb_audio_remap_t *remap, uint8_t *samples,
+void hb_audio_remap(hb_audio_remap_t *remap, uint8_t **samples,
int nsamples);
/*
diff --git a/libhb/audio_resample.c b/libhb/audio_resample.c
index 927a3b7c4..cc9b50d8b 100644
--- a/libhb/audio_resample.c
+++ b/libhb/audio_resample.c
@@ -12,27 +12,36 @@
#include "audio_resample.h"
hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat sample_fmt,
- int hb_amixdown, int do_remix,
- int normalize_mix_level)
+ int hb_amixdown, int normalize_mix)
{
hb_audio_resample_t *resample = calloc(1, sizeof(hb_audio_resample_t));
if (resample == NULL)
{
hb_error("hb_audio_resample_init: failed to allocate resample");
- return NULL;
+ goto fail;
+ }
+
+ // avresample context, initialized in hb_audio_resample_update()
+ resample->avresample = NULL;
+
+ // we don't support planar output yet
+ if (av_sample_fmt_is_planar(sample_fmt))
+ {
+ hb_error("hb_audio_resample_init: planar output not supported ('%s')",
+ av_get_sample_fmt_name(sample_fmt));
+ goto fail;
}
// convert mixdown to channel_layout/matrix_encoding combo
- int channels, matrix_encoding;
+ int matrix_encoding;
uint64_t channel_layout = hb_ff_mixdown_xlat(hb_amixdown, &matrix_encoding);
- channels = av_get_channel_layout_nb_channels(channel_layout);
- if (do_remix && (hb_amixdown == HB_AMIXDOWN_LEFT ||
- hb_amixdown == HB_AMIXDOWN_RIGHT))
+ /*
+ * When downmixing, Dual Mono to Mono is a special case:
+ * the audio must remain 2-channel until all conversions are done.
+ */
+ if (hb_amixdown == HB_AMIXDOWN_LEFT || hb_amixdown == HB_AMIXDOWN_RIGHT)
{
- /* When downmixing, Dual Mono to Mono is a special case:
- * the audio must remain 2-channel until all conversions are done. */
- channels = 2;
channel_layout = AV_CH_LAYOUT_STEREO;
resample->dual_mono_downmix = 1;
resample->dual_mono_right_only = (hb_amixdown == HB_AMIXDOWN_RIGHT);
@@ -42,35 +51,34 @@ hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat sample_fmt,
resample->dual_mono_downmix = 0;
}
- // requested channel_layout
- resample->out.channels = channels;
+ // requested output channel_layout, sample_fmt
+ resample->out.channels = av_get_channel_layout_nb_channels(channel_layout);
resample->out.channel_layout = channel_layout;
resample->out.matrix_encoding = matrix_encoding;
- resample->out.normalize_mix_level = normalize_mix_level;
-
- // requested sample_fmt
+ resample->out.normalize_mix_level = normalize_mix;
resample->out.sample_fmt = sample_fmt;
resample->out.sample_size = av_get_bytes_per_sample(sample_fmt);
// set default input characteristics
- resample->in.sample_fmt = resample->out.sample_fmt;
- resample->in.channel_layout = resample->out.channel_layout;
- resample->in.center_mix_level = HB_MIXLEV_DEFAULT;
- resample->in.surround_mix_level = HB_MIXLEV_DEFAULT;
+ resample->in.sample_fmt = resample->out.sample_fmt;
+ resample->in.channel_layout = resample->out.channel_layout;
+ resample->in.center_mix_level = HB_MIXLEV_DEFAULT;
+ resample->in.surround_mix_level = HB_MIXLEV_DEFAULT;
// by default, no conversion needed
- resample->resample_needed = 0;
- resample->avresample = NULL;
- resample->do_remix = !!do_remix;
-
+ resample->resample_needed = 0;
return resample;
+
+fail:
+ hb_audio_resample_free(resample);
+ return NULL;
}
void hb_audio_resample_set_channel_layout(hb_audio_resample_t *resample,
uint64_t channel_layout,
int channels)
{
- if (resample != NULL && resample->do_remix)
+ if (resample != NULL)
{
channel_layout = hb_ff_layout_xlat(channel_layout, channels);
if (channel_layout == AV_CH_LAYOUT_STEREO_DOWNMIX)
@@ -86,7 +94,7 @@ void hb_audio_resample_set_mix_levels(hb_audio_resample_t *resample,
double surround_mix_level,
double center_mix_level)
{
- if (resample != NULL && resample->do_remix)
+ if (resample != NULL)
{
resample->in.center_mix_level = center_mix_level;
resample->in.surround_mix_level = surround_mix_level;
@@ -193,7 +201,7 @@ void hb_audio_resample_free(hb_audio_resample_t *resample)
}
hb_buffer_t* hb_audio_resample(hb_audio_resample_t *resample,
- void *samples, int nsamples)
+ uint8_t **samples, int nsamples)
{
if (resample == NULL)
{
@@ -224,7 +232,7 @@ hb_buffer_t* hb_audio_resample(hb_audio_resample_t *resample,
out_samples = avresample_convert(resample->avresample,
(void**)&out->data, out_linesize, nsamples,
- (void**)&samples, in_linesize, nsamples);
+ (void**)samples, in_linesize, nsamples);
if (out_samples <= 0)
{
@@ -243,24 +251,27 @@ hb_buffer_t* hb_audio_resample(hb_audio_resample_t *resample,
out_size = (out_samples *
resample->out.sample_size * resample->out.channels);
out = hb_buffer_init(out_size);
- memcpy(out->data, samples, out_size);
+ memcpy(out->data, samples[0], out_size);
}
- /* Dual Mono to Mono.
+ /*
+ * Dual Mono to Mono.
*
- * Copy all left or right samples to the first half of the buffer
- * and halve the size */
+ * Copy all left or right samples to the first half of the buffer and halve
+ * the buffer size.
+ */
if (resample->dual_mono_downmix)
{
- int ii;
- int jj = !!resample->dual_mono_right_only;
- float *audio_samples = (float*)out->data;
+ int ii, jj = !!resample->dual_mono_right_only;
+ int sample_size = resample->out.sample_size;
+ uint8_t *audio_samples = out->data;
for (ii = 0; ii < out_samples; ii++)
{
- audio_samples[ii] = audio_samples[jj];
+ memcpy(audio_samples + (ii * sample_size),
+ audio_samples + (jj * sample_size), sample_size);
jj += 2;
}
- out->size = out_samples * resample->out.sample_size;
+ out->size = out_samples * sample_size;
}
return out;
diff --git a/libhb/audio_resample.h b/libhb/audio_resample.h
index baee471a6..62a536d61 100644
--- a/libhb/audio_resample.h
+++ b/libhb/audio_resample.h
@@ -27,7 +27,6 @@
typedef struct
{
- int do_remix;
int dual_mono_downmix;
int dual_mono_right_only;
@@ -67,12 +66,9 @@ typedef struct
*
* Also sets the default audio input characteristics, so that they are the same
* as the output characteristics (no conversion needed).
- *
- * If do_remix is 0, it will be assumed that any remixing was *already* done.
*/
hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat sample_fmt,
- int hb_amixdown, int do_remix,
- int normalize_mix_level);
+ int hb_amixdown, int normalize_mix);
/* The following functions set the audio input characteristics.
*
@@ -110,6 +106,6 @@ void hb_audio_resample_free(hb_audio_resample_t *resample);
* resampling is only done when necessary.
*/
hb_buffer_t* hb_audio_resample(hb_audio_resample_t *resample,
- void *samples, int nsamples);
+ uint8_t **samples, int nsamples);
#endif /* AUDIO_RESAMPLE_H */
diff --git a/libhb/deca52.c b/libhb/deca52.c
index 3a6e71e95..ba7c38485 100644
--- a/libhb/deca52.c
+++ b/libhb/deca52.c
@@ -35,12 +35,13 @@ struct hb_work_private_s
hb_list_t *list;
const AVCRC *crc_table;
uint8_t frame[3840];
- uint8_t buf[1536 * 6 * sizeof(float)]; // decoded samples (1 frame, 6 channels)
+ uint8_t buf[6][6][256 * sizeof(float)]; // decoded frame (up to 6 channels, 6 blocks * 256 samples)
+ uint8_t *samples[6]; // pointers to the start of each plane (1 per channel)
int nchannels;
- int remap_table[6];
int use_mix_levels;
uint64_t channel_layout;
+ hb_audio_remap_t *remap;
hb_audio_resample_t *resample;
};
@@ -133,17 +134,17 @@ static int deca52Init(hb_work_object_t *w, hb_job_t *job)
pv->list = hb_list_init();
pv->crc_table = av_crc_get_table(AV_CRC_16_ANSI);
- /* Downmixing */
+ /*
+ * Decoding, remapping, downmixing
+ */
if (audio->config.out.codec != HB_ACODEC_AC3_PASS)
{
- /* We want AV_SAMPLE_FMT_FLT samples */
- pv->level = 1.0;
- pv->dynamic_range_compression =
- audio->config.out.dynamic_range_compression;
-
+ /*
+ * Output AV_SAMPLE_FMT_FLT samples
+ */
pv->resample =
hb_audio_resample_init(AV_SAMPLE_FMT_FLT,
- audio->config.out.mixdown, 1,
+ audio->config.out.mixdown,
audio->config.out.normalize_mix_level);
if (pv->resample == NULL)
{
@@ -151,12 +152,39 @@ static int deca52Init(hb_work_object_t *w, hb_job_t *job)
return 1;
}
- /* liba52 doesn't provide us with Lt/Rt mix levels.
+ /*
+ * Decode to AV_SAMPLE_FMT_FLTP
+ */
+ pv->level = 1.0;
+ pv->dynamic_range_compression =
+ audio->config.out.dynamic_range_compression;
+ hb_audio_resample_set_sample_fmt(pv->resample, AV_SAMPLE_FMT_FLTP);
+
+ /*
+ * liba52 doesn't provide Lt/Rt mix levels, only Lo/Ro.
+ *
* When doing an Lt/Rt downmix, ignore mix levels
- * (this matches what liba52's own downmix code does). */
+ * (this matches what liba52's own downmix code does).
+ */
pv->use_mix_levels =
!(audio->config.out.mixdown == HB_AMIXDOWN_DOLBY ||
audio->config.out.mixdown == HB_AMIXDOWN_DOLBYPLII);
+
+ /*
+ * Remap from liba52 to Libav channel order
+ */
+ pv->remap = hb_audio_remap_init(AV_SAMPLE_FMT_FLTP, &hb_libav_chan_map,
+ &hb_liba52_chan_map);
+ if (pv->remap == NULL)
+ {
+ hb_error("deca52Init: hb_audio_remap_init() failed");
+ return 1;
+ }
+ }
+ else
+ {
+ pv->remap = NULL;
+ pv->resample = NULL;
}
return 0;
@@ -179,6 +207,7 @@ static void deca52Close(hb_work_object_t *w)
}
hb_audio_resample_free(pv->resample);
+ hb_audio_remap_free(pv->remap);
hb_list_empty(&pv->list);
a52_free(pv->state);
free(pv);
@@ -317,9 +346,12 @@ static hb_buffer_t* Decode(hb_work_object_t *w)
}
else
{
- int i, j, k;
+ int i, j;
+ float *block_samples;
- /* Feed liba52 */
+ /*
+ * Feed liba52
+ */
a52_frame(pv->state, pv->frame, &pv->flags, &pv->level, 0);
/*
@@ -348,11 +380,10 @@ static hb_buffer_t* Decode(hb_work_object_t *w)
{
pv->channel_layout = new_layout;
pv->nchannels = av_get_channel_layout_nb_channels(new_layout);
+ hb_audio_remap_set_channel_layout(pv->remap, pv->channel_layout);
hb_audio_resample_set_channel_layout(pv->resample,
pv->channel_layout,
pv->nchannels);
- hb_audio_remap_build_table(&hb_libav_chan_map, &hb_liba52_chan_map,
- pv->channel_layout, pv->remap_table);
}
if (pv->use_mix_levels)
{
@@ -366,28 +397,29 @@ static hb_buffer_t* Decode(hb_work_object_t *w)
return NULL;
}
- // decode all blocks before downmixing
+ /*
+ * decode all blocks before downmixing
+ */
for (i = 0; i < 6; i++)
{
- float *samples_in, *samples_out;
-
a52_block(pv->state);
- samples_in = (float*)a52_samples(pv->state);
- samples_out = (float*)(pv->buf +
- (i * pv->nchannels * 256 * sizeof(float)));
-
- // Planar -> interleaved, remap to Libav channel order
- for (j = 0; j < 256; j++)
+ block_samples = (float*)a52_samples(pv->state);
+
+ /*
+ * reset pv->samples (may have been modified by hb_audio_remap)
+ *
+ * copy samples to our internal buffer
+ */
+ for (j = 0; j < pv->nchannels; j++)
{
- for (k = 0; k < pv->nchannels; k++)
- {
- samples_out[(pv->nchannels*j)+k] =
- samples_in[(256*pv->remap_table[k])+j];
- }
+ pv->samples[j] = (uint8_t*)pv->buf[j];
+ memcpy(pv->buf[j][i], block_samples, 256 * sizeof(float));
+ block_samples += 256;
}
}
- out = hb_audio_resample(pv->resample, (void*)pv->buf, 1536);
+ hb_audio_remap(pv->remap, pv->samples, 1536);
+ out = hb_audio_resample(pv->resample, pv->samples, 1536);
}
if (out != NULL)
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index dd3c8879d..5248d5f52 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -190,7 +190,7 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job )
{
pv->resample =
hb_audio_resample_init(AV_SAMPLE_FMT_FLT,
- w->audio->config.out.mixdown, 1,
+ w->audio->config.out.mixdown,
w->audio->config.out.normalize_mix_level);
if (pv->resample == NULL)
{
@@ -1481,7 +1481,7 @@ static void decodeAudio(hb_audio_t *audio, hb_work_private_t *pv, uint8_t *data,
hb_log("decavcodec: hb_audio_resample_update() failed");
return;
}
- out = hb_audio_resample(pv->resample, (void*)frame.data[0],
+ out = hb_audio_resample(pv->resample, frame.extended_data,
frame.nb_samples);
}
diff --git a/libhb/declpcm.c b/libhb/declpcm.c
index e62e042d3..03210af81 100644
--- a/libhb/declpcm.c
+++ b/libhb/declpcm.c
@@ -163,7 +163,7 @@ static int declpcmInit( hb_work_object_t * w, hb_job_t * job )
pv->resample =
hb_audio_resample_init(AV_SAMPLE_FMT_FLT,
- w->audio->config.out.mixdown, 1,
+ w->audio->config.out.mixdown,
w->audio->config.out.normalize_mix_level);
if (pv->resample == NULL)
{
@@ -337,7 +337,7 @@ static hb_buffer_t *Decode( hb_work_object_t *w )
hb_log("declpcm: hb_audio_resample_update() failed");
return NULL;
}
- out = hb_audio_resample(pv->resample, (void*)pv->data, pv->nsamples);
+ out = hb_audio_resample(pv->resample, &pv->data, pv->nsamples);
if (out != NULL)
{
diff --git a/libhb/encavcodecaudio.c b/libhb/encavcodecaudio.c
index 867b56cc5..8da52d8b8 100644
--- a/libhb/encavcodecaudio.c
+++ b/libhb/encavcodecaudio.c
@@ -9,7 +9,6 @@
#include "hb.h"
#include "hbffmpeg.h"
-#include "audio_resample.h"
struct hb_work_private_s
{
@@ -18,12 +17,13 @@ struct hb_work_private_s
int out_discrete_channels;
int samples_per_frame;
+ unsigned long max_output_bytes;
unsigned long input_samples;
- unsigned long output_bytes;
+ uint8_t * output_buf;
+ uint8_t * input_buf;
hb_list_t * list;
- uint8_t * buf;
- hb_audio_resample_t *resample;
+ AVAudioResampleContext *avresample;
};
static int encavcodecaInit( hb_work_object_t *, hb_job_t * );
@@ -46,8 +46,9 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
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;
+ w->private_data = pv;
+ pv->job = job;
+ pv->list = hb_list_init();
codec = avcodec_find_encoder(w->codec_param);
if (codec == NULL)
@@ -113,29 +114,45 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
}
av_dict_free(&av_opts);
+ pv->context = context;
+ pv->samples_per_frame = context->frame_size;
+ pv->input_samples = context->frame_size * context->channels;
+ pv->input_buf = malloc(pv->input_samples * sizeof(float));
+ pv->max_output_bytes = (pv->input_samples *
+ av_get_bytes_per_sample(context->sample_fmt));
+
// sample_fmt conversion
- pv->resample = hb_audio_resample_init(context->sample_fmt,
- audio->config.out.mixdown, 0, 0);
- hb_audio_resample_set_sample_fmt(pv->resample, AV_SAMPLE_FMT_FLT);
- if (hb_audio_resample_update(pv->resample))
+ if (context->sample_fmt != AV_SAMPLE_FMT_FLT)
{
- hb_error("encavcodecaInit: hb_audio_resample_update() failed");
- hb_audio_resample_free(pv->resample);
- return 1;
+ pv->output_buf = malloc(pv->max_output_bytes);
+ pv->avresample = avresample_alloc_context();
+ if (pv->avresample == NULL)
+ {
+ hb_error("encavcodecaInit: avresample_alloc_context() failed");
+ return 1;
+ }
+ av_opt_set_int(pv->avresample, "in_sample_fmt",
+ AV_SAMPLE_FMT_FLT, 0);
+ av_opt_set_int(pv->avresample, "out_sample_fmt",
+ context->sample_fmt, 0);
+ av_opt_set_int(pv->avresample, "in_channel_layout",
+ context->channel_layout, 0);
+ av_opt_set_int(pv->avresample, "out_channel_layout",
+ context->channel_layout, 0);
+ if (avresample_open(pv->avresample))
+ {
+ hb_error("encavcodecaInit: avresample_open() failed");
+ avresample_free(&pv->avresample);
+ return 1;
+ }
+ }
+ else
+ {
+ pv->avresample = NULL;
+ pv->output_buf = pv->input_buf;
}
- pv->context = context;
- pv->samples_per_frame = context->frame_size;
audio->config.out.samples_per_frame = pv->samples_per_frame;
- pv->input_samples = pv->samples_per_frame * pv->out_discrete_channels;
-
- // Set a reasonable maximum output size
- pv->output_bytes = (context->channels * context->frame_size *
- av_get_bytes_per_sample(context->sample_fmt));
-
- pv->buf = malloc(pv->input_samples * sizeof(float));
-
- pv->list = hb_list_init();
if (context->extradata != NULL)
{
@@ -154,10 +171,9 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
**********************************************************************/
// Some encoders (e.g. flac) require a final NULL encode in order to
// finalize things.
-static void Finalize( hb_work_object_t * w )
+static void Finalize(hb_work_object_t *w)
{
- hb_work_private_t * pv = w->private_data;
- hb_buffer_t * buf;
+ hb_work_private_t *pv = w->private_data;
// Finalize with NULL input needed by FLAC to generate md5sum
// in context extradata
@@ -165,18 +181,19 @@ static void Finalize( hb_work_object_t * w )
// Prepare output packet
AVPacket pkt;
int got_packet;
- buf = hb_buffer_init( pv->output_bytes );
+ hb_buffer_t *buf = hb_buffer_init(pv->max_output_bytes);
av_init_packet(&pkt);
pkt.data = buf->data;
pkt.size = buf->alloc;
- avcodec_encode_audio2( pv->context, &pkt, NULL, &got_packet);
- hb_buffer_close( &buf );
+ avcodec_encode_audio2(pv->context, &pkt, NULL, &got_packet);
+ hb_buffer_close(&buf);
// Then we need to recopy the header since it was modified
- if ( pv->context->extradata )
+ if (pv->context->extradata != NULL)
{
- memcpy( w->config->extradata.bytes, pv->context->extradata, pv->context->extradata_size );
+ memcpy(w->config->extradata.bytes, pv->context->extradata,
+ pv->context->extradata_size);
w->config->extradata.length = pv->context->extradata_size;
}
}
@@ -196,19 +213,25 @@ static void encavcodecaClose(hb_work_object_t * w)
hb_avcodec_close(pv->context);
}
- if (pv->buf != NULL)
+ if (pv->output_buf != NULL)
+ {
+ free(pv->output_buf);
+ }
+ if (pv->input_buf != NULL && pv->input_buf != pv->output_buf)
{
- free(pv->buf);
- pv->buf = NULL;
+ free(pv->input_buf);
}
+ pv->output_buf = pv->input_buf = NULL;
if (pv->list != NULL)
{
hb_list_empty(&pv->list);
}
- hb_audio_resample_free(pv->resample);
- pv->resample = NULL;
+ if (pv->avresample != NULL)
+ {
+ avresample_free(&pv->avresample);
+ }
free(pv);
w->private_data = NULL;
@@ -219,7 +242,6 @@ 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 *resampled, *out;
uint64_t pts, pos;
if (hb_list_bytes(pv->list) < pv->input_samples * sizeof(float))
@@ -227,30 +249,47 @@ static hb_buffer_t* Encode(hb_work_object_t *w)
return NULL;
}
- hb_list_getbytes(pv->list, pv->buf, pv->input_samples * sizeof(float), &pts,
- &pos);
-
- // sample_fmt conversion
- resampled = hb_audio_resample(pv->resample, (void*)pv->buf,
- pv->samples_per_frame);
+ hb_list_getbytes(pv->list, pv->input_buf, pv->input_samples * sizeof(float),
+ &pts, &pos);
// Prepare input frame
- AVFrame frame;
- frame.nb_samples= pv->samples_per_frame;
- int size = av_samples_get_buffer_size(NULL, pv->context->channels,
- frame.nb_samples,
- pv->context->sample_fmt, 1);
- avcodec_fill_audio_frame(&frame, pv->context->channels,
- pv->context->sample_fmt, resampled->data, size, 1);
- // Libav requires timebase of audio input frames to be in sample_rate units
- frame.pts = pts + (90000 * pos / pv->out_discrete_channels /
- sizeof(float) / audio->config.out.samplerate);
+ int out_linesize;
+ int out_size = av_samples_get_buffer_size(&out_linesize,
+ pv->context->channels,
+ pv->samples_per_frame,
+ pv->context->sample_fmt, 1);
+ AVFrame frame = { .nb_samples = pv->samples_per_frame, };
+ avcodec_fill_audio_frame(&frame,
+ pv->context->channels, pv->context->sample_fmt,
+ pv->output_buf, out_size, 1);
+ if (pv->avresample != NULL)
+ {
+ int in_linesize;
+ av_samples_get_buffer_size(&in_linesize, pv->context->channels,
+ frame.nb_samples, AV_SAMPLE_FMT_FLT, 1);
+ int out_samples = avresample_convert(pv->avresample,
+ (void**)frame.extended_data,
+ out_linesize, frame.nb_samples,
+ (void**)&pv->input_buf,
+ in_linesize, frame.nb_samples);
+ if (out_samples != pv->samples_per_frame)
+ {
+ // we're not doing sample rate conversion, so this shouldn't happen
+ hb_log("encavcodecaWork: avresample_convert() failed");
+ return NULL;
+ }
+ }
+
+ // Libav requires that timebase of audio frames be in sample_rate units
+ frame.pts = pts + (90000 * pos / (sizeof(float) *
+ pv->out_discrete_channels *
+ audio->config.out.samplerate));
frame.pts = av_rescale(frame.pts, pv->context->sample_rate, 90000);
// Prepare output packet
AVPacket pkt;
int got_packet;
- out = hb_buffer_init(pv->output_bytes);
+ hb_buffer_t *out = hb_buffer_init(pv->max_output_bytes);
av_init_packet(&pkt);
pkt.data = out->data;
pkt.size = out->alloc;
@@ -260,7 +299,6 @@ static hb_buffer_t* Encode(hb_work_object_t *w)
if (ret < 0)
{
hb_log("encavcodeca: avcodec_encode_audio failed");
- hb_buffer_close(&resampled);
hb_buffer_close(&out);
return NULL;
}
@@ -287,12 +325,10 @@ static hb_buffer_t* Encode(hb_work_object_t *w)
}
else
{
- hb_buffer_close(&resampled);
hb_buffer_close(&out);
return Encode(w);
}
- hb_buffer_close(&resampled);
return out;
}
diff --git a/libhb/platform/macosx/encca_aac.c b/libhb/platform/macosx/encca_aac.c
index 4d6352511..fe592e340 100644
--- a/libhb/platform/macosx/encca_aac.c
+++ b/libhb/platform/macosx/encca_aac.c
@@ -389,7 +389,8 @@ static OSStatus inInputDataProc(AudioConverterRef converter, UInt32 *npackets,
*npackets = buffers->mBuffers[0].mDataByteSize / pv->isamplesiz;
pv->ibytes -= buffers->mBuffers[0].mDataByteSize;
- hb_audio_remap(pv->remap, (uint8_t*)buffers->mBuffers[0].mData, *npackets);
+ hb_audio_remap(pv->remap, (uint8_t**)(&buffers->mBuffers[0].mData),
+ (int)(*npackets));
return noErr;
}