LCOV - code coverage report
Current view: top level - libavformat - rtpdec_h261.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 60 0.0 %
Date: 2017-12-14 01:15:32 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*
       2             :  * RTP parser for H.261 payload format (RFC 4587)
       3             :  * Copyright (c) 2014 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 "libavcodec/get_bits.h"
      23             : #include "avformat.h"
      24             : #include "avio_internal.h"
      25             : #include "rtpdec_formats.h"
      26             : 
      27             : #define RTP_H261_PAYLOAD_HEADER_SIZE 4
      28             : 
      29             : struct PayloadContext {
      30             :     AVIOContext *buf;
      31             :     uint8_t      endbyte;
      32             :     int          endbyte_bits;
      33             :     uint32_t     timestamp;
      34             : };
      35             : 
      36           0 : static av_cold void h261_close_context(PayloadContext *pl_ctx)
      37             : {
      38             :     /* return if context is invalid */
      39           0 :     if (!pl_ctx)
      40           0 :         return;
      41             : 
      42             :     /* free buffer if it is valid */
      43           0 :     ffio_free_dyn_buf(&pl_ctx->buf);
      44             : }
      45             : 
      46           0 : static int h261_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_h261_ctx,
      47             :                               AVStream *st, AVPacket *pkt, uint32_t *timestamp,
      48             :                               const uint8_t *buf, int len, uint16_t seq,
      49             :                               int flags)
      50             : {
      51             :     int sbit, ebit, gobn, mbap, quant;
      52             :     int res;
      53             : 
      54             :     /* drop data of previous packets in case of non-continuous (lossy) packet stream */
      55           0 :     if (rtp_h261_ctx->buf && rtp_h261_ctx->timestamp != *timestamp) {
      56           0 :         ffio_free_dyn_buf(&rtp_h261_ctx->buf);
      57           0 :         rtp_h261_ctx->endbyte_bits = 0;
      58             :     }
      59             : 
      60             :     /* sanity check for size of input packet: 1 byte payload at least */
      61           0 :     if (len < RTP_H261_PAYLOAD_HEADER_SIZE + 1) {
      62           0 :         av_log(ctx, AV_LOG_ERROR, "Too short RTP/H.261 packet, got %d bytes\n", len);
      63           0 :         return AVERROR_INVALIDDATA;
      64             :     }
      65             : 
      66             :     /*
      67             :      * decode the H.261 payload header according to section 4.1 of RFC 4587:
      68             :      * (uses 4 bytes between RTP header and H.261 stream per packet)
      69             :      *
      70             :      *    0                   1                   2                   3
      71             :      *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      72             :      *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      73             :      *   |SBIT |EBIT |I|V| GOBN  |   MBAP  |  QUANT  |  HMVD   |  VMVD   |
      74             :      *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      75             :      *
      76             :      *      Start bit position (SBIT): 3 bits
      77             :      *      End bit position (EBIT): 3 bits
      78             :      *      INTRA-frame encoded data (I): 1 bit
      79             :      *      Motion Vector flag (V): 1 bit
      80             :      *      GOB number (GOBN): 4 bits
      81             :      *      Macroblock address predictor (MBAP): 5 bits
      82             :      *      Quantizer (QUANT): 5 bits
      83             :      *      Horizontal motion vector data (HMVD): 5 bits
      84             :      *      Vertical motion vector data (VMVD): 5 bits
      85             :      */
      86           0 :     sbit  =  (buf[0] >> 5) & 0x07;
      87           0 :     ebit  =  (buf[0] >> 2) & 0x07;
      88           0 :     gobn  =  (buf[1] >> 4) & 0x0f;
      89           0 :     mbap  = ((buf[1] << 1) & 0x1e) | ((buf[2] >> 7) & 0x01);
      90           0 :     quant =  (buf[2] >> 2) & 0x1f;
      91             : 
      92             :     /* pass the H.261 payload header and continue with the actual payload */
      93           0 :     buf += RTP_H261_PAYLOAD_HEADER_SIZE;
      94           0 :     len -= RTP_H261_PAYLOAD_HEADER_SIZE;
      95             : 
      96             :     /* start frame buffering with new dynamic buffer */
      97           0 :     if (!rtp_h261_ctx->buf) {
      98             :         /* sanity check: a new frame starts with gobn=0, sbit=0, mbap=0, quant=0 */
      99           0 :         if (!gobn && !sbit && !mbap && !quant) {
     100           0 :             res = avio_open_dyn_buf(&rtp_h261_ctx->buf);
     101           0 :             if (res < 0)
     102           0 :                 return res;
     103             :             /* update the timestamp in the frame packet with the one from the RTP packet */
     104           0 :             rtp_h261_ctx->timestamp = *timestamp;
     105             :         } else {
     106             :             /* frame not started yet, need more packets */
     107           0 :             return AVERROR(EAGAIN);
     108             :         }
     109             :     }
     110             : 
     111             :     /* do the "byte merging" at the boundaries of two consecutive frame fragments */
     112           0 :     if (rtp_h261_ctx->endbyte_bits || sbit) {
     113           0 :         if (rtp_h261_ctx->endbyte_bits == sbit) {
     114           0 :             rtp_h261_ctx->endbyte     |= buf[0] & (0xff >> sbit);
     115           0 :             rtp_h261_ctx->endbyte_bits = 0;
     116           0 :             buf++;
     117           0 :             len--;
     118           0 :             avio_w8(rtp_h261_ctx->buf, rtp_h261_ctx->endbyte);
     119             :         } else {
     120             :             /* ebit/sbit values inconsistent, assuming packet loss */
     121             :             GetBitContext gb;
     122           0 :             init_get_bits(&gb, buf, len*8 - ebit);
     123           0 :             skip_bits(&gb, sbit);
     124           0 :             if (rtp_h261_ctx->endbyte_bits) {
     125           0 :                 rtp_h261_ctx->endbyte |= get_bits(&gb, 8 - rtp_h261_ctx->endbyte_bits);
     126           0 :                 avio_w8(rtp_h261_ctx->buf, rtp_h261_ctx->endbyte);
     127             :             }
     128           0 :             while (get_bits_left(&gb) >= 8)
     129           0 :                 avio_w8(rtp_h261_ctx->buf, get_bits(&gb, 8));
     130           0 :             rtp_h261_ctx->endbyte_bits = get_bits_left(&gb);
     131           0 :             if (rtp_h261_ctx->endbyte_bits)
     132           0 :                 rtp_h261_ctx->endbyte = get_bits(&gb, rtp_h261_ctx->endbyte_bits) <<
     133           0 :                                         (8 - rtp_h261_ctx->endbyte_bits);
     134           0 :             ebit = 0;
     135           0 :             len  = 0;
     136             :         }
     137             :     }
     138           0 :     if (ebit) {
     139           0 :         if (len > 0)
     140           0 :             avio_write(rtp_h261_ctx->buf, buf, len - 1);
     141           0 :         rtp_h261_ctx->endbyte_bits = 8 - ebit;
     142           0 :         rtp_h261_ctx->endbyte      = buf[len - 1] & (0xff << ebit);
     143             :     } else {
     144           0 :         avio_write(rtp_h261_ctx->buf, buf, len);
     145             :     }
     146             : 
     147             :     /* RTP marker bit means: last fragment of current frame was received;
     148             :        otherwise, an additional fragment is needed for the current frame */
     149           0 :     if (!(flags & RTP_FLAG_MARKER))
     150           0 :         return AVERROR(EAGAIN);
     151             : 
     152             :     /* write the completed last byte from the "byte merging" */
     153           0 :     if (rtp_h261_ctx->endbyte_bits)
     154           0 :         avio_w8(rtp_h261_ctx->buf, rtp_h261_ctx->endbyte);
     155           0 :     rtp_h261_ctx->endbyte_bits = 0;
     156             : 
     157             :     /* close frame buffering and create resulting A/V packet */
     158           0 :     res = ff_rtp_finalize_packet(pkt, &rtp_h261_ctx->buf, st->index);
     159           0 :     if (res < 0)
     160           0 :         return res;
     161             : 
     162           0 :     return 0;
     163             : }
     164             : 
     165             : RTPDynamicProtocolHandler ff_h261_dynamic_handler = {
     166             :     .enc_name          = "H261",
     167             :     .codec_type        = AVMEDIA_TYPE_VIDEO,
     168             :     .codec_id          = AV_CODEC_ID_H261,
     169             :     .need_parsing      = AVSTREAM_PARSE_FULL,
     170             :     .priv_data_size    = sizeof(PayloadContext),
     171             :     .close             = h261_close_context,
     172             :     .parse_packet      = h261_handle_packet,
     173             :     .static_payload_id = 31,
     174             : };

Generated by: LCOV version 1.13