Commit 4a465a05 authored by Stefan Westerfeld's avatar Stefan Westerfeld

avfilter/asubprocess: add checks for subprocess output (should be wav)

Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent 58bad47d
......@@ -486,14 +486,20 @@ static int write_frame(AVFilterContext *ctx, ASubProcessContext *s, AVFilterLink
return ret;
}
static int try_read_frame(ASubProcessContext *s, AVFilterLink *outlink)
static int try_read_frame(AVFilterContext *ctx)
{
AVFilterLink *outlink = ctx->outputs[0];
ASubProcessContext *s = ctx->priv;
int ret;
if (s->state == STATE_EXPECT_RIFF && sp_can_read(s->sp) >= 12)
{
char buffer[12];
sp_read(s->sp, buffer, 12);
if ((memcmp (buffer, "RIFF", 4) && memcmp (buffer, "RF64", 4)) || memcmp (buffer + 8, "WAVE", 4)) {
av_log(ctx, AV_LOG_ERROR, "Subprocess output is not a valid wav file.\n");
return AVERROR_INVALIDDATA;
}
s->state = STATE_EXPECT_CHUNK;
}
if (s->state == STATE_EXPECT_CHUNK && sp_can_read(s->sp) >= 8)
......@@ -501,9 +507,9 @@ static int try_read_frame(ASubProcessContext *s, AVFilterLink *outlink)
unsigned char x[8];
sp_read(s->sp, x, 8);
s->chunk_size = AV_RL32 (x + 4);
if (x[0] == 'd' && x[1] == 'a' && x[2] == 't' && x[3] == 'a')
if (!memcmp (x, "data", 4))
s->state = STATE_IN_DATA_CHUNK;
else if (x[0] == 'f' && x[1] == 'm' && x[2] == 't' && x[3] == ' ' && s->chunk_size >= 16)
else if (!memcmp (x, "fmt ", 4) && s->chunk_size >= 16)
s->state = STATE_IN_FMT_CHUNK;
else
s->state = STATE_SKIP_CHUNK;
......@@ -511,8 +517,35 @@ static int try_read_frame(ASubProcessContext *s, AVFilterLink *outlink)
if (s->state == STATE_IN_FMT_CHUNK && sp_can_read(s->sp) >= 16)
{
unsigned char data[16];
int format, nb_channels, sample_rate;
sp_read(s->sp, data, 16);
s->out_bit_depth = AV_RL16 (data + 14);
format = AV_RL16(data);
nb_channels = AV_RL16(data + 2);
sample_rate = AV_RL32(data + 4);
s->out_bit_depth = AV_RL16(data + 14);
if (format != 1 && format != 0xFFFE) { // TODO: check extensible wav format: should be PCM
av_log(ctx, AV_LOG_ERROR,
"Unsupported wav format (%d) from subprocess (expected PCM).\n", format);
return AVERROR_INVALIDDATA;
}
if (nb_channels != outlink->ch_layout.nb_channels) {
av_log(ctx, AV_LOG_ERROR,
"Number of output channels (%d) from subprocess doesn't match input channels (%d).\n",
nb_channels, outlink->ch_layout.nb_channels);
return AVERROR_INVALIDDATA;
}
if (sample_rate != outlink->sample_rate) {
av_log(ctx, AV_LOG_ERROR,
"Sample rate (%d) from subprocess doesn't match input sample rate (%d).\n",
sample_rate, outlink->sample_rate);
return AVERROR_INVALIDDATA;
}
if (s->out_bit_depth != 8 && s->out_bit_depth != 16 && s->out_bit_depth != 24 && s->out_bit_depth != 32) {
av_log(ctx, AV_LOG_ERROR, "Unsupported output wav bit depth (%d) from subprocess.\n", s->out_bit_depth);
return AVERROR_INVALIDDATA;
}
s->chunk_size -= 16;
s->state = STATE_SKIP_CHUNK;
}
......@@ -560,7 +593,7 @@ static int activate(AVFilterContext *ctx)
FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
ret = try_read_frame(s, outlink);
ret = try_read_frame(ctx);
if (ret != 0)
return ret;
ret = ff_inlink_consume_frame(inlink, &in);
......@@ -588,11 +621,15 @@ static int activate(AVFilterContext *ctx)
return ret;
}
}
ret = try_read_frame(s, outlink);
ret = try_read_frame(ctx);
if (ret != 0)
return ret;
if (s->eof) {
if (s->state != STATE_IN_DATA_CHUNK) {
av_log(ctx, AV_LOG_ERROR, "Subprocess output wav is incomplete (no data chunk found)\n");
return AVERROR_INVALIDDATA;
}
// s->last_pts
ff_outlink_set_status(outlink, AVERROR_EOF, AV_NOPTS_VALUE);
return 0;
......
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