1 /* GStreamer H.263 Parser
2 * Copyright (C) <2010> Arun Raghavan <arun.raghavan@collabora.co.uk>
3 * Copyright (C) <2010> Edward Hervey <edward.hervey@collabora.co.uk>
4 * Copyright (C) <2010> Collabora Multimedia
5 * Copyright (C) <2010> Nokia Corporation
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library 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 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gst/base/gstbitreader.h>
28 #include "gsth263parse.h"
29
30 GST_DEBUG_CATEGORY_EXTERN (h263_parse_debug);
31 #define GST_CAT_DEFAULT h263_parse_debug
32
33 gboolean
gst_h263_parse_is_delta_unit(const H263Params * params)34 gst_h263_parse_is_delta_unit (const H263Params * params)
35 {
36 return (params->type == PICTURE_I);
37 }
38
39 /* Reads adapter and tries to populate params. 'fast' mode can be used to
40 * extract a subset of the data (for now, it quits once we have the picture
41 * type. */
42 GstFlowReturn
gst_h263_parse_get_params(H263Params * params,GstBuffer * buffer,gboolean fast,H263ParseState * state)43 gst_h263_parse_get_params (H263Params * params, GstBuffer * buffer,
44 gboolean fast, H263ParseState * state)
45 {
46 static const guint8 partable[6][2] = {
47 {1, 0},
48 {1, 1},
49 {12, 11},
50 {10, 11},
51 {16, 11},
52 {40, 33}
53 };
54
55 static const guint16 sizetable[8][2] = {
56 {0, 0},
57 {128, 96},
58 {176, 144},
59 {352, 288},
60 {704, 576},
61 {1408, 1152}
62 };
63
64 #ifndef GST_DISABLE_GST_DEBUG
65 static const gchar *source_format_name[] = {
66 "Forbidden",
67 "sub-QCIF",
68 "QCIF",
69 "CIF",
70 "4CIF",
71 "16CIF",
72 "Reserved",
73 "Extended PType"
74 };
75 #endif
76
77 GstBitReader br;
78 GstMapInfo map;
79 guint8 tr;
80 guint32 psc = 0, temp32;
81 guint8 temp8, pquant;
82 gboolean hasplusptype;
83
84 gst_buffer_map (buffer, &map, GST_MAP_READ);
85
86 /* FIXME: we can optimise a little by checking the value of available
87 * instead of calling using the bit reader's get_bits_* functions. */
88 gst_bit_reader_init (&br, map.data, map.size);
89
90 /* Default PCF is CIF PCF = 30000/1001 */
91 params->pcfnum = 30000;
92 params->pcfdenom = 1001;
93
94 GST_DEBUG ("NEW BUFFER");
95 if (!gst_bit_reader_get_bits_uint32 (&br, &psc, 22) ||
96 !gst_bit_reader_get_bits_uint8 (&br, &tr, 8) ||
97 !gst_bit_reader_get_bits_uint8 (&br, &temp8, 8))
98 goto more;
99
100 /* PSC : Picture Start Code 22 bits
101 * TR : Temporal Reference 8 bits
102 * PTYPE : Type Information variable
103 * bit 1 : Always "1"
104 * bit 2 : Always "0"
105 * bit 3 : Split Screen Indicator
106 * bit 4 : Document Camera Indicator
107 * bit 6-8 : Source Format
108 * if 111 : extended PTYPE is present */
109
110 /* 5.1.1 PSC : Picture Start Code (0x0020) 22 bits */
111 /* FIXME : Scan for the PSC instead of assuming it's always present
112 * and at the beginning. */
113 if (G_UNLIKELY (psc != 0x0020)) {
114 GST_WARNING ("Invalid PSC");
115 goto beach;
116 }
117
118 /* 5.1.2 TR : Temporal Reference 8 bits */
119 GST_DEBUG (" Temporal Reference : %d", tr);
120 params->temporal_ref = tr;
121
122 if ((temp8 >> 6) != 0x2) {
123 GST_WARNING ("Invalid PTYPE");
124 goto beach;
125 }
126
127 /* 5.1.3 PTYPE : Type Information variable length */
128 params->splitscreen = (temp8 & 0x20) == 0x20;
129 params->documentcamera = (temp8 & 0x10) == 0x10;
130 params->fullpicturefreezerelease = (temp8 & 0x08) == 0x08;
131 params->format = temp8 & 0x07;
132
133 hasplusptype = (temp8 & 0x07) == 0x07;
134
135 GST_DEBUG (" Split Screen Indicator : %s",
136 params->splitscreen ? "on" : "off");
137 GST_DEBUG (" Document camera indicator : %s",
138 params->documentcamera ? "on" : "off");
139 GST_DEBUG (" Full Picture Freeze Release : %s",
140 params->fullpicturefreezerelease ? "on" : "off");
141 GST_DEBUG (" Source format 0x%x (%s)", params->format,
142 source_format_name[params->format]);
143
144 if (!hasplusptype) {
145 guint8 ptype2;
146
147 /* Fill in width/height based on format */
148 params->width = sizetable[params->format][0];
149 params->height = sizetable[params->format][1];
150 GST_DEBUG (" Picture width x height: %d x %d",
151 params->width, params->height);
152
153 /* Default PAR is 12/11 */
154 params->parnum = 12;
155 params->pardenom = 11;
156
157 /* 5.1.3 : Remainder of PTYPE 5 bits */
158 if (!gst_bit_reader_get_bits_uint8 (&br, &ptype2, 5))
159 goto more;
160
161 params->type = (ptype2 & 0x10) == 0x10;
162 if ((ptype2 & 0x08) == 0x08)
163 params->features |= H263_OPTION_UMV_MODE;
164 if ((ptype2 & 0x04) == 0x04)
165 params->features |= H263_OPTION_SAC_MODE;
166 if ((ptype2 & 0x02) == 0x02)
167 params->features |= H263_OPTION_AP_MODE;
168 if ((ptype2 & 0x01) == 0x01) {
169 params->features |= H263_OPTION_PB_MODE;
170 params->type = PICTURE_PB;
171 }
172
173 GST_DEBUG (" Picture Coding Type : %s",
174 (ptype2 & 0x10) == 0x10 ? "INTER (P-picture)" : "INTRA (I-picture)");
175 GST_DEBUG (" Unrestricted Motion Vector mode (Annex D) : %s",
176 (ptype2 & 0x08) == 0x08 ? "on" : "off");
177 GST_DEBUG (" Syntax-basex Arithmetic Coding mode (Annex E) : %s",
178 (ptype2 & 0x04) == 0x04 ? "on" : "off");
179 GST_DEBUG (" Advanced Prediction mode (Annex F) : %s",
180 (ptype2 & 0x02) == 0x02 ? "on" : "off");
181 GST_DEBUG (" PB Frames mode (Annex G) : %s",
182 (ptype2 & 0x01) == 0x01 ? "on" : "off");
183
184 if (fast)
185 goto done;
186 }
187
188 if (hasplusptype) {
189 guint8 ufep;
190 guint8 cpm;
191 guint32 opptype = 0, mpptype = 0;
192
193 /* 5.1.4 PLUSPTYPE */
194
195 /* 5.1.4.1 UFEP : Update Full Extended PTYPE (3 bits) */
196 if (!gst_bit_reader_get_bits_uint8 (&br, &ufep, 3))
197 goto more;
198 GST_DEBUG (" UFEP 0x%x", ufep);
199
200 if (ufep == 1) {
201 /* 5.1.4.2 OPPTYPE : The Optional Part of PLUSPTYPE (OPPTYPE) (18 bits) */
202 if (!gst_bit_reader_get_bits_uint32 (&br, &opptype, 18))
203 goto more;
204
205 /* Last 4 bits are always "1000" */
206 if ((opptype & 0xf) != 0x8) {
207 GST_WARNING ("Corrupted OPTTYPE");
208 goto beach;
209 }
210 params->format = opptype >> 15;
211 params->custompcfpresent = (opptype & 0x4000) == 0x4000;
212 if (opptype & 0x2000)
213 params->features |= H263_OPTION_UMV_MODE;
214 if (opptype & 0x1000)
215 params->features |= H263_OPTION_SAC_MODE;
216 if (opptype & 0x0800)
217 params->features |= H263_OPTION_AP_MODE;
218 if (opptype & 0x0400)
219 params->features |= H263_OPTION_AIC_MODE;
220 if (opptype & 0x0200)
221 params->features |= H263_OPTION_DF_MODE;
222 if (opptype & 0x0100)
223 params->features |= H263_OPTION_SS_MODE;
224 if (opptype & 0x0080)
225 params->features |= H263_OPTION_RPS_MODE;
226 if (opptype & 0x0040)
227 params->features |= H263_OPTION_ISD_MODE;
228 if (opptype & 0x0020)
229 params->features |= H263_OPTION_AIV_MODE;
230 if (opptype & 0x0010)
231 params->features |= H263_OPTION_MQ_MODE;
232 /* Bit 15 is set to 1 to avoid looking like a start code */
233 if (opptype & 0x0004)
234 params->features |= H263_OPTION_ERPS_MODE;
235 if (opptype & 0x0002)
236 params->features |= H263_OPTION_DPS_MODE;
237 }
238
239 /* 5.1.4.3 MPPTYPE : The mandatory part of PLUSPTYPE (9 bits) */
240 if (!gst_bit_reader_get_bits_uint32 (&br, &mpptype, 9))
241 goto more;
242
243 /* Last 3 bits are always "001" */
244 if ((mpptype & 0x7) != 1) {
245 GST_WARNING ("Corrupted MPPTYPE");
246 goto beach;
247 }
248
249 params->type = mpptype >> 6;
250 GST_DEBUG (" Picture Coding Type : %d", params->type);
251
252 if (fast)
253 goto done;
254
255 if (mpptype & 0x2000)
256 params->features |= H263_OPTION_RPR_MODE;
257 if (mpptype & 0x1000)
258 params->features |= H263_OPTION_RRU_MODE;
259
260 /* 5.1.20 CPM : Continuous Presence Multipoint and Video Multiplex (1 bit) */
261 if (!gst_bit_reader_get_bits_uint8 (&br, &cpm, 1))
262 goto more;
263 GST_DEBUG (" Continuous Presence Multipoint and Video Multiplex : %d", cpm);
264
265 if (cpm) {
266 /* 5.1.21 PSBI : Picture Sub-Bitstream Indicator (2 bits) */
267 guint8 psbi;
268 if (!gst_bit_reader_get_bits_uint8 (&br, &psbi, 2))
269 goto more;
270 GST_DEBUG (" Picture Sub-Bitstream Indicator (PSBI):%d", psbi);
271 }
272
273 if (ufep == 1) {
274 if (params->format == 6) {
275 /* A fixed length codeword of 23 bits that is present only if the use of
276 * a custom picture format is signalled in PLUSPTYPE and UFEP is 001 */
277 guint32 cpfmt = 0;
278
279 /* 5.1.5 CPFMT : Custom Picture Format (23 bits) */
280 if (!gst_bit_reader_get_bits_uint32 (&br, &cpfmt, 23))
281 goto more;
282 if (!(cpfmt & 0x200)) {
283 GST_WARNING ("Corrupted CPFMT (0x%x)", cpfmt);
284 goto beach;
285 }
286 temp8 = cpfmt >> 19;
287 /* Bits 5-13: Picture Width Indication: Range [0, ... , 511];
288 * Number of pixels per line = (PWI + 1) * 4 */
289 params->width = (((cpfmt >> 10) & 0x1ff) + 1) * 4;
290 /* Bits 15-23 Picture Height Indication: Range [1, ... , 288];
291 * Number of lines = PHI * 4 */
292 params->height = (cpfmt & 0x1ff) * 4;
293
294 if (temp8 == 0xf) {
295 guint32 epar = 0;
296 /* 5.1.6 EPAR : Extended Pixel Aspect Ratio (16bits) */
297 if (!gst_bit_reader_get_bits_uint32 (&br, &epar, 16))
298 goto more;
299 params->parnum = epar >> 8;
300 params->pardenom = epar & 0xf;
301 } else {
302 params->parnum = partable[temp8][0];
303 params->pardenom = partable[temp8][1];
304 }
305 } else {
306 /* Fill in width/height based on format */
307 params->width = sizetable[params->format][0];
308 params->height = sizetable[params->format][1];
309 GST_DEBUG (" Picture width x height: %d x %d",
310 params->width, params->height);
311 /* Fill in default Pixel aspect ratios */
312 params->parnum = 12;
313 params->pardenom = 11;
314 }
315
316 if (params->custompcfpresent) {
317 /* 5.1.7 CPCFC : Custom Picture Clock Frequency Code (8bits) */
318 /* (we store this as a frame rate) */
319 if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 8))
320 goto more;
321 GST_DEBUG (" Custom PCF is present (%d)", (int) temp8);
322 params->pcfnum = gst_util_uint64_scale_int (1800000, 1, temp8 & 0x7f);
323 params->pcfdenom = (temp8 & 0x80) ? 1001 : 1000;
324 /* 5.1.8 ETR : Extended Temp8oral Reference (2bits) */
325 if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 2))
326 goto more;
327 params->temporal_ref |= temp8 << 8;
328 }
329
330 if (params->features & H263_OPTION_UMV_MODE) {
331 guint8 i;
332 /* 5.1.9 UUI : Unlimited Unrestricted Motion Vectors Indicator (variable length) */
333 if (!gst_bit_reader_get_bits_uint8 (&br, &i, 1))
334 goto more;
335 if (i == 0) {
336 if (!gst_bit_reader_get_bits_uint8 (&br, &i, 1))
337 goto more;
338 if (i != 1) {
339 GST_WARNING ("Corrupted UUI (0%u)", (guint) i);
340 goto beach;
341 }
342 params->uui = UUI_IS_01;
343 } else {
344 params->uui = UUI_IS_1;
345 }
346 }
347
348 if (params->features & H263_OPTION_SS_MODE) {
349 /* 5.1.10 SSS : Slice Structured Submode bits (2bits) */
350 if (!gst_bit_reader_get_bits_uint8 (&br, ¶ms->sss, 2))
351 goto more;
352 }
353
354 /* WE DO NOT SUPPORT optional Temporal, SNR, and Spatial Scalability mode */
355 /* 5.1.11 ELNUM : Enhancement Layer Number (4bits) */
356 /* 5.1.12 RLNUM : Reference Layer Number (4bits) */
357
358 if (params->features & H263_OPTION_RPS_MODE) {
359 /* 5.1.13 RPSMF : Reference Picture Selection Mode Flags (3bits) */
360 /* FIXME : We just swallow the bits */
361 if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 3))
362 goto more;
363
364 /* 5.1.14 TRPI : Temporal Reference for Prediction Indication (1bit) */
365 if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 1))
366 goto more;
367
368 if (temp8) {
369 /* 5.1.15 TRP : Temporal Reference for Prediction (10bits) */
370 /* FIXME : We just swallow the bits */
371 if (!gst_bit_reader_get_bits_uint32 (&br, &temp32, 10))
372 goto more;
373 }
374
375 /* 5.1.16 BCI Back-Channel message Indication (variable length) */
376 if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 1))
377 goto more;
378 if (temp8 == 1) {
379 /* 5.1.17 BCM Back-Channel Message (variable length) */
380 GST_ERROR ("We won't support Back-Channel Message (BCM)");
381 goto beach;
382 } else {
383 if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 1))
384 goto more;
385 if (temp8 != 1) {
386 GST_WARNING ("Corrupted BCI");
387 goto beach;
388 }
389 }
390 } /* END H263_OPTION_RPS_MODE */
391 }
392
393 GST_DEBUG (" Unrestricted Motion Vector mode (Annex D) : %s",
394 (params->features & H263_OPTION_UMV_MODE) ? "on" : "off");
395 GST_DEBUG (" Syntax-basex Arithmetic Coding mode (Annex E) : %s",
396 (params->features & H263_OPTION_SAC_MODE) ? "on" : "off");
397 GST_DEBUG (" Advanced Prediction mode (Annex F) : %s",
398 (params->features & H263_OPTION_AP_MODE) ? "on" : "off");
399 GST_DEBUG (" Advanced INTRA Coding mode (Annex I) : %s",
400 (params->features & H263_OPTION_AIC_MODE ? "on" : "off"));
401 GST_DEBUG (" Deblocking Filter mode (Annex J) : %s",
402 (params->features & H263_OPTION_DF_MODE ? "on" : "off"));
403 GST_DEBUG (" Slice Structured mode (Annex K) : %s",
404 (params->features & H263_OPTION_SS_MODE ? "on" : "off"));
405 GST_DEBUG (" Reference Picture Selection mode (Annex N) : %s",
406 (params->features & H263_OPTION_RPS_MODE ? "on" : "off"));
407 GST_DEBUG (" Independent Segment Decoding mode (Annex R) : %s",
408 (params->features & H263_OPTION_ISD_MODE ? "on" : "off"));
409 GST_DEBUG (" Alternative INTER VLC mode (Annex S) : %s",
410 (params->features & H263_OPTION_AIV_MODE ? "on" : "off"));
411 GST_DEBUG (" Modified Quantization mode (Annex T) : %s",
412 (params->features & H263_OPTION_MQ_MODE ? "on" : "off"));
413 GST_DEBUG (" Enhanced Reference Picture Selection mode (Annex U) : %s",
414 (params->features & H263_OPTION_ERPS_MODE ? "on" : "off"));
415 GST_DEBUG (" Enhanced Data Partitioned Slices mode (Annex V) : %s",
416 (params->features & H263_OPTION_DPS_MODE ? "on" : "off"));
417
418 /* END ufep == 1 */
419 /* WE DO NOT SUPPORT optional Reference Picture Resampling mode */
420 /* 5.1.18 RPRP : Reference Picture Resampling Parameters (variable length) */
421 }
422
423 /* END hasplusptype */
424 /* 5.1.19 PQUANT : Quantizer Information (5 bits) */
425 if (!gst_bit_reader_get_bits_uint8 (&br, &pquant, 5))
426 goto more;
427 GST_DEBUG (" PQUANT : 0x%x", pquant);
428
429 if (!hasplusptype) {
430 guint8 cpm;
431 /* 5.1.20 CPM : Continuous Presence Multipoint and Video Multiplex (1 bit) */
432 if (!gst_bit_reader_get_bits_uint8 (&br, &cpm, 1))
433 goto more;
434 GST_DEBUG (" Continuous Presence Multipoint and Video Multiplex : %d", cpm);
435
436 if (cpm) {
437 /* 5.1.21 PSBI : Picture Sub-Bitstream Indicator (2 bits) */
438 guint8 psbi;
439 if (!gst_bit_reader_get_bits_uint8 (&br, &psbi, 2))
440 goto more;
441 GST_DEBUG (" Picture Sub-Bitstream Indicator (PSBI):%d", psbi);
442 }
443 }
444
445 if (params->type & (PICTURE_PB | PICTURE_IMPROVED_PB)) {
446 /* 5.1.22 TRb : Temporal Reference for B-pictures in PB-frames (3/5bits) */
447 /* FIXME : We just swallow the bits */
448 if (!gst_bit_reader_get_bits_uint8 (&br, &temp8,
449 params->custompcfpresent ? 5 : 3))
450 goto more;
451
452 /* 5.1.23 DBQUANT : Quantization information for B-pictures in PB-frames (2bits) */
453 if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 2))
454 goto more;
455 }
456
457 GST_DEBUG (" Framerate defined by the stream is %d/%d",
458 params->pcfnum, params->pcfdenom);
459
460 /* We ignore the PEI and PSUPP - these may occur in any frame, and can be
461 * ignored by decoders that don't support them, except for bits of Annex W */
462
463 /* FIXME: Annex H (Forward Error Correction) requires that we poke into the
464 * stream data. */
465
466 /* FIXME: Annex P (Reference Picture Resampling) can be signaled implicitly
467 * as well as in the header. Should we set the field to false in caps if it
468 * is not specified by the header? */
469
470 /* FIXME: Annex U (Enhanced Reference Picture Selection) poses a problem - we
471 * have no means of specifying what sub-modes, if any, are used. */
472
473 done:
474 *state = GOT_HEADER;
475 more:
476 gst_buffer_unmap (buffer, &map);
477 return GST_FLOW_OK;
478
479 beach:
480 *state = PASSTHROUGH;
481 gst_buffer_unmap (buffer, &map);
482 return GST_FLOW_OK;
483 }
484
485 gint
gst_h263_parse_get_profile(const H263Params * params)486 gst_h263_parse_get_profile (const H263Params * params)
487 {
488 gboolean c, d, d1, d21, e, f, f2, g, h, i, j, k, k0, k1, l, m, n, o,
489 p, q, r, s, t, u, v, w;
490
491 /* FIXME: some parts of Annex C can be discovered, others can not */
492 c = FALSE;
493 d = (params->features & H263_OPTION_UMV_MODE) != 0;
494 /* d1: Annex D.1; d21: Annex D.2 with UUI=1; d22: Annex D.2 with UUI=01 */
495 d1 = (d && params->uui == UUI_ABSENT);
496 d21 = (d && params->uui == UUI_IS_1);
497 /* d22 = (d && params->uui == UUI_IS_01); */
498 e = (params->features & H263_OPTION_SAC_MODE) != 0;
499 /* f:Annex F.2 or F.3 may be used; f2: only Annex F.2 is used (we have no
500 * way of detecting this right now */
501 f = (params->features & H263_OPTION_AP_MODE) != 0;
502 f2 = FALSE;
503 g = (params->features & H263_OPTION_PB_MODE) != 0;
504 h = FALSE;
505 i = (params->features & H263_OPTION_AIC_MODE) != 0;
506 j = (params->features & H263_OPTION_DF_MODE) != 0;
507 k = (params->features & H263_OPTION_SS_MODE) != 0;
508 /* k0: Annex K without submodes; k1: Annex K with ASO; k2: Annex K with RS */
509 k0 = (k && params->sss == 0x0);
510 k1 = (k && params->sss == 0x2);
511 /* k2 = (k && params->sss == 0x1); */
512 l = FALSE;
513 m = (params->type == PICTURE_IMPROVED_PB);
514 n = (params->features & H263_OPTION_RPS_MODE) != 0;
515 o = FALSE;
516 p = FALSE;
517 q = (params->features & H263_OPTION_RRU_MODE) != 0;
518 r = (params->features & H263_OPTION_ISD_MODE) != 0;
519 s = (params->features & H263_OPTION_AIV_MODE) != 0;
520 t = (params->features & H263_OPTION_MQ_MODE) != 0;
521 u = (params->features & H263_OPTION_ERPS_MODE) != 0;
522 v = (params->features & H263_OPTION_DPS_MODE) != 0;
523 w = FALSE;
524
525 /* FIXME: The use of UUI in Annex D seems to be in contradiction with the
526 * profile definition in Annex X. Afaict, D.2 with UUI not present is not a
527 * meaningful state. */
528
529 /* FIXME: We have no way to distinguish between the use of section F.2 (four
530 * motion vectors per macroblock) and F.3 (overlapped block motion
531 * compensation), so we assume that they are either both present else neither
532 * is. This means if a profile supports only F.2 and not F.3, but we see that
533 * Advanced Prediction mode (Annex F) is used, we assume this profile does
534 * not apply. */
535
536 /* FIXME: We assume there is no error correction (Annex H) to avoid having to
537 * parse the stream to look for its existence. */
538
539 /* FIXME: Profiles 1 and 5-8 need the detection of Annex L.4 which can happen
540 * anywhere in the stream, so we just assume it doesn't exist and hope for
541 * the best. */
542
543 /* FIXME: Annex O support is TBD. */
544
545 /* FIXME: see note for Annex P elsewhere in this file. */
546
547 /* FIXME: Annex W.6.3.{8,11} suffer the same fate as Annex L.4 above. */
548
549 /* FIXME: We have no way of figuring out submodes when Annex U is used. Here
550 * we always assume no submode is used. */
551
552 if (!c && !d && !e && !f && !g && !h && !i && !j && !k && !l && !m && !n &&
553 !o && !p && !q && !r && !s && !t && !u && !v && !w)
554 return 0;
555 if (!c && (!d || d1) && !e && (!f || f2) && !g && !h && !k && !l && !m &&
556 !n && !o && !p && !q && !r && !s && !u && !v && !w)
557 return 1;
558 if (!c && (!d || d1) && !e && !g && !h && !i && !j && !k && !l && !m && !n &&
559 !o && !p && !q && !r && !s && !t && !u && !v && !w)
560 return 2;
561 if (!c && (!d || d1) && !e && (!f || f2) && !g && !h && (!k || k0) && !l &&
562 !m && !n && !o && !p && !q && !r && !s && !u && !v && !w)
563 return 3;
564 if (!c && (!d || d1) && !e && (!f || f2) && !g && !h && (!k || k0) && !l &&
565 !m && !n && !o && !p && !q && !r && !s && !u && !w)
566 return 4;
567 if (!c && (!d || d1 || d21) && !e && !g && !h && !k && !l && !m && !n &&
568 !o && !p && !q && !r && !s && !v && !w)
569 return 5;
570 if (!c && (!d || d1 || d21) && !e && !g && !h && (!k || k0 || k1) && !l &&
571 !m && !n && !o && !p && !q && !r && !s && !v && !w)
572 return 6;
573 if (!c && (!d || d1 || d21) && !e && !g && !h && !k && !l && !m && !n &&
574 !o && !p && !q && !r && !s && !v && !w)
575 return 7;
576 if (!c && (!d || d1 || d21) && !e && !g && !h && (!k || k0 || k1) && !l &&
577 !m && !n && !o && !p && !q && !r && !s && !v && !w)
578 /* FIXME: needs Annex O and Annex P support */
579 return 8;
580
581 return -1;
582 }
583
584 #define H263_PROFILE_NOT_0_2(profile) \
585 ((profile) != -1 && (profile) != 0 && (profile) != 2)
586
587 #define H263_FMT_UPTO_QCIF(params) \
588 ((params)->format == PICTURE_FMT_SUB_QCIF || \
589 (params)->format == PICTURE_FMT_QCIF)
590 #define H263_FMT_UPTO_CIF(params) \
591 ((params)->format == PICTURE_FMT_SUB_QCIF || \
592 (params)->format == PICTURE_FMT_QCIF || \
593 (params)->format == PICTURE_FMT_CIF)
594 #define H263_FMT_CUSTOM_UPTO_QCIF(params) \
595 ((params)->format == PICTURE_FMT_RESERVED1 && \
596 (params)->height <= 144 && \
597 (params)->width <= 176)
598 #define H263_FMT_CUSTOM_UPTO_CIF(params) \
599 ((params)->format == PICTURE_FMT_RESERVED1 && \
600 (params)->height <= 288 && \
601 (params)->width <= 352)
602
603 #define GST_FRACTION_LE(f1, f2) \
604 ((gst_value_compare (&(f1), &(f2)) == GST_VALUE_LESS_THAN) || \
605 (gst_value_compare (&(f1), &(f2)) == GST_VALUE_EQUAL))
606
607 gint
gst_h263_parse_get_level(const H263Params * params,gint profile,guint bitrate,gint fps_num,gint fps_denom)608 gst_h263_parse_get_level (const H263Params * params, gint profile,
609 guint bitrate, gint fps_num, gint fps_denom)
610 {
611 GValue fps15 = { 0, };
612 GValue fps30 = { 0, };
613 GValue fps50 = { 0, };
614 GValue fps60 = { 0, };
615 GValue fps = { 0, };
616
617 if (bitrate == 0) {
618 GST_DEBUG ("Can't calculate level since bitrate is unknown");
619 return -1;
620 }
621
622 g_value_init (&fps15, GST_TYPE_FRACTION);
623 g_value_init (&fps30, GST_TYPE_FRACTION);
624 g_value_init (&fps50, GST_TYPE_FRACTION);
625 g_value_init (&fps60, GST_TYPE_FRACTION);
626 g_value_init (&fps, GST_TYPE_FRACTION);
627
628 gst_value_set_fraction (&fps15, 15000, 1001);
629 gst_value_set_fraction (&fps30, 30000, 1001);
630 gst_value_set_fraction (&fps50, 50, 1);
631 gst_value_set_fraction (&fps60, 60000, 1001);
632
633 gst_value_set_fraction (&fps, fps_num, fps_denom);
634
635 /* Level 10 */
636 if (H263_FMT_UPTO_QCIF (params) && GST_FRACTION_LE (fps, fps15) &&
637 bitrate <= 64000)
638 return 10;
639
640 /* Level 20 */
641 if (((H263_FMT_UPTO_QCIF (params) && GST_FRACTION_LE (fps, fps30)) ||
642 (params->format == PICTURE_FMT_CIF && GST_FRACTION_LE (fps, fps15)))
643 && bitrate <= 128000)
644 return 20;
645
646 /* Level 30 */
647 if (H263_FMT_UPTO_CIF (params) && GST_FRACTION_LE (fps, fps30) &&
648 bitrate <= 384000)
649 return 30;
650
651 /* Level 40 */
652 if (H263_FMT_UPTO_CIF (params) && GST_FRACTION_LE (fps, fps30) &&
653 bitrate <= 2048000)
654 return 40;
655
656 /* Level 45 */
657 if ((H263_FMT_UPTO_QCIF (params) || (H263_FMT_CUSTOM_UPTO_QCIF (params) &&
658 H263_PROFILE_NOT_0_2 (profile))) &&
659 GST_FRACTION_LE (fps, fps15) &&
660 /* (!h263parse->custompcfpresent || H263_PROFILE_NOT_0_2(profile)) && */
661 bitrate <= 128000)
662 return 45;
663
664 /* Level 50 */
665 if ((H263_FMT_UPTO_CIF (params) || H263_FMT_CUSTOM_UPTO_CIF (params)) &&
666 (GST_FRACTION_LE (fps, fps50) ||
667 (params->width <= 352 && params->height <= 240 &&
668 GST_FRACTION_LE (fps, fps60))) && (bitrate <= 4096000))
669 return 50;
670
671 /* Level 60 */
672 if (((params->width <= 720 && params->height <= 288 &&
673 GST_FRACTION_LE (fps, fps50)) ||
674 (params->width <= 720 && params->height <= 240 &&
675 GST_FRACTION_LE (fps, fps60))) && (bitrate <= 8192000))
676 return 60;
677
678 /* Level 70 */
679 if (((params->width <= 720 && params->height <= 576 &&
680 GST_FRACTION_LE (fps, fps50)) ||
681 (params->width <= 720 && params->height <= 480 &&
682 GST_FRACTION_LE (fps, fps60))) && (bitrate <= 16384000))
683 return 70;
684
685 GST_DEBUG ("Weird - didn't match any profile!");
686 return -1;
687 }
688
689 void
gst_h263_parse_get_framerate(const H263Params * params,gint * num,gint * denom)690 gst_h263_parse_get_framerate (const H263Params * params, gint * num,
691 gint * denom)
692 {
693 *num = params->pcfnum;
694 *denom = params->pcfdenom;
695 }
696
697 void
gst_h263_parse_get_par(const H263Params * params,gint * num,gint * denom)698 gst_h263_parse_get_par (const H263Params * params, gint * num, gint * denom)
699 {
700 *num = params->parnum;
701 *denom = params->pardenom;
702 }
703