mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
6adf3c2499
In the H263 spec, CPFMT is present only if the use of a custom picture format is signalled in PLUSEPTYPE and UFEP is "001", so we need to check params->format and only if the value is 6 (custom source format) the CPFMT should be read, otherwise it's not present and wrong data will be parsed. When reading the CPFMT, the width and height were not calculated correctly (wrong bitmask). https://bugzilla.gnome.org//show_bug.cgi?id=749253
696 lines
24 KiB
C
696 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 (" 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 specfied 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;
|
|
}
|