annotate rtpdec_theora.c @ 5910:536e5527c1e0 libavformat

Define AVMediaType enum, and use it instead of enum CodecType, which is deprecated and will be dropped at the next major bump.
author stefano
date Tue, 30 Mar 2010 23:30:55 +0000
parents 38b67ae3f07d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5866
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
1 /*
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
2 * RTP Theora Protocol
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
3 * Copyright (c) 2010 Josh Allmann
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
4 *
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
5 * This file is part of FFmpeg.
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
6 *
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
11 *
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
15 * Lesser General Public License for more details.
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
16 *
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
20 */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
21
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
22 /**
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
23 * @file libavformat/rtpdec_theora.c
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
24 * @brief Theora / RTP Code
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
25 * @author Josh Allmann <joshua.allmann@gmail.com>
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
26 */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
27
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
28 #include "libavutil/avstring.h"
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
29 #include "libavutil/base64.h"
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
30 #include "libavcodec/bytestream.h"
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
31
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
32 #include <assert.h>
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
33
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
34 #include "rtpdec.h"
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
35 #include "rtpdec_theora.h"
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
36
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
37 /**
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
38 * RTP/Theora specific private data.
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
39 */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
40 struct PayloadContext {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
41 unsigned ident; ///< 24-bit stream configuration identifier
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
42 uint32_t timestamp;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
43 ByteIOContext* fragment; ///< buffer for split payloads
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
44 };
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
45
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
46 static PayloadContext *theora_new_context(void)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
47 {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
48 return av_mallocz(sizeof(PayloadContext));
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
49 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
50
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
51 static inline void free_fragment_if_needed(PayloadContext * data)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
52 {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
53 if (data->fragment) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
54 uint8_t* p;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
55 url_close_dyn_buf(data->fragment, &p);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
56 av_free(p);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
57 data->fragment = NULL;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
58 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
59 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
60
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
61 static void theora_free_context(PayloadContext * data)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
62 {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
63 free_fragment_if_needed(data);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
64 av_free(data);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
65 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
66
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
67 static int theora_handle_packet(AVFormatContext * ctx,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
68 PayloadContext * data,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
69 AVStream * st,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
70 AVPacket * pkt,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
71 uint32_t * timestamp,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
72 const uint8_t * buf, int len, int flags)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
73 {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
74
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
75 int ident, fragmented, tdt, num_pkts, pkt_len;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
76
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
77 if (len < 6) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
78 av_log(ctx, AV_LOG_ERROR, "Invalid %d byte packet\n", len);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
79 return AVERROR_INVALIDDATA;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
80 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
81
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
82 // read theora rtp headers
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
83 ident = AV_RB24(buf);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
84 fragmented = buf[3] >> 6;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
85 tdt = (buf[3] >> 4) & 3;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
86 num_pkts = buf[3] & 7;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
87 pkt_len = AV_RB16(buf + 4);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
88
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
89 if (pkt_len > len - 6) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
90 av_log(ctx, AV_LOG_ERROR,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
91 "Invalid packet length %d in %d byte packet\n", pkt_len,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
92 len);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
93 return AVERROR_INVALIDDATA;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
94 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
95
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
96 if (ident != data->ident) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
97 av_log(ctx, AV_LOG_ERROR,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
98 "Unimplemented Theora SDP configuration change detected\n");
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
99 return AVERROR_PATCHWELCOME;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
100 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
101
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
102 if (tdt) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
103 av_log(ctx, AV_LOG_ERROR,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
104 "Unimplemented RTP Theora packet settings (%d,%d,%d)\n",
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
105 fragmented, tdt, num_pkts);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
106 return AVERROR_PATCHWELCOME;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
107 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
108
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
109 buf += 6; // move past header bits
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
110 len -= 6;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
111
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
112 if (fragmented == 0) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
113 // whole frame(s)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
114 int i, data_len, write_len;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
115 buf -= 2;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
116 len += 2;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
117
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
118 // fast first pass to calculate total length
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
119 for (i = 0, data_len = 0; (i < num_pkts) && (len >= 2); i++) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
120 int off = data_len + (i << 1);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
121 pkt_len = AV_RB16(buf + off);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
122 data_len += pkt_len;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
123 len -= pkt_len + 2;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
124 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
125
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
126 if (len < 0 || i < num_pkts) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
127 av_log(ctx, AV_LOG_ERROR,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
128 "Bad packet: %d bytes left at frame %d of %d\n",
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
129 len, i, num_pkts);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
130 return AVERROR_INVALIDDATA;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
131 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
132
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
133 if (av_new_packet(pkt, data_len)) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
134 av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
135 return AVERROR_NOMEM;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
136 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
137 pkt->stream_index = st->index;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
138
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
139 // concatenate frames
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
140 for (i = 0, write_len = 0; write_len < data_len; i++) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
141 pkt_len = AV_RB16(buf);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
142 buf += 2;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
143 memcpy(pkt->data + write_len, buf, pkt_len);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
144 write_len += pkt_len;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
145 buf += pkt_len;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
146 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
147 assert(write_len == data_len);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
148
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
149 return 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
150
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
151 } else if (fragmented == 1) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
152 // start of theora data fragment
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
153 int res;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
154
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
155 // end packet has been lost somewhere, so drop buffered data
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
156 free_fragment_if_needed(data);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
157
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
158 if((res = url_open_dyn_buf(&data->fragment)) < 0)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
159 return res;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
160
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
161 put_buffer(data->fragment, buf, pkt_len);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
162 data->timestamp = *timestamp;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
163
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
164 } else {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
165 assert(fragmented < 4);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
166 if (data->timestamp != *timestamp) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
167 // skip if fragmented timestamp is incorrect;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
168 // a start packet has been lost somewhere
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
169 free_fragment_if_needed(data);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
170 av_log(ctx, AV_LOG_ERROR, "RTP timestamps don't match!\n");
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
171 return AVERROR_INVALIDDATA;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
172 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
173
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
174 // copy data to fragment buffer
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
175 put_buffer(data->fragment, buf, pkt_len);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
176
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
177 if (fragmented == 3) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
178 // end of theora data packet
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
179 uint8_t* theora_data;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
180 int frame_size = url_close_dyn_buf(data->fragment, &theora_data);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
181
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
182 if (frame_size < 0) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
183 av_log(ctx, AV_LOG_ERROR,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
184 "Error occurred when getting fragment buffer.");
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
185 return frame_size;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
186 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
187
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
188 if (av_new_packet(pkt, frame_size)) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
189 av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
190 return AVERROR_NOMEM;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
191 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
192
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
193 memcpy(pkt->data, theora_data, frame_size);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
194 pkt->stream_index = st->index;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
195
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
196 av_free(theora_data);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
197 data->fragment = NULL;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
198
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
199 return 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
200 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
201 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
202
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
203 return AVERROR(EAGAIN);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
204 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
205
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
206 /**
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
207 * Length encoding described in RFC5215 section 3.1.1.
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
208 */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
209 static int get_base128(const uint8_t ** buf, const uint8_t * buf_end)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
210 {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
211 int n = 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
212 for (; *buf < buf_end; ++*buf) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
213 n <<= 7;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
214 n += **buf & 0x7f;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
215 if (!(**buf & 0x80)) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
216 ++*buf;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
217 return n;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
218 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
219 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
220 return 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
221 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
222
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
223 /**
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
224 * Based off parse_packed_headers in Vorbis RTP
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
225 */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
226 static unsigned int
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
227 parse_packed_headers(const uint8_t * packed_headers,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
228 const uint8_t * packed_headers_end,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
229 AVCodecContext * codec, PayloadContext * theora_data)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
230 {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
231
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
232 unsigned num_packed, num_headers, length, length1, length2, extradata_alloc;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
233 uint8_t *ptr;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
234
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
235 if (packed_headers_end - packed_headers < 9) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
236 av_log(codec, AV_LOG_ERROR,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
237 "Invalid %d byte packed header.",
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
238 packed_headers_end - packed_headers);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
239 return AVERROR_INVALIDDATA;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
240 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
241
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
242 num_packed = bytestream_get_be32(&packed_headers);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
243 theora_data->ident = bytestream_get_be24(&packed_headers);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
244 length = bytestream_get_be16(&packed_headers);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
245 num_headers = get_base128(&packed_headers, packed_headers_end);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
246 length1 = get_base128(&packed_headers, packed_headers_end);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
247 length2 = get_base128(&packed_headers, packed_headers_end);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
248
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
249 if (num_packed != 1 || num_headers > 3) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
250 av_log(codec, AV_LOG_ERROR,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
251 "Unimplemented number of headers: %d packed headers, %d headers\n",
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
252 num_packed, num_headers);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
253 return AVERROR_PATCHWELCOME;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
254 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
255
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
256 if (packed_headers_end - packed_headers != length ||
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
257 length1 > length || length2 > length - length1) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
258 av_log(codec, AV_LOG_ERROR,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
259 "Bad packed header lengths (%d,%d,%d,%d)\n", length1,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
260 length2, packed_headers_end - packed_headers, length);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
261 return AVERROR_INVALIDDATA;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
262 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
263
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
264 /* allocate extra space:
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
265 * -- length/255 +2 for xiphlacing
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
266 * -- one for the '2' marker
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
267 * -- FF_INPUT_BUFFER_PADDING_SIZE required */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
268 extradata_alloc = length + length/255 + 3 + FF_INPUT_BUFFER_PADDING_SIZE;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
269
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
270 ptr = codec->extradata = av_malloc(extradata_alloc);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
271 if (!ptr) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
272 av_log(codec, AV_LOG_ERROR, "Out of memory\n");
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
273 return AVERROR_NOMEM;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
274 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
275 *ptr++ = 2;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
276 ptr += av_xiphlacing(ptr, length1);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
277 ptr += av_xiphlacing(ptr, length2);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
278 memcpy(ptr, packed_headers, length);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
279 ptr += length;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
280 codec->extradata_size = ptr - codec->extradata;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
281 // clear out remaining parts of the buffer
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
282 memset(ptr, 0, extradata_alloc - codec->extradata_size);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
283
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
284 return 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
285 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
286
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
287 static int theora_parse_fmtp_pair(AVCodecContext * codec,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
288 PayloadContext *theora_data,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
289 char *attr, char *value)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
290 {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
291 int result = 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
292
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
293 if (!strcmp(attr, "sampling")) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
294 return AVERROR_PATCHWELCOME;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
295 } else if (!strcmp(attr, "width")) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
296 /* This is an integer between 1 and 1048561
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
297 * and MUST be in multiples of 16. */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
298 codec->width = atoi(value);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
299 return 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
300 } else if (!strcmp(attr, "height")) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
301 /* This is an integer between 1 and 1048561
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
302 * and MUST be in multiples of 16. */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
303 codec->height = atoi(value);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
304 return 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
305 } else if (!strcmp(attr, "delivery-method")) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
306 /* Possible values are: inline, in_band, out_band/specific_name. */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
307 return AVERROR_PATCHWELCOME;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
308 } else if (!strcmp(attr, "configuration-uri")) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
309 /* NOTE: configuration-uri is supported only under 2 conditions:
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
310 *--after the delivery-method tag
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
311 * --with a delivery-method value of out_band */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
312 return AVERROR_PATCHWELCOME;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
313 } else if (!strcmp(attr, "configuration")) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
314 /* NOTE: configuration is supported only AFTER the delivery-method tag
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
315 * The configuration value is a base64 encoded packed header */
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
316 uint8_t *decoded_packet = NULL;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
317 int packet_size;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
318 size_t decoded_alloc = strlen(value) / 4 * 3 + 4;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
319
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
320 if (decoded_alloc <= INT_MAX) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
321 decoded_packet = av_malloc(decoded_alloc);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
322 if (decoded_packet) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
323 packet_size =
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
324 av_base64_decode(decoded_packet, value, decoded_alloc);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
325
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
326 result = parse_packed_headers
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
327 (decoded_packet, decoded_packet + packet_size, codec,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
328 theora_data);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
329 } else {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
330 av_log(codec, AV_LOG_ERROR,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
331 "Out of memory while decoding SDP configuration.\n");
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
332 result = AVERROR_NOMEM;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
333 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
334 } else {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
335 av_log(codec, AV_LOG_ERROR, "Packet too large\n");
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
336 result = AVERROR_INVALIDDATA;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
337 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
338 av_free(decoded_packet);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
339 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
340 return result;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
341 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
342
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
343 static int theora_parse_sdp_line(AVFormatContext *s, int st_index,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
344 PayloadContext *data, const char *line)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
345 {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
346 const char *p;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
347 char *value;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
348 char attr[25];
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
349 int value_size = strlen(line), attr_size = sizeof(attr), res = 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
350 AVCodecContext* codec = s->streams[st_index]->codec;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
351
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
352 assert(codec->id == CODEC_ID_THEORA);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
353 assert(data);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
354
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
355 if (!(value = av_malloc(value_size))) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
356 av_log(codec, AV_LOG_ERROR, "Out of memory\n");
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
357 return AVERROR_NOMEM;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
358 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
359
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
360 if (av_strstart(line, "fmtp:", &p)) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
361 // remove protocol identifier
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
362 while (*p && *p == ' ') p++; // strip spaces
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
363 while (*p && *p != ' ') p++; // eat protocol identifier
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
364 while (*p && *p == ' ') p++; // strip trailing spaces
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
365
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
366 while (ff_rtsp_next_attr_and_value(&p,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
367 attr, attr_size,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
368 value, value_size)) {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
369 res = theora_parse_fmtp_pair(codec, data, attr, value);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
370 if (res < 0 && res != AVERROR_PATCHWELCOME)
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
371 return res;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
372 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
373 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
374
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
375 av_free(value);
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
376 return 0;
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
377 }
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
378
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
379 RTPDynamicProtocolHandler ff_theora_dynamic_handler = {
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
380 .enc_name = "theora",
5910
536e5527c1e0 Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents: 5866
diff changeset
381 .codec_type = AVMEDIA_TYPE_VIDEO,
5866
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
382 .codec_id = CODEC_ID_THEORA,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
383 .parse_sdp_a_line = theora_parse_sdp_line,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
384 .open = theora_new_context,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
385 .close = theora_free_context,
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
386 .parse_packet = theora_handle_packet
38b67ae3f07d RTP depacketization of Theora
mstorsjo
parents:
diff changeset
387 };