Commit c533ea9d authored by Stefan Westerfeld's avatar Stefan Westerfeld

avfilter/asubprocess: use wav header instead of headerless stream data

Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent 75956610
#include "libavutil/opt.h"
#include "libavutil/mem.h"
#include "libavformat/avio.h"
#include "libavformat/avio_internal.h"
#include "audio.h"
#include "avfilter.h"
......@@ -186,12 +189,22 @@ sp_write (SP *sp, char *buffer, int count)
}
// =============================================
enum {
STATE_EXPECT_RIFF = 0,
STATE_EXPECT_CHUNK = 1,
STATE_SKIP_CHUNK = 2,
STATE_IN_DATA_CHUNK = 3,
STATE_ERROR = 4
};
typedef struct AndioWMarkContext {
const AVClass *class;
double strength;
int fd;
int state;
unsigned int state_skip;
SP *sp;
int nb_samples;
int eof;
......@@ -223,7 +236,32 @@ static int config_input(AVFilterLink *inlink)
AVFilterContext *ctx = inlink->dst;
AudioWMarkContext *s = ctx->priv;
// TODO: use inlink->sample_rate, inlink->ch_layout.nb_channels
s->sp = sp_new ("audiowmark -q add --format raw --raw-rate 44100 - - f0");
s->sp = sp_new ("audiowmark -q add - - f0");
int bit_depth = 16;
int sample_rate = inlink->sample_rate;
int nb_channels = inlink->ch_layout.nb_channels;
AVIOContext *wav_header = NULL;
uint8_t *buffer = NULL;
avio_open_dyn_buf (&wav_header);
ffio_wfourcc(wav_header, "RIFF");
avio_wl32(wav_header, -1);
ffio_wfourcc(wav_header, "WAVE");
// subchunk 1
ffio_wfourcc(wav_header, "fmt ");
avio_wl32 (wav_header, 16); // subchunk size
avio_wl16 (wav_header, 1); // uncompressed audio
avio_wl16 (wav_header, nb_channels);
avio_wl32 (wav_header, sample_rate);
avio_wl32 (wav_header, sample_rate * nb_channels * bit_depth / 8); // byte rate
avio_wl16 (wav_header, nb_channels * bit_depth / 8); // block align
avio_wl16 (wav_header, bit_depth); // bits per sample
// subchunk 2
ffio_wfourcc (wav_header, "data");
avio_wl32 (wav_header, -1);
int sz = avio_close_dyn_buf (wav_header, &buffer);
sp_write (s->sp, buffer, sz);
av_free (buffer);
#if 0
int opts = s->transients|s->detector|s->phase|s->window|
s->smoothing|s->formant|s->opitch|s->channels|
......@@ -239,6 +277,7 @@ static int config_input(AVFilterLink *inlink)
s->first_pts = AV_NOPTS_VALUE;
#endif
s->nb_samples = 1024;
s->state = STATE_EXPECT_RIFF;
return 0;
}
......@@ -251,49 +290,82 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
AVFrame *out;
int ret = 0, nb_samples;
short buffer[100000];
int k = 0;
for (int i = 0; i < in->nb_samples; i++)
{
for (int j = 0; j < inlink->ch_layout.nb_channels; j++)
{
float **xd = (float **)in->extended_data;
short ss = xd[j][i]*32000;
sp_write (s->sp, &ss, 2);
buffer[k++] = xd[j][i]*32000;
}
}
sp_write (s->sp, buffer, 2 * k);
if (s->eof)
{
while (!sp_write (s->sp, 0, 0))
;
printf ("eof\n");
while (!sp_write (s->sp, 0, 0))
;
printf ("eof\n");
}
bool gen_output = true;
while (gen_output)
{
int avail = sp_can_read (s->sp) / 2 / inlink->ch_layout.nb_channels;
if (avail > 2048)
avail = 2048;
if (avail > 0)
if (s->state == STATE_EXPECT_RIFF)
if (sp_can_read (s->sp) >= 12)
{
sp_read (s->sp, buffer, 12);
s->state = STATE_EXPECT_CHUNK;
}
if (s->state == STATE_EXPECT_CHUNK)
if (sp_can_read (s->sp) >= 8)
{
unsigned char x[8];
sp_read (s->sp, x, 8);
if (x[0] == 'd' && x[1] == 'a' && x[2] == 't' && x[3] == 'a')
s->state = STATE_IN_DATA_CHUNK;
else
{
s->state = STATE_SKIP_CHUNK;
s->state_skip = x[4] + (x[5] << 8) + (x[6] << 16) + (x[7] << 24);
}
}
if (s->state == STATE_SKIP_CHUNK && sp_can_read (s->sp) >= s->state_skip)
{
out = ff_get_audio_buffer(outlink, avail);
if (!out) {
av_frame_free(&in);
return AVERROR(ENOMEM);
while (s->state_skip)
{
char buffer[1024];
unsigned int n = FFMIN (sizeof (buffer), s->state_skip);
sp_read (s->sp, buffer, n);
s->state_skip -= n;
}
short buffer[100000]; // FIXME avail * inlink->ch_layout.nb_channels];
sp_read (s->sp, buffer, avail * 2 * inlink->ch_layout.nb_channels);
int k = 0;
for (int i = 0; i < avail; i++)
{
for (int j = 0; j < inlink->ch_layout.nb_channels; j++)
{
float **xd = (float **)out->extended_data;
xd[j][i] = buffer[k++] * (1/32000.);
}
}
ret = ff_filter_frame(outlink, out);
s->state = STATE_EXPECT_CHUNK;
}
else
gen_output = false;
bool gen_output = s->state == STATE_IN_DATA_CHUNK;
while (gen_output)
{
int avail = sp_can_read (s->sp) / 2 / inlink->ch_layout.nb_channels;
if (avail > 2048)
avail = 2048;
if (avail > 0)
{
out = ff_get_audio_buffer(outlink, avail);
if (!out) {
av_frame_free(&in);
return AVERROR(ENOMEM);
}
short buffer[100000]; // FIXME avail * inlink->ch_layout.nb_channels];
sp_read (s->sp, buffer, avail * 2 * inlink->ch_layout.nb_channels);
int k = 0;
for (int i = 0; i < avail; i++)
{
for (int j = 0; j < inlink->ch_layout.nb_channels; j++)
{
float **xd = (float **)out->extended_data;
xd[j][i] = buffer[k++] * (1/32000.);
}
}
ret = ff_filter_frame(outlink, out);
}
else {
gen_output = false;
}
}
#if 0
if (s->first_pts == AV_NOPTS_VALUE)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment