Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * RTP JPEG-compressed Video Depacketizer, RFC 2435 | |
3 | * Copyright (c) 2012 Samuel Pitoiset | |
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 "avformat.h" | |
23 | #include "rtpdec.h" | |
24 | #include "rtpdec_formats.h" | |
25 | #include "libavutil/intreadwrite.h" | |
26 | #include "libavcodec/mjpeg.h" | |
27 | #include "libavcodec/bytestream.h" | |
28 | ||
29 | /** | |
30 | * RTP/JPEG specific private data. | |
31 | */ | |
32 | struct PayloadContext { | |
33 | AVIOContext *frame; ///< current frame buffer | |
34 | uint32_t timestamp; ///< current frame timestamp | |
35 | int hdr_size; ///< size of the current frame header | |
36 | uint8_t qtables[128][128]; | |
37 | uint8_t qtables_len[128]; | |
38 | }; | |
39 | ||
40 | static const uint8_t default_quantizers[128] = { | |
41 | /* luma table */ | |
42 | 16, 11, 12, 14, 12, 10, 16, 14, | |
43 | 13, 14, 18, 17, 16, 19, 24, 40, | |
44 | 26, 24, 22, 22, 24, 49, 35, 37, | |
45 | 29, 40, 58, 51, 61, 60, 57, 51, | |
46 | 56, 55, 64, 72, 92, 78, 64, 68, | |
47 | 87, 69, 55, 56, 80, 109, 81, 87, | |
48 | 95, 98, 103, 104, 103, 62, 77, 113, | |
49 | 121, 112, 100, 120, 92, 101, 103, 99, | |
50 | ||
51 | /* chroma table */ | |
52 | 17, 18, 18, 24, 21, 24, 47, 26, | |
53 | 26, 47, 99, 66, 56, 66, 99, 99, | |
54 | 99, 99, 99, 99, 99, 99, 99, 99, | |
55 | 99, 99, 99, 99, 99, 99, 99, 99, | |
56 | 99, 99, 99, 99, 99, 99, 99, 99, | |
57 | 99, 99, 99, 99, 99, 99, 99, 99, | |
58 | 99, 99, 99, 99, 99, 99, 99, 99, | |
59 | 99, 99, 99, 99, 99, 99, 99, 99 | |
60 | }; | |
61 | ||
62 | static PayloadContext *jpeg_new_context(void) | |
63 | { | |
64 | return av_mallocz(sizeof(PayloadContext)); | |
65 | } | |
66 | ||
67 | static inline void free_frame_if_needed(PayloadContext *jpeg) | |
68 | { | |
69 | if (jpeg->frame) { | |
70 | uint8_t *p; | |
71 | avio_close_dyn_buf(jpeg->frame, &p); | |
72 | av_free(p); | |
73 | jpeg->frame = NULL; | |
74 | } | |
75 | } | |
76 | ||
77 | static void jpeg_free_context(PayloadContext *jpeg) | |
78 | { | |
79 | free_frame_if_needed(jpeg); | |
80 | av_free(jpeg); | |
81 | } | |
82 | ||
83 | static int jpeg_create_huffman_table(PutByteContext *p, int table_class, | |
84 | int table_id, const uint8_t *bits_table, | |
85 | const uint8_t *value_table) | |
86 | { | |
87 | int i, n = 0; | |
88 | ||
89 | bytestream2_put_byte(p, table_class << 4 | table_id); | |
90 | ||
91 | for (i = 1; i <= 16; i++) { | |
92 | n += bits_table[i]; | |
93 | bytestream2_put_byte(p, bits_table[i]); | |
94 | } | |
95 | ||
96 | for (i = 0; i < n; i++) { | |
97 | bytestream2_put_byte(p, value_table[i]); | |
98 | } | |
99 | return n + 17; | |
100 | } | |
101 | ||
102 | static void jpeg_put_marker(PutByteContext *pbc, int code) | |
103 | { | |
104 | bytestream2_put_byte(pbc, 0xff); | |
105 | bytestream2_put_byte(pbc, code); | |
106 | } | |
107 | ||
108 | static int jpeg_create_header(uint8_t *buf, int size, uint32_t type, uint32_t w, | |
109 | uint32_t h, const uint8_t *qtable, int nb_qtable, | |
110 | int dri) | |
111 | { | |
112 | PutByteContext pbc; | |
113 | uint8_t *dht_size_ptr; | |
114 | int dht_size, i; | |
115 | ||
116 | bytestream2_init_writer(&pbc, buf, size); | |
117 | ||
118 | /* Convert from blocks to pixels. */ | |
119 | w <<= 3; | |
120 | h <<= 3; | |
121 | ||
122 | /* SOI */ | |
123 | jpeg_put_marker(&pbc, SOI); | |
124 | ||
125 | /* JFIF header */ | |
126 | jpeg_put_marker(&pbc, APP0); | |
127 | bytestream2_put_be16(&pbc, 16); | |
128 | bytestream2_put_buffer(&pbc, "JFIF", 5); | |
129 | bytestream2_put_be16(&pbc, 0x0201); | |
130 | bytestream2_put_byte(&pbc, 0); | |
131 | bytestream2_put_be16(&pbc, 1); | |
132 | bytestream2_put_be16(&pbc, 1); | |
133 | bytestream2_put_byte(&pbc, 0); | |
134 | bytestream2_put_byte(&pbc, 0); | |
135 | ||
136 | if (dri) { | |
137 | jpeg_put_marker(&pbc, DRI); | |
138 | bytestream2_put_be16(&pbc, 4); | |
139 | bytestream2_put_be16(&pbc, dri); | |
140 | } | |
141 | ||
142 | /* DQT */ | |
143 | jpeg_put_marker(&pbc, DQT); | |
144 | bytestream2_put_be16(&pbc, 2 + nb_qtable * (1 + 64)); | |
145 | ||
146 | for (i = 0; i < nb_qtable; i++) { | |
147 | bytestream2_put_byte(&pbc, i); | |
148 | ||
149 | /* Each table is an array of 64 values given in zig-zag | |
150 | * order, identical to the format used in a JFIF DQT | |
151 | * marker segment. */ | |
152 | bytestream2_put_buffer(&pbc, qtable + 64 * i, 64); | |
153 | } | |
154 | ||
155 | /* DHT */ | |
156 | jpeg_put_marker(&pbc, DHT); | |
157 | dht_size_ptr = pbc.buffer; | |
158 | bytestream2_put_be16(&pbc, 0); | |
159 | ||
160 | dht_size = 2; | |
161 | dht_size += jpeg_create_huffman_table(&pbc, 0, 0,avpriv_mjpeg_bits_dc_luminance, | |
162 | avpriv_mjpeg_val_dc); | |
163 | dht_size += jpeg_create_huffman_table(&pbc, 0, 1, avpriv_mjpeg_bits_dc_chrominance, | |
164 | avpriv_mjpeg_val_dc); | |
165 | dht_size += jpeg_create_huffman_table(&pbc, 1, 0, avpriv_mjpeg_bits_ac_luminance, | |
166 | avpriv_mjpeg_val_ac_luminance); | |
167 | dht_size += jpeg_create_huffman_table(&pbc, 1, 1, avpriv_mjpeg_bits_ac_chrominance, | |
168 | avpriv_mjpeg_val_ac_chrominance); | |
169 | AV_WB16(dht_size_ptr, dht_size); | |
170 | ||
171 | /* SOF0 */ | |
172 | jpeg_put_marker(&pbc, SOF0); | |
173 | bytestream2_put_be16(&pbc, 17); /* size */ | |
174 | bytestream2_put_byte(&pbc, 8); /* bits per component */ | |
175 | bytestream2_put_be16(&pbc, h); | |
176 | bytestream2_put_be16(&pbc, w); | |
177 | bytestream2_put_byte(&pbc, 3); /* number of components */ | |
178 | bytestream2_put_byte(&pbc, 1); /* component number */ | |
179 | bytestream2_put_byte(&pbc, (2 << 4) | (type ? 2 : 1)); /* hsample/vsample */ | |
180 | bytestream2_put_byte(&pbc, 0); /* matrix number */ | |
181 | bytestream2_put_byte(&pbc, 2); /* component number */ | |
182 | bytestream2_put_byte(&pbc, 1 << 4 | 1); /* hsample/vsample */ | |
183 | bytestream2_put_byte(&pbc, nb_qtable == 2 ? 1 : 0); /* matrix number */ | |
184 | bytestream2_put_byte(&pbc, 3); /* component number */ | |
185 | bytestream2_put_byte(&pbc, 1 << 4 | 1); /* hsample/vsample */ | |
186 | bytestream2_put_byte(&pbc, nb_qtable == 2 ? 1 : 0); /* matrix number */ | |
187 | ||
188 | /* SOS */ | |
189 | jpeg_put_marker(&pbc, SOS); | |
190 | bytestream2_put_be16(&pbc, 12); | |
191 | bytestream2_put_byte(&pbc, 3); | |
192 | bytestream2_put_byte(&pbc, 1); | |
193 | bytestream2_put_byte(&pbc, 0); | |
194 | bytestream2_put_byte(&pbc, 2); | |
195 | bytestream2_put_byte(&pbc, 17); | |
196 | bytestream2_put_byte(&pbc, 3); | |
197 | bytestream2_put_byte(&pbc, 17); | |
198 | bytestream2_put_byte(&pbc, 0); | |
199 | bytestream2_put_byte(&pbc, 63); | |
200 | bytestream2_put_byte(&pbc, 0); | |
201 | ||
202 | /* Return the length in bytes of the JPEG header. */ | |
203 | return bytestream2_tell_p(&pbc); | |
204 | } | |
205 | ||
206 | static void create_default_qtables(uint8_t *qtables, uint8_t q) | |
207 | { | |
208 | int factor = q; | |
209 | int i; | |
210 | ||
211 | factor = av_clip(q, 1, 99); | |
212 | ||
213 | if (q < 50) | |
214 | q = 5000 / factor; | |
215 | else | |
216 | q = 200 - factor * 2; | |
217 | ||
218 | for (i = 0; i < 128; i++) { | |
219 | int val = (default_quantizers[i] * q + 50) / 100; | |
220 | ||
221 | /* Limit the quantizers to 1 <= q <= 255. */ | |
222 | val = av_clip(val, 1, 255); | |
223 | qtables[i] = val; | |
224 | } | |
225 | } | |
226 | ||
227 | static int jpeg_parse_packet(AVFormatContext *ctx, PayloadContext *jpeg, | |
228 | AVStream *st, AVPacket *pkt, uint32_t *timestamp, | |
229 | const uint8_t *buf, int len, uint16_t seq, | |
230 | int flags) | |
231 | { | |
232 | uint8_t type, q, width, height; | |
233 | const uint8_t *qtables = NULL; | |
234 | uint16_t qtable_len; | |
235 | uint32_t off; | |
236 | int ret, dri = 0; | |
237 | ||
238 | if (len < 8) { | |
239 | av_log(ctx, AV_LOG_ERROR, "Too short RTP/JPEG packet.\n"); | |
240 | return AVERROR_INVALIDDATA; | |
241 | } | |
242 | ||
243 | /* Parse the main JPEG header. */ | |
244 | off = AV_RB24(buf + 1); /* fragment byte offset */ | |
245 | type = AV_RB8(buf + 4); /* id of jpeg decoder params */ | |
246 | q = AV_RB8(buf + 5); /* quantization factor (or table id) */ | |
247 | width = AV_RB8(buf + 6); /* frame width in 8 pixel blocks */ | |
248 | height = AV_RB8(buf + 7); /* frame height in 8 pixel blocks */ | |
249 | buf += 8; | |
250 | len -= 8; | |
251 | ||
252 | if (type & 0x40) { | |
253 | if (len < 4) { | |
254 | av_log(ctx, AV_LOG_ERROR, "Too short RTP/JPEG packet.\n"); | |
255 | return AVERROR_INVALIDDATA; | |
256 | } | |
257 | dri = AV_RB16(buf); | |
258 | buf += 4; | |
259 | len -= 4; | |
260 | type &= ~0x40; | |
261 | } | |
262 | /* Parse the restart marker header. */ | |
263 | if (type > 63) { | |
264 | av_log(ctx, AV_LOG_ERROR, | |
265 | "Unimplemented RTP/JPEG restart marker header.\n"); | |
266 | return AVERROR_PATCHWELCOME; | |
267 | } | |
268 | if (type > 1) { | |
269 | av_log(ctx, AV_LOG_ERROR, "Unimplemented RTP/JPEG type %d\n", type); | |
270 | return AVERROR_PATCHWELCOME; | |
271 | } | |
272 | ||
273 | /* Parse the quantization table header. */ | |
274 | if (off == 0) { | |
275 | /* Start of JPEG data packet. */ | |
276 | uint8_t new_qtables[128]; | |
277 | uint8_t hdr[1024]; | |
278 | ||
279 | if (q > 127) { | |
280 | uint8_t precision; | |
281 | if (len < 4) { | |
282 | av_log(ctx, AV_LOG_ERROR, "Too short RTP/JPEG packet.\n"); | |
283 | return AVERROR_INVALIDDATA; | |
284 | } | |
285 | ||
286 | /* The first byte is reserved for future use. */ | |
287 | precision = AV_RB8(buf + 1); /* size of coefficients */ | |
288 | qtable_len = AV_RB16(buf + 2); /* length in bytes */ | |
289 | buf += 4; | |
290 | len -= 4; | |
291 | ||
292 | if (precision) | |
293 | av_log(ctx, AV_LOG_WARNING, "Only 8-bit precision is supported.\n"); | |
294 | ||
295 | if (qtable_len > 0) { | |
296 | if (len < qtable_len) { | |
297 | av_log(ctx, AV_LOG_ERROR, "Too short RTP/JPEG packet.\n"); | |
298 | return AVERROR_INVALIDDATA; | |
299 | } | |
300 | qtables = buf; | |
301 | buf += qtable_len; | |
302 | len -= qtable_len; | |
303 | if (q < 255) { | |
304 | if (jpeg->qtables_len[q - 128] && | |
305 | (jpeg->qtables_len[q - 128] != qtable_len || | |
306 | memcmp(qtables, &jpeg->qtables[q - 128][0], qtable_len))) { | |
307 | av_log(ctx, AV_LOG_WARNING, | |
308 | "Quantization tables for q=%d changed\n", q); | |
309 | } else if (!jpeg->qtables_len[q - 128] && qtable_len <= 128) { | |
310 | memcpy(&jpeg->qtables[q - 128][0], qtables, | |
311 | qtable_len); | |
312 | jpeg->qtables_len[q - 128] = qtable_len; | |
313 | } | |
314 | } | |
315 | } else { | |
316 | if (q == 255) { | |
317 | av_log(ctx, AV_LOG_ERROR, | |
318 | "Invalid RTP/JPEG packet. Quantization tables not found.\n"); | |
319 | return AVERROR_INVALIDDATA; | |
320 | } | |
321 | if (!jpeg->qtables_len[q - 128]) { | |
322 | av_log(ctx, AV_LOG_ERROR, | |
323 | "No quantization tables known for q=%d yet.\n", q); | |
324 | return AVERROR_INVALIDDATA; | |
325 | } | |
326 | qtables = &jpeg->qtables[q - 128][0]; | |
327 | qtable_len = jpeg->qtables_len[q - 128]; | |
328 | } | |
329 | } else { /* q <= 127 */ | |
330 | if (q == 0 || q > 99) { | |
331 | av_log(ctx, AV_LOG_ERROR, "Reserved q value %d\n", q); | |
332 | return AVERROR_INVALIDDATA; | |
333 | } | |
334 | create_default_qtables(new_qtables, q); | |
335 | qtables = new_qtables; | |
336 | qtable_len = sizeof(new_qtables); | |
337 | } | |
338 | ||
339 | /* Skip the current frame in case of the end packet | |
340 | * has been lost somewhere. */ | |
341 | free_frame_if_needed(jpeg); | |
342 | ||
343 | if ((ret = avio_open_dyn_buf(&jpeg->frame)) < 0) | |
344 | return ret; | |
345 | jpeg->timestamp = *timestamp; | |
346 | ||
347 | /* Generate a frame and scan headers that can be prepended to the | |
348 | * RTP/JPEG data payload to produce a JPEG compressed image in | |
349 | * interchange format. */ | |
350 | jpeg->hdr_size = jpeg_create_header(hdr, sizeof(hdr), type, width, | |
351 | height, qtables, | |
352 | qtable_len / 64, dri); | |
353 | ||
354 | /* Copy JPEG header to frame buffer. */ | |
355 | avio_write(jpeg->frame, hdr, jpeg->hdr_size); | |
356 | } | |
357 | ||
358 | if (!jpeg->frame) { | |
359 | av_log(ctx, AV_LOG_ERROR, | |
360 | "Received packet without a start chunk; dropping frame.\n"); | |
361 | return AVERROR(EAGAIN); | |
362 | } | |
363 | ||
364 | if (jpeg->timestamp != *timestamp) { | |
365 | /* Skip the current frame if timestamp is incorrect. | |
366 | * A start packet has been lost somewhere. */ | |
367 | free_frame_if_needed(jpeg); | |
368 | av_log(ctx, AV_LOG_ERROR, "RTP timestamps don't match.\n"); | |
369 | return AVERROR_INVALIDDATA; | |
370 | } | |
371 | ||
372 | if (off != avio_tell(jpeg->frame) - jpeg->hdr_size) { | |
373 | av_log(ctx, AV_LOG_ERROR, | |
374 | "Missing packets; dropping frame.\n"); | |
375 | return AVERROR(EAGAIN); | |
376 | } | |
377 | ||
378 | /* Copy data to frame buffer. */ | |
379 | avio_write(jpeg->frame, buf, len); | |
380 | ||
381 | if (flags & RTP_FLAG_MARKER) { | |
382 | /* End of JPEG data packet. */ | |
383 | uint8_t buf[2] = { 0xff, EOI }; | |
384 | ||
385 | /* Put EOI marker. */ | |
386 | avio_write(jpeg->frame, buf, sizeof(buf)); | |
387 | ||
388 | /* Prepare the JPEG packet. */ | |
389 | if ((ret = ff_rtp_finalize_packet(pkt, &jpeg->frame, st->index)) < 0) { | |
390 | av_log(ctx, AV_LOG_ERROR, | |
391 | "Error occurred when getting frame buffer.\n"); | |
392 | return ret; | |
393 | } | |
394 | ||
395 | return 0; | |
396 | } | |
397 | ||
398 | return AVERROR(EAGAIN); | |
399 | } | |
400 | ||
401 | RTPDynamicProtocolHandler ff_jpeg_dynamic_handler = { | |
402 | .enc_name = "JPEG", | |
403 | .codec_type = AVMEDIA_TYPE_VIDEO, | |
404 | .codec_id = AV_CODEC_ID_MJPEG, | |
405 | .alloc = jpeg_new_context, | |
406 | .free = jpeg_free_context, | |
407 | .parse_packet = jpeg_parse_packet, | |
408 | .static_payload_id = 26, | |
409 | }; |