[FFmpeg-cvslog] lavc: add a new bitstream filtering API
Anton Khirnov
git at videolan.org
Sun Apr 17 19:48:56 CEST 2016
ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Sat Nov 23 11:43:13 2013 +0100| [33d18982fa03feb061c8f744a4f0a9175c1f63ab] | committer: Anton Khirnov
lavc: add a new bitstream filtering API
Deprecate the current bitstream filtering API.
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=33d18982fa03feb061c8f744a4f0a9175c1f63ab
---
configure | 2 +-
doc/APIchanges | 4 +
libavcodec/Makefile | 2 +
libavcodec/aac_adtstoasc_bsf.c | 104 +++++++++++------
libavcodec/allcodecs.c | 21 ----
libavcodec/avcodec.h | 202 ++++++++++++++++++++++++++++++--
libavcodec/bitstream_filter.c | 147 +++++++++++++++++------
libavcodec/bitstream_filters.c | 121 +++++++++++++++++++
libavcodec/bsf.c | 219 +++++++++++++++++++++++++++++++++++
libavcodec/bsf.h | 33 ++++++
libavcodec/chomp_bsf.c | 29 ++---
libavcodec/dump_extradata_bsf.c | 94 +++++++++++----
libavcodec/h264_mp4toannexb_bsf.c | 151 ++++++++++++++----------
libavcodec/hevc_mp4toannexb_bsf.c | 127 ++++++++++----------
libavcodec/imx_dump_header_bsf.c | 63 ++++++----
libavcodec/mjpeg2jpeg_bsf.c | 69 ++++++-----
libavcodec/mjpega_dump_header_bsf.c | 106 +++++++++--------
libavcodec/movsub_bsf.c | 96 ++++++++++-----
libavcodec/noise_bsf.c | 77 ++++++++----
libavcodec/remove_extradata_bsf.c | 110 ++++++++++++++----
libavcodec/version.h | 5 +-
21 files changed, 1350 insertions(+), 432 deletions(-)
diff --git a/configure b/configure
index 5376e67..ba1fd47 100755
--- a/configure
+++ b/configure
@@ -2517,7 +2517,6 @@ ENCODER_LIST=$(find_things encoder ENC libavcodec/allcodecs.c)
DECODER_LIST=$(find_things decoder DEC libavcodec/allcodecs.c)
HWACCEL_LIST=$(find_things hwaccel HWACCEL libavcodec/allcodecs.c)
PARSER_LIST=$(find_things parser PARSER libavcodec/allcodecs.c)
-BSF_LIST=$(find_things bsf BSF libavcodec/allcodecs.c)
MUXER_LIST=$(find_things muxer _MUX libavformat/allformats.c)
DEMUXER_LIST=$(find_things demuxer DEMUX libavformat/allformats.c)
OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c)
@@ -2531,6 +2530,7 @@ find_things_extern(){
sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file"
}
+BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c)
PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c)
ALL_COMPONENTS="
diff --git a/doc/APIchanges b/doc/APIchanges
index e0c4678..c50faa6 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,10 @@ libavutil: 2015-08-28
API changes, most recent first:
+2016-xx-xx - xxxxxxx - lavc 57.15.0 - avcodec.h
+ Add a new bitstream filtering API working with AVPackets.
+ Deprecate the old bistream filtering API.
+
2016-xx-xx - xxxxxxx - lavfi 6.3.0 - avfilter.h
Add AVFilterContext.hw_device_ctx.
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 256dee3..ba1661d 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -19,6 +19,8 @@ OBJS = allcodecs.o \
avpicture.o \
bitstream.o \
bitstream_filter.o \
+ bitstream_filters.o \
+ bsf.o \
codec_desc.o \
d3d11va.o \
dirac.o \
diff --git a/libavcodec/aac_adtstoasc_bsf.c b/libavcodec/aac_adtstoasc_bsf.c
index d3cbeae..9168e2b 100644
--- a/libavcodec/aac_adtstoasc_bsf.c
+++ b/libavcodec/aac_adtstoasc_bsf.c
@@ -21,6 +21,7 @@
#include "avcodec.h"
#include "aacadtsdec.h"
+#include "bsf.h"
#include "put_bits.h"
#include "get_bits.h"
#include "mpeg4audio.h"
@@ -34,65 +35,76 @@ typedef struct AACBSFContext {
* This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4
* ADTS header and removes the ADTS header.
*/
-static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc,
- AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size,
- int keyframe)
+static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out)
{
+ AACBSFContext *ctx = bsfc->priv_data;
+
GetBitContext gb;
PutBitContext pb;
AACADTSHeaderInfo hdr;
+ AVPacket *in;
+ int ret;
- AACBSFContext *ctx = bsfc->priv_data;
+ ret = ff_bsf_get_packet(bsfc, &in);
+ if (ret < 0)
+ return ret;
- init_get_bits(&gb, buf, AAC_ADTS_HEADER_SIZE*8);
+ if (in->size < AAC_ADTS_HEADER_SIZE)
+ goto packet_too_small;
- *poutbuf = (uint8_t*) buf;
- *poutbuf_size = buf_size;
+ init_get_bits(&gb, in->data, AAC_ADTS_HEADER_SIZE * 8);
- if (avctx->extradata)
- if (show_bits(&gb, 12) != 0xfff)
- return 0;
+ if (bsfc->par_in->extradata && show_bits(&gb, 12) != 0xfff)
+ goto finish;
if (avpriv_aac_parse_header(&gb, &hdr) < 0) {
- av_log(avctx, AV_LOG_ERROR, "Error parsing ADTS frame header!\n");
- return AVERROR_INVALIDDATA;
+ av_log(bsfc, AV_LOG_ERROR, "Error parsing ADTS frame header!\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
if (!hdr.crc_absent && hdr.num_aac_frames > 1) {
- avpriv_report_missing_feature(avctx,
+ avpriv_report_missing_feature(bsfc,
"Multiple RDBs per frame with CRC");
- return AVERROR_PATCHWELCOME;
+ ret = AVERROR_PATCHWELCOME;
+ goto fail;
}
- buf += AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent;
- buf_size -= AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent;
+ in->size -= AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
+ if (in->size <= 0)
+ goto packet_too_small;
+ in->data += AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
if (!ctx->first_frame_done) {
int pce_size = 0;
uint8_t pce_data[MAX_PCE_SIZE];
+ uint8_t *extradata;
+
if (!hdr.chan_config) {
- init_get_bits(&gb, buf, buf_size * 8);
+ init_get_bits(&gb, in->data, in->size * 8);
if (get_bits(&gb, 3) != 5) {
- avpriv_report_missing_feature(avctx,
+ avpriv_report_missing_feature(bsfc,
"PCE-based channel configuration "
"without PCE as first syntax "
"element");
- return AVERROR_PATCHWELCOME;
+ ret = AVERROR_PATCHWELCOME;
+ goto fail;
}
init_put_bits(&pb, pce_data, MAX_PCE_SIZE);
pce_size = avpriv_copy_pce_data(&pb, &gb)/8;
flush_put_bits(&pb);
- buf_size -= get_bits_count(&gb)/8;
- buf += get_bits_count(&gb)/8;
+ in->size -= get_bits_count(&gb)/8;
+ in->data += get_bits_count(&gb)/8;
}
- avctx->extradata_size = 2 + pce_size;
- avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!avctx->extradata)
- return AVERROR(ENOMEM);
- init_put_bits(&pb, avctx->extradata, avctx->extradata_size);
+ extradata = av_packet_new_side_data(in, AV_PKT_DATA_NEW_EXTRADATA,
+ 2 + pce_size);
+ if (!extradata) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ init_put_bits(&pb, extradata, 2 + pce_size);
put_bits(&pb, 5, hdr.object_type);
put_bits(&pb, 4, hdr.sampling_index);
put_bits(&pb, 4, hdr.chan_config);
@@ -101,20 +113,42 @@ static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc,
put_bits(&pb, 1, 0); //is not extension
flush_put_bits(&pb);
if (pce_size) {
- memcpy(avctx->extradata + 2, pce_data, pce_size);
+ memcpy(extradata + 2, pce_data, pce_size);
}
ctx->first_frame_done = 1;
}
- *poutbuf = (uint8_t*) buf;
- *poutbuf_size = buf_size;
+finish:
+ av_packet_move_ref(out, in);
+ av_packet_free(&in);
+
+ return 0;
+
+packet_too_small:
+ av_log(bsfc, AV_LOG_ERROR, "Input packet too small\n");
+ ret = AVERROR_INVALIDDATA;
+fail:
+ av_packet_free(&in);
+ return ret;
+}
+
+static int aac_adtstoasc_init(AVBSFContext *ctx)
+{
+ av_freep(&ctx->par_out->extradata);
+ ctx->par_out->extradata_size = 0;
return 0;
}
-AVBitStreamFilter ff_aac_adtstoasc_bsf = {
- "aac_adtstoasc",
- sizeof(AACBSFContext),
- aac_adtstoasc_filter,
+static const enum AVCodecID codec_ids[] = {
+ AV_CODEC_ID_AAC, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_aac_adtstoasc_bsf = {
+ .name = "aac_adtstoasc",
+ .priv_data_size = sizeof(AACBSFContext),
+ .init = aac_adtstoasc_init,
+ .filter = aac_adtstoasc_filter,
+ .codec_ids = codec_ids,
};
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 7c2ab50..f0b57d5 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -58,13 +58,6 @@
av_register_codec_parser(&ff_##x##_parser); \
}
-#define REGISTER_BSF(X, x) \
- { \
- extern AVBitStreamFilter ff_##x##_bsf; \
- if (CONFIG_##X##_BSF) \
- av_register_bitstream_filter(&ff_##x##_bsf); \
- }
-
void avcodec_register_all(void)
{
static int initialized;
@@ -536,18 +529,4 @@ void avcodec_register_all(void)
REGISTER_PARSER(VORBIS, vorbis);
REGISTER_PARSER(VP3, vp3);
REGISTER_PARSER(VP8, vp8);
-
- /* bitstream filters */
- REGISTER_BSF(AAC_ADTSTOASC, aac_adtstoasc);
- REGISTER_BSF(CHOMP, chomp);
- REGISTER_BSF(DUMP_EXTRADATA, dump_extradata);
- REGISTER_BSF(H264_MP4TOANNEXB, h264_mp4toannexb);
- REGISTER_BSF(HEVC_MP4TOANNEXB, hevc_mp4toannexb);
- REGISTER_BSF(IMX_DUMP_HEADER, imx_dump_header);
- REGISTER_BSF(MJPEG2JPEG, mjpeg2jpeg);
- REGISTER_BSF(MJPEGA_DUMP_HEADER, mjpega_dump_header);
- REGISTER_BSF(MOV2TEXTSUB, mov2textsub);
- REGISTER_BSF(NOISE, noise);
- REGISTER_BSF(REMOVE_EXTRADATA, remove_extradata);
- REGISTER_BSF(TEXT2MOVSUB, text2movsub);
}
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 33de8ec..0ff31a0 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -4692,35 +4692,221 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes);
*/
int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes);
-
+#if FF_API_OLD_BSF
typedef struct AVBitStreamFilterContext {
void *priv_data;
struct AVBitStreamFilter *filter;
AVCodecParserContext *parser;
struct AVBitStreamFilterContext *next;
} AVBitStreamFilterContext;
+#endif
+
+typedef struct AVBSFInternal AVBSFInternal;
+
+/**
+ * The bitstream filter state.
+ *
+ * This struct must be allocated with av_bsf_alloc() and freed with
+ * av_bsf_free().
+ *
+ * The fields in the struct will only be changed (by the caller or by the
+ * filter) as described in their documentation, and are to be considered
+ * immutable otherwise.
+ */
+typedef struct AVBSFContext {
+ /**
+ * A class for logging and AVOptions
+ */
+ const AVClass *av_class;
+
+ /**
+ * The bitstream filter this context is an instance of.
+ */
+ const struct AVBitStreamFilter *filter;
+
+ /**
+ * Opaque libavcodec internal data. Must not be touched by the caller in any
+ * way.
+ */
+ AVBSFInternal *internal;
+
+ /**
+ * Opaque filter-specific private data. If filter->priv_class is non-NULL,
+ * this is an AVOptions-enabled struct.
+ */
+ void *priv_data;
+
+ /**
+ * Parameters of the input stream. Set by the caller before av_bsf_init().
+ */
+ AVCodecParameters *par_in;
+ /**
+ * Parameters of the output stream. Set by the filter in av_bsf_init().
+ */
+ AVCodecParameters *par_out;
+
+ /**
+ * The timebase used for the timestamps of the input packets. Set by the
+ * caller before av_bsf_init().
+ */
+ AVRational time_base_in;
+
+ /**
+ * The timebase used for the timestamps of the output packets. Set by the
+ * filter in av_bsf_init().
+ */
+ AVRational time_base_out;
+} AVBSFContext;
typedef struct AVBitStreamFilter {
const char *name;
+
+ /**
+ * A list of codec ids supported by the filter, terminated by
+ * AV_CODEC_ID_NONE.
+ * May be NULL, in that case the bitstream filter works with any codec id.
+ */
+ const enum AVCodecID *codec_ids;
+
+ /**
+ * A class for the private data, used to declare bitstream filter private
+ * AVOptions. This field is NULL for bitstream filters that do not declare
+ * any options.
+ *
+ * If this field is non-NULL, the first member of the filter private data
+ * must be a pointer to AVClass, which will be set by libavcodec generic
+ * code to this class.
+ */
+ const AVClass *priv_class;
+
+ /*****************************************************************
+ * No fields below this line are part of the public API. They
+ * may not be used outside of libavcodec and can be changed and
+ * removed at will.
+ * New public fields should be added right above.
+ *****************************************************************
+ */
+
int priv_data_size;
- int (*filter)(AVBitStreamFilterContext *bsfc,
- AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size, int keyframe);
- void (*close)(AVBitStreamFilterContext *bsfc);
- struct AVBitStreamFilter *next;
+ int (*init)(AVBSFContext *ctx);
+ int (*filter)(AVBSFContext *ctx, AVPacket *pkt);
+ void (*close)(AVBSFContext *ctx);
} AVBitStreamFilter;
+#if FF_API_OLD_BSF
+/**
+ * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext)
+ * is deprecated. Use the new bitstream filtering API (using AVBSFContext).
+ */
+attribute_deprecated
void av_register_bitstream_filter(AVBitStreamFilter *bsf);
+attribute_deprecated
AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
+attribute_deprecated
int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
AVCodecContext *avctx, const char *args,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe);
+attribute_deprecated
void av_bitstream_filter_close(AVBitStreamFilterContext *bsf);
-
+attribute_deprecated
AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f);
+#endif
+
+/**
+ * @return a bitstream filter with the specified name or NULL if no such
+ * bitstream filter exists.
+ */
+const AVBitStreamFilter *av_bsf_get_by_name(const char *name);
+
+/**
+ * Iterate over all registered bitstream filters.
+ *
+ * @param opaque a pointer where libavcodec will store the iteration state. Must
+ * point to NULL to start the iteration.
+ *
+ * @return the next registered bitstream filter or NULL when the iteration is
+ * finished
+ */
+const AVBitStreamFilter *av_bsf_next(void **opaque);
+
+/**
+ * Allocate a context for a given bitstream filter. The caller must fill in the
+ * context parameters as described in the documentation and then call
+ * av_bsf_init() before sending any data to the filter.
+ *
+ * @param filter the filter for which to allocate an instance.
+ * @param ctx a pointer into which the pointer to the newly-allocated context
+ * will be written. It must be freed with av_bsf_free() after the
+ * filtering is done.
+ *
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx);
+
+/**
+ * Prepare the filter for use, after all the parameters and options have been
+ * set.
+ */
+int av_bsf_init(AVBSFContext *ctx);
+
+/**
+ * Submit a packet for filtering.
+ *
+ * After sending each packet, the filter must be completely drained by calling
+ * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or
+ * AVERROR_EOF.
+ *
+ * @param pkt the packet to filter. The bitstream filter will take ownership of
+ * the packet and reset the contents of pkt. pkt is not touched if an error occurs.
+ * This parameter may be NULL, which signals the end of the stream (i.e. no more
+ * packets will be sent). That will cause the filter to output any packets it
+ * may have buffered internally.
+ *
+ * @return 0 on success, a negative AVERROR on error.
+ */
+int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt);
+
+/**
+ * Retrieve a filtered packet.
+ *
+ * @param[out] pkt this struct will be filled with the contents of the filtered
+ * packet. It is owned by the caller and must be freed using
+ * av_packet_unref() when it is no longer needed.
+ * This parameter should be "clean" (i.e. freshly allocated
+ * with av_packet_alloc() or unreffed with av_packet_unref())
+ * when this function is called. If this function returns
+ * successfully, the contents of pkt will be completely
+ * overwritten by the returned data. On failure, pkt is not
+ * touched.
+ *
+ * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the
+ * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there
+ * will be no further output from the filter. Another negative AVERROR value if
+ * an error occurs.
+ *
+ * @note one input packet may result in several output packets, so after sending
+ * a packet with av_bsf_send_packet(), this function needs to be called
+ * repeatedly until it stops returning 0. It is also possible for a filter to
+ * output fewer packets than were sent to it, so this function may return
+ * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call.
+ */
+int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt);
+
+/**
+ * Free a bitstream filter context and everything associated with it; write NULL
+ * into the supplied pointer.
+ */
+void av_bsf_free(AVBSFContext **ctx);
+
+/**
+ * Get the AVClass for AVBSFContext. It can be used in combination with
+ * AV_OPT_SEARCH_FAKE_OBJ for examining options.
+ *
+ * @see av_opt_find().
+ */
+const AVClass *av_bsf_get_class(void);
/* memory */
diff --git a/libavcodec/bitstream_filter.c b/libavcodec/bitstream_filter.c
index 3b19bbd..ab608a9 100644
--- a/libavcodec/bitstream_filter.c
+++ b/libavcodec/bitstream_filter.c
@@ -21,56 +21,70 @@
#include <string.h>
#include "avcodec.h"
+
+#include "libavutil/internal.h"
#include "libavutil/mem.h"
-static AVBitStreamFilter *first_bitstream_filter = NULL;
+#if FF_API_OLD_BSF
+FF_DISABLE_DEPRECATION_WARNINGS
AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f)
{
- if (f)
- return f->next;
- else
- return first_bitstream_filter;
+ const AVBitStreamFilter *filter = NULL;
+ void *opaque = NULL;
+
+ while (filter != f)
+ filter = av_bsf_next(&opaque);
+
+ return av_bsf_next(&opaque);
}
void av_register_bitstream_filter(AVBitStreamFilter *bsf)
{
- bsf->next = first_bitstream_filter;
- first_bitstream_filter = bsf;
}
+typedef struct BSFCompatContext {
+ AVBSFContext *ctx;
+} BSFCompatContext;
+
AVBitStreamFilterContext *av_bitstream_filter_init(const char *name)
{
- AVBitStreamFilter *bsf = first_bitstream_filter;
-
- while (bsf) {
- if (!strcmp(name, bsf->name)) {
- AVBitStreamFilterContext *bsfc =
- av_mallocz(sizeof(AVBitStreamFilterContext));
- if (!bsfc)
- return NULL;
- bsfc->filter = bsf;
- bsfc->priv_data = NULL;
- if (bsf->priv_data_size) {
- bsfc->priv_data = av_mallocz(bsf->priv_data_size);
- if (!bsfc->priv_data) {
- av_freep(&bsfc);
- return NULL;
- }
- }
- return bsfc;
- }
- bsf = bsf->next;
- }
+ AVBitStreamFilterContext *ctx = NULL;
+ BSFCompatContext *priv = NULL;
+ const AVBitStreamFilter *bsf;
+
+ bsf = av_bsf_get_by_name(name);
+ if (!bsf)
+ return NULL;
+
+ ctx = av_mallocz(sizeof(*ctx));
+ if (!ctx)
+ return NULL;
+
+ priv = av_mallocz(sizeof(*priv));
+ if (!priv)
+ goto fail;
+
+
+ ctx->filter = bsf;
+ ctx->priv_data = priv;
+
+ return ctx;
+
+fail:
+ if (priv)
+ av_bsf_free(&priv->ctx);
+ av_freep(&priv);
+ av_freep(&ctx);
return NULL;
}
void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc)
{
- if (bsfc->filter->close)
- bsfc->filter->close(bsfc);
+ BSFCompatContext *priv = bsfc->priv_data;
+
+ av_bsf_free(&priv->ctx);
av_freep(&bsfc->priv_data);
- av_parser_close(bsfc->parser);
av_free(bsfc);
}
@@ -79,8 +93,71 @@ int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe)
{
- *poutbuf = (uint8_t *)buf;
- *poutbuf_size = buf_size;
- return bsfc->filter->filter(bsfc, avctx, args, poutbuf, poutbuf_size,
- buf, buf_size, keyframe);
+ BSFCompatContext *priv = bsfc->priv_data;
+ AVPacket pkt = { 0 };
+ int ret;
+
+ if (!priv->ctx) {
+ ret = av_bsf_alloc(bsfc->filter, &priv->ctx);
+ if (ret < 0)
+ return ret;
+
+ ret = avcodec_parameters_from_context(priv->ctx->par_in, avctx);
+ if (ret < 0)
+ return ret;
+
+ priv->ctx->time_base_in = avctx->time_base;
+
+ ret = av_bsf_init(priv->ctx);
+ if (ret < 0)
+ return ret;
+
+ if (priv->ctx->par_out->extradata_size) {
+ av_freep(&avctx->extradata);
+ avctx->extradata_size = 0;
+ avctx->extradata = av_mallocz(priv->ctx->par_out->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!avctx->extradata)
+ return AVERROR(ENOMEM);
+ memcpy(avctx->extradata, priv->ctx->par_out->extradata,
+ priv->ctx->par_out->extradata_size);
+ avctx->extradata_size = priv->ctx->par_out->extradata_size;
+ }
+ }
+
+ pkt.data = buf;
+ pkt.size = buf_size;
+
+ ret = av_bsf_send_packet(priv->ctx, &pkt);
+ if (ret < 0)
+ return ret;
+
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+
+ ret = av_bsf_receive_packet(priv->ctx, &pkt);
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+ return 0;
+ else if (ret < 0)
+ return ret;
+
+ *poutbuf = av_malloc(pkt.size + AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!*poutbuf) {
+ av_packet_unref(&pkt);
+ return AVERROR(ENOMEM);
+ }
+
+ *poutbuf_size = pkt.size;
+ memcpy(*poutbuf, pkt.data, pkt.size);
+
+ av_packet_unref(&pkt);
+
+ /* drain all the remaining packets we cannot return */
+ while (ret >= 0) {
+ ret = av_bsf_receive_packet(priv->ctx, &pkt);
+ av_packet_unref(&pkt);
+ }
+
+ return 1;
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
new file mode 100644
index 0000000..897e1f8
--- /dev/null
+++ b/libavcodec/bitstream_filters.c
@@ -0,0 +1,121 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include "libavutil/common.h"
+#include "libavutil/log.h"
+
+#include "avcodec.h"
+#include "bsf.h"
+
+extern const AVBitStreamFilter ff_aac_adtstoasc_bsf;
+extern const AVBitStreamFilter ff_chomp_bsf;
+extern const AVBitStreamFilter ff_dump_extradata_bsf;
+extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf;
+extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf;
+extern const AVBitStreamFilter ff_imx_dump_header_bsf;
+extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf;
+extern const AVBitStreamFilter ff_mjpega_dump_header_bsf;
+extern const AVBitStreamFilter ff_mov2textsub_bsf;
+extern const AVBitStreamFilter ff_text2movsub_bsf;
+extern const AVBitStreamFilter ff_noise_bsf;
+extern const AVBitStreamFilter ff_remove_extradata_bsf;
+
+static const AVBitStreamFilter *bitstream_filters[] = {
+#if CONFIG_AAC_ADTSTOASC_BSF
+ &ff_aac_adtstoasc_bsf,
+#endif
+#if CONFIG_CHOMP_BSF
+ &ff_chomp_bsf,
+#endif
+#if CONFIG_DUMP_EXTRADATA_BSF
+ &ff_dump_extradata_bsf,
+#endif
+#if CONFIG_H264_MP4TOANNEXB_BSF
+ &ff_h264_mp4toannexb_bsf,
+#endif
+#if CONFIG_HEVC_MP4TOANNEXB_BSF
+ &ff_hevc_mp4toannexb_bsf,
+#endif
+#if CONFIG_IMX_DUMP_HEADER_BSF
+ &ff_imx_dump_header_bsf,
+#endif
+#if CONFIG_MJPEG2JPEG_BSF
+ &ff_mjpeg2jpeg_bsf,
+#endif
+#if CONFIG_MJPEGA_DUMP_HEADER_BSF
+ &ff_mjpeg2jpeg_bsf,
+#endif
+#if CONFIG_MOV2TEXTSUB_BSF
+ &ff_mov2textsub_bsf,
+#endif
+#if CONFIG_TEXT2MOVSUB_BSF
+ &ff_text2movsub_bsf,
+#endif
+#if CONFIG_NOISE_BSF
+ &ff_noise_bsf,
+#endif
+#if CONFIG_REMOVE_EXTRADATA_BSF
+ &ff_remove_extradata_bsf,
+#endif
+ NULL,
+};
+
+const AVBitStreamFilter *av_bsf_next(void **opaque)
+{
+ uintptr_t i = (uintptr_t)*opaque;
+ const AVBitStreamFilter *f = bitstream_filters[i];
+
+ if (f)
+ *opaque = (void*)(i + 1);
+
+ return f;
+}
+
+const AVBitStreamFilter *av_bsf_get_by_name(const char *name)
+{
+ int i;
+
+ for (i = 0; bitstream_filters[i]; i++) {
+ const AVBitStreamFilter *f = bitstream_filters[i];
+ if (!strcmp(f->name, name))
+ return f;
+ }
+
+ return NULL;
+}
+
+const AVClass *ff_bsf_child_class_next(const AVClass *prev)
+{
+ int i;
+
+ /* find the filter that corresponds to prev */
+ for (i = 0; prev && bitstream_filters[i]; i++) {
+ if (bitstream_filters[i]->priv_class == prev) {
+ i++;
+ break;
+ }
+ }
+
+ /* find next filter with priv options */
+ for (; bitstream_filters[i]; i++)
+ if (bitstream_filters[i]->priv_class)
+ return bitstream_filters[i]->priv_class;
+ return NULL;
+}
diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c
new file mode 100644
index 0000000..284c7c8
--- /dev/null
+++ b/libavcodec/bsf.c
@@ -0,0 +1,219 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+
+#include "avcodec.h"
+#include "bsf.h"
+
+struct AVBSFInternal {
+ AVPacket *buffer_pkt;
+ int eof;
+};
+
+void av_bsf_free(AVBSFContext **pctx)
+{
+ AVBSFContext *ctx;
+
+ if (!pctx || !*pctx)
+ return;
+ ctx = *pctx;
+
+ if (ctx->filter->close)
+ ctx->filter->close(ctx);
+ if (ctx->filter->priv_class && ctx->priv_data)
+ av_opt_free(ctx->priv_data);
+
+ av_opt_free(ctx);
+
+ av_packet_free(&ctx->internal->buffer_pkt);
+ av_freep(&ctx->internal);
+ av_freep(&ctx->priv_data);
+
+ avcodec_parameters_free(&ctx->par_in);
+ avcodec_parameters_free(&ctx->par_out);
+
+ av_freep(pctx);
+}
+
+static void *bsf_child_next(void *obj, void *prev)
+{
+ AVBSFContext *ctx = obj;
+ if (!prev && ctx->filter->priv_class)
+ return ctx->priv_data;
+ return NULL;
+}
+
+static const AVClass bsf_class = {
+ .class_name = "AVBSFContext",
+ .item_name = av_default_item_name,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = bsf_child_next,
+ .child_class_next = ff_bsf_child_class_next,
+};
+
+const AVClass *av_bsf_get_class(void)
+{
+ return &bsf_class;
+}
+
+int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
+{
+ AVBSFContext *ctx;
+ int ret;
+
+ ctx = av_mallocz(sizeof(*ctx));
+ if (!ctx)
+ return AVERROR(ENOMEM);
+
+ ctx->av_class = &bsf_class;
+ ctx->filter = filter;
+
+ ctx->par_in = avcodec_parameters_alloc();
+ ctx->par_out = avcodec_parameters_alloc();
+ if (!ctx->par_in || !ctx->par_out) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ ctx->internal = av_mallocz(sizeof(*ctx->internal));
+ if (!ctx->internal) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ ctx->internal->buffer_pkt = av_packet_alloc();
+ if (!ctx->internal->buffer_pkt) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ av_opt_set_defaults(ctx);
+
+ /* allocate priv data and init private options */
+ if (filter->priv_data_size) {
+ ctx->priv_data = av_mallocz(filter->priv_data_size);
+ if (!ctx->priv_data) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ if (filter->priv_class) {
+ *(const AVClass **)ctx->priv_data = filter->priv_class;
+ av_opt_set_defaults(ctx->priv_data);
+ }
+ }
+
+ *pctx = ctx;
+ return 0;
+fail:
+ av_bsf_free(&ctx);
+ return ret;
+}
+
+int av_bsf_init(AVBSFContext *ctx)
+{
+ int ret, i;
+
+ /* check that the codec is supported */
+ if (ctx->filter->codec_ids) {
+ for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++)
+ if (ctx->par_in->codec_id == ctx->filter->codec_ids[i])
+ break;
+ if (ctx->filter->codec_ids[i] == AV_CODEC_ID_NONE) {
+ const AVCodecDescriptor *desc = avcodec_descriptor_get(ctx->par_in->codec_id);
+ av_log(ctx, AV_LOG_ERROR, "Codec '%s' (%d) is not supported by the "
+ "bitstream filter '%s'. Supported codecs are: ",
+ desc ? desc->name : "unknown", ctx->par_in->codec_id, ctx->filter->name);
+ for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) {
+ desc = avcodec_descriptor_get(ctx->filter->codec_ids[i]);
+ av_log(ctx, AV_LOG_ERROR, "%s (%d) ",
+ desc ? desc->name : "unknown", ctx->filter->codec_ids[i]);
+ }
+ av_log(ctx, AV_LOG_ERROR, "\n");
+ return AVERROR(EINVAL);
+ }
+ }
+
+ /* initialize output parameters to be the same as input
+ * init below might overwrite that */
+ ret = avcodec_parameters_copy(ctx->par_out, ctx->par_in);
+ if (ret < 0)
+ return ret;
+
+ ctx->time_base_out = ctx->time_base_in;
+
+ if (ctx->filter->init) {
+ ret = ctx->filter->init(ctx);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
+{
+ if (!pkt || !pkt->data) {
+ ctx->internal->eof = 1;
+ return 0;
+ }
+
+ if (ctx->internal->eof) {
+ av_log(ctx, AV_LOG_ERROR, "A non-NULL packet sent after an EOF.\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (ctx->internal->buffer_pkt->data ||
+ ctx->internal->buffer_pkt->side_data_elems)
+ return AVERROR(EAGAIN);
+
+ av_packet_move_ref(ctx->internal->buffer_pkt, pkt);
+
+ return 0;
+}
+
+int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
+{
+ return ctx->filter->filter(ctx, pkt);
+}
+
+int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
+{
+ AVBSFInternal *in = ctx->internal;
+ AVPacket *tmp_pkt;
+
+ if (in->eof)
+ return AVERROR_EOF;
+
+ if (!ctx->internal->buffer_pkt->data &&
+ !ctx->internal->buffer_pkt->side_data_elems)
+ return AVERROR(EAGAIN);
+
+ tmp_pkt = av_packet_alloc();
+ if (!tmp_pkt)
+ return AVERROR(ENOMEM);
+
+ *pkt = ctx->internal->buffer_pkt;
+ ctx->internal->buffer_pkt = tmp_pkt;
+
+ return 0;
+}
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
new file mode 100644
index 0000000..9e05f0b
--- /dev/null
+++ b/libavcodec/bsf.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_BSF_H
+#define AVCODEC_BSF_H
+
+#include "avcodec.h"
+
+/**
+ * Called by the biststream filters to get the next packet for filtering.
+ * The filter is responsible for either freeing the packet or passing it to the
+ * caller.
+ */
+int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt);
+
+const AVClass *ff_bsf_child_class_next(const AVClass *prev);
+
+#endif /* AVCODEC_BSF_H */
diff --git a/libavcodec/chomp_bsf.c b/libavcodec/chomp_bsf.c
index 9ed7496..2e76113 100644
--- a/libavcodec/chomp_bsf.c
+++ b/libavcodec/chomp_bsf.c
@@ -20,19 +20,23 @@
*/
#include "avcodec.h"
+#include "bsf.h"
#include "internal.h"
-static int chomp_filter(AVBitStreamFilterContext *bsfc,
- AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size,
- int keyframe)
+static int chomp_filter(AVBSFContext *ctx, AVPacket *out)
{
- while (buf_size > 0 && !buf[buf_size-1])
- buf_size--;
+ AVPacket *in;
+ int ret;
- *poutbuf = (uint8_t*) buf;
- *poutbuf_size = buf_size;
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
+
+ while (in->size > 0 && !in->data[in->size - 1])
+ in->size--;
+
+ av_packet_move_ref(out, in);
+ av_packet_free(&in);
return 0;
}
@@ -40,8 +44,7 @@ static int chomp_filter(AVBitStreamFilterContext *bsfc,
/**
* This filter removes a string of NULL bytes from the end of a packet.
*/
-AVBitStreamFilter ff_chomp_bsf = {
- "chomp",
- 0,
- chomp_filter,
+const AVBitStreamFilter ff_chomp_bsf = {
+ .name = "chomp",
+ .filter = chomp_filter,
};
diff --git a/libavcodec/dump_extradata_bsf.c b/libavcodec/dump_extradata_bsf.c
index 3f54899..c960d6a 100644
--- a/libavcodec/dump_extradata_bsf.c
+++ b/libavcodec/dump_extradata_bsf.c
@@ -21,35 +21,81 @@
#include <string.h>
#include "avcodec.h"
+#include "bsf.h"
+
+#include "libavutil/log.h"
#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+
+enum DumpFreq {
+ DUMP_FREQ_KEYFRAME,
+ DUMP_FREQ_ALL,
+};
+
+typedef struct DumpExtradataContext {
+ const AVClass *class;
+ int freq;
+} DumpExtradataContext;
+
+static int dump_extradata(AVBSFContext *ctx, AVPacket *out)
+{
+ DumpExtradataContext *s = ctx->priv_data;
+ AVPacket *in;
+ int ret = 0;
+
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
+
+ if (ctx->par_in->extradata &&
+ (s->freq == DUMP_FREQ_ALL ||
+ (s->freq == DUMP_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY))) {
+ if (in->size >= INT_MAX - ctx->par_in->extradata_size) {
+ ret = AVERROR(ERANGE);
+ goto fail;
+ }
+ ret = av_new_packet(out, in->size + ctx->par_in->extradata_size);
+ if (ret < 0)
+ goto fail;
-static int dump_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size, int keyframe){
- int cmd= args ? *args : 0;
- /* cast to avoid warning about discarding qualifiers */
- if(avctx->extradata){
- if( (keyframe && (avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER) && cmd == 'a')
- ||(keyframe && (cmd=='k' || !cmd))
- ||(cmd=='e')
- /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){
- int size= buf_size + avctx->extradata_size;
- *poutbuf_size= size;
- *poutbuf= av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!*poutbuf)
- return AVERROR(ENOMEM);
-
- memcpy(*poutbuf, avctx->extradata, avctx->extradata_size);
- memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
- return 1;
+ ret = av_packet_copy_props(out, in);
+ if (ret < 0) {
+ av_packet_unref(out);
+ goto fail;
}
+
+ memcpy(out->data, ctx->par_in->extradata, ctx->par_in->extradata_size);
+ memcpy(out->data + ctx->par_in->extradata_size, in->data, in->size);
+ } else {
+ av_packet_move_ref(out, in);
}
- return 0;
+
+fail:
+ av_packet_free(&in);
+
+ return ret;
}
-AVBitStreamFilter ff_dump_extradata_bsf={
- "dump_extra",
- 0,
- dump_extradata,
+#define OFFSET(x) offsetof(DumpExtradataContext, x)
+static const AVOption options[] = {
+ { "freq", "When do dump extradata", OFFSET(freq), AV_OPT_TYPE_INT,
+ { .i64 = DUMP_FREQ_KEYFRAME }, DUMP_FREQ_KEYFRAME, DUMP_FREQ_ALL, 0, "freq" },
+ { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .unit = "freq" },
+ { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL }, .unit = "freq" },
+ { NULL },
+};
+
+static const AVClass dump_extradata_class = {
+ .class_name = "dump_extradata bsf",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_MAJOR,
+};
+
+const AVBitStreamFilter ff_dump_extradata_bsf = {
+ .name = "dump_extra",
+ .priv_data_size = sizeof(DumpExtradataContext),
+ .priv_class = &dump_extradata_class,
+ .filter = dump_extradata,
};
diff --git a/libavcodec/h264_mp4toannexb_bsf.c b/libavcodec/h264_mp4toannexb_bsf.c
index eeb250f..c1e2a28 100644
--- a/libavcodec/h264_mp4toannexb_bsf.c
+++ b/libavcodec/h264_mp4toannexb_bsf.c
@@ -23,7 +23,9 @@
#include "libavutil/intreadwrite.h"
#include "libavutil/mem.h"
+
#include "avcodec.h"
+#include "bsf.h"
typedef struct H264BSFContext {
uint8_t length_size;
@@ -31,41 +33,39 @@ typedef struct H264BSFContext {
int extradata_parsed;
} H264BSFContext;
-static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size,
+static int alloc_and_copy(AVPacket *out,
const uint8_t *sps_pps, uint32_t sps_pps_size,
const uint8_t *in, uint32_t in_size)
{
- uint32_t offset = *poutbuf_size;
+ uint32_t offset = out->size;
uint8_t nal_header_size = offset ? 3 : 4;
int err;
- *poutbuf_size += sps_pps_size + in_size + nal_header_size;
- if ((err = av_reallocp(poutbuf,
- *poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
- *poutbuf_size = 0;
+ err = av_grow_packet(out, sps_pps_size + in_size + nal_header_size);
+ if (err < 0)
return err;
- }
+
if (sps_pps)
- memcpy(*poutbuf + offset, sps_pps, sps_pps_size);
- memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size);
+ memcpy(out->data + offset, sps_pps, sps_pps_size);
+ memcpy(out->data + sps_pps_size + nal_header_size + offset, in, in_size);
if (!offset) {
- AV_WB32(*poutbuf + sps_pps_size, 1);
+ AV_WB32(out->data + sps_pps_size, 1);
} else {
- (*poutbuf + offset + sps_pps_size)[0] =
- (*poutbuf + offset + sps_pps_size)[1] = 0;
- (*poutbuf + offset + sps_pps_size)[2] = 1;
+ (out->data + offset + sps_pps_size)[0] =
+ (out->data + offset + sps_pps_size)[1] = 0;
+ (out->data + offset + sps_pps_size)[2] = 1;
}
return 0;
}
-static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding)
+static int h264_extradata_to_annexb(AVBSFContext *ctx, const int padding)
{
uint16_t unit_size;
uint64_t total_size = 0;
uint8_t *out = NULL, unit_nb, sps_done = 0,
sps_seen = 0, pps_seen = 0;
- const uint8_t *extradata = avctx->extradata + 4;
+ const uint8_t *extradata = ctx->par_in->extradata + 4;
static const uint8_t nalu_header[4] = { 0, 0, 0, 1 };
int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size
@@ -90,8 +90,8 @@ static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding)
unit_size = AV_RB16(extradata);
total_size += unit_size + 4;
if (total_size > INT_MAX - padding ||
- extradata + 2 + unit_size > avctx->extradata +
- avctx->extradata_size) {
+ extradata + 2 + unit_size > ctx->par_in->extradata +
+ ctx->par_in->extradata_size) {
av_free(out);
return AVERROR(EINVAL);
}
@@ -112,100 +112,125 @@ static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding)
memset(out + total_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
if (!sps_seen)
- av_log(avctx, AV_LOG_WARNING,
+ av_log(ctx, AV_LOG_WARNING,
"Warning: SPS NALU missing or invalid. "
"The resulting stream may not play.\n");
if (!pps_seen)
- av_log(avctx, AV_LOG_WARNING,
+ av_log(ctx, AV_LOG_WARNING,
"Warning: PPS NALU missing or invalid. "
"The resulting stream may not play.\n");
- av_free(avctx->extradata);
- avctx->extradata = out;
- avctx->extradata_size = total_size;
+ av_freep(&ctx->par_out->extradata);
+ ctx->par_out->extradata = out;
+ ctx->par_out->extradata_size = total_size;
return length_size;
}
-static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
- AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size,
- int keyframe)
+static int h264_mp4toannexb_init(AVBSFContext *ctx)
{
- H264BSFContext *ctx = bsfc->priv_data;
+ H264BSFContext *s = ctx->priv_data;
+ int ret;
+
+ /* retrieve sps and pps NAL units from extradata */
+ if (ctx->par_in->extradata_size >= 6) {
+ ret = h264_extradata_to_annexb(ctx, AV_INPUT_BUFFER_PADDING_SIZE);
+ if (ret < 0)
+ return ret;
+
+ s->length_size = ret;
+ s->first_idr = 1;
+ s->extradata_parsed = 1;
+ }
+
+ return 0;
+}
+
+static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
+{
+ H264BSFContext *s = ctx->priv_data;
+
+ AVPacket *in;
uint8_t unit_type;
int32_t nal_size;
uint32_t cumul_size = 0;
- const uint8_t *buf_end = buf + buf_size;
+ const uint8_t *buf;
+ const uint8_t *buf_end;
+ int buf_size;
int ret = 0;
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
+
/* nothing to filter */
- if (!avctx->extradata || avctx->extradata_size < 6) {
- *poutbuf = (uint8_t *)buf;
- *poutbuf_size = buf_size;
+ if (!s->extradata_parsed) {
+ av_packet_move_ref(out, in);
+ av_packet_free(&in);
return 0;
}
- /* retrieve sps and pps NAL units from extradata */
- if (!ctx->extradata_parsed) {
- ret = h264_extradata_to_annexb(avctx, AV_INPUT_BUFFER_PADDING_SIZE);
- if (ret < 0)
- return ret;
- ctx->length_size = ret;
- ctx->first_idr = 1;
- ctx->extradata_parsed = 1;
- }
+ buf = in->data;
+ buf_size = in->size;
+ buf_end = in->data + in->size;
- *poutbuf_size = 0;
- *poutbuf = NULL;
do {
- if (buf + ctx->length_size > buf_end)
+ if (buf + s->length_size > buf_end)
goto fail;
- if (ctx->length_size == 1) {
+ if (s->length_size == 1) {
nal_size = buf[0];
- } else if (ctx->length_size == 2) {
+ } else if (s->length_size == 2) {
nal_size = AV_RB16(buf);
} else
nal_size = AV_RB32(buf);
- buf += ctx->length_size;
+ buf += s->length_size;
unit_type = *buf & 0x1f;
if (buf + nal_size > buf_end || nal_size < 0)
goto fail;
/* prepend only to the first type 5 NAL unit of an IDR picture */
- if (ctx->first_idr && unit_type == 5) {
- if (alloc_and_copy(poutbuf, poutbuf_size,
- avctx->extradata, avctx->extradata_size,
+ if (s->first_idr && unit_type == 5) {
+ if (alloc_and_copy(out,
+ ctx->par_out->extradata, ctx->par_out->extradata_size,
buf, nal_size) < 0)
goto fail;
- ctx->first_idr = 0;
+ s->first_idr = 0;
} else {
- if (alloc_and_copy(poutbuf, poutbuf_size,
+ if (alloc_and_copy(out,
NULL, 0, buf, nal_size) < 0)
goto fail;
- if (!ctx->first_idr && unit_type == 1)
- ctx->first_idr = 1;
+ if (!s->first_idr && unit_type == 1)
+ s->first_idr = 1;
}
buf += nal_size;
- cumul_size += nal_size + ctx->length_size;
+ cumul_size += nal_size + s->length_size;
} while (cumul_size < buf_size);
- return 1;
+ ret = av_packet_copy_props(out, in);
+ if (ret < 0)
+ goto fail;
fail:
- av_freep(poutbuf);
- *poutbuf_size = 0;
- return AVERROR(EINVAL);
+ if (ret < 0)
+ av_packet_unref(out);
+ av_packet_free(&in);
+
+ return ret;
}
-AVBitStreamFilter ff_h264_mp4toannexb_bsf = {
- "h264_mp4toannexb",
- sizeof(H264BSFContext),
- h264_mp4toannexb_filter,
+static const enum AVCodecID codec_ids[] = {
+ AV_CODEC_ID_H264, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_h264_mp4toannexb_bsf = {
+ .name = "h264_mp4toannexb",
+ .priv_data_size = sizeof(H264BSFContext),
+ .init = h264_mp4toannexb_init,
+ .filter = h264_mp4toannexb_filter,
+ .codec_ids = codec_ids,
};
diff --git a/libavcodec/hevc_mp4toannexb_bsf.c b/libavcodec/hevc_mp4toannexb_bsf.c
index dfecf5e..8d7ac58 100644
--- a/libavcodec/hevc_mp4toannexb_bsf.c
+++ b/libavcodec/hevc_mp4toannexb_bsf.c
@@ -25,6 +25,7 @@
#include "libavutil/mem.h"
#include "avcodec.h"
+#include "bsf.h"
#include "bytestream.h"
#include "hevc.h"
@@ -33,11 +34,9 @@
typedef struct HEVCBSFContext {
uint8_t length_size;
int extradata_parsed;
-
- int logged_nonmp4_warning;
} HEVCBSFContext;
-static int hevc_extradata_to_annexb(AVCodecContext *avctx)
+static int hevc_extradata_to_annexb(AVBSFContext *ctx)
{
GetByteContext gb;
int length_size, num_arrays, i, j;
@@ -46,7 +45,7 @@ static int hevc_extradata_to_annexb(AVCodecContext *avctx)
uint8_t *new_extradata = NULL;
size_t new_extradata_size = 0;;
- bytestream2_init(&gb, avctx->extradata, avctx->extradata_size);
+ bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size);
bytestream2_skip(&gb, 21);
length_size = (bytestream2_get_byte(&gb) & 3) + 1;
@@ -58,7 +57,7 @@ static int hevc_extradata_to_annexb(AVCodecContext *avctx)
if (!(type == NAL_VPS || type == NAL_SPS || type == NAL_PPS ||
type == NAL_SEI_PREFIX || type == NAL_SEI_SUFFIX)) {
- av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
+ av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
type);
ret = AVERROR_INVALIDDATA;
goto fail;
@@ -82,12 +81,12 @@ static int hevc_extradata_to_annexb(AVCodecContext *avctx)
}
}
- av_freep(&avctx->extradata);
- avctx->extradata = new_extradata;
- avctx->extradata_size = new_extradata_size;
+ av_freep(&ctx->par_out->extradata);
+ ctx->par_out->extradata = new_extradata;
+ ctx->par_out->extradata_size = new_extradata_size;
if (!new_extradata_size)
- av_log(avctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
+ av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
return length_size;
fail:
@@ -95,52 +94,54 @@ fail:
return ret;
}
-static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
- AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size,
- int keyframe)
+static int hevc_mp4toannexb_init(AVBSFContext *ctx)
{
- HEVCBSFContext *ctx = bsfc->priv_data;
+ HEVCBSFContext *s = ctx->priv_data;
+ int ret;
+
+ if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH ||
+ AV_RB24(ctx->par_in->extradata) == 1 ||
+ AV_RB32(ctx->par_in->extradata) == 1) {
+ av_log(ctx, AV_LOG_VERBOSE,
+ "The input looks like it is Annex B already\n");
+ } else {
+ ret = hevc_extradata_to_annexb(ctx);
+ if (ret < 0)
+ return ret;
+ s->length_size = ret;
+ s->extradata_parsed = 1;
+ }
+
+ return 0;
+}
+
+static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
+{
+ HEVCBSFContext *s = ctx->priv_data;
+ AVPacket *in;
GetByteContext gb;
- uint8_t *out = NULL;
- size_t out_size = 0;
int got_irap = 0;
int i, ret = 0;
- if (!ctx->extradata_parsed) {
- if (avctx->extradata_size < MIN_HEVCC_LENGTH ||
- AV_RB24(avctx->extradata) == 1 ||
- AV_RB32(avctx->extradata) == 1) {
- if (!ctx->logged_nonmp4_warning) {
- av_log(avctx, AV_LOG_VERBOSE,
- "The input looks like it is Annex B already\n");
- ctx->logged_nonmp4_warning = 1;
- }
- *poutbuf = buf;
- *poutbuf_size = buf_size;
- return 0;
- }
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
- ret = hevc_extradata_to_annexb(avctx);
- if (ret < 0)
- return ret;
- ctx->length_size = ret;
- ctx->extradata_parsed = 1;
+ if (!s->extradata_parsed) {
+ av_packet_move_ref(out, in);
+ av_packet_free(&in);
+ return 0;
}
- *poutbuf_size = 0;
- *poutbuf = NULL;
-
- bytestream2_init(&gb, buf, buf_size);
+ bytestream2_init(&gb, in->data, in->size);
while (bytestream2_get_bytes_left(&gb)) {
uint32_t nalu_size = 0;
int nalu_type;
- int is_irap, add_extradata, extra_size;
+ int is_irap, add_extradata, extra_size, prev_size;
- for (i = 0; i < ctx->length_size; i++)
+ for (i = 0; i < s->length_size; i++)
nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
@@ -148,39 +149,47 @@ static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
/* prepend extradata to IRAP frames */
is_irap = nalu_type >= 16 && nalu_type <= 23;
add_extradata = is_irap && !got_irap;
- extra_size = add_extradata * avctx->extradata_size;
+ extra_size = add_extradata * ctx->par_out->extradata_size;
got_irap |= is_irap;
- if (SIZE_MAX - out_size < 4 ||
- SIZE_MAX - out_size - 4 < nalu_size ||
- SIZE_MAX - out_size - 4 - nalu_size < extra_size) {
+ if (SIZE_MAX - nalu_size < 4 ||
+ SIZE_MAX - 4 - nalu_size < extra_size) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
- ret = av_reallocp(&out, out_size + 4 + nalu_size + extra_size);
+ prev_size = out->size;
+
+ ret = av_grow_packet(out, 4 + nalu_size + extra_size);
if (ret < 0)
goto fail;
if (add_extradata)
- memcpy(out + out_size, avctx->extradata, extra_size);
- AV_WB32(out + out_size + extra_size, 1);
- bytestream2_get_buffer(&gb, out + out_size + 4 + extra_size, nalu_size);
- out_size += 4 + nalu_size + extra_size;
+ memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size);
+ AV_WB32(out->data + prev_size + extra_size, 1);
+ bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size);
}
- *poutbuf = out;
- *poutbuf_size = out_size;
-
- return 1;
+ ret = av_packet_copy_props(out, in);
+ if (ret < 0)
+ goto fail;
fail:
- av_freep(&out);
+ if (ret < 0)
+ av_packet_unref(out);
+ av_packet_free(&in);
+
return ret;
}
-AVBitStreamFilter ff_hevc_mp4toannexb_bsf = {
- "hevc_mp4toannexb",
- sizeof(HEVCBSFContext),
- hevc_mp4toannexb_filter,
+static const enum AVCodecID codec_ids[] = {
+ AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_hevc_mp4toannexb_bsf = {
+ .name = "hevc_mp4toannexb",
+ .priv_data_size = sizeof(HEVCBSFContext),
+ .init = hevc_mp4toannexb_init,
+ .filter = hevc_mp4toannexb_filter,
+ .codec_ids = codec_ids,
};
diff --git a/libavcodec/imx_dump_header_bsf.c b/libavcodec/imx_dump_header_bsf.c
index a79039d..71bda02 100644
--- a/libavcodec/imx_dump_header_bsf.c
+++ b/libavcodec/imx_dump_header_bsf.c
@@ -26,36 +26,51 @@
*/
#include "avcodec.h"
+#include "bsf.h"
#include "bytestream.h"
-static int imx_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size, int keyframe)
+static int imx_dump_header(AVBSFContext *ctx, AVPacket *out)
{
/* MXF essence element key */
static const uint8_t imx_header[16] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x05,0x01,0x01,0x00 };
- uint8_t *poutbufp;
-
- if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO) {
- av_log(avctx, AV_LOG_ERROR, "imx bitstream filter only applies to mpeg2video codec\n");
- return 0;
- }
-
- *poutbuf = av_malloc(buf_size + 20 + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!*poutbuf)
- return AVERROR(ENOMEM);
- poutbufp = *poutbuf;
- bytestream_put_buffer(&poutbufp, imx_header, 16);
- bytestream_put_byte(&poutbufp, 0x83); /* KLV BER long form */
- bytestream_put_be24(&poutbufp, buf_size);
- bytestream_put_buffer(&poutbufp, buf, buf_size);
- *poutbuf_size = poutbufp - *poutbuf;
- return 1;
+
+ AVPacket *in;
+ int ret = 0;
+ uint8_t *out_buf;
+
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
+
+ ret = av_new_packet(out, in->size + 20);
+ if (ret < 0)
+ goto fail;
+
+ out_buf = out->data;
+
+ bytestream_put_buffer(&out_buf, imx_header, 16);
+ bytestream_put_byte(&out_buf, 0x83); /* KLV BER long form */
+ bytestream_put_be24(&out_buf, in->size);
+ bytestream_put_buffer(&out_buf, in->data, in->size);
+
+ ret = av_packet_copy_props(out, in);
+ if (ret < 0)
+ goto fail;
+
+fail:
+ if (ret < 0)
+ av_packet_unref(out);
+ av_packet_free(&in);
+ return ret;
}
-AVBitStreamFilter ff_imx_dump_header_bsf = {
- "imxdump",
- 0,
- imx_dump_header,
+static const enum AVCodecID codec_ids[] = {
+ AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_imx_dump_header_bsf = {
+ .name = "imxdump",
+ .filter = imx_dump_header,
+ .codec_ids = codec_ids,
};
diff --git a/libavcodec/mjpeg2jpeg_bsf.c b/libavcodec/mjpeg2jpeg_bsf.c
index d277934..eec3469 100644
--- a/libavcodec/mjpeg2jpeg_bsf.c
+++ b/libavcodec/mjpeg2jpeg_bsf.c
@@ -30,6 +30,7 @@
#include "libavutil/mem.h"
#include "avcodec.h"
+#include "bsf.h"
#include "jpegtables.h"
static const uint8_t jpeg_header[] = {
@@ -75,42 +76,56 @@ static uint8_t *append_dht_segment(uint8_t *buf)
return buf;
}
-static int mjpeg2jpeg_filter(AVBitStreamFilterContext *bsfc,
- AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size,
- int keyframe)
+static int mjpeg2jpeg_filter(AVBSFContext *ctx, AVPacket *out)
{
+ AVPacket *in;
+ int ret = 0;
int input_skip, output_size;
- uint8_t *output, *out;
+ uint8_t *output;
- if (buf_size < 12) {
- av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
- return AVERROR_INVALIDDATA;
+ ret = ff_bsf_get_packet(ctx, &in);
+
+ if (in->size < 12) {
+ av_log(ctx, AV_LOG_ERROR, "input is truncated\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
- if (memcmp("AVI1", buf + 6, 4)) {
- av_log(avctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n");
- return AVERROR_INVALIDDATA;
+ if (memcmp("AVI1", in->data + 6, 4)) {
+ av_log(ctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
- input_skip = (buf[4] << 8) + buf[5] + 4;
- if (buf_size < input_skip) {
- av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
- return AVERROR_INVALIDDATA;
+
+ input_skip = (in->data[4] << 8) + in->data[5] + 4;
+ if (in->size < input_skip) {
+ av_log(ctx, AV_LOG_ERROR, "input is truncated\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
- output_size = buf_size - input_skip +
+ output_size = in->size - input_skip +
sizeof(jpeg_header) + dht_segment_size;
- output = out = av_malloc(output_size);
- if (!output)
- return AVERROR(ENOMEM);
- out = append(out, jpeg_header, sizeof(jpeg_header));
- out = append_dht_segment(out);
- out = append(out, buf + input_skip, buf_size - input_skip);
- *poutbuf = output;
- *poutbuf_size = output_size;
- return 1;
+ ret = av_new_packet(out, output_size);
+ if (ret < 0)
+ goto fail;
+
+ output = out->data;
+
+ output = append(output, jpeg_header, sizeof(jpeg_header));
+ output = append_dht_segment(output);
+ output = append(output, in->data + input_skip, in->size - input_skip);
+
+ ret = av_packet_copy_props(out, in);
+ if (ret < 0)
+ goto fail;
+
+fail:
+ if (ret < 0)
+ av_packet_unref(out);
+ av_packet_free(&in);
+ return ret;
}
-AVBitStreamFilter ff_mjpeg2jpeg_bsf = {
+const AVBitStreamFilter ff_mjpeg2jpeg_bsf = {
.name = "mjpeg2jpeg",
.filter = mjpeg2jpeg_filter,
};
diff --git a/libavcodec/mjpega_dump_header_bsf.c b/libavcodec/mjpega_dump_header_bsf.c
index dfb8916..b3ce26a 100644
--- a/libavcodec/mjpega_dump_header_bsf.c
+++ b/libavcodec/mjpega_dump_header_bsf.c
@@ -26,71 +26,83 @@
*/
#include "avcodec.h"
+#include "bsf.h"
#include "bytestream.h"
#include "mjpeg.h"
-static int mjpega_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size, int keyframe)
+static int mjpega_dump_header(AVBSFContext *ctx, AVPacket *out)
{
- uint8_t *poutbufp;
+ AVPacket *in;
+ uint8_t *out_buf;
unsigned dqt = 0, dht = 0, sof0 = 0;
- int i;
+ int ret = 0, i;
- if (avctx->codec_id != AV_CODEC_ID_MJPEG) {
- av_log(avctx, AV_LOG_ERROR, "mjpega bitstream filter only applies to mjpeg codec\n");
- return 0;
- }
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
+
+ ret = av_new_packet(out, in->size + 44);
+ if (ret < 0)
+ goto fail;
+
+ ret = av_packet_copy_props(out, in);
+ if (ret < 0)
+ goto fail;
- *poutbuf_size = 0;
- *poutbuf = av_malloc(buf_size + 44 + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!*poutbuf)
- return AVERROR(ENOMEM);
- poutbufp = *poutbuf;
- bytestream_put_byte(&poutbufp, 0xff);
- bytestream_put_byte(&poutbufp, SOI);
- bytestream_put_byte(&poutbufp, 0xff);
- bytestream_put_byte(&poutbufp, APP1);
- bytestream_put_be16(&poutbufp, 42); /* size */
- bytestream_put_be32(&poutbufp, 0);
- bytestream_put_buffer(&poutbufp, "mjpg", 4);
- bytestream_put_be32(&poutbufp, buf_size + 44); /* field size */
- bytestream_put_be32(&poutbufp, buf_size + 44); /* pad field size */
- bytestream_put_be32(&poutbufp, 0); /* next ptr */
+ out_buf = out->data;
+ bytestream_put_byte(&out_buf, 0xff);
+ bytestream_put_byte(&out_buf, SOI);
+ bytestream_put_byte(&out_buf, 0xff);
+ bytestream_put_byte(&out_buf, APP1);
+ bytestream_put_be16(&out_buf, 42); /* size */
+ bytestream_put_be32(&out_buf, 0);
+ bytestream_put_buffer(&out_buf, "mjpg", 4);
+ bytestream_put_be32(&out_buf, in->size + 44); /* field size */
+ bytestream_put_be32(&out_buf, in->size + 44); /* pad field size */
+ bytestream_put_be32(&out_buf, 0); /* next ptr */
- for (i = 0; i < buf_size - 1; i++) {
- if (buf[i] == 0xff) {
- switch (buf[i + 1]) {
+ for (i = 0; i < in->size - 1; i++) {
+ if (in->data[i] == 0xff) {
+ switch (in->data[i + 1]) {
case DQT: dqt = i + 46; break;
case DHT: dht = i + 46; break;
case SOF0: sof0 = i + 46; break;
case SOS:
- bytestream_put_be32(&poutbufp, dqt); /* quant off */
- bytestream_put_be32(&poutbufp, dht); /* huff off */
- bytestream_put_be32(&poutbufp, sof0); /* image off */
- bytestream_put_be32(&poutbufp, i + 46); /* scan off */
- bytestream_put_be32(&poutbufp, i + 46 + AV_RB16(buf + i + 2)); /* data off */
- bytestream_put_buffer(&poutbufp, buf + 2, buf_size - 2); /* skip already written SOI */
- *poutbuf_size = poutbufp - *poutbuf;
- return 1;
+ bytestream_put_be32(&out_buf, dqt); /* quant off */
+ bytestream_put_be32(&out_buf, dht); /* huff off */
+ bytestream_put_be32(&out_buf, sof0); /* image off */
+ bytestream_put_be32(&out_buf, i + 46); /* scan off */
+ bytestream_put_be32(&out_buf, i + 46 + AV_RB16(in->data + i + 2)); /* data off */
+ bytestream_put_buffer(&out_buf, in->data + 2, in->size - 2); /* skip already written SOI */
+
+ out->size = out_buf - out->data;
+ av_packet_free(&in);
+ return 0;
case APP1:
- if (i + 8 < buf_size && AV_RL32(buf + i + 8) == AV_RL32("mjpg")) {
- av_log(avctx, AV_LOG_ERROR, "bitstream already formatted\n");
- memcpy(*poutbuf, buf, buf_size);
- *poutbuf_size = buf_size;
- return 1;
+ if (i + 8 < in->size && AV_RL32(in->data + i + 8) == AV_RL32("mjpg")) {
+ av_log(ctx, AV_LOG_ERROR, "bitstream already formatted\n");
+ av_packet_unref(out);
+ av_packet_move_ref(out, in);
+ av_packet_free(&in);
+ return 0;
}
}
}
}
- av_freep(poutbuf);
- av_log(avctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n");
- return 0;
+ av_log(ctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n");
+fail:
+ av_packet_unref(out);
+ av_packet_free(&in);
+ return AVERROR_INVALIDDATA;
}
-AVBitStreamFilter ff_mjpega_dump_header_bsf = {
- "mjpegadump",
- 0,
- mjpega_dump_header,
+static const enum AVCodecID codec_ids[] = {
+ AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_mjpega_dump_header_bsf = {
+ .name = "mjpegadump",
+ .filter = mjpega_dump_header,
+ .codec_ids = codec_ids,
};
diff --git a/libavcodec/movsub_bsf.c b/libavcodec/movsub_bsf.c
index 0484303..fc6b236 100644
--- a/libavcodec/movsub_bsf.c
+++ b/libavcodec/movsub_bsf.c
@@ -21,41 +21,79 @@
#include "libavutil/common.h"
#include "libavutil/intreadwrite.h"
#include "avcodec.h"
+#include "bsf.h"
+static int text2movsub(AVBSFContext *ctx, AVPacket *out)
+{
+ AVPacket *in;
+ int ret = 0;
-static int text2movsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size, int keyframe){
- if (buf_size > 0xffff) return 0;
- *poutbuf_size = buf_size + 2;
- *poutbuf = av_malloc(*poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!*poutbuf)
- return AVERROR(ENOMEM);
- AV_WB16(*poutbuf, buf_size);
- memcpy(*poutbuf + 2, buf, buf_size);
- return 1;
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
+
+ if (in->size > 0xffff) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ ret = av_new_packet(out, in->size + 2);
+ if (ret < 0) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ ret = av_packet_copy_props(out, in);
+ if (ret < 0)
+ goto fail;
+
+ AV_WB16(out->data, in->size);
+ memcpy(out->data + 2, in->data, in->size);
+
+fail:
+ if (ret < 0)
+ av_packet_unref(out);
+ av_packet_free(&in);
+ return ret;
}
-AVBitStreamFilter ff_text2movsub_bsf={
- "text2movsub",
- 0,
- text2movsub,
+const AVBitStreamFilter ff_text2movsub_bsf = {
+ .name = "text2movsub",
+ .filter = text2movsub,
};
-static int mov2textsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size, int keyframe){
- if (buf_size < 2) return 0;
- *poutbuf_size = FFMIN(buf_size - 2, AV_RB16(buf));
- *poutbuf = av_malloc(*poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!*poutbuf)
- return AVERROR(ENOMEM);
- memcpy(*poutbuf, buf + 2, *poutbuf_size);
- return 1;
+static int mov2textsub(AVBSFContext *ctx, AVPacket *out)
+{
+ AVPacket *in;
+ int ret = 0;
+
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
+
+ if (in->size < 2) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ ret = av_new_packet(out, FFMIN(in->size - 2, AV_RB16(in->data)));
+ if (ret < 0)
+ goto fail;
+
+ ret = av_packet_copy_props(out, in);
+ if (ret < 0)
+ goto fail;
+
+ memcpy(out->data, in->data + 2, out->size);
+
+fail:
+ if (ret < 0)
+ av_packet_unref(out);
+ av_packet_free(&in);
+ return ret;
}
-AVBitStreamFilter ff_mov2textsub_bsf={
- "mov2textsub",
- 0,
- mov2textsub,
+const AVBitStreamFilter ff_mov2textsub_bsf = {
+ .name = "mov2textsub",
+ .filter = mov2textsub,
};
diff --git a/libavcodec/noise_bsf.c b/libavcodec/noise_bsf.c
index 81840bd..3b41dbf 100644
--- a/libavcodec/noise_bsf.c
+++ b/libavcodec/noise_bsf.c
@@ -22,30 +22,67 @@
#include <string.h>
#include "avcodec.h"
+#include "bsf.h"
+
+#include "libavutil/log.h"
#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+
+typedef struct NoiseContext {
+ const AVClass *class;
+ int amount;
+ unsigned int state;
+} NoiseContext;
+
+static int noise(AVBSFContext *ctx, AVPacket *out)
+{
+ NoiseContext *s = ctx->priv_data;
+ AVPacket *in;
+ int amount = s->amount > 0 ? s->amount : (s->state % 10001 + 1);
+ int i, ret = 0;
+
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
+
+ ret = av_new_packet(out, in->size);
+ if (ret < 0)
+ goto fail;
+ ret = av_packet_copy_props(out, in);
+ if (ret < 0)
+ goto fail;
-static int noise(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size, int keyframe){
- unsigned int *state= bsfc->priv_data;
- int amount= args ? atoi(args) : (*state % 10001+1);
- int i;
-
- *poutbuf= av_malloc(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!*poutbuf)
- return AVERROR(ENOMEM);
- memcpy(*poutbuf, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
- for(i=0; i<buf_size; i++){
- (*state) += (*poutbuf)[i] + 1;
- if(*state % amount == 0)
- (*poutbuf)[i] = *state;
+ memcpy(out->data, in->data, in->size);
+
+ for (i = 0; i < out->size; i++) {
+ s->state += out->data[i] + 1;
+ if (s->state % amount == 0)
+ out->data[i] = s->state;
}
- return 1;
+fail:
+ if (ret < 0)
+ av_packet_unref(out);
+ av_packet_free(&in);
+ return ret;
}
-AVBitStreamFilter ff_noise_bsf={
- "noise",
- sizeof(int),
- noise,
+#define OFFSET(x) offsetof(NoiseContext, x)
+static const AVOption options[] = {
+ { "amount", NULL, OFFSET(amount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX },
+ { NULL },
+};
+
+static const AVClass noise_class = {
+ .class_name = "noise",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+const AVBitStreamFilter ff_noise_bsf = {
+ .name = "noise",
+ .priv_data_size = sizeof(int),
+ .priv_class = &noise_class,
+ .filter = noise,
};
diff --git a/libavcodec/remove_extradata_bsf.c b/libavcodec/remove_extradata_bsf.c
index b82c867..a89fa06 100644
--- a/libavcodec/remove_extradata_bsf.c
+++ b/libavcodec/remove_extradata_bsf.c
@@ -18,39 +18,99 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+
#include "avcodec.h"
+#include "bsf.h"
+enum RemoveFreq {
+ REMOVE_FREQ_KEYFRAME,
+ REMOVE_FREQ_ALL,
+};
-static int remove_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size, int keyframe){
- int cmd= args ? *args : 0;
- AVCodecParserContext *s;
+typedef struct RemoveExtradataContext {
+ const AVClass *class;
+ int freq;
- if(!bsfc->parser){
- bsfc->parser= av_parser_init(avctx->codec_id);
- }
- s= bsfc->parser;
-
- if(s && s->parser->split){
- if( (((avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ||
- (avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER)) && cmd == 'a')
- ||(!keyframe && cmd=='k')
- ||(cmd=='e' || !cmd)
- ){
- int i= s->parser->split(avctx, buf, buf_size);
- buf += i;
- buf_size -= i;
+ AVCodecParserContext *parser;
+ AVCodecContext *avctx;
+} RemoveExtradataContext;
+
+static int remove_extradata(AVBSFContext *ctx, AVPacket *out)
+{
+ RemoveExtradataContext *s = ctx->priv_data;
+
+ AVPacket *in;
+ int ret;
+
+ ret = ff_bsf_get_packet(ctx, &in);
+ if (ret < 0)
+ return ret;
+
+ if (s->parser && s->parser->parser->split) {
+ if (s->freq == REMOVE_FREQ_ALL ||
+ (s->freq == REMOVE_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY)) {
+ int i = s->parser->parser->split(s->avctx, in->data, in->size);
+ in->data += i;
+ in->size -= i;
}
}
- *poutbuf= (uint8_t *) buf;
- *poutbuf_size= buf_size;
+
+ av_packet_move_ref(out, in);
+ av_packet_free(&in);
return 0;
}
-AVBitStreamFilter ff_remove_extradata_bsf={
- "remove_extra",
- 0,
- remove_extradata,
+static int remove_extradata_init(AVBSFContext *ctx)
+{
+ RemoveExtradataContext *s = ctx->priv_data;
+ int ret;
+
+ s->parser = av_parser_init(ctx->par_in->codec_id);
+
+ if (s->parser) {
+ s->avctx = avcodec_alloc_context3(NULL);
+ if (!s->avctx)
+ return AVERROR(ENOMEM);
+
+ ret = avcodec_parameters_to_context(s->avctx, ctx->par_in);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void remove_extradata_close(AVBSFContext *ctx)
+{
+ RemoveExtradataContext *s = ctx->priv_data;
+
+ avcodec_free_context(&s->avctx);
+ av_parser_close(s->parser);
+}
+
+#define OFFSET(x) offsetof(RemoveExtradataContext, x)
+static const AVOption options[] = {
+ { "freq", NULL, OFFSET(freq), AV_OPT_TYPE_INT, { .i64 = REMOVE_FREQ_KEYFRAME }, REMOVE_FREQ_KEYFRAME, REMOVE_FREQ_ALL, 0, "freq" },
+ { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_KEYFRAME }, .unit = "freq" },
+ { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL }, .unit = "freq" },
+ { NULL },
+};
+
+static const AVClass remove_extradata_class = {
+ .class_name = "remove_extradata",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+const AVBitStreamFilter ff_remove_extradata_bsf = {
+ .name = "remove_extra",
+ .priv_data_size = sizeof(RemoveExtradataContext),
+ .priv_class = &remove_extradata_class,
+ .init = remove_extradata_init,
+ .close = remove_extradata_close,
+ .filter = remove_extradata,
};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index d247c09..d5045fb 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,7 +28,7 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 57
-#define LIBAVCODEC_VERSION_MINOR 14
+#define LIBAVCODEC_VERSION_MINOR 15
#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
@@ -197,5 +197,8 @@
#ifndef FF_API_PRIVATE_OPT
#define FF_API_PRIVATE_OPT (LIBAVCODEC_VERSION_MAJOR < 59)
#endif
+#ifndef FF_API_OLD_BSF
+#define FF_API_OLD_BSF (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
#endif /* AVCODEC_VERSION_H */
More information about the ffmpeg-cvslog
mailing list