703 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			703 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* GStreamer H.263 Parser
 | |
|  * Copyright (C) <2010> Arun Raghavan <arun.raghavan@collabora.co.uk>
 | |
|  * Copyright (C) <2010> Edward Hervey <edward.hervey@collabora.co.uk>
 | |
|  * Copyright (C) <2010> Collabora Multimedia
 | |
|  * Copyright (C) <2010> Nokia Corporation
 | |
|  * 
 | |
|  * This library is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU Library General Public
 | |
|  * License as published by the Free Software Foundation; either
 | |
|  * version 2 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This library is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * Library General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Library General Public
 | |
|  * License along with this library; if not, write to the
 | |
|  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 | |
|  * Boston, MA 02110-1301, USA.
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include "config.h"
 | |
| #endif
 | |
| 
 | |
| #include <gst/base/gstbitreader.h>
 | |
| #include "gsth263parse.h"
 | |
| 
 | |
| GST_DEBUG_CATEGORY_EXTERN (h263_parse_debug);
 | |
| #define GST_CAT_DEFAULT h263_parse_debug
 | |
| 
 | |
| gboolean
 | |
| gst_h263_parse_is_delta_unit (const H263Params * params)
 | |
| {
 | |
|   return (params->type == PICTURE_I);
 | |
| }
 | |
| 
 | |
| /* Reads adapter and tries to populate params. 'fast' mode can be used to
 | |
|  * extract a subset of the data (for now, it quits once we have the picture
 | |
|  * type. */
 | |
| GstFlowReturn
 | |
| gst_h263_parse_get_params (H263Params * params, GstBuffer * buffer,
 | |
|     gboolean fast, H263ParseState * state)
 | |
