#include "libavutil/pixdesc.h"
#include "libavutil/pixfmt.h"
-#include "libavcodec/avcodec.h"
+#include "libavcodec/defs.h"
+#include "libavcodec/get_bits.h"
#include "vpcc.h"
+#define VP9_SYNCCODE 0x498342
+
enum VPX_CHROMA_SUBSAMPLING
{
VPX_SUBSAMPLING_420_VERTICAL = 0,
}
}
+static void parse_bitstream(GetBitContext *gb, int *profile, int *bit_depth) {
+ int keyframe, invisible;
+
+ if (get_bits(gb, 2) != 0x2) // frame marker
+ return;
+ *profile = get_bits1(gb);
+ *profile |= get_bits1(gb) << 1;
+ if (*profile == 3)
+ *profile += get_bits1(gb);
+
+ if (get_bits1(gb))
+ return;
+
+ keyframe = !get_bits1(gb);
+ invisible = !get_bits1(gb);
+ get_bits1(gb);
+
+ if (keyframe) {
+ if (get_bits(gb, 24) != VP9_SYNCCODE)
+ return;
+ } else {
+ int intraonly = invisible ? get_bits1(gb) : 0;
+ if (!intraonly || get_bits(gb, 24) != VP9_SYNCCODE)
+ return;
+ if (*profile < 1) {
+ *bit_depth = 8;
+ return;
+ }
+ }
+
+ *bit_depth = *profile <= 1 ? 8 : 10 + get_bits1(gb) * 2;
+}
+
int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
+ const uint8_t *data, int len,
AVRational *frame_rate, VPCC *vpcc)
{
int profile = par->profile;
- int level = par->level == FF_LEVEL_UNKNOWN ?
+ int level = par->level == AV_LEVEL_UNKNOWN ?
get_vp9_level(par, frame_rate) : par->level;
int bit_depth = get_bit_depth(s, par->format);
int vpx_chroma_subsampling =
if (bit_depth < 0 || vpx_chroma_subsampling < 0)
return AVERROR_INVALIDDATA;
- if (profile == FF_PROFILE_UNKNOWN) {
+ if (len && (profile == AV_PROFILE_UNKNOWN || !bit_depth)) {
+ GetBitContext gb;
+
+ int ret = init_get_bits8(&gb, data, len);
+ if (ret < 0)
+ return ret;
+
+ parse_bitstream(&gb, &profile, &bit_depth);
+ }
+
+ if (profile == AV_PROFILE_UNKNOWN && bit_depth) {
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;
+ profile = (bit_depth == 8) ? AV_PROFILE_VP9_0 : AV_PROFILE_VP9_2;
} else {
- profile = (bit_depth == 8) ? FF_PROFILE_VP9_1 : FF_PROFILE_VP9_3;
+ profile = (bit_depth == 8) ? AV_PROFILE_VP9_1 : AV_PROFILE_VP9_3;
}
}
+ if (profile == AV_PROFILE_UNKNOWN || !bit_depth)
+ av_log(s, AV_LOG_WARNING, "VP9 profile and/or bit depth not set or could not be derived\n");
+
vpcc->profile = profile;
vpcc->level = level;
vpcc->bitdepth = bit_depth;
}
int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
+ const uint8_t *data, int len,
AVCodecParameters *par)
{
VPCC vpcc;
int ret;
- ret = ff_isom_get_vpcc_features(s, par, NULL, &vpcc);
+ ret = ff_isom_get_vpcc_features(s, par, data, len, NULL, &vpcc);
if (ret < 0)
return ret;
+ avio_w8(pb, 1); /* version */
+ avio_wb24(pb, 0); /* flags */
avio_w8(pb, vpcc.profile);
avio_w8(pb, vpcc.level);
avio_w8(pb, (vpcc.bitdepth << 4) | (vpcc.chroma_subsampling << 1) | vpcc.full_range_flag);