Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * RTP parser for VP9 payload format (draft version 0) - experimental
  3.  * Copyright (c) 2015 Thomas Volkert <thomas@homer-conferencing.com>
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include "libavutil/intreadwrite.h"
  23.  
  24. #include "avio_internal.h"
  25. #include "rtpdec_formats.h"
  26.  
  27. #define RTP_VP9_DESC_REQUIRED_SIZE 1
  28.  
  29. struct PayloadContext {
  30.     AVIOContext *buf;
  31.     uint32_t     timestamp;
  32. };
  33.  
  34. static av_cold int vp9_init(AVFormatContext *ctx, int st_index,
  35.                             PayloadContext *data)
  36. {
  37.     av_log(ctx, AV_LOG_WARNING,
  38.            "RTP/VP9 support is still experimental\n");
  39.  
  40.     return 0;
  41. }
  42.  
  43. static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
  44.                              AVStream *st, AVPacket *pkt, uint32_t *timestamp,
  45.                              const uint8_t *buf, int len, uint16_t seq,
  46.                              int flags)
  47. {
  48.     int has_pic_id, has_layer_idc, has_ref_idc, has_ss_data, has_su_data;
  49.     av_unused int pic_id = 0, non_key_frame = 0;
  50.     av_unused int layer_temporal = -1, layer_spatial = -1, layer_quality = -1;
  51.     int ref_fields = 0, has_ref_field_ext_pic_id = 0;
  52.     int first_fragment, last_fragment;
  53.     int rtp_m;
  54.     int res = 0;
  55.  
  56.     /* drop data of previous packets in case of non-continuous (lossy) packet stream */
  57.     if (rtp_vp9_ctx->buf && rtp_vp9_ctx->timestamp != *timestamp)
  58.         ffio_free_dyn_buf(&rtp_vp9_ctx->buf);
  59.  
  60.     /* sanity check for size of input packet: 1 byte payload at least */
  61.     if (len < RTP_VP9_DESC_REQUIRED_SIZE + 1) {
  62.         av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet, got %d bytes\n", len);
  63.         return AVERROR_INVALIDDATA;
  64.     }
  65.  
  66.     /*
  67.      *     decode the required VP9 payload descriptor according to section 4.2 of the spec.:
  68.      *
  69.      *      0 1 2 3 4 5 6 7
  70.      *     +-+-+-+-+-+-+-+-+
  71.      *     |I|L|F|B|E|V|U|-| (REQUIRED)
  72.      *     +-+-+-+-+-+-+-+-+
  73.      *
  74.      *     I: PictureID present
  75.      *     L: Layer indices present
  76.      *     F: Reference indices present
  77.      *     B: Start of VP9 frame
  78.      *     E: End of picture
  79.      *     V: Scalability Structure (SS) present
  80.      *     U: Scalability Structure Update (SU) present
  81.      */
  82.     has_pic_id     = !!(buf[0] & 0x80);
  83.     has_layer_idc  = !!(buf[0] & 0x40);
  84.     has_ref_idc    = !!(buf[0] & 0x20);
  85.     first_fragment = !!(buf[0] & 0x10);
  86.     last_fragment  = !!(buf[0] & 0x08);
  87.     has_ss_data    = !!(buf[0] & 0x04);
  88.     has_su_data    = !!(buf[0] & 0x02);
  89.  
  90.     rtp_m = !!(flags & RTP_FLAG_MARKER);
  91.  
  92.     /* sanity check for markers: B should always be equal to the RTP M marker */
  93.     if (last_fragment != rtp_m) {
  94.         av_log(ctx, AV_LOG_ERROR, "Invalid combination of B and M marker (%d != %d)\n", last_fragment, rtp_m);
  95.         return AVERROR_INVALIDDATA;
  96.     }
  97.  
  98.     /* pass the extensions field */
  99.     buf += RTP_VP9_DESC_REQUIRED_SIZE;
  100.     len -= RTP_VP9_DESC_REQUIRED_SIZE;
  101.  
  102.     /*
  103.      *         decode the 1-byte/2-byte picture ID:
  104.      *
  105.      *          0 1 2 3 4 5 6 7
  106.      *         +-+-+-+-+-+-+-+-+
  107.      *   I:    |M|PICTURE ID   | (RECOMMENDED)
  108.      *         +-+-+-+-+-+-+-+-+
  109.      *   M:    | EXTENDED PID  | (RECOMMENDED)
  110.      *         +-+-+-+-+-+-+-+-+
  111.      *
  112.      *   M: The most significant bit of the first octet is an extension flag.
  113.      *   PictureID:  8 or 16 bits including the M bit.
  114.      */
  115.     if (has_pic_id) {
  116.         /* check for 1-byte or 2-byte picture index */
  117.         if (buf[0] & 0x80) {
  118.             if (len < 2) {
  119.                 av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
  120.                 return AVERROR_INVALIDDATA;
  121.             }
  122.             pic_id = AV_RB16(buf) & 0x7fff;
  123.             buf += 2;
  124.             len -= 2;
  125.         } else {
  126.             pic_id = buf[0] & 0x7f;
  127.             buf++;
  128.             len--;
  129.         }
  130.     }
  131.  
  132.     /*
  133.      *         decode layer indices
  134.      *
  135.      *          0 1 2 3 4 5 6 7
  136.      *         +-+-+-+-+-+-+-+-+
  137.      *   L:    | T | S | Q | R | (CONDITIONALLY RECOMMENDED)
  138.      *         +-+-+-+-+-+-+-+-+
  139.      *
  140.      *   T, S and Q are 2-bit indices for temporal, spatial, and quality layers.
  141.      *   If "F" is set in the initial octet, R is 2 bits representing the number
  142.      *   of reference fields this frame refers to.
  143.      */
  144.     if (has_layer_idc) {
  145.         if (len < 1) {
  146.             av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
  147.             return AVERROR_INVALIDDATA;
  148.         }
  149.         layer_temporal = buf[0] & 0xC0;
  150.         layer_spatial  = buf[0] & 0x30;
  151.         layer_quality  = buf[0] & 0x0C;
  152.         if (has_ref_idc) {
  153.             ref_fields = buf[0] & 0x03;
  154.             if (ref_fields)
  155.                 non_key_frame = 1;
  156.         }
  157.         buf++;
  158.         len--;
  159.     }
  160.  
  161.     /*
  162.      *         decode the reference fields
  163.      *
  164.      *          0 1 2 3 4 5 6 7
  165.      *         +-+-+-+-+-+-+-+-+              -\
  166.      *   F:    | PID |X| RS| RQ| (OPTIONAL)    .
  167.      *         +-+-+-+-+-+-+-+-+               . - R times
  168.      *   X:    | EXTENDED PID  | (OPTIONAL)    .
  169.      *         +-+-+-+-+-+-+-+-+              -/
  170.      *
  171.      *   PID:  The relative Picture ID referred to by this frame.
  172.      *   RS and RQ:  The spatial and quality layer IDs.
  173.      *   X: 1 if this layer index has an extended relative Picture ID.
  174.      */
  175.     if (has_ref_idc) {
  176.         while (ref_fields) {
  177.             if (len < 1) {
  178.                 av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
  179.                 return AVERROR_INVALIDDATA;
  180.             }
  181.  
  182.             has_ref_field_ext_pic_id = buf[0] & 0x10;
  183.  
  184.             /* pass ref. field */
  185.             if (has_ref_field_ext_pic_id) {
  186.                 if (len < 2) {
  187.                     av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
  188.                     return AVERROR_INVALIDDATA;
  189.                 }
  190.  
  191.                 /* ignore ref. data */
  192.  
  193.                 buf += 2;
  194.                 len -= 2;
  195.             } else {
  196.  
  197.                 /* ignore ref. data */
  198.  
  199.                 buf++;
  200.                 len--;
  201.             }
  202.             ref_fields--;
  203.         }
  204.     }
  205.  
  206.     /*
  207.      *         decode the scalability structure (SS)
  208.      *
  209.      *          0 1 2 3 4 5 6 7
  210.      *         +-+-+-+-+-+-+-+-+
  211.      *   V:    | PATTERN LENGTH|
  212.      *         +-+-+-+-+-+-+-+-+                           -\
  213.      *         | T | S | Q | R | (OPTIONAL)                 .
  214.      *         +-+-+-+-+-+-+-+-+              -\            .
  215.      *         | PID |X| RS| RQ| (OPTIONAL)    .            . - PAT. LEN. times
  216.      *         +-+-+-+-+-+-+-+-+               . - R times  .
  217.      *   X:    | EXTENDED PID  | (OPTIONAL)    .            .
  218.      *         +-+-+-+-+-+-+-+-+              -/           -/
  219.      *
  220.      *   PID:  The relative Picture ID referred to by this frame.
  221.      *   RS and RQ:  The spatial and quality layer IDs.
  222.      *   X: 1 if this layer index has an extended relative Picture ID.
  223.      */
  224.     if (has_ss_data) {
  225.         avpriv_report_missing_feature(ctx, "VP9 scalability structure data");
  226.         return AVERROR(ENOSYS);
  227.     }
  228.  
  229.     /*
  230.      * decode the scalability update structure (SU)
  231.      *
  232.      *  spec. is tbd
  233.      */
  234.     if (has_su_data) {
  235.         avpriv_report_missing_feature(ctx, "VP9 scalability update structure data");
  236.         return AVERROR(ENOSYS);
  237.     }
  238.  
  239.     /*
  240.      * decode the VP9 payload header
  241.      *
  242.      *  spec. is tbd
  243.      */
  244.     //XXX: implement when specified
  245.  
  246.     /* sanity check: 1 byte payload as minimum */
  247.     if (len < 1) {
  248.         av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
  249.         return AVERROR_INVALIDDATA;
  250.     }
  251.  
  252.     /* start frame buffering with new dynamic buffer */
  253.     if (!rtp_vp9_ctx->buf) {
  254.         /* sanity check: a new frame should have started */
  255.         if (first_fragment) {
  256.             res = avio_open_dyn_buf(&rtp_vp9_ctx->buf);
  257.             if (res < 0)
  258.                 return res;
  259.             /* update the timestamp in the frame packet with the one from the RTP packet */
  260.             rtp_vp9_ctx->timestamp = *timestamp;
  261.         } else {
  262.             /* frame not started yet, need more packets */
  263.             return AVERROR(EAGAIN);
  264.         }
  265.     }
  266.  
  267.     /* write the fragment to the dyn. buffer */
  268.     avio_write(rtp_vp9_ctx->buf, buf, len);
  269.  
  270.     /* do we need more fragments? */
  271.     if (!last_fragment)
  272.         return AVERROR(EAGAIN);
  273.  
  274.     /* close frame buffering and create resulting A/V packet */
  275.     res = ff_rtp_finalize_packet(pkt, &rtp_vp9_ctx->buf, st->index);
  276.     if (res < 0)
  277.         return res;
  278.  
  279.     return 0;
  280. }
  281.  
  282. RTPDynamicProtocolHandler ff_vp9_dynamic_handler = {
  283.     .enc_name         = "VP9",
  284.     .codec_type       = AVMEDIA_TYPE_VIDEO,
  285.     .codec_id         = AV_CODEC_ID_VP9,
  286.     .priv_data_size   = sizeof(PayloadContext),
  287.     .init             = vp9_init,
  288.     .parse_packet     = vp9_handle_packet
  289. };
  290.