| {
 | |
|   static const guint8 partable[6][2] = {
 | |
|     {1, 0},
 | |
|     {1, 1},
 | |
|     {12, 11},
 | |
|     {10, 11},
 | |
|     {16, 11},
 | |
|     {40, 33}
 | |
|   };
 | |
| 
 | |
|   static const guint16 sizetable[8][2] = {
 | |
|     {0, 0},
 | |
|     {128, 96},
 | |
|     {176, 144},
 | |
|     {352, 288},
 | |
|     {704, 576},
 | |
|     {1408, 1152}
 | |
|   };
 | |
| 
 | |
| #ifndef GST_DISABLE_GST_DEBUG
 | |
|   static const gchar *source_format_name[] = {
 | |
|     "Forbidden",
 | |
|     "sub-QCIF",
 | |
|     "QCIF",
 | |
|     "CIF",
 | |
|     "4CIF",
 | |
|     "16CIF",
 | |
|     "Reserved",
 | |
|     "Extended PType"
 | |
|   };
 | |
| #endif
 | |
| 
 | |
|   GstBitReader br;
 | |
|   GstMapInfo map;
 | |
|   guint8 tr;
 | |
|   guint32 psc = 0, temp32;
 | |
|   guint8 temp8, pquant;
 | |
|   gboolean hasplusptype;
 | |
| 
 | |
|   gst_buffer_map (buffer, &map, GST_MAP_READ);
 | |
| 
 | |
|   /* FIXME: we can optimise a little by checking the value of available
 | |
|    * instead of calling using the bit reader's get_bits_* functions. */
 | |
|   gst_bit_reader_init (&br, map.data, map.size);
 | |
| 
 | |
|   /* Default PCF is CIF PCF = 30000/1001 */
 | |
|   params->pcfnum = 30000;
 | |
|   params->pcfdenom = 1001;
 | |
| 
 | |
|   GST_DEBUG ("NEW BUFFER");
 | |
|   if (!gst_bit_reader_get_bits_uint32 (&br, &psc, 22) ||
 | |
|       !gst_bit_reader_get_bits_uint8 (&br, &tr, 8) ||
 | |
|       !gst_bit_reader_get_bits_uint8 (&br, &temp8, 8))
 | |
|     goto more;
 | |
| 
 | |
|   /* PSC   : Picture Start Code                 22 bits
 | |
|    * TR    : Temporal Reference                 8  bits
 | |
|    * PTYPE : Type Information                   variable
 | |
|    *  bit 1 : Always "1"
 | |
|    *  bit 2 : Always "0"
 | |
|    *  bit 3 : Split Screen Indicator
 | |
|    *  bit 4 : Document Camera Indicator
 | |
|    *  bit 6-8 : Source Format
 | |
|    *            if 111 : extended PTYPE is present */
 | |
| 
 | |
|   /* 5.1.1 PSC : Picture Start Code (0x0020)    22 bits */
 | |
|   /* FIXME : Scan for the PSC instead of assuming it's always present
 | |
|    * and at the beginning. */
 | |
|   if (G_UNLIKELY (psc != 0x0020)) {
 | |
|     GST_WARNING ("Invalid PSC");
 | |
|     goto beach;
 | |
|   }
 | |
| 
 | |
|   /* 5.1.2 TR : Temporal Reference              8 bits */
 | |
|   GST_DEBUG (" Temporal Reference : %d", tr);
 | |
|   params->temporal_ref = tr;
 | |
| 
 | |
|   if ((temp8 >> 6) != 0x2) {
 | |
|     GST_WARNING ("Invalid PTYPE");
 | |
|     goto beach;
 | |
|   }
 | |
| 
 | |
|   /* 5.1.3 PTYPE : Type Information             variable length */
 | |
|   params->splitscreen = (temp8 & 0x20) == 0x20;
 | |
|   params->documentcamera = (temp8 & 0x10) == 0x10;
 | |
|   params->fullpicturefreezerelease = (temp8 & 0x08) == 0x08;
 | |
|   params->format = temp8 & 0x07;
 | |
| 
 | |
|   hasplusptype = (temp8 & 0x07) == 0x07;
 | |
| 
 | |
|   GST_DEBUG (" Split Screen Indicator : %s",
 | |
|       params->splitscreen ? "on" : "off");
 | |
|   GST_DEBUG (" Document camera indicator : %s",
 | |
|       params->documentcamera ? "on" : "off");
 | |
|   GST_DEBUG (" Full Picture Freeze Release : %s",
 | |
|       params->fullpicturefreezerelease ? "on" : "off");
 | |
|   GST_DEBUG (" Source format 0x%x (%s)", params->format,
 | |
|       source_format_name[params->format]);
 | |
| 
 | |
|   if (!hasplusptype) {
 | |
|     guint8 ptype2;
 | |
| 
 | |
|     /* Fill in width/height based on format */
 | |
|     params->width = sizetable[params->format][0];
 | |
|     params->height = sizetable[params->format][1];
 | |
|     GST_DEBUG (" Picture width x height: %d x %d",
 | |
|         params->width, params->height);
 | |
| 
 | |
|     /* Default PAR is 12/11 */
 | |
|     params->parnum = 12;
 | |
|     params->pardenom = 11;
 | |
| 
 | |
|     /* 5.1.3 : Remainder of PTYPE                5 bits */
 | |
|     if (!gst_bit_reader_get_bits_uint8 (&br, &ptype2, 5))
 | |
|       goto more;
 | |
| 
 | |
|     params->type = (ptype2 & 0x10) == 0x10;
 | |
|     if ((ptype2 & 0x08) == 0x08)
 | |
|       params->features |= H263_OPTION_UMV_MODE;
 | |
|     if ((ptype2 & 0x04) == 0x04)
 | |
|       params->features |= H263_OPTION_SAC_MODE;
 | |
|     if ((ptype2 & 0x02) == 0x02)
 | |
|       params->features |= H263_OPTION_AP_MODE;
 | |
|     if ((ptype2 & 0x01) == 0x01) {
 | |
|       params->features |= H263_OPTION_PB_MODE;
 | |
|       params->type = PICTURE_PB;
 | |
|     }
 | |
| 
 | |
|     GST_DEBUG (" Picture Coding Type : %s",
 | |
|         (ptype2 & 0x10) == 0x10 ? "INTER (P-picture)" : "INTRA (I-picture)");
 | |
|     GST_DEBUG (" Unrestricted Motion Vector mode (Annex D) : %s",
 | |
|         (ptype2 & 0x08) == 0x08 ? "on" : "off");
 | |
|     GST_DEBUG (" Syntax-basex Arithmetic Coding mode (Annex E) : %s",
 | |
|         (ptype2 & 0x04) == 0x04 ? "on" : "off");
 | |
|     GST_DEBUG (" Advanced Prediction mode (Annex F) : %s",
 | |
|         (ptype2 & 0x02) == 0x02 ? "on" : "off");
 | |
|     GST_DEBUG (" PB Frames mode (Annex G) : %s",
 | |
|         (ptype2 & 0x01) == 0x01 ? "on" : "off");
 | |
| 
 | |
|     if (fast)
 | |
|       goto done;
 | |
|   }
 | |
| 
 | |
|   if (hasplusptype) {
 | |
|     guint8 ufep;
 | |
|     guint8 cpm;
 | |
|     guint32 opptype = 0, mpptype = 0;
 | |
| 
 | |
|     /* 5.1.4 PLUSPTYPE */
 | |
| 
 | |
|     /* 5.1.4.1 UFEP : Update Full Extended PTYPE (3 bits) */
 | |
|     if (!gst_bit_reader_get_bits_uint8 (&br, &ufep, 3))
 | |
|       goto more;
 | |
|     GST_DEBUG (" UFEP 0x%x", ufep);
 | |
| 
 | |
|     if (ufep == 1) {
 | |
|       /* 5.1.4.2 OPPTYPE : The Optional Part of PLUSPTYPE (OPPTYPE) (18 bits) */
 | |
|       if (!gst_bit_reader_get_bits_uint32 (&br, &opptype, 18))
 | |
|         goto more;
 | |
| 
 | |
|       /* Last 4 bits are always "1000" */
 | |
|       if ((opptype & 0xf) != 0x8) {
 | |
|         GST_WARNING ("Corrupted OPTTYPE");
 | |
|         goto beach;
 | |
|       }
 | |
|       params->format = opptype >> 15;
 | |
|       params->custompcfpresent = (opptype & 0x4000) == 0x4000;
 | |
|       if (opptype & 0x2000)
 | |
|         params->features |= H263_OPTION_UMV_MODE;
 | |
|       if (opptype & 0x1000)
 | |
|         params->features |= H263_OPTION_SAC_MODE;
 | |
|       if (opptype & 0x0800)
 | |
|         params->features |= H263_OPTION_AP_MODE;
 | |
|       if (opptype & 0x0400)
 | |
|         params->features |= H263_OPTION_AIC_MODE;
 | |
|       if (opptype & 0x0200)
 | |
|         params->features |= H263_OPTION_DF_MODE;
 | |
|       if (opptype & 0x0100)
 | |
|         params->features |= H263_OPTION_SS_MODE;
 | |
|       if (opptype & 0x0080)
 | |
|         params->features |= H263_OPTION_RPS_MODE;
 | |
|       if (opptype & 0x0040)
 | |
|         params->features |= H263_OPTION_ISD_MODE;
 | |
|       if (opptype & 0x0020)
 | |
|         params->features |= H263_OPTION_AIV_MODE;
 | |
|       if (opptype & 0x0010)
 | |
|         params->features |= H263_OPTION_MQ_MODE;
 | |
|       /* Bit 15 is set to 1 to avoid looking like a start code */
 | |
|       if (opptype & 0x0004)
 | |
|         params->features |= H263_OPTION_ERPS_MODE;
 | |
|       if (opptype & 0x0002)
 | |
|         params->features |= H263_OPTION_DPS_MODE;
 | |
|     }
 | |
| 
 | |
|     /* 5.1.4.3 MPPTYPE : The mandatory part of PLUSPTYPE (9 bits) */
 | |
|     if (!gst_bit_reader_get_bits_uint32 (&br, &mpptype, 9))
 | |
|       goto more;
 | |
| 
 | |
|     /* Last 3 bits are always "001" */
 | |
|     if ((mpptype & 0x7) != 1) {
 | |
|       GST_WARNING ("Corrupted MPPTYPE");
 | |
|       goto beach;
 | |
|     }
 | |
| 
 | |
|     params->type = mpptype >> 6;
 | |
|     GST_DEBUG (" Picture Coding Type : %d", params->type);
 | |
| 
 | |
|     if (fast)
 | |
|       goto done;
 | |
| 
 | |
|     if (mpptype & 0x2000)
 | |
|       params->features |= H263_OPTION_RPR_MODE;
 | |
|     if (mpptype & 0x1000)
 | |
|       params->features |= H263_OPTION_RRU_MODE;
 | |
| 
 | |
|     /* 5.1.20 CPM : Continuous Presence Multipoint and Video Multiplex (1 bit) */
 | |
|     if (!gst_bit_reader_get_bits_uint8 (&br, &cpm, 1))
 | |
|       goto more;
 | |
|     GST_DEBUG (" Continuous Presence Multipoint and Video Multiplex : %d", cpm);
 | |
| 
 | |
|     if (cpm) {
 | |
|       /* 5.1.21 PSBI : Picture Sub-Bitstream Indicator (2 bits) */
 | |
|       guint8 psbi;
 | |
|       if (!gst_bit_reader_get_bits_uint8 (&br, &psbi, 2))
 | |
|         goto more;
 | |
|       GST_DEBUG (" Picture Sub-Bitstream Indicator (PSBI):%d", psbi);
 | |
|     }
 | |
| 
 | |
|     if (ufep == 1) {
 | |
|       if (params->format == 6) {
 | |
|         /* A fixed length codeword of 23 bits that is present only if the use of
 | |
|          * a custom picture format is signalled in PLUSPTYPE and UFEP is 001 */
 | |
|         guint32 cpfmt = 0;
 | |
| 
 | |
|         /* 5.1.5 CPFMT : Custom Picture Format (23 bits) */
 | |
|         if (!gst_bit_reader_get_bits_uint32 (&br, &cpfmt, 23))
 | |
|           goto more;
 | |
|         if (!(cpfmt & 0x200)) {
 | |
|           GST_WARNING ("Corrupted CPFMT (0x%x)", cpfmt);
 | |
|           goto beach;
 | |
|         }
 | |
|         temp8 = cpfmt >> 19;
 | |
|         /* Bits 5-13: Picture Width Indication: Range [0, ... , 511];
 | |
|          * Number of pixels per line = (PWI + 1) * 4 */
 | |
|         params->width = (((cpfmt >> 10) & 0x1ff) + 1) * 4;
 | |
|         /* Bits 15-23  Picture Height Indication: Range [1, ... , 288];
 | |
|          * Number of lines = PHI * 4 */
 | |
|         params->height = (cpfmt & 0x1ff) * 4;
 | |
| 
 | |
|         if (temp8 == 0xf) {
 | |
|           guint32 epar = 0;
 | |
|           /* 5.1.6 EPAR : Extended Pixel Aspect Ratio (16bits) */
 | |
|           if (!gst_bit_reader_get_bits_uint32 (&br, &epar, 16))
 | |
|             goto more;
 | |
|           params->parnum = epar >> 8;
 | |
|           params->pardenom = epar & 0xf;
 | |
|         } else {
 | |
|           params->parnum = partable[temp8][0];
 | |
|           params->pardenom = partable[temp8][1];
 | |
|         }
 | |
|       } else {
 | |
|         /* Fill in width/height based on format */
 | |
|         params->width = sizetable[params->format][0];
 | |
|         params->height = sizetable[params->format][1];
 | |
|         GST_DEBUG (" Picture width x height: %d x %d",
 | |
|             params->width, params->height);
 | |
|         /* Fill in default Pixel aspect ratios */
 | |
|         params->parnum = 12;
 | |
|         params->pardenom = 11;
 | |
|       }
 | |
| 
 | |
|       if (params->custompcfpresent) {
 | |
|         /* 5.1.7 CPCFC : Custom Picture Clock Frequency Code (8bits) */
 | |
|         /* (we store this as a frame rate) */
 | |
|         if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 8))
 | |
|           goto more;
 | |
|         GST_DEBUG ("  Custom PCF is present (%d)", (int) temp8);
 | |
|         params->pcfnum = gst_util_uint64_scale_int (1800000, 1, temp8 & 0x7f);
 | |
|         params->pcfdenom = (temp8 & 0x80) ? 1001 : 1000;
 | |
|         /* 5.1.8 ETR : Extended Temp8oral Reference (2bits) */
 | |
|         if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 2))
 | |
