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