Imported Upstream version 6.1
[platform/upstream/ffmpeg.git] / libavformat / vpcc.c
index 8b4f913..a597791 100644 (file)
 
 #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,
@@ -114,11 +117,45 @@ static int get_vp9_level(AVCodecParameters *par, AVRational *frame_rate) {
     }
 }
 
+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 =
@@ -129,15 +166,28 @@ int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
     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;
@@ -148,15 +198,18 @@ int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
 }
 
 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);