int show_bsfs(void *optctx, const char *opt, const char *arg)
{
- AVBitStreamFilter *bsf = NULL;
+ const AVBitStreamFilter *bsf = NULL;
+ void *opaque = NULL;
printf("Bitstream filters:\n");
- while ((bsf = av_bitstream_filter_next(bsf)))
+ while ((bsf = av_bsf_next(&opaque)))
printf("%s\n", bsf->name);
printf("\n");
return 0;
}
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
- AVBitStreamFilterContext *bsfc;
if (!ost)
continue;
- bsfc = ost->bitstream_filters;
- while (bsfc) {
- AVBitStreamFilterContext *next = bsfc->next;
- av_bitstream_filter_close(bsfc);
- bsfc = next;
- }
- ost->bitstream_filters = NULL;
+ for (j = 0; j < ost->nb_bitstream_filters; j++)
+ av_bsf_free(&ost->bsf_ctx[j]);
+ av_freep(&ost->bsf_ctx);
+ av_freep(&ost->bsf_extradata_updated);
+
av_frame_free(&ost->filtered_frame);
av_frame_free(&ost->last_frame);
}
}
-static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
+static void write_packet(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
{
AVStream *st = ost->st;
- AVBitStreamFilterContext *bsfc = ost->bitstream_filters;
- AVCodecContext *avctx = ost->encoding_needed ? ost->enc_ctx : ost->st->codec;
int ret;
if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
}
}
- if (bsfc)
- av_packet_split_side_data(pkt);
-
- if ((ret = av_apply_bitstream_filters(avctx, pkt, bsfc)) < 0) {
- print_error("", ret);
- if (exit_on_error)
- exit_program(1);
- }
- if (pkt->size == 0 && pkt->side_data_elems == 0)
- return;
- if (!st->codecpar->extradata_size && avctx->extradata_size) {
- st->codecpar->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!st->codecpar->extradata) {
- av_log(NULL, AV_LOG_ERROR, "Could not allocate extradata buffer to copy parser data.\n");
- exit_program(1);
- }
- st->codecpar->extradata_size = avctx->extradata_size;
- memcpy(st->codecpar->extradata, avctx->extradata, avctx->extradata_size);
- }
-
if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
if (pkt->dts != AV_NOPTS_VALUE &&
pkt->pts != AV_NOPTS_VALUE &&
}
}
+static void output_packet(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
+{
+ int ret = 0;
+
+ /* apply the output bitstream filters, if any */
+ if (ost->nb_bitstream_filters) {
+ int idx;
+
+ ret = av_bsf_send_packet(ost->bsf_ctx[0], pkt);
+ if (ret < 0)
+ goto finish;
+
+ idx = 1;
+ while (idx) {
+ /* get a packet from the previous filter up the chain */
+ ret = av_bsf_receive_packet(ost->bsf_ctx[idx - 1], pkt);
+ /* HACK! - aac_adtstoasc updates extradata after filtering the first frame when
+ * the api states this shouldn't happen after init(). Propagate it here to the
+ * muxer and to the next filters in the chain to workaround this.
+ * TODO/FIXME - Make aac_adtstoasc use new packet side data instead of changing
+ * par_out->extradata and adapt muxers accordingly to get rid of this. */
+ if (!(ost->bsf_extradata_updated[idx - 1] & 1)) {
+ ret = avcodec_parameters_copy(ost->st->codecpar, ost->bsf_ctx[idx - 1]->par_out);
+ if (ret < 0)
+ goto finish;
+ ost->bsf_extradata_updated[idx - 1] |= 1;
+ }
+ if (ret == AVERROR(EAGAIN)) {
+ ret = 0;
+ idx--;
+ continue;
+ } else if (ret < 0)
+ goto finish;
+
+ /* send it to the next filter down the chain or to the muxer */
+ if (idx < ost->nb_bitstream_filters) {
+ /* HACK/FIXME! - See above */
+ if (!(ost->bsf_extradata_updated[idx] & 2)) {
+ ret = avcodec_parameters_copy(ost->bsf_ctx[idx]->par_out, ost->bsf_ctx[idx - 1]->par_out);
+ if (ret < 0)
+ goto finish;
+ ost->bsf_extradata_updated[idx] |= 2;
+ }
+ ret = av_bsf_send_packet(ost->bsf_ctx[idx], pkt);
+ if (ret < 0)
+ goto finish;
+ idx++;
+ } else
+ write_packet(s, pkt, ost);
+ }
+ } else
+ write_packet(s, pkt, ost);
+
+finish:
+ if (ret < 0 && ret != AVERROR_EOF) {
+ av_log(NULL, AV_LOG_ERROR, "Error applying bitstream filters to an output "
+ "packet for stream #%d:%d.\n", ost->file_index, ost->index);
+ if(exit_on_error)
+ exit_program(1);
+ }
+}
+
static int check_recording_time(OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base));
}
- write_frame(s, &pkt, ost);
+ output_packet(s, &pkt, ost);
}
}
pkt.pts += 90 * sub->end_display_time;
}
pkt.dts = pkt.pts;
- write_frame(s, &pkt, ost);
+ output_packet(s, &pkt, ost);
}
}
pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base);
pkt.flags |= AV_PKT_FLAG_KEY;
- write_frame(s, &pkt, ost);
+ output_packet(s, &pkt, ost);
} else
#endif
{
}
frame_size = pkt.size;
- write_frame(s, &pkt, ost);
+ output_packet(s, &pkt, ost);
/* if two pass, output log */
if (ost->logfile && enc->stats_out) {
}
av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base);
pkt_size = pkt.size;
- write_frame(os, &pkt, ost);
+ output_packet(os, &pkt, ost);
if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) {
do_video_stats(ost, pkt_size);
}
}
#endif
- write_frame(of->ctx, &opkt, ost);
+ output_packet(of->ctx, &opkt, ost);
}
int guess_input_channel_layout(InputStream *ist)
return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b);
}
+static int init_output_bsfs(OutputStream *ost)
+{
+ AVBSFContext *ctx;
+ int i, ret;
+
+ if (!ost->nb_bitstream_filters)
+ return 0;
+
+ for (i = 0; i < ost->nb_bitstream_filters; i++) {
+ ctx = ost->bsf_ctx[i];
+
+ ret = avcodec_parameters_copy(ctx->par_in,
+ i ? ost->bsf_ctx[i - 1]->par_out : ost->st->codecpar);
+ if (ret < 0)
+ return ret;
+
+ ctx->time_base_in = i ? ost->bsf_ctx[i - 1]->time_base_out : ost->st->time_base;
+
+ ret = av_bsf_init(ctx);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error initializing bistream filter: %s\n",
+ ost->bsf_ctx[i]->filter->name);
+ return ret;
+ }
+ }
+
+ ctx = ost->bsf_ctx[ost->nb_bitstream_filters - 1];
+ ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out);
+ if (ret < 0)
+ return ret;
+
+ ost->st->time_base = ctx->time_base_out;
+
+ return 0;
+}
+
static int init_output_stream(OutputStream *ost, char *error, int error_len)
{
int ret = 0;
return ret;
}
+ /* initialize bitstream filters for the output stream
+ * needs to be done here, because the codec id for streamcopy is not
+ * known until now */
+ ret = init_output_bsfs(ost);
+ if (ret < 0)
+ return ret;
+
return ret;
}
int64_t first_pts;
/* dts of the last packet sent to the muxer */
int64_t last_mux_dts;
- AVBitStreamFilterContext *bitstream_filters;
+
+ int nb_bitstream_filters;
+ uint8_t *bsf_extradata_updated;
+ AVBSFContext **bsf_ctx;
+
AVCodecContext *enc_ctx;
AVCodecParameters *ref_par; /* associated input codec parameters with encoders options applied */
AVCodec *enc;
OutputStream *ost;
AVStream *st = avformat_new_stream(oc, NULL);
int idx = oc->nb_streams - 1, ret = 0;
- char *bsf = NULL, *next, *codec_tag = NULL;
- AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL;
+ const char *bsfs = NULL;
+ char *next, *codec_tag = NULL;
double qscale = -1;
int i;
ost->copy_prior_start = -1;
MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st);
- MATCH_PER_STREAM_OPT(bitstream_filters, str, bsf, oc, st);
- while (bsf) {
- char *arg = NULL;
- if (next = strchr(bsf, ','))
- *next++ = 0;
- if (arg = strchr(bsf, '='))
- *arg++ = 0;
- if (!(bsfc = av_bitstream_filter_init(bsf))) {
- av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf);
+ MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st);
+ while (bsfs && *bsfs) {
+ const AVBitStreamFilter *filter;
+ char *bsf, *bsf_options_str, *bsf_name;
+
+ bsf = av_get_token(&bsfs, ",");
+ if (!bsf)
+ exit_program(1);
+ bsf_name = av_strtok(bsf, "=", &bsf_options_str);
+ if (!bsf_name)
+ exit_program(1);
+
+ filter = av_bsf_get_by_name(bsf_name);
+ if (!filter) {
+ av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf_name);
exit_program(1);
}
- if (bsfc_prev)
- bsfc_prev->next = bsfc;
- else
- ost->bitstream_filters = bsfc;
- if (arg)
- if (!(bsfc->args = av_strdup(arg))) {
- av_log(NULL, AV_LOG_FATAL, "Bitstream filter memory allocation failed\n");
+
+ ost->bsf_ctx = av_realloc_array(ost->bsf_ctx,
+ ost->nb_bitstream_filters + 1,
+ sizeof(*ost->bsf_ctx));
+ if (!ost->bsf_ctx)
+ exit_program(1);
+
+ ret = av_bsf_alloc(filter, &ost->bsf_ctx[ost->nb_bitstream_filters]);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error allocating a bistream filter context\n");
+ exit_program(1);
+ }
+
+ if (bsf_options_str && filter->priv_class) {
+ const AVOption *opt = av_opt_next(ost->bsf_ctx[ost->nb_bitstream_filters]->priv_data, NULL);
+ const char * shorthand[2] = {NULL};
+
+ if (opt)
+ shorthand[0] = opt->name;
+
+ ret = av_opt_set_from_string(ost->bsf_ctx[ost->nb_bitstream_filters]->priv_data, bsf_options_str, shorthand, "=", ":");
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error parsing options for bitstream filter %s\n", bsf_name);
exit_program(1);
}
+ }
+ av_freep(&bsf);
- bsfc_prev = bsfc;
- bsf = next;
+ ost->nb_bitstream_filters++;
+
+ if (*bsfs)
+ bsfs++;
+ }
+ if (ost->nb_bitstream_filters) {
+ ost->bsf_extradata_updated = av_mallocz_array(ost->nb_bitstream_filters, sizeof(*ost->bsf_extradata_updated));
+ if (!ost->bsf_extradata_updated) {
+ av_log(NULL, AV_LOG_FATAL, "Bitstream filter memory allocation failed\n");
+ exit_program(1);
+ }
}
MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st);
-d6c688432b88ca62ea8abb885272af52 *tests/data/fate/ffmpeg-bsf-remove-k.avi
-129982 tests/data/fate/ffmpeg-bsf-remove-k.avi
+6196f1d6b59d16c045de627221d8685f *tests/data/fate/ffmpeg-bsf-remove-k.avi
+130072 tests/data/fate/ffmpeg-bsf-remove-k.avi
+#extradata 0: 30, 0x4a4d065a
#tb 0: 1/25
#media_type 0: video
#codec_id 0: mpeg4
#dimensions 0: 716x236
#sar 0: 1/1
-0, 0, -9223372036854775808, 1, 20164, 0x66bf5e52
-0, 1, -9223372036854775808, 1, 17878, 0xc081a405, F=0x0
-0, 2, -9223372036854775808, 1, 22723, 0x60935d28, F=0x0
-0, 3, -9223372036854775808, 1, 18655, 0xe5c33ada, F=0x0
-0, 4, -9223372036854775808, 1, 12928, 0x84d6a9d7, F=0x0
-0, 5, -9223372036854775808, 1, 4788, 0xbf9e1939, F=0x0
-0, 6, -9223372036854775808, 1, 3160, 0x867423c7, F=0x0
-0, 7, -9223372036854775808, 1, 2049, 0x523ffd85, F=0x0
-0, 8, -9223372036854775808, 1, 1440, 0x363ff725, F=0x0
-0, 9, -9223372036854775808, 1, 1300, 0x0d3c9c74, F=0x0
-0, 10, -9223372036854775808, 1, 1081, 0xbfb0365c, F=0x0
-0, 11, -9223372036854775808, 1, 1011, 0x9d310f90, F=0x0
-0, 12, -9223372036854775808, 1, 2513, 0xbcd803b5
-0, 13, -9223372036854775808, 1, 881, 0x7492d262, F=0x0
-0, 14, -9223372036854775808, 1, 896, 0x1ff1d335, F=0x0
-0, 15, -9223372036854775808, 1, 973, 0x72c1fc04, F=0x0
-0, 16, -9223372036854775808, 1, 1075, 0xa5881d73, F=0x0
-0, 17, -9223372036854775808, 1, 933, 0xf0aae974, F=0x0
-0, 18, -9223372036854775808, 1, 1079, 0xbdce1b40, F=0x0
-0, 19, -9223372036854775808, 1, 964, 0x323fe4ab, F=0x0
-0, 20, -9223372036854775808, 1, 1015, 0x78a4fe96, F=0x0
-0, 21, -9223372036854775808, 1, 990, 0x9cd4ff25, F=0x0
-0, 22, -9223372036854775808, 1, 1093, 0x98712e2e, F=0x0
-0, 23, -9223372036854775808, 1, 1200, 0x37957156, F=0x0
-0, 24, -9223372036854775808, 1, 2851, 0xb05be8a1
+0, 0, 0, 1, 20194, 0x174f64ac
+0, 1, 1, 1, 17878, 0xc081a405, F=0x0
+0, 2, 2, 1, 22723, 0x60935d28, F=0x0
+0, 3, 3, 1, 18655, 0xe5c33ada, F=0x0
+0, 4, 4, 1, 12928, 0x84d6a9d7, F=0x0
+0, 5, 5, 1, 4788, 0xbf9e1939, F=0x0
+0, 6, 6, 1, 3160, 0x867423c7, F=0x0
+0, 7, 7, 1, 2049, 0x523ffd85, F=0x0
+0, 8, 8, 1, 1440, 0x363ff725, F=0x0
+0, 9, 9, 1, 1300, 0x0d3c9c74, F=0x0
+0, 10, 10, 1, 1081, 0xbfb0365c, F=0x0
+0, 11, 11, 1, 1011, 0x9d310f90, F=0x0
+0, 12, 12, 1, 2543, 0x64500a0f
+0, 13, 13, 1, 881, 0x7492d262, F=0x0
+0, 14, 14, 1, 896, 0x1ff1d335, F=0x0
+0, 15, 15, 1, 973, 0x72c1fc04, F=0x0
+0, 16, 16, 1, 1075, 0xa5881d73, F=0x0
+0, 17, 17, 1, 933, 0xf0aae974, F=0x0
+0, 18, 18, 1, 1079, 0xbdce1b40, F=0x0
+0, 19, 19, 1, 964, 0x323fe4ab, F=0x0
+0, 20, 20, 1, 1015, 0x78a4fe96, F=0x0
+0, 21, 21, 1, 990, 0x9cd4ff25, F=0x0
+0, 22, 22, 1, 1093, 0x98712e2e, F=0x0
+0, 23, 23, 1, 1200, 0x37957156, F=0x0
+0, 24, 24, 1, 2881, 0xbb1feefb
-6196f1d6b59d16c045de627221d8685f *tests/data/fate/ffmpeg-bsf-remove-r.avi
-130072 tests/data/fate/ffmpeg-bsf-remove-r.avi
-#extradata 0: 30, 0x4a4d065a
+d6c688432b88ca62ea8abb885272af52 *tests/data/fate/ffmpeg-bsf-remove-r.avi
+129982 tests/data/fate/ffmpeg-bsf-remove-r.avi
#tb 0: 1/25
#media_type 0: video
#codec_id 0: mpeg4
#dimensions 0: 716x236
#sar 0: 1/1
-0, 0, 0, 1, 20194, 0x174f64ac
-0, 1, 1, 1, 17878, 0xc081a405, F=0x0
-0, 2, 2, 1, 22723, 0x60935d28, F=0x0
-0, 3, 3, 1, 18655, 0xe5c33ada, F=0x0
-0, 4, 4, 1, 12928, 0x84d6a9d7, F=0x0
-0, 5, 5, 1, 4788, 0xbf9e1939, F=0x0
-0, 6, 6, 1, 3160, 0x867423c7, F=0x0
-0, 7, 7, 1, 2049, 0x523ffd85, F=0x0
-0, 8, 8, 1, 1440, 0x363ff725, F=0x0
-0, 9, 9, 1, 1300, 0x0d3c9c74, F=0x0
-0, 10, 10, 1, 1081, 0xbfb0365c, F=0x0
-0, 11, 11, 1, 1011, 0x9d310f90, F=0x0
-0, 12, 12, 1, 2543, 0x64500a0f
-0, 13, 13, 1, 881, 0x7492d262, F=0x0
-0, 14, 14, 1, 896, 0x1ff1d335, F=0x0
-0, 15, 15, 1, 973, 0x72c1fc04, F=0x0
-0, 16, 16, 1, 1075, 0xa5881d73, F=0x0
-0, 17, 17, 1, 933, 0xf0aae974, F=0x0
-0, 18, 18, 1, 1079, 0xbdce1b40, F=0x0
-0, 19, 19, 1, 964, 0x323fe4ab, F=0x0
-0, 20, 20, 1, 1015, 0x78a4fe96, F=0x0
-0, 21, 21, 1, 990, 0x9cd4ff25, F=0x0
-0, 22, 22, 1, 1093, 0x98712e2e, F=0x0
-0, 23, 23, 1, 1200, 0x37957156, F=0x0
-0, 24, 24, 1, 2881, 0xbb1feefb
+0, 0, -9223372036854775808, 1, 20164, 0x66bf5e52
+0, 1, -9223372036854775808, 1, 17878, 0xc081a405, F=0x0
+0, 2, -9223372036854775808, 1, 22723, 0x60935d28, F=0x0
+0, 3, -9223372036854775808, 1, 18655, 0xe5c33ada, F=0x0
+0, 4, -9223372036854775808, 1, 12928, 0x84d6a9d7, F=0x0
+0, 5, -9223372036854775808, 1, 4788, 0xbf9e1939, F=0x0
+0, 6, -9223372036854775808, 1, 3160, 0x867423c7, F=0x0
+0, 7, -9223372036854775808, 1, 2049, 0x523ffd85, F=0x0
+0, 8, -9223372036854775808, 1, 1440, 0x363ff725, F=0x0
+0, 9, -9223372036854775808, 1, 1300, 0x0d3c9c74, F=0x0
+0, 10, -9223372036854775808, 1, 1081, 0xbfb0365c, F=0x0
+0, 11, -9223372036854775808, 1, 1011, 0x9d310f90, F=0x0
+0, 12, -9223372036854775808, 1, 2513, 0xbcd803b5
+0, 13, -9223372036854775808, 1, 881, 0x7492d262, F=0x0
+0, 14, -9223372036854775808, 1, 896, 0x1ff1d335, F=0x0
+0, 15, -9223372036854775808, 1, 973, 0x72c1fc04, F=0x0
+0, 16, -9223372036854775808, 1, 1075, 0xa5881d73, F=0x0
+0, 17, -9223372036854775808, 1, 933, 0xf0aae974, F=0x0
+0, 18, -9223372036854775808, 1, 1079, 0xbdce1b40, F=0x0
+0, 19, -9223372036854775808, 1, 964, 0x323fe4ab, F=0x0
+0, 20, -9223372036854775808, 1, 1015, 0x78a4fe96, F=0x0
+0, 21, -9223372036854775808, 1, 990, 0x9cd4ff25, F=0x0
+0, 22, -9223372036854775808, 1, 1093, 0x98712e2e, F=0x0
+0, 23, -9223372036854775808, 1, 1200, 0x37957156, F=0x0
+0, 24, -9223372036854775808, 1, 2851, 0xb05be8a1
-f52716e8110147553567ee617bfe6af8 *tests/data/fate/h264_mp4toannexb_ticket2991.h264
-1999668 tests/data/fate/h264_mp4toannexb_ticket2991.h264
+05d66e60ab22ee004720e0051af0fe74 *tests/data/fate/h264_mp4toannexb_ticket2991.h264
+1985815 tests/data/fate/h264_mp4toannexb_ticket2991.h264
#extradata 0: 79, 0x1ec61105
#tb 0: 1/1200000
#media_type 0: video
0, 4612606, 4612606, 40040, 11198, 0x6a9de1fb, F=0x0
0, 4652646, 4652646, 40040, 15572, 0xd6cb6c4b, F=0x0
0, 4692686, 4692686, 40040, 12072, 0x8928b77f, F=0x0
-0, 4732727, 4732727, 40040, 33025, 0x79359fc1, F=0x0
+0, 4732727, 4732727, 40040, 19172, 0x549b6b87, F=0x0
-5db6b7b766c7a9fd5f42292d7467a36d
+c9535e459c2ee4ead6d84b93bc7e9f46