• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &params->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