Branch data Line data Source code
1 : : /* GStreamer
2 : : * Copyright (C) 2007 Jan Schmidt <thaytan@mad.scientist.com>
3 : : * Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
4 : : *
5 : : * This library is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Library General Public
7 : : * License as published by the Free Software Foundation; either
8 : : * version 2 of the License, or (at your option) any later version.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Library General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Library General Public
16 : : * License along with this library; if not, write to the
17 : : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : : * Boston, MA 02111-1307, USA.
19 : : */
20 : :
21 : : #include <gst/base/gstbitreader.h>
22 : : #include <string.h>
23 : :
24 : : #include "mpegutil.h"
25 : :
26 : : /* default intra quant matrix, in zig-zag order */
27 : : const guint8 default_intra_quantizer_matrix[64] = {
28 : : 8,
29 : : 16, 16,
30 : : 19, 16, 19,
31 : : 22, 22, 22, 22,
32 : : 22, 22, 26, 24, 26,
33 : : 27, 27, 27, 26, 26, 26,
34 : : 26, 27, 27, 27, 29, 29, 29,
35 : : 34, 34, 34, 29, 29, 29, 27, 27,
36 : : 29, 29, 32, 32, 34, 34, 37,
37 : : 38, 37, 35, 35, 34, 35,
38 : : 38, 38, 40, 40, 40,
39 : : 48, 48, 46, 46,
40 : : 56, 56, 58,
41 : : 69, 69,
42 : : 83
43 : : };
44 : :
45 : : const guint8 mpeg_zigzag_8x8[64] = {
46 : : 0, 1, 8, 16, 9, 2, 3, 10,
47 : : 17, 24, 32, 25, 18, 11, 4, 5,
48 : : 12, 19, 26, 33, 40, 48, 41, 34,
49 : : 27, 20, 13, 6, 7, 14, 21, 28,
50 : : 35, 42, 49, 56, 57, 50, 43, 36,
51 : : 29, 22, 15, 23, 30, 37, 44, 51,
52 : : 58, 59, 52, 45, 38, 31, 39, 46,
53 : : 53, 60, 61, 54, 47, 55, 62, 63
54 : : };
55 : :
56 : : #define READ_UINT8(reader, val, nbits) { \
57 : : if (!gst_bit_reader_get_bits_uint8 (reader, &val, nbits)) { \
58 : : GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
59 : : goto error; \
60 : : } \
61 : : }
62 : :
63 : : #define READ_UINT16(reader, val, nbits) { \
64 : : if (!gst_bit_reader_get_bits_uint16 (reader, &val, nbits)) { \
65 : : GST_WARNING ("failed to read uint16, nbits: %d", nbits); \
66 : : goto error; \
67 : : } \
68 : : }
69 : :
70 : : #define READ_UINT32(reader, val, nbits) { \
71 : : if (!gst_bit_reader_get_bits_uint32 (reader, &val, nbits)) { \
72 : : GST_WARNING ("failed to read uint32, nbits: %d", nbits); \
73 : : goto error; \
74 : : } \
75 : : }
76 : :
77 : : #define READ_UINT64(reader, val, nbits) { \
78 : : if (!gst_bit_reader_get_bits_uint64 (reader, &val, nbits)) { \
79 : : GST_WARNING ("failed to read uint32, nbits: %d", nbits); \
80 : : goto error; \
81 : : } \
82 : : }
83 : :
84 : : static void
85 : 0 : set_fps_from_code (MPEGSeqHdr * hdr, guint8 fps_code)
86 : : {
87 : 0 : const gint framerates[][2] = {
88 : : {30, 1}, {24000, 1001}, {24, 1}, {25, 1},
89 : : {30000, 1001}, {30, 1}, {50, 1}, {60000, 1001},
90 : : {60, 1}, {30, 1}
91 : : };
92 : :
93 [ # # ]: 0 : if (fps_code < 10) {
94 : 0 : hdr->fps_n = framerates[fps_code][0];
95 : 0 : hdr->fps_d = framerates[fps_code][1];
96 : : } else {
97 : : /* Force a valid framerate */
98 : 0 : hdr->fps_n = 30000;
99 : 0 : hdr->fps_d = 1001;
100 : : }
101 : 0 : }
102 : :
103 : : /* Set the Pixel Aspect Ratio in our hdr from a DAR code in the data */
104 : : static void
105 : 0 : set_par_from_dar (MPEGSeqHdr * hdr, guint8 asr_code)
106 : : {
107 : : /* Pixel_width = DAR_width * display_vertical_size */
108 : : /* Pixel_height = DAR_height * display_horizontal_size */
109 [ # # # # ]: 0 : switch (asr_code) {
110 : : case 0x02: /* 3:4 DAR = 4:3 pixels */
111 : 0 : hdr->par_w = 4 * hdr->height;
112 : 0 : hdr->par_h = 3 * hdr->width;
113 : 0 : break;
114 : : case 0x03: /* 9:16 DAR */
115 : 0 : hdr->par_w = 16 * hdr->height;
116 : 0 : hdr->par_h = 9 * hdr->width;
117 : 0 : break;
118 : : case 0x04: /* 1:2.21 DAR */
119 : 0 : hdr->par_w = 221 * hdr->height;
120 : 0 : hdr->par_h = 100 * hdr->width;
121 : 0 : break;
122 : : case 0x01: /* Square pixels */
123 : : default:
124 : 0 : hdr->par_w = hdr->par_h = 1;
125 : 0 : break;
126 : : }
127 : 0 : }
128 : :
129 : : gboolean
130 : 0 : mpeg_util_parse_sequence_extension (MPEGSeqExtHdr * hdr, GstBuffer * buffer)
131 : : {
132 : 0 : GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);;
133 : :
134 : : /* skip sync word */
135 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 8 * 4))
136 : 0 : return FALSE;
137 : :
138 : : /* skip extension code */
139 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 4))
140 : 0 : return FALSE;
141 : :
142 : : /* skip profile and level escape bit */
143 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 1))
144 : 0 : return FALSE;
145 : :
146 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->profile, 3);
147 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->level, 4);
148 : :
149 : : /* progressive */
150 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->progressive, 1);
151 : :
152 : : /* chroma format */
153 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->chroma_format, 2);
154 : :
155 : : /* resolution extension */
156 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->horiz_size_ext, 2);
157 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->vert_size_ext, 2);
158 : :
159 [ # # ][ # # ]: 0 : READ_UINT16 (&reader, hdr->bitrate_ext, 12);
160 : :
161 : : /* skip to framerate extension */
162 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 9))
163 : 0 : return FALSE;
164 : :
165 : : /* framerate extension */
166 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->fps_n_ext, 2);
167 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->fps_d_ext, 2);
168 : :
169 : 0 : return TRUE;
170 : :
171 : : error:
172 [ # # ]: 0 : GST_WARNING ("error parsing \"Sequence Extension\"");
173 : 0 : return FALSE;
174 : : }
175 : :
176 : : gboolean
177 : 0 : mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, GstBuffer * buffer)
178 : : {
179 : 0 : GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
180 : : guint8 dar_idx, par_idx;
181 : : guint8 load_intra_flag, load_non_intra_flag;
182 : :
183 : : /* skip sync word */
184 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 8 * 4))
185 : 0 : return FALSE;
186 : :
187 : : /* resolution */
188 [ # # ][ # # ]: 0 : READ_UINT16 (&reader, hdr->width, 12);
189 [ # # ][ # # ]: 0 : READ_UINT16 (&reader, hdr->height, 12);
190 : :
191 : : /* aspect ratio */
192 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, dar_idx, 4);
193 : 0 : set_par_from_dar (hdr, dar_idx);
194 : :
195 : : /* framerate */
196 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, par_idx, 4);
197 : 0 : set_fps_from_code (hdr, par_idx);
198 : :
199 : : /* bitrate */
200 [ # # ][ # # ]: 0 : READ_UINT32 (&reader, hdr->bitrate, 18);
201 : :
202 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 1))
203 : 0 : return FALSE;
204 : :
205 : : /* VBV buffer size */
206 [ # # ][ # # ]: 0 : READ_UINT16 (&reader, hdr->vbv_buffer, 10);
207 : :
208 : : /* constrained parameters flag */
209 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->constrained_parameters_flag, 1);
210 : :
211 : : /* intra quantizer matrix */
212 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, load_intra_flag, 1);
213 [ # # ]: 0 : if (load_intra_flag) {
214 : : gint i;
215 [ # # ]: 0 : for (i = 0; i < 64; i++)
216 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->intra_quantizer_matrix[mpeg_zigzag_8x8[i]], 8);
217 : : } else
218 : 0 : memcpy (hdr->intra_quantizer_matrix, default_intra_quantizer_matrix, 64);
219 : :
220 : : /* non intra quantizer matrix */
221 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, load_non_intra_flag, 1);
222 [ # # ]: 0 : if (load_non_intra_flag) {
223 : : gint i;
224 [ # # ]: 0 : for (i = 0; i < 64; i++)
225 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->non_intra_quantizer_matrix[mpeg_zigzag_8x8[i]],
226 : : 8);
227 : : } else
228 : 0 : memset (hdr->non_intra_quantizer_matrix, 16, 64);
229 : :
230 : 0 : return TRUE;
231 : :
232 : : error:
233 [ # # ]: 0 : GST_WARNING ("error parsing \"Sequence Header\"");
234 : 0 : return FALSE;
235 : : }
236 : :
237 : : gboolean
238 : 0 : mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, GstBuffer * buffer)
239 : : {
240 : 0 : GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
241 : :
242 : : /* skip sync word */
243 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 8 * 4))
244 : 0 : return FALSE;
245 : :
246 : : /* temperal sequence number */
247 [ # # ]: 0 : if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->tsn, 10))
248 : 0 : return FALSE;
249 : :
250 : : /* frame type */
251 [ # # ]: 0 : if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->pic_type, 3))
252 : 0 : return FALSE;
253 : :
254 [ # # ][ # # ]: 0 : if (hdr->pic_type == 0 || hdr->pic_type > 4)
255 : 0 : return FALSE; /* Corrupted picture packet */
256 : :
257 : : /* VBV delay */
258 [ # # ]: 0 : if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->vbv_delay, 16))
259 : 0 : return FALSE;
260 : :
261 [ # # ][ # # ]: 0 : if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) {
262 : :
263 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->full_pel_forward_vector, 1);
264 : :
265 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->f_code[0][0], 3);
266 : 0 : hdr->f_code[0][1] = hdr->f_code[0][0];
267 : : } else {
268 : 0 : hdr->full_pel_forward_vector = 0;
269 : 0 : hdr->f_code[0][0] = hdr->f_code[0][1] = 0;
270 : : }
271 : :
272 [ # # ]: 0 : if (hdr->pic_type == B_FRAME) {
273 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->full_pel_backward_vector, 1);
274 : :
275 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, hdr->f_code[1][0], 3);
276 : 0 : hdr->f_code[1][1] = hdr->f_code[1][0];
277 : : } else {
278 : 0 : hdr->full_pel_backward_vector = 0;
279 : 0 : hdr->f_code[1][0] = hdr->f_code[1][1] = 0;
280 : : }
281 : :
282 : 0 : return TRUE;
283 : :
284 : : error:
285 [ # # ]: 0 : GST_WARNING ("error parsing \"Picture Header\"");
286 : 0 : return FALSE;
287 : : }
288 : :
289 : : gboolean
290 : 0 : mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext,
291 : : GstBuffer * buffer)
292 : : {
293 : 0 : GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
294 : :
295 : : /* skip sync word */
296 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 8 * 4))
297 : 0 : return FALSE;
298 : :
299 : : /* skip extension code */
300 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 4))
301 : 0 : return FALSE;
302 : :
303 : : /* f_code */
304 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->f_code[0][0], 4);
305 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->f_code[0][1], 4);
306 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->f_code[1][0], 4);
307 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->f_code[1][1], 4);
308 : :
309 : : /* intra DC precision */
310 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->intra_dc_precision, 2);
311 : :
312 : : /* picture structure */
313 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->picture_structure, 2);
314 : :
315 : : /* top field first */
316 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->top_field_first, 1);
317 : :
318 : : /* frame pred frame dct */
319 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->frame_pred_frame_dct, 1);
320 : :
321 : : /* concealment motion vectors */
322 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->concealment_motion_vectors, 1);
323 : :
324 : : /* q scale type */
325 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->q_scale_type, 1);
326 : :
327 : : /* intra vlc format */
328 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->intra_vlc_format, 1);
329 : :
330 : : /* alternate scan */
331 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->alternate_scan, 1);
332 : :
333 : : /* repeat first field */
334 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->repeat_first_field, 1);
335 : :
336 : : /* chroma_420_type */
337 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->chroma_420_type, 1);
338 : :
339 : : /* progressive_frame */
340 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, ext->progressive_frame, 1);
341 : :
342 : 0 : return TRUE;
343 : :
344 : : error:
345 [ # # ]: 0 : GST_WARNING ("error parsing \"Picture Coding Extension\"");
346 : 0 : return FALSE;
347 : : }
348 : :
349 : : gboolean
350 : 0 : mpeg_util_parse_gop (MPEGGop * gop, GstBuffer * buffer)
351 : : {
352 : 0 : GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
353 : :
354 : : /* skip sync word */
355 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 8 * 4))
356 : 0 : return FALSE;
357 : :
358 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, gop->drop_frame_flag, 1);
359 : :
360 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, gop->hour, 5);
361 : :
362 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, gop->minute, 6);
363 : :
364 : : /* skip unused bit */
365 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 1))
366 : 0 : return FALSE;
367 : :
368 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, gop->second, 6);
369 : :
370 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, gop->frame, 6);
371 : :
372 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, gop->closed_gop, 1);
373 : :
374 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, gop->broken_gop, 1);
375 : :
376 : 0 : return TRUE;
377 : :
378 : : error:
379 [ # # ]: 0 : GST_WARNING ("error parsing \"GOP\"");
380 : 0 : return FALSE;
381 : : }
382 : :
383 : : gboolean
384 : 0 : mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, GstBuffer * buffer)
385 : : {
386 : 0 : GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
387 : : guint8 load_intra_flag, load_non_intra_flag;
388 : :
389 : : /* skip sync word */
390 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 8 * 4))
391 : 0 : return FALSE;
392 : :
393 : : /* skip extension code */
394 [ # # ]: 0 : if (!gst_bit_reader_skip (&reader, 4))
395 : 0 : return FALSE;
396 : :
397 : : /* intra quantizer matrix */
398 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, load_intra_flag, 1);
399 [ # # ]: 0 : if (load_intra_flag) {
400 : : gint i;
401 [ # # ]: 0 : for (i = 0; i < 64; i++) {
402 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, qm->intra_quantizer_matrix[mpeg_zigzag_8x8[i]], 8);
403 : : }
404 : : } else
405 : 0 : memcpy (qm->intra_quantizer_matrix, default_intra_quantizer_matrix, 64);
406 : :
407 : : /* non intra quantizer matrix */
408 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, load_non_intra_flag, 1);
409 [ # # ]: 0 : if (load_non_intra_flag) {
410 : : gint i;
411 [ # # ]: 0 : for (i = 0; i < 64; i++) {
412 [ # # ][ # # ]: 0 : READ_UINT8 (&reader, qm->non_intra_quantizer_matrix[mpeg_zigzag_8x8[i]],
413 : : 8);
414 : : }
415 : : } else
416 : 0 : memset (qm->non_intra_quantizer_matrix, 16, 64);
417 : :
418 : 0 : return TRUE;
419 : :
420 : : error:
421 [ # # ]: 0 : GST_WARNING ("error parsing \"Quant Matrix Extension\"");
422 : 0 : return FALSE;
423 : :
424 : : }
425 : :
426 : : #undef READ_UINT8
427 : : #undef READ_UINT16
428 : : #undef READ_UINT32
429 : : #undef READ_UINT64
|