|           goto more;
 | |
|         params->temporal_ref |= temp8 << 8;
 | |
|       }
 | |
| 
 | |
|       if (params->features & H263_OPTION_UMV_MODE) {
 | |
|         guint8 i;
 | |
|         /* 5.1.9 UUI : Unlimited Unrestricted Motion Vectors Indicator (variable length) */
 | |
|         if (!gst_bit_reader_get_bits_uint8 (&br, &i, 1))
 | |
|           goto more;
 | |
|         if (i == 0) {
 | |
|           if (!gst_bit_reader_get_bits_uint8 (&br, &i, 1))
 | |
|             goto more;
 | |
|           if (i != 1) {
 | |
|             GST_WARNING ("Corrupted UUI (0%u)", (guint) i);
 | |
|             goto beach;
 | |
|           }
 | |
|           params->uui = UUI_IS_01;
 | |
|         } else {
 | |
|           params->uui = UUI_IS_1;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (params->features & H263_OPTION_SS_MODE) {
 | |
|         /* 5.1.10 SSS : Slice Structured Submode bits (2bits) */
 | |
|         if (!gst_bit_reader_get_bits_uint8 (&br, ¶ms->sss, 2))
 | |
|           goto more;
 | |
|       }
 | |
| 
 | |
|       /* WE DO NOT SUPPORT optional Temporal, SNR, and Spatial Scalability mode */
 | |
|       /* 5.1.11 ELNUM : Enhancement Layer Number (4bits) */
 | |
|       /* 5.1.12 RLNUM : Reference Layer Number (4bits) */
 | |
| 
 | |
|       if (params->features & H263_OPTION_RPS_MODE) {
 | |
|         /* 5.1.13 RPSMF : Reference Picture Selection Mode Flags (3bits) */
 | |
|         /* FIXME : We just swallow the bits */
 | |
|         if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 3))
 | |
|           goto more;
 | |
| 
 | |
|         /* 5.1.14 TRPI : Temporal Reference for Prediction Indication (1bit) */
 | |
|         if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 1))
 | |
