Message ID | 20180402224706.10718-2-sw@jkqxz.net |
---|---|
State | Superseded |
Headers | show |
On 4/2/2018 7:47 PM, Mark Thompson wrote: > Can adjust the colour information. > --- > And nothing else, so meh. Still, offers a clean filter for testing VP9 CBS. > > I think it should have some FATE tests along the same lines as H.26[45] and MPEG-2, running across a set of streams and making sure it reads and writes them back correctly. Not clear what set of streams to use, though - should I just pick a random set of the conformance test vectors which look sensible, or is there some more obvious subset? Use the existing conformance test samples, especially for profiles 1 to 3 since there's one for each pixel format and bit depth. > > > configure | 1 + > libavcodec/Makefile | 1 + > libavcodec/bitstream_filters.c | 1 + > libavcodec/vp9_metadata_bsf.c | 143 +++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 146 insertions(+) > create mode 100644 libavcodec/vp9_metadata_bsf.c > > diff --git a/configure b/configure > index 890de64ab4..28970cbdf8 100755 > --- a/configure > +++ b/configure > @@ -2986,6 +2986,7 @@ hevc_metadata_bsf_select="cbs_h265" > mjpeg2jpeg_bsf_select="jpegtables" > mpeg2_metadata_bsf_select="cbs_mpeg2" > trace_headers_bsf_select="cbs" > +vp9_metadata_bsf_select="cbs_vp9" > > # external libraries > aac_at_decoder_deps="audiotoolbox" > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index 6ee16d855b..1a172f5597 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -1067,6 +1067,7 @@ OBJS-$(CONFIG_NULL_BSF) += null_bsf.o > OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o > OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o > OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o > +OBJS-$(CONFIG_VP9_METADATA_BSF) += vp9_metadata_bsf.o > OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o > OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o > OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o > diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c > index 18b698a85f..c21373621c 100644 > --- a/libavcodec/bitstream_filters.c > +++ b/libavcodec/bitstream_filters.c > @@ -49,6 +49,7 @@ extern const AVBitStreamFilter ff_null_bsf; > extern const AVBitStreamFilter ff_remove_extradata_bsf; > extern const AVBitStreamFilter ff_text2movsub_bsf; > extern const AVBitStreamFilter ff_trace_headers_bsf; > +extern const AVBitStreamFilter ff_vp9_metadata_bsf; > extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf; > extern const AVBitStreamFilter ff_vp9_superframe_bsf; > extern const AVBitStreamFilter ff_vp9_superframe_split_bsf; > diff --git a/libavcodec/vp9_metadata_bsf.c b/libavcodec/vp9_metadata_bsf.c > new file mode 100644 > index 0000000000..39994611a0 > --- /dev/null > +++ b/libavcodec/vp9_metadata_bsf.c > @@ -0,0 +1,143 @@ > +/* > + * This file is part of FFmpeg. > + * > + * FFmpeg 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. > + * > + * FFmpeg 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 FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +#include "libavutil/avstring.h" > +#include "libavutil/common.h" > +#include "libavutil/opt.h" > + > +#include "bsf.h" > +#include "cbs.h" > +#include "cbs_vp9.h" > + > +typedef struct VP9MetadataContext { > + const AVClass *class; > + > + CodedBitstreamContext *cbc; > + CodedBitstreamFragment fragment; > + > + int color_space; > + int color_range; > + > + int color_range_rgb_warned; > +} VP9MetadataContext; > + > + > +static int vp9_metadata_filter(AVBSFContext *bsf, AVPacket *out) > +{ > + VP9MetadataContext *ctx = bsf->priv_data; > + AVPacket *in = NULL; > + CodedBitstreamFragment *frag = &ctx->fragment; > + int err, i; > + > + err = ff_bsf_get_packet(bsf, &in); > + if (err < 0) > + return err; > + > + err = ff_cbs_read_packet(ctx->cbc, frag, in); > + if (err < 0) { > + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); > + goto fail; > + } > + > + for (i = 0; i < frag->nb_units; i++) { > + VP9RawFrame *frame = frag->units[i].content; > + VP9RawFrameHeader *header = &frame->header; > + > + if (ctx->color_space >= 0) { > + header->color_space = ctx->color_space; > + } > + if (ctx->color_range >= 0) { > + if (ctx->color_range == 0 && > + header->color_space == VP9_CS_RGB && > + !ctx->color_range_rgb_warned) { > + av_log(bsf, AV_LOG_WARNING, "Warning: color_range cannot " > + "be set to limited in RGB streams.\n"); > + ctx->color_range_rgb_warned = 1; > + } else { > + header->color_range = ctx->color_range; > + } > + } > + } > + > + err = ff_cbs_write_packet(ctx->cbc, out, frag); > + if (err < 0) { > + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); > + goto fail; > + } > + > + err = av_packet_copy_props(out, in); > + if (err < 0) > + goto fail; > + > + err = 0; > +fail: > + ff_cbs_fragment_uninit(ctx->cbc, frag); > + > + if (err < 0) > + av_packet_unref(out); > + av_packet_free(&in); > + > + return err; > +} > + > +static int vp9_metadata_init(AVBSFContext *bsf) > +{ > + VP9MetadataContext *ctx = bsf->priv_data; > + > + return ff_cbs_init(&ctx->cbc, AV_CODEC_ID_VP9, bsf); > +} > + > +static void vp9_metadata_close(AVBSFContext *bsf) > +{ > + VP9MetadataContext *ctx = bsf->priv_data; > + ff_cbs_close(&ctx->cbc); > +} > + > +#define OFFSET(x) offsetof(VP9MetadataContext, x) > +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) > +static const AVOption vp9_metadata_options[] = { > + { "color_space", "Set colour space (see section 7.2.2)", > + OFFSET(color_space), AV_OPT_TYPE_INT, > + { .i64 = -1 }, -1, 7, FLAGS }, From -1 to VP9_CS_RGB maybe? And instead of saying to look at the spec you could add named constants, so a simple ffmpeg -h bsf=vp9_metadata will be enough. > + { "color_range", "Set colour range (see section 7.2.2)", > + OFFSET(color_range), AV_OPT_TYPE_INT, > + { .i64 = -1 }, -1, 1, FLAGS }, Same. Use the usual names tv/pc as in other parts of the code. > + > + { NULL } > +}; > + > +static const AVClass vp9_metadata_class = { > + .class_name = "vp9_metadata_bsf", > + .item_name = av_default_item_name, > + .option = vp9_metadata_options, > + .version = LIBAVUTIL_VERSION_INT, > +}; > + > +static const enum AVCodecID vp9_metadata_codec_ids[] = { > + AV_CODEC_ID_VP9, AV_CODEC_ID_NONE, > +}; > + > +const AVBitStreamFilter ff_vp9_metadata_bsf = { > + .name = "vp9_metadata", > + .priv_data_size = sizeof(VP9MetadataContext), > + .priv_class = &vp9_metadata_class, > + .init = &vp9_metadata_init, > + .close = &vp9_metadata_close, > + .filter = &vp9_metadata_filter, > + .codec_ids = vp9_metadata_codec_ids, > +}; >
diff --git a/configure b/configure index 890de64ab4..28970cbdf8 100755 --- a/configure +++ b/configure @@ -2986,6 +2986,7 @@ hevc_metadata_bsf_select="cbs_h265" mjpeg2jpeg_bsf_select="jpegtables" mpeg2_metadata_bsf_select="cbs_mpeg2" trace_headers_bsf_select="cbs" +vp9_metadata_bsf_select="cbs_vp9" # external libraries aac_at_decoder_deps="audiotoolbox" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6ee16d855b..1a172f5597 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1067,6 +1067,7 @@ OBJS-$(CONFIG_NULL_BSF) += null_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o +OBJS-$(CONFIG_VP9_METADATA_BSF) += vp9_metadata_bsf.o OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 18b698a85f..c21373621c 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -49,6 +49,7 @@ extern const AVBitStreamFilter ff_null_bsf; extern const AVBitStreamFilter ff_remove_extradata_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; extern const AVBitStreamFilter ff_trace_headers_bsf; +extern const AVBitStreamFilter ff_vp9_metadata_bsf; extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf; extern const AVBitStreamFilter ff_vp9_superframe_bsf; extern const AVBitStreamFilter ff_vp9_superframe_split_bsf; diff --git a/libavcodec/vp9_metadata_bsf.c b/libavcodec/vp9_metadata_bsf.c new file mode 100644 index 0000000000..39994611a0 --- /dev/null +++ b/libavcodec/vp9_metadata_bsf.c @@ -0,0 +1,143 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "bsf.h" +#include "cbs.h" +#include "cbs_vp9.h" + +typedef struct VP9MetadataContext { + const AVClass *class; + + CodedBitstreamContext *cbc; + CodedBitstreamFragment fragment; + + int color_space; + int color_range; + + int color_range_rgb_warned; +} VP9MetadataContext; + + +static int vp9_metadata_filter(AVBSFContext *bsf, AVPacket *out) +{ + VP9MetadataContext *ctx = bsf->priv_data; + AVPacket *in = NULL; + CodedBitstreamFragment *frag = &ctx->fragment; + int err, i; + + err = ff_bsf_get_packet(bsf, &in); + if (err < 0) + return err; + + err = ff_cbs_read_packet(ctx->cbc, frag, in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + for (i = 0; i < frag->nb_units; i++) { + VP9RawFrame *frame = frag->units[i].content; + VP9RawFrameHeader *header = &frame->header; + + if (ctx->color_space >= 0) { + header->color_space = ctx->color_space; + } + if (ctx->color_range >= 0) { + if (ctx->color_range == 0 && + header->color_space == VP9_CS_RGB && + !ctx->color_range_rgb_warned) { + av_log(bsf, AV_LOG_WARNING, "Warning: color_range cannot " + "be set to limited in RGB streams.\n"); + ctx->color_range_rgb_warned = 1; + } else { + header->color_range = ctx->color_range; + } + } + } + + err = ff_cbs_write_packet(ctx->cbc, out, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + + err = av_packet_copy_props(out, in); + if (err < 0) + goto fail; + + err = 0; +fail: + ff_cbs_fragment_uninit(ctx->cbc, frag); + + if (err < 0) + av_packet_unref(out); + av_packet_free(&in); + + return err; +} + +static int vp9_metadata_init(AVBSFContext *bsf) +{ + VP9MetadataContext *ctx = bsf->priv_data; + + return ff_cbs_init(&ctx->cbc, AV_CODEC_ID_VP9, bsf); +} + +static void vp9_metadata_close(AVBSFContext *bsf) +{ + VP9MetadataContext *ctx = bsf->priv_data; + ff_cbs_close(&ctx->cbc); +} + +#define OFFSET(x) offsetof(VP9MetadataContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) +static const AVOption vp9_metadata_options[] = { + { "color_space", "Set colour space (see section 7.2.2)", + OFFSET(color_space), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 7, FLAGS }, + { "color_range", "Set colour range (see section 7.2.2)", + OFFSET(color_range), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 1, FLAGS }, + + { NULL } +}; + +static const AVClass vp9_metadata_class = { + .class_name = "vp9_metadata_bsf", + .item_name = av_default_item_name, + .option = vp9_metadata_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const enum AVCodecID vp9_metadata_codec_ids[] = { + AV_CODEC_ID_VP9, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_vp9_metadata_bsf = { + .name = "vp9_metadata", + .priv_data_size = sizeof(VP9MetadataContext), + .priv_class = &vp9_metadata_class, + .init = &vp9_metadata_init, + .close = &vp9_metadata_close, + .filter = &vp9_metadata_filter, + .codec_ids = vp9_metadata_codec_ids, +};