codecparsers: VC1: Handle interlaced fields

This commit is contained in:
Thibault Saunier 2011-10-10 14:19:48 -03:00
parent 88766dc738
commit 14590f06a0
2 changed files with 214 additions and 35 deletions

View File

@ -386,6 +386,43 @@ calculate_nb_pan_scan_win (GstVC1AdvancedSeqHdr * advseqhdr,
} }
} }
static gboolean
decode_refdist (GstBitReader * br, guint16 * value)
{
guint16 tmp;
gint i = 2;
if (!gst_bit_reader_peek_bits_uint16 (br, &tmp, i))
goto failed;
if (tmp < 0x03) {
READ_UINT16 (br, *value, i);
return TRUE;
}
do {
i++;
if (!gst_bit_reader_peek_bits_uint16 (br, &tmp, i))
goto failed;
if (!(tmp >> i)) {
READ_UINT16 (br, *value, i);
return TRUE;
}
} while (i < 16);
failed:
{
GST_WARNING ("Could not decode end 0 returning");
return FALSE;
}
}
static gboolean static gboolean
decode_vlc (GstBitReader * br, guint * res, const VLCTable * table, decode_vlc (GstBitReader * br, guint * res, const VLCTable * table,
guint length) guint length)
@ -868,7 +905,7 @@ failed:
static GstVC1ParserResult static GstVC1ParserResult
parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr,
GstVC1SeqHdr * seqhdr, GstVC1BitPlanes * bitplanes) GstVC1SeqHdr * seqhdr, GstVC1BitPlanes * bitplanes, gboolean field2)
{ {
GstVC1AdvancedSeqHdr *advhdr = &seqhdr->advanced; GstVC1AdvancedSeqHdr *advhdr = &seqhdr->advanced;
GstVC1PicAdvanced *pic = &framehdr->pic.advanced; GstVC1PicAdvanced *pic = &framehdr->pic.advanced;
@ -888,9 +925,44 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr,
goto failed; goto failed;
pic->fcm = (guint8) fcm; pic->fcm = (guint8) fcm;
} } else
pic->fcm = GST_VC1_FRAME_PROGRESSIVE;
framehdr->ptype = (guint8) get_unary (br, 0, 4); if (pic->fcm == GST_VC1_FIELD_INTERLACE) {
READ_UINT8 (br, pic->fptype, 3);
if (field2) {
switch (pic->fptype) {
case 0x00:
case 0x02:
framehdr->ptype = GST_VC1_PICTURE_TYPE_I;
case 0x01:
case 0x03:
framehdr->ptype = GST_VC1_PICTURE_TYPE_P;
case 0x04:
case 0x06:
framehdr->ptype = GST_VC1_PICTURE_TYPE_B;
case 0x05:
case 0x07:
framehdr->ptype = GST_VC1_PICTURE_TYPE_BI;
}
} else {
switch (pic->fptype) {
case 0x00:
case 0x01:
framehdr->ptype = GST_VC1_PICTURE_TYPE_I;
case 0x02:
case 0x03:
framehdr->ptype = GST_VC1_PICTURE_TYPE_P;
case 0x04:
case 0x05:
framehdr->ptype = GST_VC1_PICTURE_TYPE_B;
case 0x06:
case 0x07:
framehdr->ptype = GST_VC1_PICTURE_TYPE_BI;
}
}
} else
framehdr->ptype = (guint8) get_unary (br, 0, 4);
if (advhdr->tfcntrflag) { if (advhdr->tfcntrflag) {
READ_UINT8 (br, pic->tfcntr, 8); READ_UINT8 (br, pic->tfcntr, 8);
@ -937,6 +1009,11 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr,
if (advhdr->interlace) { if (advhdr->interlace) {
READ_UINT8 (br, pic->uvsamp, 1); READ_UINT8 (br, pic->uvsamp, 1);
GST_DEBUG ("uvsamp %u", pic->uvsamp); GST_DEBUG ("uvsamp %u", pic->uvsamp);
if (pic->fcm == GST_VC1_FIELD_INTERLACE && entrypthdr->refdist_flag &&
pic->fptype < 4)
decode_refdist (br, &pic->refdist);
else
pic->refdist = 0;
} }
if (advhdr->finterpflag) { if (advhdr->finterpflag) {
@ -944,8 +1021,12 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr,
GST_DEBUG ("interpfrm %u", framehdr->interpfrm); GST_DEBUG ("interpfrm %u", framehdr->interpfrm);
} }
if (framehdr->ptype == GST_VC1_PICTURE_TYPE_B) { if ((pic->fcm != GST_VC1_FIELD_INTERLACE &&
framehdr->ptype == GST_VC1_PICTURE_TYPE_B) ||
(pic->fcm == GST_VC1_FIELD_INTERLACE && (pic->fptype > 4))) {
guint bfraction; guint bfraction;
if (!decode_vlc (br, &bfraction, vc1_bfraction_vlc_table, if (!decode_vlc (br, &bfraction, vc1_bfraction_vlc_table,
G_N_ELEMENTS (vc1_bfraction_vlc_table))) G_N_ELEMENTS (vc1_bfraction_vlc_table)))
goto failed; goto failed;
@ -1038,32 +1119,47 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr,
else else
pic->mvrange = 0; pic->mvrange = 0;
if (pic->fcm == GST_VC1_FRAME_INTERLACE) { if (pic->fcm != GST_VC1_FRAME_PROGRESSIVE) {
if (entrypthdr->extended_dmv) if (entrypthdr->extended_dmv)
pic->dmvrange = get_unary (br, 0, 3); pic->dmvrange = get_unary (br, 0, 3);
READ_UINT8 (br, pic->intcomp, 1);
} else {
READ_UINT8 (br, pic->mvmode, 1);
} }
if (!bitplane_decoding (br, bitplanes ? bitplanes->directmb : NULL, if (pic->fcm == GST_VC1_FRAME_INTERLACE)
seqhdr, &pic->directmb)) READ_UINT8 (br, pic->intcomp, 1);
goto failed; else
READ_UINT8 (br, pic->mvmode, 1);
if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, if (pic->fcm == GST_VC1_FIELD_INTERLACE) {
seqhdr, &pic->skipmb))
goto failed;
if (pic->fcm == GST_VC1_FRAME_INTERLACE) { if (!bitplane_decoding (br, bitplanes ? bitplanes->forwardmb : NULL,
if (gst_bit_reader_get_remaining (br) < 11) seqhdr, &pic->forwardmb))
goto failed;
} else {
if (!bitplane_decoding (br, bitplanes ? bitplanes->directmb : NULL,
seqhdr, &pic->directmb))
goto failed;
if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL,
seqhdr, &pic->skipmb))
goto failed;
}
if (pic->fcm != GST_VC1_FRAME_PROGRESSIVE) {
if (gst_bit_reader_get_remaining (br) < 7)
goto failed; goto failed;
pic->mbmodetab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); pic->mbmodetab = gst_bit_reader_get_bits_uint8_unchecked (br, 2);
pic->imvtab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); pic->imvtab = gst_bit_reader_get_bits_uint8_unchecked (br, 2);
pic->icbptab = gst_bit_reader_get_bits_uint8_unchecked (br, 3); pic->icbptab = gst_bit_reader_get_bits_uint8_unchecked (br, 3);
pic->mvbptab2 = gst_bit_reader_get_bits_uint8_unchecked (br, 2);
pic->mvbptab4 = gst_bit_reader_get_bits_uint8_unchecked (br, 2); if (pic->fcm == GST_VC1_FRAME_INTERLACE)
READ_UINT8 (br, pic->mvbptab2, 2);
if (pic->fcm == GST_VC1_FRAME_INTERLACE ||
(pic->fcm == GST_VC1_FIELD_INTERLACE
&& pic->mvmode == GST_VC1_MVMODE_MIXED_MV))
READ_UINT8 (br, pic->mvbptab4, 2);
} else { } else {
READ_UINT8 (br, pic->mvtab, 2); READ_UINT8 (br, pic->mvtab, 2);
@ -1092,15 +1188,24 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr,
break; break;
case GST_VC1_PICTURE_TYPE_P: case GST_VC1_PICTURE_TYPE_P:
if (pic->fcm == GST_VC1_FIELD_INTERLACE) {
READ_UINT8 (br, pic->numref, 1);
if (pic->numref)
READ_UINT8 (br, pic->reffield, 1);
}
if (entrypthdr->extended_mv) if (entrypthdr->extended_mv)
pic->mvrange = get_unary (br, 0, 3); pic->mvrange = get_unary (br, 0, 3);
else else
pic->mvrange = 0; pic->mvrange = 0;
if (pic->fcm == GST_VC1_FRAME_INTERLACE) { if (pic->fcm != GST_VC1_FRAME_PROGRESSIVE) {
if (entrypthdr->extended_dmv) if (entrypthdr->extended_dmv)
pic->dmvrange = get_unary (br, 0, 3); pic->dmvrange = get_unary (br, 0, 3);
}
if (pic->fcm == GST_VC1_FRAME_INTERLACE) {
READ_UINT8 (br, pic->mvswitch4, 1); READ_UINT8 (br, pic->mvswitch4, 1);
READ_UINT8 (br, pic->intcomp, 1); READ_UINT8 (br, pic->intcomp, 1);
@ -1115,35 +1220,55 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr,
if (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP) { if (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP) {
pic->mvmode2 = vc1_mvmode2_table[mvmodeidx][get_unary (br, 1, 3)]; pic->mvmode2 = vc1_mvmode2_table[mvmodeidx][get_unary (br, 1, 3)];
if (pic->fcm == GST_VC1_FIELD_INTERLACE)
pic->intcompfield = decode012 (br);
READ_UINT8 (br, pic->lumscale, 6); READ_UINT8 (br, pic->lumscale, 6);
READ_UINT8 (br, pic->lumshift, 6); READ_UINT8 (br, pic->lumshift, 6);
GST_DEBUG ("lumscale %u lumshift %u", pic->lumscale, pic->lumshift); GST_DEBUG ("lumscale %u lumshift %u", pic->lumscale, pic->lumshift);
if (pic->fcm == GST_VC1_FIELD_INTERLACE && pic->intcompfield) {
READ_UINT8 (br, pic->lumscale2, 6);
READ_UINT8 (br, pic->lumshift2, 6);
}
} }
if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV || if (pic->fcm == GST_VC1_FRAME_PROGRESSIVE) {
(pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP && if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV ||
pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) { (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP &&
if (!bitplane_decoding (br, bitplanes ? bitplanes->mvtypemb : NULL, pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) {
seqhdr, &pic->mvtypemb))
goto failed; if (!bitplane_decoding (br, bitplanes ? bitplanes->mvtypemb : NULL,
GST_DEBUG ("mvtypemb %u", pic->mvtypemb); seqhdr, &pic->mvtypemb))
goto failed;
GST_DEBUG ("mvtypemb %u", pic->mvtypemb);
}
} }
} }
if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, if (pic->fcm != GST_VC1_FIELD_INTERLACE) {
seqhdr, &pic->skipmb)) if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL,
goto failed; seqhdr, &pic->skipmb))
goto failed;
}
if (pic->fcm == GST_VC1_FRAME_INTERLACE) { if (pic->fcm != GST_VC1_FRAME_PROGRESSIVE) {
if (gst_bit_reader_get_remaining (br) < 9) if (gst_bit_reader_get_remaining (br) < 7)
goto failed; goto failed;
pic->mbmodetab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); pic->mbmodetab = gst_bit_reader_get_bits_uint8_unchecked (br, 2);
pic->imvtab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); pic->imvtab = gst_bit_reader_get_bits_uint8_unchecked (br, 2);
pic->icbptab = gst_bit_reader_get_bits_uint8_unchecked (br, 3); pic->icbptab = gst_bit_reader_get_bits_uint8_unchecked (br, 3);
pic->mvbptab2 = gst_bit_reader_get_bits_uint8_unchecked (br, 2);
if (pic->mvswitch4) if (pic->fcm != GST_VC1_FIELD_INTERLACE) {
READ_UINT8 (br, pic->mvbptab2, 2);
if (pic->mvswitch4)
READ_UINT8 (br, pic->mvbptab4, 2);
} else if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV)
READ_UINT8 (br, pic->mvbptab4, 2); READ_UINT8 (br, pic->mvbptab4, 2);
} else { } else {
@ -1898,7 +2023,8 @@ gst_vc1_parse_frame_header (const guint8 * data, gsize size,
gst_bit_reader_init (&br, data, size); gst_bit_reader_init (&br, data, size);
if (seqhdr->profile == GST_VC1_PROFILE_ADVANCED) if (seqhdr->profile == GST_VC1_PROFILE_ADVANCED)
result = parse_frame_header_advanced (&br, framehdr, seqhdr, bitplanes); result = parse_frame_header_advanced (&br, framehdr, seqhdr, bitplanes,
FALSE);
else else
result = parse_frame_header (&br, framehdr, seqhdr, bitplanes); result = parse_frame_header (&br, framehdr, seqhdr, bitplanes);
@ -1906,6 +2032,35 @@ gst_vc1_parse_frame_header (const guint8 * data, gsize size,
return result; return result;
} }
/**
* gst_vc1_parse_field_header:
* @data: The data to parse
* @size: the size of @data
* @fieldhdr: The #GstVC1FrameHdr to fill.
* @seqhdr: The #GstVC1SeqHdr currently being parsed
* @bitplanes: The #GstVC1BitPlanes to store bitplanes in or %NULL
*
* Parses @data, and fills @fieldhdr fields.
*
* Returns: a #GstVC1ParserResult
*/
GstVC1ParserResult
gst_vc1_parse_field_header (const guint8 * data, gsize size,
GstVC1FrameHdr * fieldhdr, GstVC1SeqHdr * seqhdr,
GstVC1BitPlanes * bitplanes)
{
GstBitReader br;
GstVC1ParserResult result;
ensure_debug_category ();
gst_bit_reader_init (&br, data, size);
result = parse_frame_header_advanced (&br, fieldhdr, seqhdr, bitplanes, TRUE);
return result;
}
/** /**
* gst_vc1_bitplanes_new: * gst_vc1_bitplanes_new:
* @seqhdr: The #GstVC1SeqHdr from which to set @bitplanes * @seqhdr: The #GstVC1SeqHdr from which to set @bitplanes
@ -1949,6 +2104,7 @@ gst_vc1_bitplanes_free_1 (GstVC1BitPlanes * bitplanes)
g_free (bitplanes->mvtypemb); g_free (bitplanes->mvtypemb);
g_free (bitplanes->skipmb); g_free (bitplanes->skipmb);
g_free (bitplanes->directmb); g_free (bitplanes->directmb);
g_free (bitplanes->forwardmb);
} }
/** /**
@ -1984,6 +2140,8 @@ gst_vc1_bitplanes_ensure_size (GstVC1BitPlanes * bitplanes,
g_realloc_n (bitplanes->skipmb, bitplanes->size, sizeof (guint8)); g_realloc_n (bitplanes->skipmb, bitplanes->size, sizeof (guint8));
bitplanes->directmb = bitplanes->directmb =
g_realloc_n (bitplanes->directmb, bitplanes->size, sizeof (guint8)); g_realloc_n (bitplanes->directmb, bitplanes->size, sizeof (guint8));
bitplanes->forwardmb =
g_realloc_n (bitplanes->forwardmb, bitplanes->size, sizeof (guint8));
} else { } else {
bitplanes->size = seqhdr->mb_height * seqhdr->mb_stride; bitplanes->size = seqhdr->mb_height * seqhdr->mb_stride;
bitplanes->acpred = g_malloc0 (bitplanes->size * sizeof (guint8)); bitplanes->acpred = g_malloc0 (bitplanes->size * sizeof (guint8));
@ -1992,6 +2150,7 @@ gst_vc1_bitplanes_ensure_size (GstVC1BitPlanes * bitplanes,
bitplanes->mvtypemb = g_malloc0 (bitplanes->size * sizeof (guint8)); bitplanes->mvtypemb = g_malloc0 (bitplanes->size * sizeof (guint8));
bitplanes->skipmb = g_malloc0 (bitplanes->size * sizeof (guint8)); bitplanes->skipmb = g_malloc0 (bitplanes->size * sizeof (guint8));
bitplanes->directmb = g_malloc0 (bitplanes->size * sizeof (guint8)); bitplanes->directmb = g_malloc0 (bitplanes->size * sizeof (guint8));
bitplanes->forwardmb = g_malloc0 (bitplanes->size * sizeof (guint8));
} }
return TRUE; return TRUE;

View File

@ -426,6 +426,7 @@ struct _GstVC1PicAdvanced
guint8 mvtypemb; guint8 mvtypemb;
guint8 skipmb; guint8 skipmb;
guint8 directmb; guint8 directmb;
guint8 forwardmb; /* B pic interlace field only */
/* For interlaced pictures only */ /* For interlaced pictures only */
guint8 fieldtx; guint8 fieldtx;
@ -441,6 +442,18 @@ struct _GstVC1PicAdvanced
/* P picture */ /* P picture */
guint8 mvswitch4; guint8 mvswitch4;
/* For interlaced fields only */
guint16 refdist;
guint8 fptype; /* Raw value */
/* P pic */
guint8 numref;
guint8 reffield;
guint8 lumscale2;
guint8 lumshift2;
guint8 intcompfield;
}; };
struct _GstVC1BitPlanes struct _GstVC1BitPlanes
@ -451,6 +464,7 @@ struct _GstVC1BitPlanes
guint8 *mvtypemb; guint8 *mvtypemb;
guint8 *skipmb; guint8 *skipmb;
guint8 *directmb; guint8 *directmb;
guint8 *forwardmb;
guint size; /* Size of the arrays */ guint size; /* Size of the arrays */
}; };
@ -585,6 +599,12 @@ GstVC1ParserResult gst_vc1_parse_frame_header (const guint8 *data,
GstVC1SeqHdr *seqhdr, GstVC1SeqHdr *seqhdr,
GstVC1BitPlanes *bitplanes); GstVC1BitPlanes *bitplanes);
GstVC1ParserResult gst_vc1_parse_field_header (const guint8 *data,
gsize size,
GstVC1FrameHdr * fieldhdr,
GstVC1SeqHdr *seqhdr,
GstVC1BitPlanes *bitplanes);
GstVC1BitPlanes * gst_vc1_bitplanes_new (void); GstVC1BitPlanes * gst_vc1_bitplanes_new (void);
void gst_vc1_bitplanes_free (GstVC1BitPlanes *bitplanes); void gst_vc1_bitplanes_free (GstVC1BitPlanes *bitplanes);