|           goto more;
 | |
| 
 | |
|         if (temp8) {
 | |
|           /* 5.1.15 TRP : Temporal Reference for Prediction (10bits) */
 | |
|           /* FIXME : We just swallow the bits */
 | |
|           if (!gst_bit_reader_get_bits_uint32 (&br, &temp32, 10))
 | |
|             goto more;
 | |
|         }
 | |
| 
 | |
|         /* 5.1.16 BCI Back-Channel message Indication (variable length) */
 | |
|         if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 1))
 | |
|           goto more;
 | |
|         if (temp8 == 1) {
 | |
|           /* 5.1.17 BCM Back-Channel Message (variable length) */
 | |
|           GST_ERROR ("We won't support Back-Channel Message (BCM)");
 | |
|           goto beach;
 | |
|         } else {
 | |
|           if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 1))
 | |
|             goto more;
 | |
|           if (temp8 != 1) {
 | |
|             GST_WARNING ("Corrupted BCI");
 | |
|             goto beach;
 | |
|           }
 | |
|         }
 | |
|       }                         /* END H263_OPTION_RPS_MODE */
 | |
|     }
 | |
| 
 | |
|     GST_DEBUG (" Unrestricted Motion Vector mode (Annex D) : %s",
 | |
|         (params->features & H263_OPTION_UMV_MODE) ? "on" : "off");
 | |
