History

avformat/vpcc: parse bitstream data to get profile and bitdepth

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.

James Almer committed 4 years ago

Commit cb925c01 parent e9a67ab4 files · +62 −4Browse files

Unified · Split

4 files
  1. libavformat/dashenc.c +1 −1
  2. libavformat/movenc.c +3 −1
  3. libavformat/vpcc.c +53 −2
  4. libavformat/vpcc.h +5 −0
libavformat/dashenc.c+1−1
@@ -338,7 +338,7 @@ static int init_segment_types(AVFormatContext *s) · 337 unmodified lines
338static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par,338static 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);
libavformat/movenc.c+3−1
@@ -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 */
libavformat/vpcc.c+53−2
@@ -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
27enum VPX_CHROMA_SUBSAMPLING30enum 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
120static 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
117int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,153int 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
150int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,200int 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
libavformat/vpcc.h+5−0
@@ -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 AVERROR52 * @return >=0 in case of success, a negative value corresponding to an AVERROR
50 * code in case of failure53 * code in case of failure
51 */54 */
52int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,55int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
56 const uint8_t *data, int len,
53 AVCodecParameters *par);57 AVCodecParameters *par);
54 58
55int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,59int 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 */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t