Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * RTP/Quicktime support.
  3.  * Copyright (c) 2009 Ronald S. Bultje
  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. /**
  23.  * @file
  24.  * @brief Quicktime-style RTP support
  25.  * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
  26.  */
  27.  
  28. #include "avformat.h"
  29. #include "internal.h"
  30. #include "avio_internal.h"
  31. #include "rtp.h"
  32. #include "rtpdec.h"
  33. #include "isom.h"
  34. #include "libavcodec/get_bits.h"
  35.  
  36. struct PayloadContext {
  37.     AVPacket pkt;
  38.     int bytes_per_frame, remaining;
  39.     uint32_t timestamp;
  40. };
  41.  
  42. static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
  43.                                AVStream *st, AVPacket *pkt,
  44.                                uint32_t *timestamp, const uint8_t *buf,
  45.                                int len, uint16_t seq, int flags)
  46. {
  47.     AVIOContext pb;
  48.     GetBitContext gb;
  49.     int packing_scheme, has_payload_desc, has_packet_info, alen,
  50.         has_marker_bit = flags & RTP_FLAG_MARKER;
  51.  
  52.     if (qt->remaining) {
  53.         int num = qt->pkt.size / qt->bytes_per_frame;
  54.  
  55.         if (av_new_packet(pkt, qt->bytes_per_frame))
  56.             return AVERROR(ENOMEM);
  57.         pkt->stream_index = st->index;
  58.         pkt->flags        = qt->pkt.flags;
  59.         memcpy(pkt->data,
  60.                &qt->pkt.data[(num - qt->remaining) * qt->bytes_per_frame],
  61.                qt->bytes_per_frame);
  62.         if (--qt->remaining == 0) {
  63.             av_freep(&qt->pkt.data);
  64.             qt->pkt.size = 0;
  65.         }
  66.         return qt->remaining > 0;
  67.     }
  68.  
  69.     /**
  70.      * The RTP payload is described in:
  71.      * http://developer.apple.com/quicktime/icefloe/dispatch026.html
  72.      */
  73.     init_get_bits(&gb, buf, len << 3);
  74.     ffio_init_context(&pb, buf, len, 0, NULL, NULL, NULL, NULL);
  75.  
  76.     if (len < 4)
  77.         return AVERROR_INVALIDDATA;
  78.  
  79.     skip_bits(&gb, 4); // version
  80.     if ((packing_scheme = get_bits(&gb, 2)) == 0)
  81.         return AVERROR_INVALIDDATA;
  82.     if (get_bits1(&gb))
  83.         flags          |= RTP_FLAG_KEY;
  84.     has_payload_desc    = get_bits1(&gb);
  85.     has_packet_info     = get_bits1(&gb);
  86.     skip_bits(&gb, 23); // reserved:7, cache payload info:1, payload ID:15
  87.  
  88.     if (has_payload_desc) {
  89.         int data_len, pos, is_start, is_finish;
  90.         uint32_t tag;
  91.  
  92.         pos = get_bits_count(&gb) >> 3;
  93.         if (pos + 12 > len)
  94.             return AVERROR_INVALIDDATA;
  95.  
  96.         skip_bits(&gb, 2); // has non-I frames:1, is sparse:1
  97.         is_start  = get_bits1(&gb);
  98.         is_finish = get_bits1(&gb);
  99.         if (!is_start || !is_finish) {
  100.             avpriv_request_sample(s, "RTP-X-QT with payload description "
  101.                                   "split over several packets");
  102.             return AVERROR_PATCHWELCOME;
  103.         }
  104.         skip_bits(&gb, 12); // reserved
  105.         data_len = get_bits(&gb, 16);
  106.  
  107.         avio_seek(&pb, pos + 4, SEEK_SET);
  108.         tag = avio_rl32(&pb);
  109.         if ((st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
  110.                  tag != MKTAG('v','i','d','e')) ||
  111.             (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
  112.                  tag != MKTAG('s','o','u','n')))
  113.             return AVERROR_INVALIDDATA;
  114.         avpriv_set_pts_info(st, 32, 1, avio_rb32(&pb));
  115.  
  116.         if (pos + data_len > len)
  117.             return AVERROR_INVALIDDATA;
  118.         /* TLVs */
  119.         while (avio_tell(&pb) + 4 < pos + data_len) {
  120.             int tlv_len = avio_rb16(&pb);
  121.             tag = avio_rl16(&pb);
  122.             if (avio_tell(&pb) + tlv_len > pos + data_len)
  123.                 return AVERROR_INVALIDDATA;
  124.  
  125. #define MKTAG16(a,b) MKTAG(a,b,0,0)
  126.             switch (tag) {
  127.             case MKTAG16('s','d'): {
  128.                 MOVStreamContext *msc;
  129.                 void *priv_data = st->priv_data;
  130.                 int nb_streams = s->nb_streams;
  131.                 MOVContext *mc = av_mallocz(sizeof(*mc));
  132.                 if (!mc)
  133.                     return AVERROR(ENOMEM);
  134.                 mc->fc = s;
  135.                 st->priv_data = msc = av_mallocz(sizeof(MOVStreamContext));
  136.                 if (!msc) {
  137.                     av_free(mc);
  138.                     st->priv_data = priv_data;
  139.                     return AVERROR(ENOMEM);
  140.                 }
  141.                 /* ff_mov_read_stsd_entries updates stream s->nb_streams-1,
  142.                  * so set it temporarily to indicate which stream to update. */
  143.                 s->nb_streams = st->index + 1;
  144.                 ff_mov_read_stsd_entries(mc, &pb, 1);
  145.                 qt->bytes_per_frame = msc->bytes_per_frame;
  146.                 av_free(msc);
  147.                 av_free(mc);
  148.                 st->priv_data = priv_data;
  149.                 s->nb_streams = nb_streams;
  150.                 break;
  151.             }
  152.             default:
  153.                 avio_skip(&pb, tlv_len);
  154.                 break;
  155.             }
  156.         }
  157.  
  158.         /* 32-bit alignment */
  159.         avio_skip(&pb, ((avio_tell(&pb) + 3) & ~3) - avio_tell(&pb));
  160.     } else
  161.         avio_seek(&pb, 4, SEEK_SET);
  162.  
  163.     if (has_packet_info) {
  164.         avpriv_request_sample(s, "RTP-X-QT with packet-specific info");
  165.         return AVERROR_PATCHWELCOME;
  166.     }
  167.  
  168.     alen = len - avio_tell(&pb);
  169.     if (alen <= 0)
  170.         return AVERROR_INVALIDDATA;
  171.  
  172.     switch (packing_scheme) {
  173.     case 3: /* one data packet spread over 1 or multiple RTP packets */
  174.         if (qt->pkt.size > 0 && qt->timestamp == *timestamp) {
  175.             int err;
  176.             if ((err = av_reallocp(&qt->pkt.data, qt->pkt.size + alen +
  177.                                    FF_INPUT_BUFFER_PADDING_SIZE)) < 0) {
  178.                 qt->pkt.size = 0;
  179.                 return err;
  180.             }
  181.         } else {
  182.             av_freep(&qt->pkt.data);
  183.             av_init_packet(&qt->pkt);
  184.             qt->pkt.data = av_realloc(NULL, alen + FF_INPUT_BUFFER_PADDING_SIZE);
  185.             if (!qt->pkt.data)
  186.                 return AVERROR(ENOMEM);
  187.             qt->pkt.size = 0;
  188.             qt->timestamp = *timestamp;
  189.         }
  190.         memcpy(qt->pkt.data + qt->pkt.size, buf + avio_tell(&pb), alen);
  191.         qt->pkt.size += alen;
  192.         if (has_marker_bit) {
  193.             int ret = av_packet_from_data(pkt, qt->pkt.data, qt->pkt.size);
  194.             if (ret < 0)
  195.                 return ret;
  196.  
  197.             qt->pkt.size = 0;
  198.             qt->pkt.data = NULL;
  199.             pkt->flags        = flags & RTP_FLAG_KEY ? AV_PKT_FLAG_KEY : 0;
  200.             pkt->stream_index = st->index;
  201.             memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
  202.             return 0;
  203.         }
  204.         return AVERROR(EAGAIN);
  205.  
  206.     case 1: /* constant packet size, multiple packets per RTP packet */
  207.         if (qt->bytes_per_frame == 0 ||
  208.             alen % qt->bytes_per_frame != 0)
  209.             return AVERROR_INVALIDDATA; /* wrongly padded */
  210.         qt->remaining = (alen / qt->bytes_per_frame) - 1;
  211.         if (av_new_packet(pkt, qt->bytes_per_frame))
  212.             return AVERROR(ENOMEM);
  213.         memcpy(pkt->data, buf + avio_tell(&pb), qt->bytes_per_frame);
  214.         pkt->flags = flags & RTP_FLAG_KEY ? AV_PKT_FLAG_KEY : 0;
  215.         pkt->stream_index = st->index;
  216.         if (qt->remaining > 0) {
  217.             av_freep(&qt->pkt.data);
  218.             qt->pkt.data = av_realloc(NULL, qt->remaining * qt->bytes_per_frame);
  219.             if (!qt->pkt.data) {
  220.                 av_free_packet(pkt);
  221.                 return AVERROR(ENOMEM);
  222.             }
  223.             qt->pkt.size = qt->remaining * qt->bytes_per_frame;
  224.             memcpy(qt->pkt.data,
  225.                    buf + avio_tell(&pb) + qt->bytes_per_frame,
  226.                    qt->remaining * qt->bytes_per_frame);
  227.             qt->pkt.flags = pkt->flags;
  228.             return 1;
  229.         }
  230.         return 0;
  231.  
  232.     default:  /* unimplemented */
  233.         avpriv_request_sample(NULL, "RTP-X-QT with packing scheme 2");
  234.         return AVERROR_PATCHWELCOME;
  235.     }
  236. }
  237.  
  238. static PayloadContext *qt_rtp_new(void)
  239. {
  240.     return av_mallocz(sizeof(PayloadContext));
  241. }
  242.  
  243. static void qt_rtp_free(PayloadContext *qt)
  244. {
  245.     av_freep(&qt->pkt.data);
  246.     av_free(qt);
  247. }
  248.  
  249. #define RTP_QT_HANDLER(m, n, s, t) \
  250. RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \
  251.     .enc_name         = s, \
  252.     .codec_type       = t, \
  253.     .codec_id         = AV_CODEC_ID_NONE, \
  254.     .alloc            = qt_rtp_new,    \
  255.     .free             = qt_rtp_free,   \
  256.     .parse_packet     = qt_rtp_parse_packet, \
  257. }
  258.  
  259. RTP_QT_HANDLER(qt,        vid, "X-QT",        AVMEDIA_TYPE_VIDEO);
  260. RTP_QT_HANDLER(qt,        aud, "X-QT",        AVMEDIA_TYPE_AUDIO);
  261. RTP_QT_HANDLER(quicktime, vid, "X-QUICKTIME", AVMEDIA_TYPE_VIDEO);
  262. RTP_QT_HANDLER(quicktime, aud, "X-QUICKTIME", AVMEDIA_TYPE_AUDIO);
  263.