|     GST_DEBUG (" Syntax-basex Arithmetic Coding mode (Annex E) : %s",
 | |
|         (params->features & H263_OPTION_SAC_MODE) ? "on" : "off");
 | |
|     GST_DEBUG (" Advanced Prediction mode (Annex F) : %s",
 | |
|         (params->features & H263_OPTION_AP_MODE) ? "on" : "off");
 | |
|     GST_DEBUG (" Advanced INTRA Coding mode (Annex I) : %s",
 | |
|         (params->features & H263_OPTION_AIC_MODE ? "on" : "off"));
 | |
|     GST_DEBUG (" Deblocking Filter mode (Annex J) : %s",
 | |
|         (params->features & H263_OPTION_DF_MODE ? "on" : "off"));
 | |
|     GST_DEBUG (" Slice Structured mode (Annex K) : %s",
 | |
|         (params->features & H263_OPTION_SS_MODE ? "on" : "off"));
 | |
|     GST_DEBUG (" Reference Picture Selection mode (Annex N) : %s",
 | |
|         (params->features & H263_OPTION_RPS_MODE ? "on" : "off"));
 | |
|     GST_DEBUG (" Independent Segment Decoding mode (Annex R) : %s",
 | |
|         (params->features & H263_OPTION_ISD_MODE ? "on" : "off"));
 | |
|     GST_DEBUG (" Alternative INTER VLC mode (Annex S) : %s",
 | |
|         (params->features & H263_OPTION_AIV_MODE ? "on" : "off"));
 | |
|     GST_DEBUG (" Modified Quantization mode (Annex T) : %s",
 | |
|         (params->features & H263_OPTION_MQ_MODE ? "on" : "off"));
 | |
|     GST_DEBUG (" Enhanced Reference Picture Selection mode (Annex U) : %s",
 | |
|         (params->features & H263_OPTION_ERPS_MODE ? "on" : "off"));
 | |
|     GST_DEBUG (" Enhanced Data Partitioned Slices mode (Annex V) : %s",
 | |
|         (params->features & H263_OPTION_DPS_MODE ? "on" : "off"));
 | |
| 
 | |
|     /* END ufep == 1 */
 | |
|     /* WE DO NOT SUPPORT optional Reference Picture Resampling mode */
 | |
|     /* 5.1.18 RPRP : Reference Picture Resampling Parameters (variable length) */
 | |
|   }
 | |
| 
 | |
|   /* END hasplusptype */
 | |
|   /* 5.1.19 PQUANT : Quantizer Information (5 bits) */
 | |
|   if (!gst_bit_reader_get_bits_uint8 (&br, &pquant, 5))
 | |
|     goto more;
 | |
|   GST_DEBUG (" PQUANT : 0x%x", pquant);
 | |
| 
 | |
|   if (!hasplusptype) {
 | |
|     guint8 cpm;
 | |
|     /* 5.1.20 CPM : Continuous Presence Multipoint and Video Multiplex (1 bit) */
 | |
|     if (!gst_bit_reader_get_bits_uint8 (&br, &cpm, 1))
 | |
|       goto more;
 | |
|     GST_DEBUG (" Continuous Presence Multipoint and Video Multiplex : %d", cpm);
 | |
| 
 | |
|     if (cpm) {
 | |
|       /* 5.1.21 PSBI : Picture Sub-Bitstream Indicator (2 bits) */
 | |
|       guint8 psbi;
 | |
|       if (!gst_bit_reader_get_bits_uint8 (&br, &psbi, 2))
 | |
|         goto more;
 | |
|       GST_DEBUG (" Picture Sub-Bitstream Indicator (PSBI):%d", psbi);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (params->type & (PICTURE_PB | PICTURE_IMPROVED_PB)) {
 | |
|     /* 5.1.22 TRb : Temporal Reference for B-pictures in PB-frames (3/5bits) */
 | |
|     /* FIXME : We just swallow the bits */
 | |
|     if (!gst_bit_reader_get_bits_uint8 (&br, &temp8,
 | |
|             params->custompcfpresent ? 5 : 3))
 | |
|       goto more;
 | |
| 
 | |
|     /* 5.1.23 DBQUANT : Quantization information for B-pictures in PB-frames (2bits) */
 | |
|     if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 2))
 | |
|       goto more;
 | |
|   }
 | |
