Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * RTP H.263 Depacketizer, RFC 2190
  3.  * Copyright (c) 2012 Martin Storsjo
  4.  * Based on the GStreamer H.263 Depayloder:
  5.  * Copyright 2005 Wim Taymans
  6.  * Copyright 2007 Edward Hervey
  7.  * Copyright 2007 Nokia Corporation
  8.  * Copyright 2007 Collabora Ltd, Philippe Kalaf
  9.  * Copyright 2010 Mark Nauwelaerts
  10.  *
  11.  * This file is part of FFmpeg.
  12.  *
  13.  * FFmpeg is free software; you can redistribute it and/or
  14.  * modify it under the terms of the GNU Lesser General Public
  15.  * License as published by the Free Software Foundation; either
  16.  * version 2.1 of the License, or (at your option) any later version.
  17.  *
  18.  * FFmpeg is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  21.  * Lesser General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU Lesser General Public
  24.  * License along with FFmpeg; if not, write to the Free Software
  25.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26.  */
  27.  
  28. #include "avformat.h"
  29. #include "rtpdec_formats.h"
  30. #include "libavutil/attributes.h"
  31. #include "libavutil/intreadwrite.h"
  32. #include "libavcodec/get_bits.h"
  33.  
  34. struct PayloadContext {
  35.     AVIOContext *buf;
  36.     uint8_t      endbyte;
  37.     int          endbyte_bits;
  38.     uint32_t     timestamp;
  39.     int          newformat;
  40. };
  41.  
  42. static PayloadContext *h263_new_context(void)
  43. {
  44.     return av_mallocz(sizeof(PayloadContext));
  45. }
  46.  
  47. static void h263_free_context(PayloadContext *data)
  48. {
  49.     if (!data)
  50.         return;
  51.     if (data->buf) {
  52.         uint8_t *p;
  53.         avio_close_dyn_buf(data->buf, &p);
  54.         av_free(p);
  55.     }
  56.     av_free(data);
  57. }
  58.  
  59. static av_cold int h263_init(AVFormatContext *ctx, int st_index, PayloadContext *data)
  60. {
  61.     if (st_index < 0)
  62.         return 0;
  63.     ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL;
  64.     return 0;
  65. }
  66.  
  67. static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data,
  68.                               AVStream *st, AVPacket *pkt, uint32_t *timestamp,
  69.                               const uint8_t *buf, int len, uint16_t seq,
  70.                               int flags)
  71. {
  72.     /* Corresponding to header fields in the RFC */
  73.     int f, p, i, sbit, ebit, src, r;
  74.     int header_size, ret;
  75.  
  76.     if (data->newformat)
  77.         return ff_h263_handle_packet(ctx, data, st, pkt, timestamp, buf, len,
  78.                                      seq, flags);
  79.  
  80.     if (data->buf && data->timestamp != *timestamp) {
  81.         /* Dropping old buffered, unfinished data */
  82.         uint8_t *p;
  83.         avio_close_dyn_buf(data->buf, &p);
  84.         av_free(p);
  85.         data->buf = NULL;
  86.     }
  87.  
  88.     if (len < 4) {
  89.         av_log(ctx, AV_LOG_ERROR, "Too short H.263 RTP packet: %d\n", len);
  90.         return AVERROR_INVALIDDATA;
  91.     }
  92.  
  93.     f = buf[0] & 0x80;
  94.     p = buf[0] & 0x40;
  95.     if (!f) {
  96.         /* Mode A */
  97.         header_size = 4;
  98.         i = buf[1] & 0x10;
  99.         r = ((buf[1] & 0x01) << 3) | ((buf[2] & 0xe0) >> 5);
  100.     } else if (!p) {
  101.         /* Mode B */
  102.         header_size = 8;
  103.         if (len < header_size) {
  104.             av_log(ctx, AV_LOG_ERROR,
  105.                    "Too short H.263 RTP packet: %d bytes, %d header bytes\n",
  106.                    len, header_size);
  107.             return AVERROR_INVALIDDATA;
  108.         }
  109.         r = buf[3] & 0x03;
  110.         i = buf[4] & 0x80;
  111.     } else {
  112.         /* Mode C */
  113.         header_size = 12;
  114.         if (len < header_size) {
  115.             av_log(ctx, AV_LOG_ERROR,
  116.                    "Too short H.263 RTP packet: %d bytes, %d header bytes\n",
  117.                    len, header_size);
  118.             return AVERROR_INVALIDDATA;
  119.         }
  120.         r = buf[3] & 0x03;
  121.         i = buf[4] & 0x80;
  122.     }
  123.     sbit = (buf[0] >> 3) & 0x7;
  124.     ebit =  buf[0]       & 0x7;
  125.     src  = (buf[1] & 0xe0) >> 5;
  126.     if (!(buf[0] & 0xf8)) { /* Reserved bits in RFC 2429/4629 are zero */
  127.         if ((src == 0 || src >= 6) && r) {
  128.             /* Invalid src for this format, and bits that should be zero
  129.              * according to RFC 2190 aren't zero. */
  130.             av_log(ctx, AV_LOG_WARNING,
  131.                    "Interpreting H263 RTP data as RFC 2429/4629 even though "
  132.                    "signalled with a static payload type.\n");
  133.             data->newformat = 1;
  134.             return ff_h263_handle_packet(ctx, data, st, pkt, timestamp, buf,
  135.                                          len, seq, flags);
  136.         }
  137.     }
  138.  
  139.     buf += header_size;
  140.     len -= header_size;
  141.  
  142.     if (!data->buf) {
  143.         /* Check the picture start code, only start buffering a new frame
  144.          * if this is correct */
  145.         if (len > 4 && AV_RB32(buf) >> 10 == 0x20) {
  146.             ret = avio_open_dyn_buf(&data->buf);
  147.             if (ret < 0)
  148.                 return ret;
  149.             data->timestamp = *timestamp;
  150.         } else {
  151.             /* Frame not started yet, skipping */
  152.             return AVERROR(EAGAIN);
  153.         }
  154.     }
  155.  
  156.     if (data->endbyte_bits || sbit) {
  157.         if (data->endbyte_bits == sbit) {
  158.             data->endbyte |= buf[0] & (0xff >> sbit);
  159.             data->endbyte_bits = 0;
  160.             buf++;
  161.             len--;
  162.             avio_w8(data->buf, data->endbyte);
  163.         } else {
  164.             /* Start/end skip bits not matching - missed packets? */
  165.             GetBitContext gb;
  166.             init_get_bits(&gb, buf, len*8 - ebit);
  167.             skip_bits(&gb, sbit);
  168.             if (data->endbyte_bits) {
  169.                 data->endbyte |= get_bits(&gb, 8 - data->endbyte_bits);
  170.                 avio_w8(data->buf, data->endbyte);
  171.             }
  172.             while (get_bits_left(&gb) >= 8)
  173.                 avio_w8(data->buf, get_bits(&gb, 8));
  174.             data->endbyte_bits = get_bits_left(&gb);
  175.             if (data->endbyte_bits)
  176.                 data->endbyte = get_bits(&gb, data->endbyte_bits) <<
  177.                                 (8 - data->endbyte_bits);
  178.             ebit = 0;
  179.             len = 0;
  180.         }
  181.     }
  182.     if (ebit) {
  183.         if (len > 0)
  184.             avio_write(data->buf, buf, len - 1);
  185.         data->endbyte_bits = 8 - ebit;
  186.         data->endbyte = buf[len - 1] & (0xff << ebit);
  187.     } else {
  188.         avio_write(data->buf, buf, len);
  189.     }
  190.  
  191.     if (!(flags & RTP_FLAG_MARKER))
  192.         return AVERROR(EAGAIN);
  193.  
  194.     if (data->endbyte_bits)
  195.         avio_w8(data->buf, data->endbyte);
  196.     data->endbyte_bits = 0;
  197.  
  198.     ret = ff_rtp_finalize_packet(pkt, &data->buf, st->index);
  199.     if (ret < 0)
  200.         return ret;
  201.     if (!i)
  202.         pkt->flags   |= AV_PKT_FLAG_KEY;
  203.  
  204.     return 0;
  205. }
  206.  
  207. RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler = {
  208.     .codec_type        = AVMEDIA_TYPE_VIDEO,
  209.     .codec_id          = AV_CODEC_ID_H263,
  210.     .init              = h263_init,
  211.     .parse_packet      = h263_handle_packet,
  212.     .alloc             = h263_new_context,
  213.     .free              = h263_free_context,
  214.     .static_payload_id = 34,
  215. };
  216.