Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Xiph RTP Protocols
  3.  * Copyright (c) 2009 Colin McQuillian
  4.  * Copyright (c) 2010 Josh Allmann
  5.  *
  6.  * This file is part of FFmpeg.
  7.  *
  8.  * FFmpeg is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  * FFmpeg is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with FFmpeg; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21.  */
  22.  
  23. /**
  24.  * @file
  25.  * @brief Xiph / RTP Code
  26.  * @author Colin McQuillan <m.niloc@gmail.com>
  27.  * @author Josh Allmann <joshua.allmann@gmail.com>
  28.  */
  29.  
  30. #include "libavutil/attributes.h"
  31. #include "libavutil/avassert.h"
  32. #include "libavutil/avstring.h"
  33. #include "libavutil/base64.h"
  34. #include "libavcodec/bytestream.h"
  35.  
  36. #include "avio_internal.h"
  37. #include "internal.h"
  38. #include "rtpdec.h"
  39. #include "rtpdec_formats.h"
  40.  
  41. /**
  42.  * RTP/Xiph specific private data.
  43.  */
  44. struct PayloadContext {
  45.     unsigned ident;             ///< 24-bit stream configuration identifier
  46.     uint32_t timestamp;
  47.     AVIOContext* fragment;    ///< buffer for split payloads
  48.     uint8_t *split_buf;
  49.     int split_pos, split_buf_len, split_buf_size;
  50.     int split_pkts;
  51. };
  52.  
  53. static void xiph_close_context(PayloadContext * data)
  54. {
  55.     ffio_free_dyn_buf(&data->fragment);
  56.     av_freep(&data->split_buf);
  57. }
  58.  
  59.  
  60. static int xiph_handle_packet(AVFormatContext *ctx, PayloadContext *data,
  61.                               AVStream *st, AVPacket *pkt, uint32_t *timestamp,
  62.                               const uint8_t *buf, int len, uint16_t seq,
  63.                               int flags)
  64. {
  65.  
  66.     int ident, fragmented, tdt, num_pkts, pkt_len;
  67.  
  68.     if (!buf) {
  69.         if (!data->split_buf || data->split_pos + 2 > data->split_buf_len ||
  70.             data->split_pkts <= 0) {
  71.             av_log(ctx, AV_LOG_ERROR, "No more data to return\n");
  72.             return AVERROR_INVALIDDATA;
  73.         }
  74.         pkt_len = AV_RB16(data->split_buf + data->split_pos);
  75.         data->split_pos += 2;
  76.         if (pkt_len > data->split_buf_len - data->split_pos) {
  77.             av_log(ctx, AV_LOG_ERROR, "Not enough data to return\n");
  78.             return AVERROR_INVALIDDATA;
  79.         }
  80.         if (av_new_packet(pkt, pkt_len)) {
  81.             av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
  82.             return AVERROR(ENOMEM);
  83.         }
  84.         pkt->stream_index = st->index;
  85.         memcpy(pkt->data, data->split_buf + data->split_pos, pkt_len);
  86.         data->split_pos += pkt_len;
  87.         data->split_pkts--;
  88.         return data->split_pkts > 0;
  89.     }
  90.  
  91.     if (len < 6 || len > INT_MAX/2) {
  92.         av_log(ctx, AV_LOG_ERROR, "Invalid %d byte packet\n", len);
  93.         return AVERROR_INVALIDDATA;
  94.     }
  95.  
  96.     // read xiph rtp headers
  97.     ident       = AV_RB24(buf);
  98.     fragmented  = buf[3] >> 6;
  99.     tdt         = (buf[3] >> 4) & 3;
  100.     num_pkts    = buf[3] & 0xf;
  101.     pkt_len     = AV_RB16(buf + 4);
  102.  
  103.     if (pkt_len > len - 6) {
  104.         av_log(ctx, AV_LOG_ERROR,
  105.                "Invalid packet length %d in %d byte packet\n", pkt_len,
  106.                len);
  107.         return AVERROR_INVALIDDATA;
  108.     }
  109.  
  110.     if (ident != data->ident) {
  111.         av_log(ctx, AV_LOG_ERROR,
  112.                "Unimplemented Xiph SDP configuration change detected\n");
  113.         return AVERROR_PATCHWELCOME;
  114.     }
  115.  
  116.     if (tdt) {
  117.         av_log(ctx, AV_LOG_ERROR,
  118.                "Unimplemented RTP Xiph packet settings (%d,%d,%d)\n",
  119.                fragmented, tdt, num_pkts);
  120.         return AVERROR_PATCHWELCOME;
  121.     }
  122.  
  123.     buf += 6; // move past header bits
  124.     len -= 6;
  125.  
  126.     if (fragmented == 0) {
  127.         if (av_new_packet(pkt, pkt_len)) {
  128.             av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
  129.             return AVERROR(ENOMEM);
  130.         }
  131.         pkt->stream_index = st->index;
  132.         memcpy(pkt->data, buf, pkt_len);
  133.         buf += pkt_len;
  134.         len -= pkt_len;
  135.         num_pkts--;
  136.  
  137.         if (num_pkts > 0) {
  138.             if (len > data->split_buf_size || !data->split_buf) {
  139.                 av_freep(&data->split_buf);
  140.                 data->split_buf_size = 2 * len;
  141.                 data->split_buf = av_malloc(data->split_buf_size);
  142.                 if (!data->split_buf) {
  143.                     av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
  144.                     av_free_packet(pkt);
  145.                     return AVERROR(ENOMEM);
  146.                 }
  147.             }
  148.             memcpy(data->split_buf, buf, len);
  149.             data->split_buf_len = len;
  150.             data->split_pos = 0;
  151.             data->split_pkts = num_pkts;
  152.             return 1;
  153.         }
  154.  
  155.         return 0;
  156.  
  157.     } else if (fragmented == 1) {
  158.         // start of xiph data fragment
  159.         int res;
  160.  
  161.         // end packet has been lost somewhere, so drop buffered data
  162.         ffio_free_dyn_buf(&data->fragment);
  163.  
  164.         if((res = avio_open_dyn_buf(&data->fragment)) < 0)
  165.             return res;
  166.  
  167.         avio_write(data->fragment, buf, pkt_len);
  168.         data->timestamp = *timestamp;
  169.  
  170.     } else {
  171.         av_assert1(fragmented < 4);
  172.         if (data->timestamp != *timestamp) {
  173.             // skip if fragmented timestamp is incorrect;
  174.             // a start packet has been lost somewhere
  175.             ffio_free_dyn_buf(&data->fragment);
  176.             av_log(ctx, AV_LOG_ERROR, "RTP timestamps don't match!\n");
  177.             return AVERROR_INVALIDDATA;
  178.         }
  179.         if (!data->fragment) {
  180.             av_log(ctx, AV_LOG_WARNING,
  181.                    "Received packet without a start fragment; dropping.\n");
  182.             return AVERROR(EAGAIN);
  183.         }
  184.  
  185.         // copy data to fragment buffer
  186.         avio_write(data->fragment, buf, pkt_len);
  187.  
  188.         if (fragmented == 3) {
  189.             // end of xiph data packet
  190.             int ret = ff_rtp_finalize_packet(pkt, &data->fragment, st->index);
  191.             if (ret < 0) {
  192.                 av_log(ctx, AV_LOG_ERROR,
  193.                        "Error occurred when getting fragment buffer.");
  194.                 return ret;
  195.             }
  196.  
  197.             return 0;
  198.         }
  199.     }
  200.  
  201.    return AVERROR(EAGAIN);
  202. }
  203.  
  204. /**
  205.  * Length encoding described in RFC5215 section 3.1.1.
  206.  */
  207. static int get_base128(const uint8_t ** buf, const uint8_t * buf_end)
  208. {
  209.     int n = 0;
  210.     for (; *buf < buf_end; ++*buf) {
  211.         n <<= 7;
  212.         n += **buf & 0x7f;
  213.         if (!(**buf & 0x80)) {
  214.             ++*buf;
  215.             return n;
  216.         }
  217.     }
  218.     return 0;
  219. }
  220.  
  221. /**
  222.  * Based off parse_packed_headers in Vorbis RTP
  223.  */
  224. static int
  225. parse_packed_headers(const uint8_t * packed_headers,
  226.                      const uint8_t * packed_headers_end,
  227.                      AVCodecContext * codec, PayloadContext * xiph_data)
  228. {
  229.  
  230.     unsigned num_packed, num_headers, length, length1, length2, extradata_alloc;
  231.     uint8_t *ptr;
  232.  
  233.     if (packed_headers_end - packed_headers < 9) {
  234.         av_log(codec, AV_LOG_ERROR,
  235.                "Invalid %"PTRDIFF_SPECIFIER" byte packed header.",
  236.                packed_headers_end - packed_headers);
  237.         return AVERROR_INVALIDDATA;
  238.     }
  239.  
  240.     num_packed         = bytestream_get_be32(&packed_headers);
  241.     xiph_data->ident   = bytestream_get_be24(&packed_headers);
  242.     length             = bytestream_get_be16(&packed_headers);
  243.     num_headers        = get_base128(&packed_headers, packed_headers_end);
  244.     length1            = get_base128(&packed_headers, packed_headers_end);
  245.     length2            = get_base128(&packed_headers, packed_headers_end);
  246.  
  247.     if (num_packed != 1 || num_headers > 3) {
  248.         av_log(codec, AV_LOG_ERROR,
  249.                "Unimplemented number of headers: %d packed headers, %d headers\n",
  250.                num_packed, num_headers);
  251.         return AVERROR_PATCHWELCOME;
  252.     }
  253.  
  254.     if (packed_headers_end - packed_headers != length ||
  255.         length1 > length || length2 > length - length1) {
  256.         av_log(codec, AV_LOG_ERROR,
  257.                "Bad packed header lengths (%d,%d,%"PTRDIFF_SPECIFIER",%d)\n", length1,
  258.                length2, packed_headers_end - packed_headers, length);
  259.         return AVERROR_INVALIDDATA;
  260.     }
  261.  
  262.     /* allocate extra space:
  263.      * -- length/255 +2 for xiphlacing
  264.      * -- one for the '2' marker
  265.      * -- AV_INPUT_BUFFER_PADDING_SIZE required */
  266.     extradata_alloc = length + length/255 + 3 + AV_INPUT_BUFFER_PADDING_SIZE;
  267.  
  268.     if (ff_alloc_extradata(codec, extradata_alloc)) {
  269.         av_log(codec, AV_LOG_ERROR, "Out of memory\n");
  270.         return AVERROR(ENOMEM);
  271.     }
  272.     ptr = codec->extradata;
  273.     *ptr++ = 2;
  274.     ptr += av_xiphlacing(ptr, length1);
  275.     ptr += av_xiphlacing(ptr, length2);
  276.     memcpy(ptr, packed_headers, length);
  277.     ptr += length;
  278.     codec->extradata_size = ptr - codec->extradata;
  279.     // clear out remaining parts of the buffer
  280.     memset(ptr, 0, extradata_alloc - codec->extradata_size);
  281.  
  282.     return 0;
  283. }
  284.  
  285. static int xiph_parse_fmtp_pair(AVFormatContext *s,
  286.                                 AVStream* stream,
  287.                                 PayloadContext *xiph_data,
  288.                                 const char *attr, const char *value)
  289. {
  290.     AVCodecContext *codec = stream->codec;
  291.     int result = 0;
  292.  
  293.     if (!strcmp(attr, "sampling")) {
  294.         if (!strcmp(value, "YCbCr-4:2:0")) {
  295.             codec->pix_fmt = AV_PIX_FMT_YUV420P;
  296.         } else if (!strcmp(value, "YCbCr-4:4:2")) {
  297.             codec->pix_fmt = AV_PIX_FMT_YUV422P;
  298.         } else if (!strcmp(value, "YCbCr-4:4:4")) {
  299.             codec->pix_fmt = AV_PIX_FMT_YUV444P;
  300.         } else {
  301.             av_log(s, AV_LOG_ERROR,
  302.                    "Unsupported pixel format %s\n", attr);
  303.             return AVERROR_INVALIDDATA;
  304.         }
  305.     } else if (!strcmp(attr, "width")) {
  306.         /* This is an integer between 1 and 1048561
  307.          * and MUST be in multiples of 16. */
  308.         codec->width = atoi(value);
  309.         return 0;
  310.     } else if (!strcmp(attr, "height")) {
  311.         /* This is an integer between 1 and 1048561
  312.          * and MUST be in multiples of 16. */
  313.         codec->height = atoi(value);
  314.         return 0;
  315.     } else if (!strcmp(attr, "delivery-method")) {
  316.         /* Possible values are: inline, in_band, out_band/specific_name. */
  317.         return AVERROR_PATCHWELCOME;
  318.     } else if (!strcmp(attr, "configuration-uri")) {
  319.         /* NOTE: configuration-uri is supported only under 2 conditions:
  320.          *--after the delivery-method tag
  321.          * --with a delivery-method value of out_band */
  322.         return AVERROR_PATCHWELCOME;
  323.     } else if (!strcmp(attr, "configuration")) {
  324.         /* NOTE: configuration is supported only AFTER the delivery-method tag
  325.          * The configuration value is a base64 encoded packed header */
  326.         uint8_t *decoded_packet = NULL;
  327.         int packet_size;
  328.         size_t decoded_alloc = strlen(value) / 4 * 3 + 4;
  329.  
  330.         if (decoded_alloc <= INT_MAX) {
  331.             decoded_packet = av_malloc(decoded_alloc);
  332.             if (decoded_packet) {
  333.                 packet_size =
  334.                     av_base64_decode(decoded_packet, value, decoded_alloc);
  335.  
  336.                 result = parse_packed_headers
  337.                     (decoded_packet, decoded_packet + packet_size, codec,
  338.                     xiph_data);
  339.             } else {
  340.                 av_log(s, AV_LOG_ERROR,
  341.                        "Out of memory while decoding SDP configuration.\n");
  342.                 result = AVERROR(ENOMEM);
  343.             }
  344.         } else {
  345.             av_log(s, AV_LOG_ERROR, "Packet too large\n");
  346.             result = AVERROR_INVALIDDATA;
  347.         }
  348.         av_free(decoded_packet);
  349.     }
  350.     return result;
  351. }
  352.  
  353. static int xiph_parse_sdp_line(AVFormatContext *s, int st_index,
  354.                                PayloadContext *data, const char *line)
  355. {
  356.     const char *p;
  357.  
  358.     if (st_index < 0)
  359.         return 0;
  360.  
  361.     if (av_strstart(line, "fmtp:", &p)) {
  362.         return ff_parse_fmtp(s, s->streams[st_index], data, p,
  363.                              xiph_parse_fmtp_pair);
  364.     }
  365.  
  366.     return 0;
  367. }
  368.  
  369. RTPDynamicProtocolHandler ff_theora_dynamic_handler = {
  370.     .enc_name         = "theora",
  371.     .codec_type       = AVMEDIA_TYPE_VIDEO,
  372.     .codec_id         = AV_CODEC_ID_THEORA,
  373.     .priv_data_size   = sizeof(PayloadContext),
  374.     .parse_sdp_a_line = xiph_parse_sdp_line,
  375.     .close            = xiph_close_context,
  376.     .parse_packet     = xiph_handle_packet,
  377. };
  378.  
  379. RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = {
  380.     .enc_name         = "vorbis",
  381.     .codec_type       = AVMEDIA_TYPE_AUDIO,
  382.     .codec_id         = AV_CODEC_ID_VORBIS,
  383.     .need_parsing     = AVSTREAM_PARSE_HEADERS,
  384.     .priv_data_size   = sizeof(PayloadContext),
  385.     .parse_sdp_a_line = xiph_parse_sdp_line,
  386.     .close            = xiph_close_context,
  387.     .parse_packet     = xiph_handle_packet,
  388. };
  389.