| 
 | |
|   GST_DEBUG (" Framerate defined by the stream is %d/%d",
 | |
|       params->pcfnum, params->pcfdenom);
 | |
| 
 | |
|   /* We ignore the PEI and PSUPP - these may occur in any frame, and can be
 | |
|    * ignored by decoders that don't support them, except for bits of Annex W */
 | |
| 
 | |
|   /* FIXME: Annex H (Forward Error Correction) requires that we poke into the
 | |
|    * stream data. */
 | |
| 
 | |
|   /* FIXME: Annex P (Reference Picture Resampling) can be signaled implicitly
 | |
|    * as well as in the header. Should we set the field to false in caps if it
 | |
|    * is not specified by the header? */
 | |
| 
 | |
|   /* FIXME: Annex U (Enhanced Reference Picture Selection) poses a problem - we
 | |
|    * have no means of specifying what sub-modes, if any, are used. */
 | |
| 
 | |
| done:
 | |
|   *state = GOT_HEADER;
 | |
| more:
 | |
|   gst_buffer_unmap (buffer, &map);
 | |
|   return GST_FLOW_OK;
 | |
| 
 | |
| beach:
 | |
|   *state = PASSTHROUGH;
 | |
|   gst_buffer_unmap (buffer, &map);
 | |
|   return GST_FLOW_OK;
 | |
| }
 | |
| 
 | |
| gint
 | |
| gst_h263_parse_get_profile (const H263Params * params)
 | |
