]> git.sesse.net Git - ffmpeg/blob - libavformat/rtpdec_mpeg4.c
Merge commit 'fca9ca539c8c6e4fe0072486c7e0479a08a15e7c'
[ffmpeg] / libavformat / rtpdec_mpeg4.c
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 MPEG-4 / 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(AVCodecParameters *par, const char *value)
101 {
102     /* decode the hexa encoded parameter */
103     int len = ff_hex_to_data(NULL, value);
104     av_freep(&par->extradata);
105     if (ff_alloc_extradata(par, len))
106         return AVERROR(ENOMEM);
107     ff_hex_to_data(par->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     AVCodecParameters *par = stream->codecpar;
278     int res, i;
279
280     if (!strcmp(attr, "config")) {
281         res = parse_fmtp_config(par, value);
282
283         if (res < 0)
284             return res;
285     }
286
287     if (par->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 val = atoi(value);
293                     if (val > 32) {
294                         av_log(s, AV_LOG_ERROR,
295                                "The %s field size is invalid (%d)\n",
296                                attr, val);
297                         return AVERROR_INVALIDDATA;
298                     }
299                     *(int *)((char *)data+
300                         attr_names[i].offset) = val;
301                 } else if (attr_names[i].type == ATTR_NAME_TYPE_STR) {
302                     char *val = av_strdup(value);
303                     if (!val)
304                         return AVERROR(ENOMEM);
305                     *(char **)((char *)data+
306                         attr_names[i].offset) = val;
307                 }
308             }
309         }
310     }
311     return 0;
312 }
313
314 static int parse_sdp_line(AVFormatContext *s, int st_index,
315                           PayloadContext *data, const char *line)
316 {
317     const char *p;
318
319     if (st_index < 0)
320         return 0;
321
322     if (av_strstart(line, "fmtp:", &p))
323         return ff_parse_fmtp(s, s->streams[st_index], data, p, parse_fmtp);
324
325     return 0;
326 }
327
328 RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = {
329     .enc_name           = "MP4V-ES",
330     .codec_type         = AVMEDIA_TYPE_VIDEO,
331     .codec_id           = AV_CODEC_ID_MPEG4,
332     .need_parsing       = AVSTREAM_PARSE_FULL,
333     .priv_data_size     = sizeof(PayloadContext),
334     .parse_sdp_a_line   = parse_sdp_line,
335 };
336
337 RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = {
338     .enc_name           = "mpeg4-generic",
339     .codec_type         = AVMEDIA_TYPE_AUDIO,
340     .codec_id           = AV_CODEC_ID_AAC,
341     .priv_data_size     = sizeof(PayloadContext),
342     .parse_sdp_a_line   = parse_sdp_line,
343     .close              = close_context,
344     .parse_packet       = aac_parse_packet,
345 };