]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtpdec_vp9.c
apedec: Convert to the new bitstream reader
[ffmpeg] / libavformat / rtpdec_vp9.c
index 71ea480056bac7849171897fcc042cedfc08d158..c0e6217e9f04c45893647361273163917dbdb35e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * RTP parser for VP9 payload format (draft version 0) - experimental
+ * RTP parser for VP9 payload format (draft version 02) - experimental
  * Copyright (c) 2015 Thomas Volkert <thomas@homer-conferencing.com>
  *
  * This file is part of Libav.
@@ -45,8 +45,8 @@ static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
                              const uint8_t *buf, int len, uint16_t seq,
                              int flags)
 {
-    int has_pic_id, has_layer_idc, has_ref_idc, has_ss_data, has_su_data;
-    av_unused int pic_id = 0, non_key_frame = 0;
+    int has_pic_id, has_layer_idc, has_ref_idc, has_ss_data;
+    av_unused int pic_id = 0, non_key_frame = 0, inter_picture_layer_frame;
     av_unused int layer_temporal = -1, layer_spatial = -1, layer_quality = -1;
     int ref_fields = 0, has_ref_field_ext_pic_id = 0;
     int first_fragment, last_fragment;
@@ -68,24 +68,24 @@ static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
      *
      *      0 1 2 3 4 5 6 7
      *     +-+-+-+-+-+-+-+-+
-     *     |I|L|F|B|E|V|U|-| (REQUIRED)
+     *     |I|P|L|F|B|E|V|-| (REQUIRED)
      *     +-+-+-+-+-+-+-+-+
      *
      *     I: PictureID present
+     *     P: Inter-picture predicted layer frame
      *     L: Layer indices present
-     *     F: Reference indices present
+     *     F: Flexible mode
      *     B: Start of VP9 frame
      *     E: End of picture
      *     V: Scalability Structure (SS) present
-     *     U: Scalability Structure Update (SU) present
      */
     has_pic_id     = !!(buf[0] & 0x80);
-    has_layer_idc  = !!(buf[0] & 0x40);
-    has_ref_idc    = !!(buf[0] & 0x20);
-    first_fragment = !!(buf[0] & 0x10);
-    last_fragment  = !!(buf[0] & 0x08);
-    has_ss_data    = !!(buf[0] & 0x04);
-    has_su_data    = !!(buf[0] & 0x02);
+    inter_picture_layer_frame = !!(buf[0] & 0x40);
+    has_layer_idc  = !!(buf[0] & 0x20);
+    has_ref_idc    = !!(buf[0] & 0x10);
+    first_fragment = !!(buf[0] & 0x08);
+    last_fragment  = !!(buf[0] & 0x04);
+    has_ss_data    = !!(buf[0] & 0x02);
 
     rtp_m = !!(flags & RTP_FLAG_MARKER);
 
@@ -222,18 +222,64 @@ static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
      *   X: 1 if this layer index has an extended relative Picture ID.
      */
     if (has_ss_data) {
-        avpriv_report_missing_feature(ctx, "VP9 scalability structure data");
-        return AVERROR(ENOSYS);
-    }
-
-    /*
-     * decode the scalability update structure (SU)
-     *
-     *  spec. is tbd
-     */
-    if (has_su_data) {
-        avpriv_report_missing_feature(ctx, "VP9 scalability update structure data");
-        return AVERROR(ENOSYS);
+        int n_s, y, g, i;
+        if (len < 1) {
+            av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+            return AVERROR_INVALIDDATA;
+        }
+        n_s = buf[0] >> 5;
+        y = !!(buf[0] & 0x10);
+        g = !!(buf[0] & 0x08);
+        buf++;
+        len--;
+        if (n_s > 0) {
+            avpriv_report_missing_feature(ctx, "VP9 scalability structure with multiple layers");
+            return AVERROR_PATCHWELCOME;
+        }
+        if (y) {
+            if (len < 4 * (n_s + 1)) {
+                av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+                return AVERROR_INVALIDDATA;
+            }
+            for (i = 0; i < n_s + 1; i++) {
+                av_unused int w, h;
+                w = AV_RB16(buf);
+                h = AV_RB16(buf + 2);
+                buf += 4;
+                len -= 4;
+            }
+        }
+        if (g) {
+            int n_g;
+            if (len < 1) {
+                av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+                return AVERROR_INVALIDDATA;
+            }
+            n_g = buf[0];
+            buf++;
+            len--;
+            for (i = 0; i < n_g; i++) {
+                av_unused int t, u, r, j;
+                if (len < 1) {
+                    av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+                    return AVERROR_INVALIDDATA;
+                }
+                t = buf[0] >> 5;
+                u = !!(buf[0] & 0x10);
+                r = (buf[0] >> 2) & 0x03;
+                buf++;
+                len--;
+                if (len < r) {
+                    av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+                    return AVERROR_INVALIDDATA;
+                }
+                for (j = 0; j < r; j++) {
+                    av_unused int p_diff = buf[0];
+                    buf++;
+                    len--;
+                }
+            }
+        }
     }
 
     /*
@@ -279,11 +325,17 @@ static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
     return 0;
 }
 
+static void vp9_close_context(PayloadContext *vp9)
+{
+    ffio_free_dyn_buf(&vp9->buf);
+}
+
 RTPDynamicProtocolHandler ff_vp9_dynamic_handler = {
     .enc_name         = "VP9",
     .codec_type       = AVMEDIA_TYPE_VIDEO,
     .codec_id         = AV_CODEC_ID_VP9,
     .priv_data_size   = sizeof(PayloadContext),
     .init             = vp9_init,
+    .close            = vp9_close_context,
     .parse_packet     = vp9_handle_packet
 };