]> granicus.if.org Git - handbrake/commitdiff
Improve support for planar audio.
authorRodeo <tdskywalker@gmail.com>
Wed, 21 Nov 2012 18:29:34 +0000 (18:29 +0000)
committerRodeo <tdskywalker@gmail.com>
Wed, 21 Nov 2012 18:29:34 +0000 (18:29 +0000)
- 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

libhb/audio_remap.c
libhb/audio_remap.h
libhb/audio_resample.c
libhb/audio_resample.h
libhb/deca52.c
libhb/decavcodec.c
libhb/declpcm.c
libhb/encavcodecaudio.c
libhb/platform/macosx/encca_aac.c

index 6daaee9fbbb24288f5ab59ce7230b7d8b85c8b80..afc9c3209211b479264841771b23c929e7ecf135 100644 (file)
@@ -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);
     }
 }
 
index a776fe57b27e850403bb4cab7ff3dd029067e1ba..0bdd23bb71b2bd61c9e01695ba1ceb17655b2d1d 100644 (file)
@@ -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);
 
 /*
index 927a3b7c4807b316a276e093bc5c887810479497..cc9b50d8b196b60cdda744fc35ab4448e34c306b 100644 (file)
 #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;
index baee471a62b701382d43ccb315d4a9187c2a9e9d..62a536d61565f6f65b948410f7ee5c5a635576f7 100644 (file)
@@ -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 */
index 3a6e71e956f16979589480378fb5776859467333..ba7c38485d71919720aa2ebb701aced0345606b3 100644 (file)
@@ -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)
index dd3c8879db0f97be92609d3d16fb9b5c13fa6a4a..5248d5f52ad92756dcab18793a023ca53ea44645 100644 (file)
@@ -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);
             }
 
index e62e042d3ce54838acc9ad1dba51fd02b46b53fc..03210af81aac38aae21bb3e36d6a445573ab0d8e 100644 (file)
@@ -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)
     {
index 867b56cc5a454bb43b9d7a05125276a0f29f43be..8da52d8b86f5e3c3a229907d189d97b76f37a9ff 100644 (file)
@@ -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;
 }
 
index 4d6352511f66a7722fc3d4c4d011c1bce886c740..fe592e34093993c97bb7900e79aa98181916587a 100644 (file)
@@ -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;
 }