| {
 | |
|   gboolean c, d, d1, d21, e, f, f2, g, h, i, j, k, k0, k1, l, m, n, o,
 | |
|       p, q, r, s, t, u, v, w;
 | |
| 
 | |
|   /* FIXME: some parts of Annex C can be discovered, others can not */
 | |
|   c = FALSE;
 | |
|   d = (params->features & H263_OPTION_UMV_MODE) != 0;
 | |
|   /* d1: Annex D.1; d21: Annex D.2 with UUI=1; d22: Annex D.2 with UUI=01 */
 | |
|   d1 = (d && params->uui == UUI_ABSENT);
 | |
|   d21 = (d && params->uui == UUI_IS_1);
 | |
|   /* d22 = (d && params->uui == UUI_IS_01); */
 | |
|   e = (params->features & H263_OPTION_SAC_MODE) != 0;
 | |
|   /* f:Annex  F.2 or F.3 may be used; f2: only Annex F.2 is used (we have no
 | |
|    * way of detecting this right now */
 | |
|   f = (params->features & H263_OPTION_AP_MODE) != 0;
 | |
|   f2 = FALSE;
 | |
|   g = (params->features & H263_OPTION_PB_MODE) != 0;
 | |
|   h = FALSE;
 | |
|   i = (params->features & H263_OPTION_AIC_MODE) != 0;
 | |
|   j = (params->features & H263_OPTION_DF_MODE) != 0;
 | |
|   k = (params->features & H263_OPTION_SS_MODE) != 0;
 | |
|   /* k0: Annex K without submodes; k1: Annex K with ASO; k2: Annex K with RS */
 | |
|   k0 = (k && params->sss == 0x0);
 | |
|   k1 = (k && params->sss == 0x2);
 | |
|   /* k2 = (k && params->sss == 0x1); */
 | |
|   l = FALSE;
 | |
|   m = (params->type == PICTURE_IMPROVED_PB);
 | |
|   n = (params->features & H263_OPTION_RPS_MODE) != 0;
 | |
|   o = FALSE;
 | |
|   p = FALSE;
 | |
|   q = (params->features & H263_OPTION_RRU_MODE) != 0;
 | |
|   r = (params->features & H263_OPTION_ISD_MODE) != 0;
 | |
|   s = (params->features & H263_OPTION_AIV_MODE) != 0;
 | |
|   t = (params->features & H263_OPTION_MQ_MODE) != 0;
 | |
|   u = (params->features & H263_OPTION_ERPS_MODE) != 0;
 | |
|   v = (params->features & H263_OPTION_DPS_MODE) != 0;
 | |
|   w = FALSE;
 | |
| 
 | |
|   /* FIXME: The use of UUI in Annex D seems to be in contradiction with the
 | |
|    * profile definition in Annex X. Afaict, D.2 with UUI not present is not a
 | |
|    * meaningful state. */
 | |
| 
 | |
|   /* FIXME: We have no way to distinguish between the use of section F.2 (four
 | |
|    * motion vectors per macroblock) and F.3 (overlapped block motion
 | |
|    * compensation), so we assume that they are either both present else neither
 | |
|    * is. This means if a profile supports only F.2 and not F.3, but we see that
 | |
|    * Advanced Prediction mode (Annex F) is used, we assume this profile does
 | |
|    * not apply. */
 | |
| 
 | |
|   /* FIXME: We assume there is no error correction (Annex H) to avoid having to
 | |
|    * parse the stream to look for its existence. */
 | |
| 
 | |
|   /* FIXME: Profiles 1 and 5-8 need the detection of Annex L.4 which can happen
 | |
|    * anywhere in the stream, so we just assume it doesn't exist and hope for
 | |
|    * the best. */
 | |
| 
 | |
|   /* FIXME: Annex O support is TBD. */
 | |
| 
 | |
|   /* FIXME: see note for Annex P elsewhere in this file. */
 | |
| 
 | |
|   /* FIXME: Annex W.6.3.{8,11} suffer the same fate as Annex L.4 above. */
 | |
| 
 | |
|   /* FIXME: We have no way of figuring out submodes when Annex U is used. Here
 | |
|    * we always assume no submode is used. */
 | |
| 
 | |
|   if (!c && !d && !e && !f && !g && !h && !i && !j && !k && !l && !m && !n &&
 | |
|       !o && !p && !q && !r && !s && !t && !u && !v && !w)
 | |
|     return 0;
 | |
|   if (!c && (!d || d1) && !e && (!f || f2) && !g && !h && !k && !l && !m &&
 | |
|       !n && !o && !p && !q && !r && !s && !u && !v && !w)
 | |
|     return 1;
 | |
|   if (!c && (!d || d1) && !e && !g && !h && !i && !j && !k && !l && !m && !n &&
 | |
|       !o && !p && !q && !r && !s && !t && !u && !v && !w)
 | |
|     return 2;
 | |
|   if (!c && (!d || d1) && !e && (!f || f2) && !g && !h && (!k || k0) && !l &&
 | |
|       !m && !n && !o && !p && !q && !r && !s && !u && !v && !w)
 | |
|     return 3;
 | |
|   if (!c && (!d || d1) && !e && (!f || f2) && !g && !h && (!k || k0) && !l &&
 | |
|       !m && !n && !o && !p && !q && !r && !s && !u && !w)
 | |
|     return 4;
 | |
|   if (!c && (!d || d1 || d21) && !e && !g && !h && !k && !l && !m && !n &&
 | |
|       !o && !p && !q && !r && !s && !v && !w)
 | |
|     return 5;
 | |
|   if (!c && (!d || d1 || d21) && !e && !g && !h && (!k || k0 || k1) && !l &&
 | |
|       !m && !n && !o && !p && !q && !r && !s && !v && !w)
 | |
|     return 6;
 | |
|   if (!c && (!d || d1 || d21) && !e && !g && !h && !k && !l && !m && !n &&
 | |
|       !o && !p && !q && !r && !s && !v && !w)
 | |
|     return 7;
 | |
|   if (!c && (!d || d1 || d21) && !e && !g && !h && (!k || k0 || k1) && !l &&
 | |
|       !m && !n && !o && !p && !q && !r && !s && !v && !w)
 | |
|     /* FIXME: needs Annex O and Annex P support */
 | |
|     return 8;
 | |
| 
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| #define H263_PROFILE_NOT_0_2(profile) \
 | |
|   ((profile) != -1 && (profile) != 0 && (profile) != 2)
 | |
| 
 | |
| #define H263_FMT_UPTO_QCIF(params) \
 | |
|   ((params)->format == PICTURE_FMT_SUB_QCIF || \
 | |
|    (params)->format == PICTURE_FMT_QCIF)
 | |
| #define H263_FMT_UPTO_CIF(params) \
 | |
|   ((params)->format == PICTURE_FMT_SUB_QCIF || \
 | |
|    (params)->format == PICTURE_FMT_QCIF || \
 | |
|    (params)->format == PICTURE_FMT_CIF)
 | |
| #define H263_FMT_CUSTOM_UPTO_QCIF(params) \
 | |
|    ((params)->format == PICTURE_FMT_RESERVED1 && \
 | |
|     (params)->height <= 144 && \
 | |
|     (params)->width <= 176)
 | |
| #define H263_FMT_CUSTOM_UPTO_CIF(params) \
 | |
|    ((params)->format == PICTURE_FMT_RESERVED1 && \
 | |
|     (params)->height <= 288 && \
 | |
|     (params)->width <= 352)
 | |
| 
 | |
| #define GST_FRACTION_LE(f1, f2) \
 | |
|   ((gst_value_compare (&(f1), &(f2)) == GST_VALUE_LESS_THAN) || \
 | |
|    (gst_value_compare (&(f1), &(f2)) == GST_VALUE_EQUAL))
 | |
| 
 | |
| gint
 | |
| gst_h263_parse_get_level (const H263Params * params, gint profile,
 | |
|     guint bitrate, gint fps_num, gint fps_denom)
 | |
| {
 | |
|   GValue fps15 = { 0, };
 | |
|   GValue fps30 = { 0, };
 | |
|   GValue fps50 = { 0, };
 | |
|   GValue fps60 = { 0, };
 | |
|   GValue fps = { 0, };
 | |
| 
 | |
|   if (bitrate == 0) {
 | |
|     GST_DEBUG ("Can't calculate level since bitrate is unknown");
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   g_value_init (&fps15, GST_TYPE_FRACTION);
 | |
|   g_value_init (&fps30, GST_TYPE_FRACTION);
 | |
|   g_value_init (&fps50, GST_TYPE_FRACTION);
 | |
|   g_value_init (&fps60, GST_TYPE_FRACTION);
 | |
|   g_value_init (&fps, GST_TYPE_FRACTION);
 | |
| 
 | |
|   gst_value_set_fraction (&fps15, 15000, 1001);
 | |
|   gst_value_set_fraction (&fps30, 30000, 1001);
 | |
|   gst_value_set_fraction (&fps50, 50, 1);
 | |
|   gst_value_set_fraction (&fps60, 60000, 1001);
 | |
| 
 | |
|   gst_value_set_fraction (&fps, fps_num, fps_denom);
 | |
| 
 | |
|   /* Level 10 */
 | |
|   if (H263_FMT_UPTO_QCIF (params) && GST_FRACTION_LE (fps, fps15) &&
 | |
|       bitrate <= 64000)
 | |
|     return 10;
 | |
| 
 | |
|   /* Level 20 */
 | |
|   if (((H263_FMT_UPTO_QCIF (params) && GST_FRACTION_LE (fps, fps30)) ||
 | |
|           (params->format == PICTURE_FMT_CIF && GST_FRACTION_LE (fps, fps15)))
 | |
|       && bitrate <= 128000)
 | |
|     return 20;
 | |
| 
 | |
|   /* Level 30 */
 | |
|   if (H263_FMT_UPTO_CIF (params) && GST_FRACTION_LE (fps, fps30) &&
 | |
|       bitrate <= 384000)
 | |
|     return 30;
 | |
| 
 | |
|   /* Level 40 */
 | |
|   if (H263_FMT_UPTO_CIF (params) && GST_FRACTION_LE (fps, fps30) &&
 | |
|       bitrate <= 2048000)
 | |
|     return 40;
 | |
| 
 | |
|   /* Level 45 */
 | |
|   if ((H263_FMT_UPTO_QCIF (params) || (H263_FMT_CUSTOM_UPTO_QCIF (params) &&
 | |
|               H263_PROFILE_NOT_0_2 (profile))) &&
 | |
|       GST_FRACTION_LE (fps, fps15) &&
 | |
|       /* (!h263parse->custompcfpresent || H263_PROFILE_NOT_0_2(profile)) && */
 | |
|       bitrate <= 128000)
 | |
|     return 45;
 | |
| 
 | |
|   /* Level 50 */
 | |
|   if ((H263_FMT_UPTO_CIF (params) || H263_FMT_CUSTOM_UPTO_CIF (params)) &&
 | |
|       (GST_FRACTION_LE (fps, fps50) ||
 | |
|           (params->width <= 352 && params->height <= 240 &&
 | |
|               GST_FRACTION_LE (fps, fps60))) && (bitrate <= 4096000))
 | |
|     return 50;
 | |
| 
 | |
|   /* Level 60 */
 | |
|   if (((params->width <= 720 && params->height <= 288 &&
 | |
|               GST_FRACTION_LE (fps, fps50)) ||
 | |
|           (params->width <= 720 && params->height <= 240 &&
 | |
|               GST_FRACTION_LE (fps, fps60))) && (bitrate <= 8192000))
 | |
|     return 60;
 | |
| 
 | |
|   /* Level 70 */
 | |
|   if (((params->width <= 720 && params->height <= 576 &&
 | |
|               GST_FRACTION_LE (fps, fps50)) ||
 | |
|           (params->width <= 720 && params->height <= 480 &&
 | |
|               GST_FRACTION_LE (fps, fps60))) && (bitrate <= 16384000))
 | |
|     return 70;
 | |
| 
 | |
|   GST_DEBUG ("Weird - didn't match any profile!");
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| void
 | |
| gst_h263_parse_get_framerate (const H263Params * params, gint * num,
 | |
|     gint * denom)
 | |
| {
 | |
|   *num = params->pcfnum;
 | |
|   *denom = params->pcfdenom;
 | |
| }
 | |
| 
 | |
| void
 | |
| gst_h263_parse_get_par (const H263Params * params, gint * num, gint * denom)
 | |
| {
 | |
|   *num = params->parnum;
 | |
|   *denom = params->pardenom;
 | |
| }
 |