-- KongQun Yang (KQ) On Tue, Jun 14, 2016 at 4:34 PM, Hendrik Leppkes <h.lepp...@gmail.com> wrote:
> On Wed, Jun 15, 2016 at 12:05 AM, Kongqun Yang <yangkong...@gmail.com> > wrote: > > Implemented according to the draft specification > > "VP Codec ISO Media File Format Binding": > > > http://www.webmproject.org/vp9/#draft-vp-codec-iso-media-file-format-binding > > > > '-strict -2' is required to use this feature. > > > > Not sure I really like the vpc name, when I read vpc I don't think of > vp9, and the correlation to avc/hevc is also not really there, as > those codecs are actually called that. AVC and HEVC, the C isn't added > randomly. > If anything, it should have been vp9.c then, but oh well. > > But anyway, if Ronald is ok with the name I won't complain. > > > --- > > libavformat/Makefile | 2 +- > > libavformat/isom.c | 3 + > > libavformat/movenc.c | 26 +++++++++ > > libavformat/vpc.c | 159 > +++++++++++++++++++++++++++++++++++++++++++++++++++ > > libavformat/vpc.h | 44 ++++++++++++++ > > 5 files changed, 233 insertions(+), 1 deletion(-) > > create mode 100644 libavformat/vpc.c > > create mode 100644 libavformat/vpc.h > > > > diff --git a/libavformat/Makefile b/libavformat/Makefile > > index 6684ead..be8c261 100644 > > --- a/libavformat/Makefile > > +++ b/libavformat/Makefile > > @@ -276,7 +276,7 @@ OBJS-$(CONFIG_MM_DEMUXER) += mm.o > > OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o > > OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o > > OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o > replaygain.o > > -OBJS-$(CONFIG_MOV_MUXER) += movenc.o avc.o hevc.o \ > > +OBJS-$(CONFIG_MOV_MUXER) += movenc.o avc.o hevc.o vpc.o > \ > > movenchint.o mov_chan.o > rtp.o \ > > movenccenc.o rawutils.o > > OBJS-$(CONFIG_MP2_MUXER) += mp3enc.o rawenc.o id3v2enc.o > > diff --git a/libavformat/isom.c b/libavformat/isom.c > > index b1757e2..9a65268 100644 > > --- a/libavformat/isom.c > > +++ b/libavformat/isom.c > > @@ -59,6 +59,7 @@ const AVCodecTag ff_mp4_obj_type[] = { > > { AV_CODEC_ID_AC3 , 0xA5 }, > > { AV_CODEC_ID_EAC3 , 0xA6 }, > > { AV_CODEC_ID_DTS , 0xA9 }, /* mp4ra.org */ > > + { AV_CODEC_ID_VP9 , 0xC0 }, /* non standard, update when > there is a standard value */ > > { AV_CODEC_ID_TSCC2 , 0xD0 }, /* non standard, camtasia uses > it */ > > { AV_CODEC_ID_VORBIS , 0xDD }, /* non standard, gpac uses it */ > > { AV_CODEC_ID_DVD_SUBTITLE, 0xE0 }, /* non standard, see > unsupported-embedded-subs-2.mp4 */ > > @@ -179,6 +180,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = { > > { AV_CODEC_ID_H264, MKTAG('a', 'i', 'v', 'x') }, /* XAVC 4:2:2 > 10bit */ > > { AV_CODEC_ID_H264, MKTAG('r', 'v', '6', '4') }, /* X-Com Radvision > */ > > > > + { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') }, /* VP9 */ > > + > > { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', ' ') }, > > { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', '1') }, /* Apple > MPEG-1 Camcorder */ > > { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */ > > diff --git a/libavformat/movenc.c b/libavformat/movenc.c > > index 2f00091..e4c51e8 100644 > > --- a/libavformat/movenc.c > > +++ b/libavformat/movenc.c > > @@ -49,6 +49,7 @@ > > #include "hevc.h" > > #include "rtpenc.h" > > #include "mov_chan.h" > > +#include "vpc.h" > > > > static const AVOption options[] = { > > { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), > AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, > AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, > > @@ -1039,6 +1040,17 @@ static int mov_write_avcc_tag(AVIOContext *pb, > MOVTrack *track) > > return update_size(pb, pos); > > } > > > > +static int mov_write_vpcc_tag(AVIOContext *pb, MOVTrack *track) > > +{ > > + int64_t pos = avio_tell(pb); > > + > > + avio_wb32(pb, 0); > > + ffio_wfourcc(pb, "vpcC"); > > + avio_wb32(pb, 0); /* version & flags */ > > + ff_isom_write_vpcc(pb, track->par); > > + return update_size(pb, pos); > > +} > > + > > static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track) > > { > > int64_t pos = avio_tell(pb); > > @@ -1143,6 +1155,7 @@ static int mp4_get_codec_tag(AVFormatContext *s, > MOVTrack *track) > > > > if (track->par->codec_id == AV_CODEC_ID_H264) tag = > MKTAG('a','v','c','1'); > > else if (track->par->codec_id == AV_CODEC_ID_HEVC) tag = > MKTAG('h','e','v','1'); > > + else if (track->par->codec_id == AV_CODEC_ID_VP9) tag = > MKTAG('v','p','0','9'); > > else if (track->par->codec_id == AV_CODEC_ID_AC3) tag = > MKTAG('a','c','-','3'); > > else if (track->par->codec_id == AV_CODEC_ID_EAC3) tag = > MKTAG('e','c','-','3'); > > else if (track->par->codec_id == AV_CODEC_ID_DIRAC) tag = > MKTAG('d','r','a','c'); > > @@ -1758,6 +1771,8 @@ static int mov_write_video_tag(AVIOContext *pb, > MOVMuxContext *mov, MOVTrack *tr > > mov_write_avcc_tag(pb, track); > > if (track->mode == MODE_IPOD) > > mov_write_uuid_tag_ipod(pb); > > + } else if (track->par->codec_id == AV_CODEC_ID_VP9) { > > + mov_write_vpcc_tag(pb, track); > > } else if (track->par->codec_id == AV_CODEC_ID_VC1 && > track->vos_len > 0) > > mov_write_dvc1_tag(pb, track); > > else if (track->par->codec_id == AV_CODEC_ID_VP6F || > > @@ -5369,6 +5384,17 @@ static int mov_write_header(AVFormatContext *s) > > pix_fmt == AV_PIX_FMT_MONOWHITE || > > pix_fmt == AV_PIX_FMT_MONOBLACK; > > } > > + if (track->mode == MODE_MP4 && > > + track->par->codec_id == AV_CODEC_ID_VP9) { > > + if (s->strict_std_compliance > > FF_COMPLIANCE_EXPERIMENTAL) { > > + av_log(s, AV_LOG_ERROR, > > + "VP9 in MP4 support is experimental, add " > > + "'-strict %d' if you want to use it.\n", > > + FF_COMPLIANCE_EXPERIMENTAL); > > + ret = AVERROR_EXPERIMENTAL; > > + goto error; > > + } > > + } > > } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { > > track->timescale = st->codecpar->sample_rate; > > if (!st->codecpar->frame_size && > !av_get_bits_per_sample(st->codecpar->codec_id)) { > > diff --git a/libavformat/vpc.c b/libavformat/vpc.c > > new file mode 100644 > > index 0000000..890c5a6 > > --- /dev/null > > +++ b/libavformat/vpc.c > > @@ -0,0 +1,159 @@ > > +/* > > + * Copyright (c) 2016 Google Inc. > > + * Copyright (c) 2016 KongQun Yang (kqy...@google.com) > > + * > > + * 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/pixdesc.h" > > +#include "libavutil/pixfmt.h" > > +#include "vpc.h" > > + > > +enum VpxColorSpace > > +{ > > + VPX_COLOR_SPACE_UNSPECIFIED = 0, > > + VPX_COLOR_SPACE_BT601 = 1, > > + VPX_COLOR_SPACE_BT709 = 2, > > + VPX_COLOR_SPACE_SMPTE_170 = 3, > > + VPX_COLOR_SPACE_SMPTE_240 = 4, > > + VPX_COLOR_SPACE_BT2020_NCL = 5, > > + VPX_COLOR_SPACE_BT2020_CL = 6, > > + VPX_COLOR_SPACE_RGB = 7, > > +}; > > + > > +static int get_vpx_color_space(enum AVColorSpace color_space) > > +{ > > + switch (color_space) { > > + case AVCOL_SPC_RGB: > > + return VPX_COLOR_SPACE_RGB; > > + case AVCOL_SPC_BT709: > > + return VPX_COLOR_SPACE_BT709; > > + case AVCOL_SPC_UNSPECIFIED: > > + return VPX_COLOR_SPACE_UNSPECIFIED; > > + case AVCOL_SPC_BT470BG: > > + return VPX_COLOR_SPACE_BT601; > > + case AVCOL_SPC_SMPTE170M: > > + return VPX_COLOR_SPACE_SMPTE_170; > > + case AVCOL_SPC_SMPTE240M: > > + return VPX_COLOR_SPACE_SMPTE_240; > > + case AVCOL_SPC_BT2020_NCL: > > + return VPX_COLOR_SPACE_BT2020_NCL; > > + case AVCOL_SPC_BT2020_CL: > > + return VPX_COLOR_SPACE_BT2020_CL; > > + default: > > + av_log(NULL, AV_LOG_ERROR, "Unsupported color space (%d)\n", > > + color_space); > > + return -1; > > + } > > +} > > + > > +enum VPX_CHROMA_SUBSAMPLING > > +{ > > + VPX_SUBSAMPLING_420_VERTICAL = 0, > > + VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA = 1, > > + VPX_SUBSAMPLING_422 = 2, > > + VPX_SUBSAMPLING_444 = 3, > > +}; > > + > > +static int get_vpx_chroma_subsampling(enum AVPixelFormat pixel_format, > > + enum AVChromaLocation > chroma_location) > > +{ > > + switch (pixel_format) { > > + case AV_PIX_FMT_YUV420P: > > + case AV_PIX_FMT_YUV420P10LE: > > + case AV_PIX_FMT_YUV420P10BE: > > + case AV_PIX_FMT_YUV420P12LE: > > + case AV_PIX_FMT_YUV420P12BE: > > + if (chroma_location == AVCHROMA_LOC_LEFT) > > + return VPX_SUBSAMPLING_420_VERTICAL; > > + // Otherwise assume collocated. > > + return VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA; > > + case AV_PIX_FMT_YUV422P: > > + case AV_PIX_FMT_YUV422P10LE: > > + case AV_PIX_FMT_YUV422P10BE: > > + case AV_PIX_FMT_YUV422P12LE: > > + case AV_PIX_FMT_YUV422P12BE: > > + return VPX_SUBSAMPLING_422; > > + case AV_PIX_FMT_YUV444P: > > + case AV_PIX_FMT_YUV444P10LE: > > + case AV_PIX_FMT_YUV444P10BE: > > + case AV_PIX_FMT_YUV444P12LE: > > + case AV_PIX_FMT_YUV444P12BE: > > + return VPX_SUBSAMPLING_444; > > + default: > > + av_log(NULL, AV_LOG_ERROR, "Unsupported pixel format (%d)\n", > > + pixel_format); > > + return -1; > > + } > > +} > > We have subsampling info in the pixel formt descriptors, it would seem > smarter to use thoe instead of hardcoding a long list of ever-changing > pixel formats. > You already use the descriptor in get_bit_depth below, so try looking > at log2_chroma_w/log2_chroma_h, or using > av_pix_fmt_get_chroma_sub_sample (which just returns those two values > to you). > Good idea. Didn't know about these utility functions. Thanks for the pointer. Done. > > > + > > +static int get_bit_depth(enum AVPixelFormat pixel_format) > > +{ > > + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixel_format); > > + if (desc == NULL) { > > + av_log(NULL, AV_LOG_ERROR, "Unsupported pixel format (%d)\n", > > + pixel_format); > > + return -1; > > + } > > + return desc->comp[0].depth; > > +} > > + > > +static int get_vpx_transfer_function( > > + enum AVColorTransferCharacteristic transfer) > > +{ > > + return !!(transfer == AVCOL_TRC_SMPTEST2084); > > This looks like an odd way to write it, if its ever extended to make > use of more values, you'll have to change it entirely. > But really just a style nit. > > > +} > > + > > +static int get_vpx_video_full_range_flag(enum AVColorRange color_range) > > +{ > > + return !!(color_range == AVCOL_RANGE_JPEG); > > +} > > + > > +int ff_isom_write_vpcc(AVIOContext *pb, AVCodecParameters *par) > > +{ > > + int profile = par->profile; > > + int level = par->level == FF_LEVEL_UNKNOWN ? 0 : par->level; > > + int bit_depth = get_bit_depth(par->format); > > + int vpx_color_space = get_vpx_color_space(par->color_space); > > + int vpx_chroma_subsampling = > > + get_vpx_chroma_subsampling(par->format, par->chroma_location); > > + int vpx_transfer_function = > get_vpx_transfer_function(par->color_trc); > > + int vpx_video_full_range_flag = > > + get_vpx_video_full_range_flag(par->color_range); > > + > > + if (bit_depth < 0 || vpx_color_space < 0 || vpx_chroma_subsampling > < 0) > > + return AVERROR_INVALIDDATA; > > + > > + if (profile == FF_PROFILE_UNKNOWN) { > > + if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL || > > + vpx_chroma_subsampling == > VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) { > > + profile = (bit_depth == 8) ? FF_PROFILE_VP9_0 : > FF_PROFILE_VP9_2; > > + } else { > > + profile = (bit_depth == 8) ? FF_PROFILE_VP9_1 : > FF_PROFILE_VP9_3; > > + } > > + } > > + > > + avio_w8(pb, profile); > > + avio_w8(pb, level); > > + avio_w8(pb, (bit_depth << 4) | vpx_color_space); > > + avio_w8(pb, (vpx_chroma_subsampling << 4) | (vpx_transfer_function > << 1) | > > + vpx_video_full_range_flag); > > + > > + // vp9 does not have codec initialization data. > > + avio_wb16(pb, 0); > > + return 0; > > +} > > diff --git a/libavformat/vpc.h b/libavformat/vpc.h > > new file mode 100644 > > index 0000000..6d609cc > > --- /dev/null > > +++ b/libavformat/vpc.h > > @@ -0,0 +1,44 @@ > > +/* > > + * Copyright (c) 2016 Google Inc. > > + * Copyright (c) 2016 KongQun Yang (kqy...@google.com) > > + * > > + * 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 > > + */ > > + > > +/** > > + * @file > > + * internal header for VPx codec (de)muxer utilities. > > + */ > > + > > +#ifndef AVFORMAT_VPC_H > > +#define AVFORMAT_VPC_H > > + > > +#include <stdint.h> > > +#include "avio.h" > > +#include "libavcodec/avcodec.h" > > + > > +/** > > + * Writes VP codec configuration to the provided AVIOContext. > > + * > > + * @param pb address of the AVIOContext where the vpcC shall be written. > > + * @param par address of the AVCodecParameters which contains codec > information. > > + * @return >=0 in case of success, a negative value corresponding to an > AVERROR > > + * code in case of failure > > + */ > > +int ff_isom_write_vpcc(AVIOContext *pb, AVCodecParameters *par); > > + > > +#endif /* AVFORMAT_VPC_H */ > > -- > > 2.8.0.rc3.226.g39d4020 > > > > _______________________________________________ > > ffmpeg-devel mailing list > > ffmpeg-devel@ffmpeg.org > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel