History

avfilter/af_biquads: always return same number of samples with block processing

Paul B Mahol committed 4 years ago

Commit b5aa5141 parent 30e2bb01 file · +56 −12Browse files

Unified · Split

libavfilter/af_biquads.c+56−12
@@ -149,6 +149,9 @@ typedef struct BiquadsContext { · 148 unmodified lines
149 ChanCache *cache;149 ChanCache *cache;
150 int block_align;150 int block_align;
151 151
152 int64_t pts;
153 int nb_samples;
154
152 void (*filter)(struct BiquadsContext *s, const void *ibuf, void *obuf, int len,155 void (*filter)(struct BiquadsContext *s, const void *ibuf, void *obuf, int len,
153 double *i1, double *i2, double *o1, double *o2,156 double *i1, double *i2, double *o1, double *o2,
154 double b0, double b1, double b2, double a0, double a1, double a2, int *clippings,157 double b0, double b1, double b2, double a0, double a1, double a2, int *clippings,
@@ -995,7 +998,6 @@ static int config_filter(AVFilterLink *outlink, int reset) · 840 unmodified lines
995 return AVERROR(ENOMEM);998 return AVERROR(ENOMEM);
996 av_samples_set_silence(s->block[i]->extended_data, 0, s->block_samples * 2,999 av_samples_set_silence(s->block[i]->extended_data, 0, s->block_samples * 2,
997 s->block[i]->ch_layout.nb_channels, s->block[i]->format);1000 s->block[i]->ch_layout.nb_channels, s->block[i]->format);
998
999 }1001 }
1000 }1002 }
1001 1003
@@ -1142,6 +1144,7 @@ static int config_output(AVFilterLink *outlink) · 140 unmodified lines
1142 1144
1143typedef struct ThreadData {1145typedef struct ThreadData {
1144 AVFrame *in, *out;1146 AVFrame *in, *out;
1147 int eof;
1145} ThreadData;1148} ThreadData;
1146 1149
1147static void reverse_samples(AVFrame *out, AVFrame *in, int p,1150static void reverse_samples(AVFrame *out, AVFrame *in, int p,
@@ -1194,7 +1197,6 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job · 46 unmodified lines
1194 enum AVChannel channel = av_channel_layout_channel_from_index(&inlink->ch_layout, ch);1197 enum AVChannel channel = av_channel_layout_channel_from_index(&inlink->ch_layout, ch);
1195 1198
1196 if (av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0) {1199 if (av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0) {
1197
1198 if (buf != out_buf)1200 if (buf != out_buf)
1199 memcpy(out_buf->extended_data[ch], buf->extended_data[ch],1201 memcpy(out_buf->extended_data[ch], buf->extended_data[ch],
1200 buf->nb_samples * s->block_align);1202 buf->nb_samples * s->block_align);
@@ -1205,9 +1207,14 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job · 4 unmodified lines
1205 s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples,1207 s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples,
1206 &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2,1208 &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2,
1207 s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);1209 s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);
1210 } else if (td->eof) {
1211 memcpy(out_buf->extended_data[ch], s->block[1]->extended_data[ch] + s->block_align * s->block_samples,
1212 s->nb_samples * s->block_align);
1208 } else {1213 } else {
1209 memcpy(s->block[0]->extended_data[ch] + s->block_align * s->block_samples, buf->extended_data[ch],1214 memcpy(s->block[0]->extended_data[ch] + s->block_align * s->block_samples, buf->extended_data[ch],
1210 buf->nb_samples * s->block_align);1215 buf->nb_samples * s->block_align);
1216 memset(s->block[0]->extended_data[ch] + s->block_align * (s->block_samples + buf->nb_samples),
1217 0, (s->block_samples - buf->nb_samples) * s->block_align);
1211 s->filter(s, s->block[0]->extended_data[ch], s->block[1]->extended_data[ch], s->block_samples,1218 s->filter(s, s->block[0]->extended_data[ch], s->block[1]->extended_data[ch], s->block_samples,
1212 &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2,1219 &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2,
1213 s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);1220 s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);
@@ -1220,15 +1227,17 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job · 6 unmodified lines
1220 s->block_samples,1227 s->block_samples,
1221 &s->cache[ch].ri1, &s->cache[ch].ri2, &s->cache[ch].ro1, &s->cache[ch].ro2,1228 &s->cache[ch].ri1, &s->cache[ch].ri2, &s->cache[ch].ro1, &s->cache[ch].ro2,
1222 s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);1229 s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);
1223 reverse_samples(s->block[2], s->block[1], ch, 0, 0, s->block_samples * 2);1230 reverse_samples(s->block[2], s->block[1], ch, 0, 0, 2 * s->block_samples);
1224 s->cache[ch].ri1 = 0.;1231 s->cache[ch].ri1 = 0.;
1225 s->cache[ch].ri2 = 0.;1232 s->cache[ch].ri2 = 0.;
1226 s->cache[ch].ro1 = 0.;1233 s->cache[ch].ro1 = 0.;
1227 s->cache[ch].ro2 = 0.;1234 s->cache[ch].ro2 = 0.;
1228 s->filter(s, s->block[2]->extended_data[ch], s->block[2]->extended_data[ch], s->block[2]->nb_samples,1235 s->filter(s, s->block[2]->extended_data[ch], s->block[2]->extended_data[ch], 2 * s->block_samples,
1229 &s->cache[ch].ri1, &s->cache[ch].ri2, &s->cache[ch].ro1, &s->cache[ch].ro2,1236 &s->cache[ch].ri1, &s->cache[ch].ri2, &s->cache[ch].ro1, &s->cache[ch].ro2,
1230 s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);1237 s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);
1231 reverse_samples(out_buf, s->block[2], ch, 0, s->block_samples, out_buf->nb_samples);1238 reverse_samples(s->block[1], s->block[2], ch, 0, 0, 2 * s->block_samples);
1239 memcpy(out_buf->extended_data[ch], s->block[1]->extended_data[ch],
1240 s->block_samples * s->block_align);
1232 memmove(s->block[0]->extended_data[ch], s->block[0]->extended_data[ch] + s->block_align * s->block_samples,1241 memmove(s->block[0]->extended_data[ch], s->block[0]->extended_data[ch] + s->block_align * s->block_samples,
1233 s->block_samples * s->block_align);1242 s->block_samples * s->block_align);
1234 }1243 }
@@ -1237,14 +1246,14 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job · 2 unmodified lines
1237 return 0;1246 return 0;
1238}1247}
1239 1248
1240static int filter_frame(AVFilterLink *inlink, AVFrame *buf)1249static int filter_frame(AVFilterLink *inlink, AVFrame *buf, int eof)
1241{1250{
1242 AVFilterContext *ctx = inlink->dst;1251 AVFilterContext *ctx = inlink->dst;
1243 BiquadsContext *s = ctx->priv;1252 BiquadsContext *s = ctx->priv;
1244 AVFilterLink *outlink = ctx->outputs[0];1253 AVFilterLink *outlink = ctx->outputs[0];
1245 AVFrame *out_buf;1254 AVFrame *out_buf;
1246 ThreadData td;1255 ThreadData td;
1247 int ch, ret;1256 int ch, ret, drop = 0;
1248 1257
1249 if (s->bypass)1258 if (s->bypass)
1250 return ff_filter_frame(outlink, buf);1259 return ff_filter_frame(outlink, buf);
@@ -1258,10 +1267,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) · 7 unmodified lines
1258 av_channel_layout_from_string(&s->ch_layout,1267 av_channel_layout_from_string(&s->ch_layout,
1259 s->ch_layout_str);1268 s->ch_layout_str);
1260 1269
1261 if (av_frame_is_writable(buf)) {1270 if (av_frame_is_writable(buf) && s->block_samples == 0) {
1262 out_buf = buf;1271 out_buf = buf;
1263 } else {1272 } else {
1264 out_buf = ff_get_audio_buffer(outlink, buf->nb_samples);1273 out_buf = ff_get_audio_buffer(outlink, s->block_samples > 0 ? s->block_samples : buf->nb_samples);
1265 if (!out_buf) {1274 if (!out_buf) {
1266 av_frame_free(&buf);1275 av_frame_free(&buf);
1267 return AVERROR(ENOMEM);1276 return AVERROR(ENOMEM);
@@ -1269,8 +1278,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) · 1 unmodified line
1269 av_frame_copy_props(out_buf, buf);1278 av_frame_copy_props(out_buf, buf);
1270 }1279 }
1271 1280
1281 if (s->block_samples > 0 && s->pts == AV_NOPTS_VALUE)
1282 drop = 1;
1272 td.in = buf;1283 td.in = buf;
1273 td.out = out_buf;1284 td.out = out_buf;
1285 td.eof = eof;
1274 ff_filter_execute(ctx, filter_channel, &td, NULL,1286 ff_filter_execute(ctx, filter_channel, &td, NULL,
1275 FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx)));1287 FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx)));
1276 1288
@@ -1281,10 +1293,26 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) · 4 unmodified lines
1281 s->cache[ch].clippings = 0;1293 s->cache[ch].clippings = 0;
1282 }1294 }
1283 1295
1296 if (s->block_samples > 0) {
1297 int nb_samples = buf->nb_samples;
1298 int64_t pts = buf->pts;
1299
1300 out_buf->pts = s->pts;
1301 out_buf->nb_samples = s->nb_samples;
1302 s->pts = pts;
1303 s->nb_samples = nb_samples;
1304 }
1305
1284 if (buf != out_buf)1306 if (buf != out_buf)
1285 av_frame_free(&buf);1307 av_frame_free(&buf);
1286 1308
1287 return ff_filter_frame(outlink, out_buf);1309 if (!drop)
1310 return ff_filter_frame(outlink, out_buf);
1311 else {
1312 av_frame_free(&out_buf);
1313 ff_filter_set_ready(ctx, 10);
1314 return 0;
1315 }
1288}1316}
1289 1317
1290static int activate(AVFilterContext *ctx)1318static int activate(AVFilterContext *ctx)
@@ -1293,6 +1321,8 @@ static int activate(AVFilterContext *ctx) · 2 unmodified lines
1293 AVFilterLink *outlink = ctx->outputs[0];1321 AVFilterLink *outlink = ctx->outputs[0];
1294 BiquadsContext *s = ctx->priv;1322 BiquadsContext *s = ctx->priv;
1295 AVFrame *in = NULL;1323 AVFrame *in = NULL;
1324 int64_t pts;
1325 int status;
1296 int ret;1326 int ret;
1297 1327
1298 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);1328 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
@@ -1305,14 +1335,27 @@ static int activate(AVFilterContext *ctx) · 6 unmodified lines
1305 if (ret < 0)1335 if (ret < 0)
1306 return ret;1336 return ret;
1307 if (ret > 0)1337 if (ret > 0)
1308 return filter_frame(inlink, in);1338 return filter_frame(inlink, in, 0);
1309 1339
1310 if (s->block_samples > 0 && ff_inlink_queued_samples(inlink) >= s->block_samples) {1340 if (s->block_samples > 0 && ff_inlink_queued_samples(inlink) >= s->block_samples) {
1311 ff_filter_set_ready(ctx, 10);1341 ff_filter_set_ready(ctx, 10);
1312 return 0;1342 return 0;
1313 }1343 }
1314 1344
1315 FF_FILTER_FORWARD_STATUS(inlink, outlink);1345 if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
1346 if (s->block_samples > 0) {
1347 AVFrame *in = ff_get_audio_buffer(outlink, s->block_samples);
1348 if (!in)
1349 return AVERROR(ENOMEM);
1350
1351 ret = filter_frame(inlink, in, 1);
1352 }
1353
1354 ff_outlink_set_status(outlink, status, pts);
1355
1356 return ret;
1357 }
1358
1316 FF_FILTER_FORWARD_WANTED(outlink, inlink);1359 FF_FILTER_FORWARD_WANTED(outlink, inlink);
1317 1360
1318 return FFERROR_NOT_READY;1361 return FFERROR_NOT_READY;
@@ -1365,6 +1408,7 @@ static av_cold int name_##_init(AVFilterContext *ctx) \ · 46 unmodified lines
1365{ \1408{ \
1366 BiquadsContext *s = ctx->priv; \1409 BiquadsContext *s = ctx->priv; \
1367 s->filter_type = name_; \1410 s->filter_type = name_; \
1411 s->pts = AV_NOPTS_VALUE; \
1368 return 0; \1412 return 0; \
1369} \1413} \
1370 \1414 \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t