summaryrefslogtreecommitdiffstats
path: root/audio/filter/af_lavcac3enc.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/filter/af_lavcac3enc.c')
-rw-r--r--audio/filter/af_lavcac3enc.c216
1 files changed, 82 insertions, 134 deletions
diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c
index de7d563b76..dc2aeb5045 100644
--- a/audio/filter/af_lavcac3enc.c
+++ b/audio/filter/af_lavcac3enc.c
@@ -34,7 +34,8 @@
#include "config.h"
#include "af.h"
-#include "audio/reorder_ch.h"
+#include "audio/audio_buffer.h"
+#include "audio/fmt-conversion.h"
#define AC3_MAX_CHANNELS 6
@@ -53,10 +54,9 @@ typedef struct af_ac3enc_s {
bool planarize;
int add_iec61937_header;
int bit_rate;
- int pending_data_size;
- char *pending_data;
- int pending_len;
- int expect_len;
+ struct mp_audio_buffer *pending;
+ int in_samples; // samples of input per AC3 frame
+ int out_samples; // upper bound on encoded output per AC3 frame
int min_channel_num;
int in_sampleformat;
} af_ac3enc_t;
@@ -93,17 +93,18 @@ static int control(struct af_instance *af, int cmd, void *arg)
if (!mp_audio_config_equals(in, &orig_in))
return AF_FALSE;
- s->pending_len = 0;
- int expect_samples = AC3_FRAME_SIZE;
- s->expect_len = expect_samples * in->nch * in->bps;
- assert(s->expect_len <= s->pending_data_size);
- if (s->add_iec61937_header)
- af->mul = 1;
- else
- af->mul = (double)(AC3_MAX_CODED_FRAME_SIZE / (2 * 2)) / expect_samples;
+ s->in_samples = AC3_FRAME_SIZE;
+ if (s->add_iec61937_header) {
+ s->out_samples = AC3_FRAME_SIZE;
+ } else {
+ s->out_samples = AC3_MAX_CODED_FRAME_SIZE / af->data->sstride;
+ }
+ af->mul = s->out_samples / (double)s->in_samples;
+
+ mp_audio_buffer_reinit(s->pending, in);
mp_msg(MSGT_AFILTER, MSGL_DBG2, "af_lavcac3enc reinit: %d, %d, %f, %d.\n",
- in->nch, in->rate, af->mul, s->expect_len);
+ in->nch, in->rate, af->mul, s->in_samples);
bit_rate = s->bit_rate ? s->bit_rate : default_bit_rate[in->nch];
@@ -172,83 +173,56 @@ static void uninit(struct af_instance* af)
avcodec_close(s->lavc_actx);
av_free(s->lavc_actx);
}
- free(s->pending_data);
- free(s);
}
}
// Filter data through filter
static struct mp_audio* play(struct af_instance* af, struct mp_audio* audio)
{
+ struct mp_audio *out = af->data;
af_ac3enc_t *s = af->setup;
- struct mp_audio *c = audio; // Current working data
- struct mp_audio *l;
- int left, outsize = 0;
- char *buf, *src;
- int max_output_len;
- int frame_num = (mp_audio_psize(audio) + s->pending_len) / s->expect_len;
- int samplesize = af_fmt2bits(s->in_sampleformat) / 8;
-
- if (s->add_iec61937_header)
- max_output_len = AC3_FRAME_SIZE * 2 * 2 * frame_num;
- else
- max_output_len = AC3_MAX_CODED_FRAME_SIZE * frame_num;
+ int num_frames = (audio->samples + mp_audio_buffer_samples(s->pending))
+ / s->in_samples;
- mp_audio_realloc_min(af->data, max_output_len / af->data->sstride);
- af->data->samples = max_output_len / af->data->sstride;
+ int max_out_samples = s->out_samples * num_frames;
+ mp_audio_realloc_min(out, max_out_samples);
+ out->samples = 0;
- l = af->data; // Local data
- buf = l->planes[0];
- src = c->planes[0];
- left = mp_audio_psize(c);
-
-
- while (left > 0) {
+ while (audio->samples > 0) {
int ret;
- if (left + s->pending_len < s->expect_len) {
- memcpy(s->pending_data + s->pending_len, src, left);
- src += left;
- s->pending_len += left;
- left = 0;
- break;
- }
-
- char *src2 = src;
-
- if (s->pending_len) {
- int needs = s->expect_len - s->pending_len;
- if (needs > 0) {
- memcpy(s->pending_data + s->pending_len, src, needs);
- src += needs;
- left -= needs;
+ int consumed_pending = 0;
+ struct mp_audio in_frame;
+ int pending = mp_audio_buffer_samples(s->pending);
+ if (pending == 0 && audio->samples >= s->in_samples) {
+ in_frame = *audio;
+ mp_audio_skip_samples(audio, s->in_samples);
+ } else {
+ if (pending > 0 && pending < s->in_samples) {
+ struct mp_audio tmp = *audio;
+ tmp.samples = MPMIN(tmp.samples, s->in_samples);
+ mp_audio_buffer_append(s->pending, &tmp);
+ mp_audio_skip_samples(audio, tmp.samples);
}
- src2= s->pending_data;
- }
-
- void *data = (void *) src2;
- if (s->planarize) {
- void *data2 = malloc(s->expect_len);
- reorder_to_planar(data2, data, samplesize,
- c->nch, s->expect_len / samplesize / c->nch);
- data = data2;
+ mp_audio_buffer_peek(s->pending, &in_frame);
+ if (in_frame.samples < s->in_samples)
+ break;
+ consumed_pending = s->in_samples;
}
+ in_frame.samples = s->in_samples;
AVFrame *frame = avcodec_alloc_frame();
if (!frame) {
mp_msg(MSGT_AFILTER, MSGL_FATAL, "[libaf] Could not allocate memory \n");
return NULL;
}
- frame->nb_samples = AC3_FRAME_SIZE;
+ frame->nb_samples = s->in_samples;
frame->format = s->lavc_actx->sample_fmt;
frame->channel_layout = s->lavc_actx->channel_layout;
-
- ret = avcodec_fill_audio_frame(frame, c->nch, s->lavc_actx->sample_fmt,
- (const uint8_t*)data, s->expect_len, 0);
- if (ret < 0) {
- mp_msg(MSGT_AFILTER, MSGL_FATAL, "[lavac3enc] Frame setup failed.\n");
- return NULL;
- }
+ assert(in_frame.num_planes <= AV_NUM_DATA_POINTERS);
+ for (int n = 0; n < in_frame.num_planes; n++)
+ frame->data[n] = in_frame.planes[n];
+ frame->linesize[0] = s->in_samples * audio->sstride;
int ok;
ret = avcodec_encode_audio2(s->lavc_actx, &s->pkt, frame, &ok);
@@ -257,58 +231,52 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* audio)
return NULL;
}
- if (s->planarize)
- free(data);
-
avcodec_free_frame(&frame);
- if (s->pending_len) {
- s->pending_len = 0;
- } else {
- src += s->expect_len;
- left -= s->expect_len;
- }
+ mp_audio_buffer_skip(s->pending, consumed_pending);
mp_msg(MSGT_AFILTER, MSGL_DBG2, "avcodec_encode_audio got %d, pending %d.\n",
- s->pkt.size, s->pending_len);
+ s->pkt.size, mp_audio_buffer_samples(s->pending));
- int len = s->pkt.size;
+ int frame_size = s->pkt.size;
int header_len = 0;
- if (s->add_iec61937_header) {
- assert(s->pkt.size > 5);
- int bsmod = s->pkt.data[5] & 0x7;
+ char hdr[8];
- AV_WB16(buf, 0xF872); // iec 61937 syncword 1
- AV_WB16(buf + 2, 0x4E1F); // iec 61937 syncword 2
- buf[4] = bsmod; // bsmod
- buf[5] = 0x01; // data-type ac3
- AV_WB16(buf + 6, len << 3); // number of bits in payload
+ if (s->add_iec61937_header && s->pkt.size > 5) {
+ int bsmod = s->pkt.data[5] & 0x7;
+ int len = frame_size;
- memset(buf + 8 + len, 0, AC3_FRAME_SIZE * 2 * 2 - 8 - len);
+ frame_size = AC3_FRAME_SIZE * 2 * 2;
header_len = 8;
- len = AC3_FRAME_SIZE * 2 * 2;
+
+ AV_WB16(hdr, 0xF872); // iec 61937 syncword 1
+ AV_WB16(hdr + 2, 0x4E1F); // iec 61937 syncword 2
+ hdr[4] = bsmod; // bsmod
+ hdr[5] = 0x01; // data-type ac3
+ AV_WB16(hdr + 6, len << 3); // number of bits in payload
}
- assert(buf + len <= (char *)af->data->planes[0] + mp_audio_psize(af->data));
- assert(s->pkt.size <= len - header_len);
+ size_t max_size = (max_out_samples - out->samples) * out->sstride;
+ if (frame_size > max_size)
+ abort();
+ char *buf = (char *)out->planes[0] + out->samples * out->sstride;
+ memcpy(buf, hdr, header_len);
memcpy(buf + header_len, s->pkt.data, s->pkt.size);
-
- outsize += len;
- buf += len;
+ memset(buf + header_len + s->pkt.size, 0,
+ frame_size - (header_len + s->pkt.size));
+ out->samples += frame_size / out->sstride;
}
- c->planes[0] = l->planes[0];
- mp_audio_set_num_channels(c, 2);
- mp_audio_set_format(c, af->data->format);
- c->samples = outsize / c->sstride;
- mp_msg(MSGT_AFILTER, MSGL_DBG2, "play return size %d, pending %d\n",
- outsize, s->pending_len);
- return c;
+
+ mp_audio_buffer_append(s->pending, audio);
+
+ *audio = *out;
+ return audio;
}
static int af_open(struct af_instance* af){
- af_ac3enc_t *s = calloc(1,sizeof(af_ac3enc_t));
+ af_ac3enc_t *s = talloc_zero(af, af_ac3enc_t);
af->control=control;
af->uninit=uninit;
af->play=play;
@@ -326,45 +294,25 @@ static int af_open(struct af_instance* af){
return AF_ERROR;
}
const enum AVSampleFormat *fmts = s->lavc_acodec->sample_fmts;
- for (int i = 0; ; i++) {
- if (fmts[i] == AV_SAMPLE_FMT_NONE) {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "Audio LAVC, encoder doesn't "
- "support expected sample formats!\n");
- return AF_ERROR;
- } else if (fmts[i] == AV_SAMPLE_FMT_S16) {
- s->in_sampleformat = AF_FORMAT_S16_NE;
+ for (int i = 0; fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
+ s->in_sampleformat = af_from_avformat(fmts[i]);
+ if (s->in_sampleformat) {
s->lavc_actx->sample_fmt = fmts[i];
- s->planarize = 0;
- break;
- } else if (fmts[i] == AV_SAMPLE_FMT_FLT) {
- s->in_sampleformat = AF_FORMAT_FLOAT_NE;
- s->lavc_actx->sample_fmt = fmts[i];
- s->planarize = 0;
- break;
- } else if (fmts[i] == AV_SAMPLE_FMT_S16P) {
- s->in_sampleformat = AF_FORMAT_S16_NE;
- s->lavc_actx->sample_fmt = fmts[i];
- s->planarize = 1;
- break;
- } else if (fmts[i] == AV_SAMPLE_FMT_FLTP) {
- s->in_sampleformat = AF_FORMAT_FLOAT_NE;
- s->lavc_actx->sample_fmt = fmts[i];
- s->planarize = 1;
break;
}
}
+ if (!s->in_sampleformat) {
+ mp_msg(MSGT_AFILTER, MSGL_ERR, "Audio LAVC, encoder doesn't "
+ "support expected sample formats!\n");
+ return AF_ERROR;
+ }
mp_msg(MSGT_AFILTER, MSGL_V, "[af_lavcac3enc]: in sample format: %s\n",
af_fmt_to_str(s->in_sampleformat));
- s->pending_data_size = AF_NCH * AC3_FRAME_SIZE *
- af_fmt2bits(s->in_sampleformat) / 8;
- s->pending_data = malloc(s->pending_data_size);
-
- if (s->planarize)
- mp_msg(MSGT_AFILTER, MSGL_WARN,
- "[af_lavcac3enc]: need to planarize audio data\n");
av_init_packet(&s->pkt);
+ s->pending = mp_audio_buffer_create(af);
+
return AF_OK;
}