| @@ -22,8 +22,11 @@ · 21 unmodified lines |
| 22 | 22 | #include "libavutil/pixdesc.h" |
| 23 | 23 | #include "libavutil/pixfmt.h" |
| 24 | 24 | #include "libavcodec/avcodec.h" |
| 25 | +#include "libavcodec/get_bits.h" |
| 25 | 26 | #include "vpcc.h" |
| 26 | 27 | |
| 28 | +#define VP9_SYNCCODE 0x498342 |
| 29 | + |
| 27 | 30 | enum VPX_CHROMA_SUBSAMPLING |
| 28 | 31 | { |
| 29 | 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 | 153 | int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, |
| 154 | + const uint8_t *data, int len, |
| 118 | 155 | AVRational *frame_rate, VPCC *vpcc) |
| 119 | 156 | { |
| 120 | 157 | int profile = par->profile; |
| @@ -129,7 +166,17 @@ int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, · 8 unmodified lines |
| 129 | 166 | if (bit_depth < 0 || vpx_chroma_subsampling < 0) |
| 130 | 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 | 180 | if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL || |
| 134 | 181 | vpx_chroma_subsampling == VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) { |
| 135 | 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 | 191 | vpcc->profile = profile; |
| 142 | 192 | vpcc->level = level; |
| 143 | 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 | 200 | int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb, |
| 201 | + const uint8_t *data, int len, |
| 151 | 202 | AVCodecParameters *par) |
| 152 | 203 | { |
| 153 | 204 | VPCC vpcc; |
| 154 | 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 | 208 | if (ret < 0) |
| 158 | 209 | return ret; |
| 159 | 210 | |