Profile can be derived from values codecpar pixel format only with software formats. For hardware formats, we're forced to parse a frame header to get the required information.
Unified · Split
| @@ -338,7 +338,7 @@ static int init_segment_types(AVFormatContext *s) · 337 unmodified lines | |||
| 338 | static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par, | 338 | static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par, |
| 339 | AVRational *frame_rate, char *str, int size) { | 339 | AVRational *frame_rate, char *str, int size) { |
| 340 | VPCC vpcc; | 340 | VPCC vpcc; |
| 341 | int ret = ff_isom_get_vpcc_features(s, par, frame_rate, &vpcc); | 341 | int ret = ff_isom_get_vpcc_features(s, par, NULL, 0, frame_rate, &vpcc); |
| 342 | if (ret == 0) { | 342 | if (ret == 0) { |
| 343 | av_strlcatf(str, size, "vp09.%02d.%02d.%02d", | 343 | av_strlcatf(str, size, "vp09.%02d.%02d.%02d", |
| 344 | vpcc.profile, vpcc.level, vpcc.bitdepth); | 344 | vpcc.profile, vpcc.level, vpcc.bitdepth); |
| @@ -1375,7 +1375,8 @@ static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra · 1374 unmodified lines | |||
| 1375 | ffio_wfourcc(pb, "vpcC"); | 1375 | ffio_wfourcc(pb, "vpcC"); |
| 1376 | avio_w8(pb, 1); /* version */ | 1376 | avio_w8(pb, 1); /* version */ |
| 1377 | avio_wb24(pb, 0); /* flags */ | 1377 | avio_wb24(pb, 0); /* flags */ |
| 1378 | ff_isom_write_vpcc(s, pb, track->par); | 1378 | ff_isom_write_vpcc(s, pb, track->vos_data, track->vos_len, track->par); |
| 1379 | |||
| 1379 | return update_size(pb, pos); | 1380 | return update_size(pb, pos); |
| 1380 | } | 1381 | } |
| 1381 | 1382 | ||
| @@ -6033,6 +6034,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) · 4651 unmodified lines | |||
| 6033 | if ((par->codec_id == AV_CODEC_ID_DNXHD || | 6034 | if ((par->codec_id == AV_CODEC_ID_DNXHD || |
| 6034 | par->codec_id == AV_CODEC_ID_H264 || | 6035 | par->codec_id == AV_CODEC_ID_H264 || |
| 6035 | par->codec_id == AV_CODEC_ID_HEVC || | 6036 | par->codec_id == AV_CODEC_ID_HEVC || |
| 6037 | par->codec_id == AV_CODEC_ID_VP9 || | ||
| 6036 | par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len && | 6038 | par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len && |
| 6037 | !TAG_IS_AVCI(trk->tag)) { | 6039 | !TAG_IS_AVCI(trk->tag)) { |
| 6038 | /* copy frame to create needed atoms */ | 6040 | /* copy frame to create needed atoms */ |
| @@ -22,8 +22,11 @@ · 21 unmodified lines | |||
| 22 | #include "libavutil/pixdesc.h" | 22 | #include "libavutil/pixdesc.h" |
| 23 | #include "libavutil/pixfmt.h" | 23 | #include "libavutil/pixfmt.h" |
| 24 | #include "libavcodec/avcodec.h" | 24 | #include "libavcodec/avcodec.h" |
| 25 | #include "libavcodec/get_bits.h" | ||
| 25 | #include "vpcc.h" | 26 | #include "vpcc.h" |
| 26 | 27 | ||
| 28 | #define VP9_SYNCCODE 0x498342 | ||
| 29 | |||
| 27 | enum VPX_CHROMA_SUBSAMPLING | 30 | enum VPX_CHROMA_SUBSAMPLING |
| 28 | { | 31 | { |
| 29 | VPX_SUBSAMPLING_420_VERTICAL = 0, | 32 | VPX_SUBSAMPLING_420_VERTICAL = 0, |
| @@ -114,7 +117,41 @@ static int get_vp9_level(AVCodecParameters *par, AVRational *frame_rate) { · 84 unmodified lines | |||
| 114 | } | 117 | } |
| 115 | } | 118 | } |
| 116 | 119 | ||
| 120 | static void parse_bitstream(GetBitContext *gb, int *profile, int *bit_depth) { | ||
| 121 | int keyframe, invisible; | ||
| 122 | |||
| 123 | if (get_bits(gb, 2) != 0x2) // frame marker | ||
| 124 | return; | ||
| 125 | *profile = get_bits1(gb); | ||
| 126 | *profile |= get_bits1(gb) << 1; | ||
| 127 | if (*profile == 3) | ||
| 128 | *profile += get_bits1(gb); | ||
| 129 | |||
| 130 | if (get_bits1(gb)) | ||
| 131 | return; | ||
| 132 | |||
| 133 | keyframe = !get_bits1(gb); | ||
| 134 | invisible = !get_bits1(gb); | ||
| 135 | get_bits1(gb); | ||
| 136 | |||
| 137 | if (keyframe) { | ||
| 138 | if (get_bits(gb, 24) != VP9_SYNCCODE) | ||
| 139 | return; | ||
| 140 | } else { | ||
| 141 | int intraonly = invisible ? get_bits1(gb) : 0; | ||
| 142 | if (!intraonly || get_bits(gb, 24) != VP9_SYNCCODE) | ||
| 143 | return; | ||
| 144 | if (*profile < 1) { | ||
| 145 | *bit_depth = 8; | ||
| 146 | return; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | *bit_depth = *profile <= 1 ? 8 : 10 + get_bits1(gb) * 2; | ||
| 151 | } | ||
| 152 | |||
| 117 | int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, | 153 | int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, |
| 154 | const uint8_t *data, int len, | ||
| 118 | AVRational *frame_rate, VPCC *vpcc) | 155 | AVRational *frame_rate, VPCC *vpcc) |
| 119 | { | 156 | { |
| 120 | int profile = par->profile; | 157 | int profile = par->profile; |
| @@ -129,7 +166,17 @@ int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, · 8 unmodified lines | |||
| 129 | if (bit_depth < 0 || vpx_chroma_subsampling < 0) | 166 | if (bit_depth < 0 || vpx_chroma_subsampling < 0) |
| 130 | return AVERROR_INVALIDDATA; | 167 | return AVERROR_INVALIDDATA; |
| 131 | 168 | ||
| 132 | if (profile == FF_PROFILE_UNKNOWN) { | 169 | if (len && (profile == FF_PROFILE_UNKNOWN || !bit_depth)) { |
| 170 | GetBitContext gb; | ||
| 171 | |||
| 172 | int ret = init_get_bits8(&gb, data, len); | ||
| 173 | if (ret < 0) | ||
| 174 | return ret; | ||
| 175 | |||
| 176 | parse_bitstream(&gb, &profile, &bit_depth); | ||
| 177 | } | ||
| 178 | |||
| 179 | if (profile == FF_PROFILE_UNKNOWN && bit_depth) { | ||
| 133 | if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL || | 180 | if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL || |
| 134 | vpx_chroma_subsampling == VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) { | 181 | vpx_chroma_subsampling == VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) { |
| 135 | profile = (bit_depth == 8) ? FF_PROFILE_VP9_0 : FF_PROFILE_VP9_2; | 182 | profile = (bit_depth == 8) ? FF_PROFILE_VP9_0 : FF_PROFILE_VP9_2; |
| @@ -138,6 +185,9 @@ int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, · 2 unmodified lines | |||
| 138 | } | 185 | } |
| 139 | } | 186 | } |
| 140 | 187 | ||
| 188 | if (profile == FF_PROFILE_UNKNOWN || !bit_depth) | ||
| 189 | av_log(s, AV_LOG_WARNING, "VP9 profile and/or bit depth not set or could not be derived\n"); | ||
| 190 | |||
| 141 | vpcc->profile = profile; | 191 | vpcc->profile = profile; |
| 142 | vpcc->level = level; | 192 | vpcc->level = level; |
| 143 | vpcc->bitdepth = bit_depth; | 193 | vpcc->bitdepth = bit_depth; |
| @@ -148,12 +198,13 @@ int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, · 4 unmodified lines | |||
| 148 | } | 198 | } |
| 149 | 199 | ||
| 150 | int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb, | 200 | int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb, |
| 201 | const uint8_t *data, int len, | ||
| 151 | AVCodecParameters *par) | 202 | AVCodecParameters *par) |
| 152 | { | 203 | { |
| 153 | VPCC vpcc; | 204 | VPCC vpcc; |
| 154 | int ret; | 205 | int ret; |
| 155 | 206 | ||
| 156 | ret = ff_isom_get_vpcc_features(s, par, NULL, &vpcc); | 207 | ret = ff_isom_get_vpcc_features(s, par, data, len, NULL, &vpcc); |
| 157 | if (ret < 0) | 208 | if (ret < 0) |
| 158 | return ret; | 209 | return ret; |
| 159 | 210 | ||
| @@ -45,14 +45,19 @@ typedef struct VPCC { · 44 unmodified lines | |||
| 45 | * | 45 | * |
| 46 | * @param s address of the AVFormatContext for the logging context. | 46 | * @param s address of the AVFormatContext for the logging context. |
| 47 | * @param pb address of the AVIOContext where the vpcC shall be written. | 47 | * @param pb address of the AVIOContext where the vpcC shall be written. |
| 48 | * @param data address of a data array which contains coded bitstream data from | ||
| 49 | * which codec information can be extracted. May be NULL. | ||
| 50 | * @param len length of the data array. | ||
| 48 | * @param par address of the AVCodecParameters which contains codec information. | 51 | * @param par address of the AVCodecParameters which contains codec information. |
| 49 | * @return >=0 in case of success, a negative value corresponding to an AVERROR | 52 | * @return >=0 in case of success, a negative value corresponding to an AVERROR |
| 50 | * code in case of failure | 53 | * code in case of failure |
| 51 | */ | 54 | */ |
| 52 | int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb, | 55 | int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb, |
| 56 | const uint8_t *data, int len, | ||
| 53 | AVCodecParameters *par); | 57 | AVCodecParameters *par); |
| 54 | 58 | ||
| 55 | int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, | 59 | int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, |
| 60 | const uint8_t *data, int len, | ||
| 56 | AVRational *frame_rate, VPCC *vpcc); | 61 | AVRational *frame_rate, VPCC *vpcc); |
| 57 | 62 | ||
| 58 | #endif /* AVFORMAT_VPCC_H */ | 63 | #endif /* AVFORMAT_VPCC_H */ |