Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Common code for the RTP depacketization of MPEG-4 formats.
  3.  * Copyright (c) 2010 Fabrice Bellard
  4.  *                    Romain Degez
  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 MPEG4 / RTP Code
  26.  * @author Fabrice Bellard
  27.  * @author Romain Degez
  28.  */
  29.  
  30. #include "rtpdec_formats.h"
  31. #include "internal.h"
  32. #include "libavutil/attributes.h"
  33. #include "libavutil/avstring.h"
  34. #include "libavcodec/get_bits.h"
  35.  
  36. #define MAX_AAC_HBR_FRAME_SIZE 8191
  37.  
  38. /** Structure listing useful vars to parse RTP packet payload */
  39. struct PayloadContext {
  40.     int sizelength;
  41.     int indexlength;
  42.     int indexdeltalength;
  43.     int profile_level_id;
  44.     int streamtype;
  45.     int objecttype;
  46.     char *mode;
  47.  
  48.     /** mpeg 4 AU headers */
  49.     struct AUHeaders {
  50.         int size;
  51.         int index;
  52.         int cts_flag;
  53.         int cts;
  54.         int dts_flag;
  55.         int dts;
  56.         int rap_flag;
  57.         int streamstate;
  58.     } *au_headers;
  59.     int au_headers_allocated;
  60.     int nb_au_headers;
  61.     int au_headers_length_bytes;
  62.     int cur_au_index;
  63.  
  64.     uint8_t buf[FFMAX(RTP_MAX_PACKET_LENGTH, MAX_AAC_HBR_FRAME_SIZE)];
  65.     int buf_pos, buf_size;
  66.     uint32_t timestamp;
  67. };
  68.  
  69. typedef struct AttrNameMap {
  70.     const char *str;
  71.     uint16_t    type;
  72.     uint32_t    offset;
  73. } AttrNameMap;
  74.  
  75. /* All known fmtp parameters and the corresponding RTPAttrTypeEnum */
  76. #define ATTR_NAME_TYPE_INT 0
  77. #define ATTR_NAME_TYPE_STR 1
  78. static const AttrNameMap attr_names[] = {
  79.     { "SizeLength",       ATTR_NAME_TYPE_INT,
  80.       offsetof(PayloadContext, sizelength) },
  81.     { "IndexLength",      ATTR_NAME_TYPE_INT,
  82.       offsetof(PayloadContext, indexlength) },
  83.     { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
  84.       offsetof(PayloadContext, indexdeltalength) },
  85.     { "profile-level-id", ATTR_NAME_TYPE_INT,
  86.       offsetof(PayloadContext, profile_level_id) },
  87.     { "StreamType",       ATTR_NAME_TYPE_INT,
  88.       offsetof(PayloadContext, streamtype) },
  89.     { "mode",             ATTR_NAME_TYPE_STR,
  90.       offsetof(PayloadContext, mode) },
  91.     { NULL, -1, -1 },
  92. };
  93.  
  94. static void close_context(PayloadContext *data)
  95. {
  96.     av_freep(&data->au_headers);
  97.     av_freep(&data->mode);
  98. }
  99.  
  100. static int parse_fmtp_config(AVCodecContext *codec, const char *value)
  101. {
  102.     /* decode the hexa encoded parameter */
  103.     int len = ff_hex_to_data(NULL, value);
  104.     av_freep(&codec->extradata);
  105.     if (ff_alloc_extradata(codec, len))
  106.         return AVERROR(ENOMEM);
  107.     ff_hex_to_data(codec->extradata, value);
  108.     return 0;
  109. }
  110.  
  111. static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf, int len)
  112. {
  113.     int au_headers_length, au_header_size, i;
  114.     GetBitContext getbitcontext;
  115.  
  116.     if (len < 2)
  117.         return AVERROR_INVALIDDATA;
  118.  
  119.     /* decode the first 2 bytes where the AUHeader sections are stored
  120.        length in bits */
  121.     au_headers_length = AV_RB16(buf);
  122.  
  123.     if (au_headers_length > RTP_MAX_PACKET_LENGTH)
  124.       return -1;
  125.  
  126.     data->au_headers_length_bytes = (au_headers_length + 7) / 8;
  127.  
  128.     /* skip AU headers length section (2 bytes) */
  129.     buf += 2;
  130.     len -= 2;
  131.  
  132.     if (len < data->au_headers_length_bytes)
  133.         return AVERROR_INVALIDDATA;
  134.  
  135.     init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8);
  136.  
  137.     /* XXX: Wrong if optional additional sections are present (cts, dts etc...) */
  138.     au_header_size = data->sizelength + data->indexlength;
  139.     if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
  140.         return -1;
  141.  
  142.     data->nb_au_headers = au_headers_length / au_header_size;
  143.     if (!data->au_headers || data->au_headers_allocated < data->nb_au_headers) {
  144.         av_free(data->au_headers);
  145.         data->au_headers = av_malloc(sizeof(struct AUHeaders) * data->nb_au_headers);
  146.         if (!data->au_headers)
  147.             return AVERROR(ENOMEM);
  148.         data->au_headers_allocated = data->nb_au_headers;
  149.     }
  150.  
  151.     for (i = 0; i < data->nb_au_headers; ++i) {
  152.         data->au_headers[i].size  = get_bits_long(&getbitcontext, data->sizelength);
  153.         data->au_headers[i].index = get_bits_long(&getbitcontext, data->indexlength);
  154.     }
  155.  
  156.     return 0;
  157. }
  158.  
  159.  
  160. /* Follows RFC 3640 */
  161. static int aac_parse_packet(AVFormatContext *ctx, PayloadContext *data,
  162.                             AVStream *st, AVPacket *pkt, uint32_t *timestamp,
  163.                             const uint8_t *buf, int len, uint16_t seq,
  164.                             int flags)
  165. {
  166.     int ret;
  167.  
  168.  
  169.     if (!buf) {
  170.         if (data->cur_au_index > data->nb_au_headers) {
  171.             av_log(ctx, AV_LOG_ERROR, "Invalid parser state\n");
  172.             return AVERROR_INVALIDDATA;
  173.         }
  174.         if (data->buf_size - data->buf_pos < data->au_headers[data->cur_au_index].size) {
  175.             av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n");
  176.             return AVERROR_INVALIDDATA;
  177.         }
  178.         if ((ret = av_new_packet(pkt, data->au_headers[data->cur_au_index].size)) < 0) {
  179.             av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
  180.             return ret;
  181.         }
  182.         memcpy(pkt->data, &data->buf[data->buf_pos], data->au_headers[data->cur_au_index].size);
  183.         data->buf_pos += data->au_headers[data->cur_au_index].size;
  184.         pkt->stream_index = st->index;
  185.         data->cur_au_index++;
  186.  
  187.         if (data->cur_au_index == data->nb_au_headers) {
  188.             data->buf_pos = 0;
  189.             return 0;
  190.         }
  191.  
  192.         return 1;
  193.     }
  194.  
  195.     if (rtp_parse_mp4_au(data, buf, len)) {
  196.         av_log(ctx, AV_LOG_ERROR, "Error parsing AU headers\n");
  197.         return -1;
  198.     }
  199.  
  200.     buf += data->au_headers_length_bytes + 2;
  201.     len -= data->au_headers_length_bytes + 2;
  202.     if (data->nb_au_headers == 1 && len < data->au_headers[0].size) {
  203.         /* Packet is fragmented */
  204.  
  205.         if (!data->buf_pos) {
  206.             if (data->au_headers[0].size > MAX_AAC_HBR_FRAME_SIZE) {
  207.                 av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n");
  208.                 return AVERROR_INVALIDDATA;
  209.             }
  210.  
  211.             data->buf_size = data->au_headers[0].size;
  212.             data->timestamp = *timestamp;
  213.         }
  214.  
  215.         if (data->timestamp != *timestamp ||
  216.             data->au_headers[0].size != data->buf_size ||
  217.             data->buf_pos + len > MAX_AAC_HBR_FRAME_SIZE) {
  218.             data->buf_pos = 0;
  219.             data->buf_size = 0;
  220.             av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n");
  221.             return AVERROR_INVALIDDATA;
  222.         }
  223.  
  224.         memcpy(&data->buf[data->buf_pos], buf, len);
  225.         data->buf_pos += len;
  226.  
  227.         if (!(flags & RTP_FLAG_MARKER))
  228.             return AVERROR(EAGAIN);
  229.  
  230.         if (data->buf_pos != data->buf_size) {
  231.             data->buf_pos = 0;
  232.             av_log(ctx, AV_LOG_ERROR, "Missed some packets, discarding frame\n");
  233.             return AVERROR_INVALIDDATA;
  234.         }
  235.  
  236.         data->buf_pos = 0;
  237.         ret = av_new_packet(pkt, data->buf_size);
  238.         if (ret < 0) {
  239.             av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
  240.             return ret;
  241.         }
  242.         pkt->stream_index = st->index;
  243.  
  244.         memcpy(pkt->data, data->buf, data->buf_size);
  245.  
  246.         return 0;
  247.     }
  248.  
  249.     if (len < data->au_headers[0].size) {
  250.         av_log(ctx, AV_LOG_ERROR, "First AU larger than packet size\n");
  251.         return AVERROR_INVALIDDATA;
  252.     }
  253.     if ((ret = av_new_packet(pkt, data->au_headers[0].size)) < 0) {
  254.         av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
  255.         return ret;
  256.     }
  257.     memcpy(pkt->data, buf, data->au_headers[0].size);
  258.     len -= data->au_headers[0].size;
  259.     buf += data->au_headers[0].size;
  260.     pkt->stream_index = st->index;
  261.  
  262.     if (len > 0 && data->nb_au_headers > 1) {
  263.         data->buf_size = FFMIN(len, sizeof(data->buf));
  264.         memcpy(data->buf, buf, data->buf_size);
  265.         data->cur_au_index = 1;
  266.         data->buf_pos = 0;
  267.         return 1;
  268.     }
  269.  
  270.     return 0;
  271. }
  272.  
  273. static int parse_fmtp(AVFormatContext *s,
  274.                       AVStream *stream, PayloadContext *data,
  275.                       const char *attr, const char *value)
  276. {
  277.     AVCodecContext *codec = stream->codec;
  278.     int res, i;
  279.  
  280.     if (!strcmp(attr, "config")) {
  281.         res = parse_fmtp_config(codec, value);
  282.  
  283.         if (res < 0)
  284.             return res;
  285.     }
  286.  
  287.     if (codec->codec_id == AV_CODEC_ID_AAC) {
  288.         /* Looking for a known attribute */
  289.         for (i = 0; attr_names[i].str; ++i) {
  290.             if (!av_strcasecmp(attr, attr_names[i].str)) {
  291.                 if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
  292.                     *(int *)((char *)data+
  293.                         attr_names[i].offset) = atoi(value);
  294.                 } else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
  295.                     *(char **)((char *)data+
  296.                         attr_names[i].offset) = av_strdup(value);
  297.             }
  298.         }
  299.     }
  300.     return 0;
  301. }
  302.  
  303. static int parse_sdp_line(AVFormatContext *s, int st_index,
  304.                           PayloadContext *data, const char *line)
  305. {
  306.     const char *p;
  307.  
  308.     if (st_index < 0)
  309.         return 0;
  310.  
  311.     if (av_strstart(line, "fmtp:", &p))
  312.         return ff_parse_fmtp(s, s->streams[st_index], data, p, parse_fmtp);
  313.  
  314.     return 0;
  315. }
  316.  
  317. RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = {
  318.     .enc_name           = "MP4V-ES",
  319.     .codec_type         = AVMEDIA_TYPE_VIDEO,
  320.     .codec_id           = AV_CODEC_ID_MPEG4,
  321.     .need_parsing       = AVSTREAM_PARSE_FULL,
  322.     .priv_data_size     = sizeof(PayloadContext),
  323.     .parse_sdp_a_line   = parse_sdp_line,
  324. };
  325.  
  326. RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = {
  327.     .enc_name           = "mpeg4-generic",
  328.     .codec_type         = AVMEDIA_TYPE_AUDIO,
  329.     .codec_id           = AV_CODEC_ID_AAC,
  330.     .priv_data_size     = sizeof(PayloadContext),
  331.     .parse_sdp_a_line   = parse_sdp_line,
  332.     .close              = close_context,
  333.     .parse_packet       = aac_parse_packet,
  334. };
  335.