From 0a478db7dd5909f8f7281db352b227965c45e094 Mon Sep 17 00:00:00 2001 From: Sreerenj Balachandran Date: Thu, 6 Oct 2011 16:55:43 +0300 Subject: [PATCH 01/26] h264parse: correct parsing of "numberOfPictureParameterSets" See #661113. --- gst/videoparsers/gsth264parse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c index 63301551f5..afc17bdd2b 100644 --- a/gst/videoparsers/gsth264parse.c +++ b/gst/videoparsers/gsth264parse.c @@ -1257,9 +1257,9 @@ gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps) off = nalu.offset + nalu.size; } - num_pps = data[0]; - data++; - size++; + num_pps = data[off]; + off++; + for (i = 0; i < num_pps; i++) { parseres = gst_h264_parser_identify_nalu_avc (h264parse->nalparser, data, off, size, 2, &nalu); From f8239ff6924c7e03af73707ef5fd9e218c0f9f5c Mon Sep 17 00:00:00 2001 From: Sreerenj Balachandran Date: Thu, 13 Oct 2011 16:52:43 +0300 Subject: [PATCH 02/26] h264parse: correct debug message and remove some dead code See #661113. --- gst/videoparsers/gsth264parse.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c index afc17bdd2b..d931111597 100644 --- a/gst/videoparsers/gsth264parse.c +++ b/gst/videoparsers/gsth264parse.c @@ -624,8 +624,7 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse, "current offset: %u, Nal offset: %u, Nal Size: %u", current_off, nalu.offset, nalu.size); - current_off = nalu.offset + nalu.size; - GST_DEBUG_OBJECT (h264parse, "current off. %u, %u", current_off, + GST_DEBUG_OBJECT (h264parse, "current off. %u", nalu.offset + nalu.size); if (!h264parse->nalu.size && !h264parse->nalu.valid) h264parse->nalu = nalu; @@ -1314,7 +1313,7 @@ gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps) /* ERRORS */ avcc_too_small: { - GST_DEBUG_OBJECT (h264parse, "avcC size %u < 7", size); + GST_DEBUG_OBJECT (h264parse, "avcC size %u < 8", size); goto refuse_caps; } wrong_version: From c90bf89b1696b0a61c1f43f4baeb3c59c8d5049c Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Wed, 14 Sep 2011 14:21:47 +0200 Subject: [PATCH 03/26] codecparsers: mpeg2: fix quant_matrix_extension() parser for chroma intra QM. --- gst-libs/gst/codecparsers/gstmpegvideoparser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-libs/gst/codecparsers/gstmpegvideoparser.c b/gst-libs/gst/codecparsers/gstmpegvideoparser.c index e871017fa0..399e834767 100644 --- a/gst-libs/gst/codecparsers/gstmpegvideoparser.c +++ b/gst-libs/gst/codecparsers/gstmpegvideoparser.c @@ -520,7 +520,7 @@ gst_mpeg_video_parse_quant_matrix_extension (GstMpegVideoQuantMatrixExt * quant, } READ_UINT8 (&br, quant->load_chroma_intra_quantiser_matrix, 1); - if (quant->load_non_intra_quantiser_matrix) { + if (quant->load_chroma_intra_quantiser_matrix) { for (i = 0; i < 64; i++) { READ_UINT8 (&br, quant->chroma_intra_quantiser_matrix[mpeg_zigzag_8x8[i]], 8); From bd686a637017d638b0aabac0b4b9ae39c6e2b247 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Fri, 30 Sep 2011 11:38:15 +0200 Subject: [PATCH 04/26] codecparsers: vc1: handle End-of-Sequence correctly. --- gst-libs/gst/codecparsers/gstvc1parser.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 8b0b785672..043d484c20 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -1200,8 +1200,8 @@ gst_vc1_identify_next_bdu (const guint8 * data, gsize size, GstVC1BDU * bdu) ensure_debug_category (); - if (size <= 4) { - GST_DEBUG ("Can't parse, buffer is to small size %" G_GSSIZE_FORMAT, size); + if (size < 4) { + GST_DEBUG ("Can't parse, buffer has too small size %" G_GSSIZE_FORMAT, size); return GST_VC1_PARSER_ERROR; } @@ -1218,6 +1218,12 @@ gst_vc1_identify_next_bdu (const guint8 * data, gsize size, GstVC1BDU * bdu) bdu->data = (guint8 *) data; bdu->type = (GstVC1StartCode) (data[bdu->offset - 1]); + if (bdu->type == GST_VC1_END_OF_SEQ) { + GST_DEBUG ("End-of-Sequence BDU found"); + bdu->size = 0; + return GST_VC1_PARSER_OK; + } + off2 = scan_for_start_codes (data + bdu->offset, size - bdu->offset); if (off2 < 0) { GST_DEBUG ("Bdu start %d, No end found", bdu->offset); From 604ce193dd090f43619f1cf9f155bb539dd91016 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Fri, 30 Sep 2011 12:41:13 +0200 Subject: [PATCH 05/26] codecparsers: vc1: use GstVC1ParserResult type name similarly to other parsers. --- gst-libs/gst/codecparsers/gstvc1parser.c | 20 ++++++++++---------- gst-libs/gst/codecparsers/gstvc1parser.h | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 043d484c20..7f644f42e9 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -563,7 +563,7 @@ get_unary (GstBitReader * br, gint stop, gint len) return i; } -static GstVC1ParseResult +static GstVC1ParserResult parse_hrd_param_flag (GstBitReader * br, GstVC1HrdParam * hrd_param) { guint i; @@ -599,7 +599,7 @@ failed: return GST_VC1_PARSER_ERROR; } -static GstVC1ParseResult +static GstVC1ParserResult parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) { GstVC1AdvancedSeqHdr *advanced = &seqhdr->profile.advanced; @@ -715,7 +715,7 @@ failed: return GST_VC1_PARSER_ERROR; } -static GstVC1ParseResult +static GstVC1ParserResult parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, GstVC1SeqHdr * seqhdr) { @@ -972,7 +972,7 @@ failed: return GST_VC1_PARSER_ERROR; } -static GstVC1ParseResult +static GstVC1ParserResult parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, GstVC1SeqHdr * seqhdr) { @@ -1189,9 +1189,9 @@ failed: * * Parses @data and fills @bdu fields * - * Returns: a #GstVC1ParseResult + * Returns: a #GstVC1ParserResult */ -GstVC1ParseResult +GstVC1ParserResult gst_vc1_identify_next_bdu (const guint8 * data, gsize size, GstVC1BDU * bdu) { gint off1, off2; @@ -1248,9 +1248,9 @@ gst_vc1_identify_next_bdu (const guint8 * data, gsize size, GstVC1BDU * bdu) * * Parses @data, and fills @seqhdr fields. * - * Returns: a #GstVC1ParseResult + * Returns: a #GstVC1ParserResult */ -GstVC1ParseResult +GstVC1ParserResult gst_vc1_parse_sequence_header (const guint8 * data, gsize size, GstVC1SeqHdr * seqhdr) { @@ -1355,7 +1355,7 @@ failed: * * Returns: a #GstVC1EntryPointHdr */ -GstVC1ParseResult +GstVC1ParserResult gst_vc1_parse_entry_point_header (const guint8 * data, gsize size, GstVC1EntryPointHdr * entrypoint, GstVC1SeqHdr * seqhdr) { @@ -1430,7 +1430,7 @@ failed: * * Returns: a #GstVC1EntryPointHdr */ -GstVC1ParseResult +GstVC1ParserResult gst_vc1_parse_frame_header (const guint8 * data, gsize size, GstVC1FrameHdr * framehdr, GstVC1SeqHdr * seqhdr) { diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index 511df64170..fc3698eb42 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -66,7 +66,7 @@ typedef enum { GST_VC1_PARSER_NO_BDU, GST_VC1_PARSER_NO_BDU_END, GST_VC1_PARSER_ERROR, -} GstVC1ParseResult; +} GstVC1ParserResult; typedef enum { @@ -445,21 +445,21 @@ struct _GstVC1BDU guint8 * data; }; -GstVC1ParseResult gst_vc1_identify_next_bdu (const guint8 *data, +GstVC1ParserResult gst_vc1_identify_next_bdu (const guint8 *data, gsize size, GstVC1BDU *bdu); -GstVC1ParseResult gst_vc1_parse_sequence_header (const guint8 *data, +GstVC1ParserResult gst_vc1_parse_sequence_header (const guint8 *data, gsize size, GstVC1SeqHdr * seqhdr); -GstVC1ParseResult gst_vc1_parse_entry_point_header (const guint8 *data, +GstVC1ParserResult gst_vc1_parse_entry_point_header (const guint8 *data, gsize size, GstVC1EntryPointHdr * entrypoint, GstVC1SeqHdr *seqhdr); -GstVC1ParseResult gst_vc1_parse_frame_header (const guint8 *data, +GstVC1ParserResult gst_vc1_parse_frame_header (const guint8 *data, gsize size, GstVC1FrameHdr * framehdr, GstVC1SeqHdr *seqhdr); From 8ca7640663018286b9d3c0453f41687b20efc92f Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 3 Oct 2011 14:22:17 -0300 Subject: [PATCH 06/26] codecparsers: VC1: Fix after GstVC1ParserResult renaming --- docs/libs/gst-plugins-bad-libs-sections.txt | 2 +- tests/check/libs/vc1parser.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/libs/gst-plugins-bad-libs-sections.txt b/docs/libs/gst-plugins-bad-libs-sections.txt index cd515e6af6..3509f3648b 100644 --- a/docs/libs/gst-plugins-bad-libs-sections.txt +++ b/docs/libs/gst-plugins-bad-libs-sections.txt @@ -52,7 +52,7 @@ MAX_HRD_NUM_LEAKY_BUCKETS GST_VC1_BFRACTION_BASIS GstVC1StartCode GstVC1Profile -GstVC1ParseResult +GstVC1ParserResult GstVC1PictureType GstVC1Level GstVC1QuantizerSpec diff --git a/tests/check/libs/vc1parser.c b/tests/check/libs/vc1parser.c index 5c9ef73ee5..d7e5395487 100644 --- a/tests/check/libs/vc1parser.c +++ b/tests/check/libs/vc1parser.c @@ -786,7 +786,7 @@ static guint8 pframe2_adv[] = { GST_START_TEST (test_vc1_identify_bdu) { - GstVC1ParseResult res; + GstVC1ParserResult res; GstVC1BDU bdu; GstVC1SeqHdr hdr; GstVC1EntryPointHdr entrypt; From b181bd8bae41a0b50556f0d325d06bd5a7ae04e7 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Mon, 3 Oct 2011 11:14:25 +0200 Subject: [PATCH 07/26] codecparsers: vc1: compute altpquant. --- gst-libs/gst/codecparsers/gstvc1parser.c | 9 +++++---- gst-libs/gst/codecparsers/gstvc1parser.h | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 7f644f42e9..2b2797746c 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -493,11 +493,12 @@ parse_vopdquant (GstBitReader * br, GstVC1FrameHdr * framehdr, guint8 dquant) READ_UINT8 (br, vopdquant->pqdiff, 3); - if (vopdquant->pqdiff == 7) + if (vopdquant->pqdiff != 7) + vopdquant->altpquant = framehdr->pquant + vopdquant->pqdiff + 1; + else { READ_UINT8 (br, vopdquant->abspq, 5); - else - vopdquant->abspq = framehdr->pquant + vopdquant->pqdiff + 1; - + vopdquant->altpquant = vopdquant->abspq; + } } else { READ_UINT8 (br, vopdquant->dquantfrm, 1); GST_DEBUG (" %u DquantFrm %u", gst_bit_reader_get_pos (br), diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index fc3698eb42..35d0b9b3c1 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -379,6 +379,8 @@ struct _GstVC1VopDquant guint8 pqdiff; guint8 abspq; + /* Computed */ + guint8 altpquant; /* if dqant != 2*/ guint8 dquantfrm; From de4a1049e2ee39e349277578aba627b845792da5 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Mon, 3 Oct 2011 11:42:32 +0200 Subject: [PATCH 08/26] codecparsers: vc1: record picture layer header size in bits. --- gst-libs/gst/codecparsers/gstvc1parser.c | 7 +++++-- gst-libs/gst/codecparsers/gstvc1parser.h | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 2b2797746c..001f3d7dd0 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -1436,14 +1436,17 @@ gst_vc1_parse_frame_header (const guint8 * data, gsize size, GstVC1FrameHdr * framehdr, GstVC1SeqHdr * seqhdr) { GstBitReader br; + GstVC1ParserResult result; ensure_debug_category (); gst_bit_reader_init (&br, data, size); if (seqhdr->profiletype == GST_VC1_PROFILE_ADVANCED) - return parse_frame_header_advanced (&br, framehdr, seqhdr); + result = parse_frame_header_advanced (&br, framehdr, seqhdr); else - return parse_frame_header (&br, framehdr, seqhdr); + result = parse_frame_header (&br, framehdr, seqhdr); + framehdr->header_size = gst_bit_reader_get_pos (&br); + return result; } diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index 35d0b9b3c1..60344a0699 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -431,6 +431,9 @@ struct _GstVC1FrameHdr GstVC1PicSimpleMain simple; GstVC1PicAdvanced advanced; } pic; + + /* Size of the picture layer in bits */ + guint header_size; }; /** From 6137d841a06d5f91fa7ef23deeccbe76f04a6eb9 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Mon, 3 Oct 2011 15:36:08 +0200 Subject: [PATCH 09/26] codecparsers: vc1: debug cosmetics. --- gst-libs/gst/codecparsers/gstvc1parser.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 001f3d7dd0..263d992f85 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -868,8 +868,10 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, if (framehdr->dquant) parse_vopdquant (br, framehdr, framehdr->dquant); - GST_DEBUG ("acpred %u, condover %u transacfrm %u transacfrm2 %u,", - pic->acpred, pic->condover, framehdr->transacfrm, pic->transacfrm2); + GST_DEBUG + ("acpred %u, condover %u, transacfrm %u, transacfrm2 %u, transdctab %u", + pic->acpred, pic->condover, framehdr->transacfrm, pic->transacfrm2, + framehdr->transdctab); break; case GST_VC1_PICTURE_TYPE_B: From 2b5e7c1f0f6207ade511f46aecd2a9792febacfe Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 3 Oct 2011 14:25:00 -0300 Subject: [PATCH 10/26] codecparsers: VC1: compute MB height and width Add them to GstVC1SequenceHdr --- gst-libs/gst/codecparsers/gstvc1parser.c | 19 ++++++++++++++----- gst-libs/gst/codecparsers/gstvc1parser.h | 2 ++ tests/check/libs/vc1parser.c | 15 +++++++++------ 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 263d992f85..ad726bd56b 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -649,6 +649,8 @@ parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) gst_bit_reader_get_bits_uint16_unchecked (br, 12); advanced->max_coded_width = (advanced->max_coded_width + 1) << 1; advanced->max_coded_height = (advanced->max_coded_height + 1) << 1; + seqhdr->mb_height = (advanced->max_coded_height + 15) >> 4; + seqhdr->mb_width = (advanced->max_coded_width + 15) >> 4; advanced->pulldown = gst_bit_reader_get_bits_uint8_unchecked (br, 1); advanced->interlace = gst_bit_reader_get_bits_uint8_unchecked (br, 1); advanced->tfcntrflag = gst_bit_reader_get_bits_uint8_unchecked (br, 1); @@ -724,8 +726,8 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, GstVC1PicAdvanced *pic = &framehdr->pic.advanced; GstVC1EntryPointHdr *entrypthdr = &advhdr->entrypoint; guint8 mvmodeidx; - guint width = (entrypthdr->coded_width + 15) >> 4; - guint height = (entrypthdr->coded_height + 15) >> 4; + guint width = seqhdr->mb_width; + guint height = seqhdr->mb_height; GST_DEBUG ("Parsing Frame header advanced %u", advhdr->interlace); @@ -982,8 +984,8 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, guint8 mvmodeidx; GstVC1PicSimpleMain *pic = &framehdr->pic.simple; GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr->profile.simplemain; - guint width = (simplehdr->coded_width + 15) >> 4; - guint height = (simplehdr->coded_height + 15) >> 4; + guint width = seqhdr->mb_width; + guint height = seqhdr->mb_height; GST_DEBUG ("Parsing frame header in simple or main mode"); @@ -1204,7 +1206,8 @@ gst_vc1_identify_next_bdu (const guint8 * data, gsize size, GstVC1BDU * bdu) ensure_debug_category (); if (size < 4) { - GST_DEBUG ("Can't parse, buffer has too small size %" G_GSSIZE_FORMAT, size); + GST_DEBUG ("Can't parse, buffer has too small size %" G_GSSIZE_FORMAT, + size); return GST_VC1_PARSER_ERROR; } @@ -1339,6 +1342,10 @@ gst_vc1_parse_sequence_header (const guint8 * data, gsize size, simplehdr->slice_code); } + /* compute height and width */ + seqhdr->mb_height = (simplehdr->coded_height + 15) >> 4; + seqhdr->mb_width = (simplehdr->coded_width + 15) >> 4; + return GST_VC1_PARSER_OK; failed: @@ -1399,6 +1406,8 @@ gst_vc1_parse_entry_point_header (const guint8 * data, gsize size, READ_UINT16 (&br, entrypoint->coded_height, 12); entrypoint->coded_height = (entrypoint->coded_height + 1) << 1; entrypoint->coded_width = (entrypoint->coded_width + 1) << 1; + seqhdr->mb_height = (entrypoint->coded_height + 15) >> 4; + seqhdr->mb_width = (entrypoint->coded_width + 15) >> 4; } if (entrypoint->extended_mv) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index 60344a0699..aad83fa557 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -268,6 +268,8 @@ struct _GstVC1SeqHdr /* calculated */ guint framerate; /* Around in fps, 0 if unknown*/ guint bitrate; /* Around in kpbs, 0 if unknown*/ + guint mb_height; + guint mb_width; union { GstVC1AdvancedSeqHdr advanced; diff --git a/tests/check/libs/vc1parser.c b/tests/check/libs/vc1parser.c index d7e5395487..1fd9e39a65 100644 --- a/tests/check/libs/vc1parser.c +++ b/tests/check/libs/vc1parser.c @@ -825,14 +825,14 @@ GST_START_TEST (test_vc1_parse_p_frame_header_main) GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; + simplehdr->coded_height = 240; + simplehdr->coded_width = 320; + assert_equals_int (gst_vc1_parse_sequence_header (pframe_header_main, sizeof (pframe_header_main), &seqhdr), GST_VC1_PARSER_OK); assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN); - simplehdr->coded_height = 240; - simplehdr->coded_width = 320; - assert_equals_int (seqhdr.frmrtq_postproc, 7); assert_equals_int (seqhdr.bitrtq_postproc, 2); assert_equals_int (simplehdr->loop_filter, 1); @@ -869,13 +869,15 @@ GST_START_TEST (test_vc1_parse_b_frame_header_main) GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; + simplehdr->coded_height = 240; + simplehdr->coded_width = 320; + assert_equals_int (gst_vc1_parse_sequence_header (bframe_header_main, sizeof (bframe_header_main), &seqhdr), GST_VC1_PARSER_OK); assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN); - - simplehdr->coded_height = 240; - simplehdr->coded_width = 320; + assert_equals_int (seqhdr.mb_height, 15); + assert_equals_int (seqhdr.mb_width, 20); assert_equals_int (seqhdr.frmrtq_postproc, 7); assert_equals_int (seqhdr.bitrtq_postproc, 3); @@ -915,6 +917,7 @@ GST_START_TEST (test_vc1_parse_bi_frame_header_main) GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; + simplehdr->coded_height = 240; simplehdr->coded_width = 320; From 446e0a521603d2bf1fd51147d027ef5470cd26de Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Wed, 5 Oct 2011 08:26:31 -0300 Subject: [PATCH 11/26] codecparsers: VC1: Compute framerate and bitrate in simple/main profiles --- gst-libs/gst/codecparsers/gstvc1parser.c | 52 +++++++++++++----------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index ad726bd56b..3e82ab56db 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -564,6 +564,33 @@ get_unary (GstBitReader * br, gint stop, gint len) return i; } +static inline void +calculate_framerate_bitrate (GstVC1SeqHdr * seqhdr) +{ + /* Calulate bitrate and framerate */ + if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 30) { + seqhdr->framerate = 0; + seqhdr->bitrate = 0; + } else if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 30) { + seqhdr->framerate = 2; + seqhdr->bitrate = 1952; + } else if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 31) { + seqhdr->framerate = 6; + seqhdr->bitrate = 2016; + } else { + if (seqhdr->frmrtq_postproc == 7) { + seqhdr->framerate = 30; + } else { + seqhdr->framerate = 2 + (seqhdr->frmrtq_postproc * 4); + } + if (seqhdr->bitrtq_postproc == 31) { + seqhdr->bitrate = 2016; + } else { + seqhdr->bitrate = 32 + (seqhdr->bitrtq_postproc * 64); + } + } +} + static GstVC1ParserResult parse_hrd_param_flag (GstBitReader * br, GstVC1HrdParam * hrd_param) { @@ -612,34 +639,12 @@ parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) READ_UINT8 (br, seqhdr->colordiff_format, 2); READ_UINT8 (br, seqhdr->frmrtq_postproc, 3); READ_UINT8 (br, seqhdr->bitrtq_postproc, 5); + calculate_framerate_bitrate (seqhdr); GST_DEBUG ("level %u, colordiff_format %u , frmrtq_postproc %u," " bitrtq_postproc %u", advanced->level, seqhdr->colordiff_format, seqhdr->frmrtq_postproc, seqhdr->bitrtq_postproc); - /* Calulate bitrate and framerate */ - if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 30) { - seqhdr->framerate = 0; - seqhdr->bitrate = 0; - } else if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 30) { - seqhdr->framerate = 2; - seqhdr->bitrate = 1952; - } else if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 31) { - seqhdr->framerate = 6; - seqhdr->bitrate = 2016; - } else { - if (seqhdr->frmrtq_postproc == 7) { - seqhdr->framerate = 30; - } else { - seqhdr->framerate = 2 + (seqhdr->frmrtq_postproc * 4); - } - if (seqhdr->bitrtq_postproc == 31) { - seqhdr->bitrate = 2016; - } else { - seqhdr->bitrate = 32 + (seqhdr->bitrtq_postproc * 64); - } - } - if (gst_bit_reader_get_remaining (br) < 32) goto failed; @@ -1293,6 +1298,7 @@ gst_vc1_parse_sequence_header (const guint8 * data, gsize size, seqhdr->frmrtq_postproc = gst_bit_reader_get_bits_uint8_unchecked (&br, 3); seqhdr->bitrtq_postproc = gst_bit_reader_get_bits_uint8_unchecked (&br, 5); simplehdr->loop_filter = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + calculate_framerate_bitrate (seqhdr); /* Skipping reserved3 bit */ gst_bit_reader_skip_unchecked (&br, 1); From fc09e451084be59f27f843457982714a619f8ab4 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Wed, 5 Oct 2011 12:15:00 -0300 Subject: [PATCH 12/26] codecparsers: VC1: Implement Sequence Layer Data Structures Instead of having a single VC1SequenceHeader structure, use the 3 structs from the "Table 265: Sequence Layer Data Structure" of the specification for the library to be more flexible. Implement the functions to parse them --- docs/libs/gst-plugins-bad-libs-sections.txt | 9 +- gst-libs/gst/codecparsers/gstvc1parser.c | 438 ++++++++++++++------ gst-libs/gst/codecparsers/gstvc1parser.h | 141 +++++-- tests/check/libs/vc1parser.c | 164 ++++---- 4 files changed, 497 insertions(+), 255 deletions(-) diff --git a/docs/libs/gst-plugins-bad-libs-sections.txt b/docs/libs/gst-plugins-bad-libs-sections.txt index 3509f3648b..4b5e221eac 100644 --- a/docs/libs/gst-plugins-bad-libs-sections.txt +++ b/docs/libs/gst-plugins-bad-libs-sections.txt @@ -61,7 +61,10 @@ GstVC1Condover GstVC1MvMode GstVC1SeqHdr GstVC1AdvancedSeqHdr -GstVC1SimpleMainSeqHdr +GstVC1SeqLayer +GstVC1SeqStructA +GstVC1SeqStructB +GstVC1SeqStructC GstVC1HrdParam GstVC1EntryPointHdr GstVC1FrameHdr @@ -72,6 +75,10 @@ GstVC1VopDquant GstVC1BDU gst_vc1_identify_next_bdu gst_vc1_parse_sequence_header +gst_vc1_parse_sequence_layer +gst_vc1_parse_sequence_header_struct_a +gst_vc1_parse_sequence_header_struct_b +gst_vc1_parse_sequence_header_struct_c gst_vc1_parse_entry_point_header gst_vc1_parse_frame_header diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 3e82ab56db..aad915d8b8 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -565,28 +565,28 @@ get_unary (GstBitReader * br, gint stop, gint len) } static inline void -calculate_framerate_bitrate (GstVC1SeqHdr * seqhdr) +calculate_framerate_bitrate (guint8 frmrtq_postproc, guint8 bitrtq_postproc, + guint * framerate, guint * bitrate) { - /* Calulate bitrate and framerate */ - if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 30) { - seqhdr->framerate = 0; - seqhdr->bitrate = 0; - } else if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 30) { - seqhdr->framerate = 2; - seqhdr->bitrate = 1952; - } else if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 31) { - seqhdr->framerate = 6; - seqhdr->bitrate = 2016; + if (frmrtq_postproc == 0 && bitrtq_postproc == 30) { + *framerate = 0; + *bitrate = 0; + } else if (frmrtq_postproc == 0 && bitrtq_postproc == 30) { + *framerate = 2; + *bitrate = 1952; + } else if (frmrtq_postproc == 0 && bitrtq_postproc == 31) { + *framerate = 6; + *bitrate = 2016; } else { - if (seqhdr->frmrtq_postproc == 7) { - seqhdr->framerate = 30; + if (frmrtq_postproc == 7) { + *framerate = 30; } else { - seqhdr->framerate = 2 + (seqhdr->frmrtq_postproc * 4); + *framerate = 2 + (frmrtq_postproc * 4); } - if (seqhdr->bitrtq_postproc == 31) { - seqhdr->bitrate = 2016; + if (bitrtq_postproc == 31) { + *bitrate = 2016; } else { - seqhdr->bitrate = 32 + (seqhdr->bitrtq_postproc * 64); + *bitrate = 32 + (bitrtq_postproc * 64); } } } @@ -630,20 +630,22 @@ failed: static GstVC1ParserResult parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) { - GstVC1AdvancedSeqHdr *advanced = &seqhdr->profile.advanced; + GstVC1AdvancedSeqHdr *advanced = &seqhdr->advanced; GST_DEBUG ("Parsing sequence header in advanced mode"); READ_UINT8 (br, advanced->level, 3); - READ_UINT8 (br, seqhdr->colordiff_format, 2); - READ_UINT8 (br, seqhdr->frmrtq_postproc, 3); - READ_UINT8 (br, seqhdr->bitrtq_postproc, 5); - calculate_framerate_bitrate (seqhdr); + READ_UINT8 (br, advanced->colordiff_format, 2); + READ_UINT8 (br, advanced->frmrtq_postproc, 3); + READ_UINT8 (br, advanced->bitrtq_postproc, 5); + + calculate_framerate_bitrate (advanced->frmrtq_postproc, + advanced->bitrtq_postproc, &advanced->framerate, &advanced->bitrate); GST_DEBUG ("level %u, colordiff_format %u , frmrtq_postproc %u," - " bitrtq_postproc %u", advanced->level, seqhdr->colordiff_format, - seqhdr->frmrtq_postproc, seqhdr->bitrtq_postproc); + " bitrtq_postproc %u", advanced->level, advanced->colordiff_format, + advanced->frmrtq_postproc, advanced->bitrtq_postproc); if (gst_bit_reader_get_remaining (br) < 32) goto failed; @@ -659,13 +661,13 @@ parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) advanced->pulldown = gst_bit_reader_get_bits_uint8_unchecked (br, 1); advanced->interlace = gst_bit_reader_get_bits_uint8_unchecked (br, 1); advanced->tfcntrflag = gst_bit_reader_get_bits_uint8_unchecked (br, 1); - seqhdr->finterpflag = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + advanced->finterpflag = gst_bit_reader_get_bits_uint8_unchecked (br, 1); GST_DEBUG ("postprocflag %u, max_coded_width %u, max_coded_height %u," "pulldown %u, interlace %u, tfcntrflag %u, finterpflag %u", advanced->postprocflag, advanced->max_coded_width, advanced->max_coded_height, advanced->pulldown, - advanced->interlace, advanced->tfcntrflag, seqhdr->finterpflag); + advanced->interlace, advanced->tfcntrflag, advanced->finterpflag); /* Skipping reserved bit */ gst_bit_reader_skip_unchecked (br, 1); @@ -727,7 +729,7 @@ static GstVC1ParserResult parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, GstVC1SeqHdr * seqhdr) { - GstVC1AdvancedSeqHdr *advhdr = &seqhdr->profile.advanced; + GstVC1AdvancedSeqHdr *advhdr = &seqhdr->advanced; GstVC1PicAdvanced *pic = &framehdr->pic.advanced; GstVC1EntryPointHdr *entrypthdr = &advhdr->entrypoint; guint8 mvmodeidx; @@ -737,7 +739,7 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, GST_DEBUG ("Parsing Frame header advanced %u", advhdr->interlace); /* Set the conveninence fields */ - framehdr->profile = seqhdr->profiletype; + framehdr->profile = seqhdr->profile; framehdr->dquant = entrypthdr->dquant; if (advhdr->interlace) { @@ -798,7 +800,7 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, GST_DEBUG ("uvsamp %u", pic->uvsamp); } - if (seqhdr->finterpflag) { + if (advhdr->finterpflag) { READ_UINT8 (br, framehdr->interpfrm, 1); GST_DEBUG ("interpfrm %u", framehdr->interpfrm); } @@ -988,31 +990,28 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, { guint8 mvmodeidx; GstVC1PicSimpleMain *pic = &framehdr->pic.simple; - GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr->profile.simplemain; - guint width = seqhdr->mb_width; - guint height = seqhdr->mb_height; - + GstVC1SeqStructC *structc = &seqhdr->struct_c; GST_DEBUG ("Parsing frame header in simple or main mode"); /* Set the conveninence fields */ - framehdr->profile = seqhdr->profiletype; - framehdr->dquant = simplehdr->dquant; + framehdr->profile = seqhdr->profile; + framehdr->dquant = structc->dquant; framehdr->interpfrm = 0; - if (seqhdr->finterpflag) + if (structc->finterpflag) READ_UINT8 (br, framehdr->interpfrm, 1); READ_UINT8 (br, pic->frmcnt, 2); pic->rangeredfrm = 0; - if (simplehdr->rangered) { + if (structc->rangered) { READ_UINT8 (br, pic->rangeredfrm, 2); } /* Figuring out the picture type */ READ_UINT8 (br, framehdr->ptype, 1); - if (simplehdr->maxbframes) { + if (structc->maxbframes) { if (!framehdr->ptype) { READ_UINT8 (br, framehdr->ptype, 1); @@ -1055,7 +1054,7 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, GST_DEBUG ("pqindex %u", framehdr->pqindex); /* compute pquant */ - if (simplehdr->quantizer == GST_VC1_QUANTIZER_IMPLICITLY) + if (structc->quantizer == GST_VC1_QUANTIZER_IMPLICITLY) framehdr->pquant = vc1_pquant_table[0][framehdr->pqindex]; else framehdr->pquant = vc1_pquant_table[1][framehdr->pqindex]; @@ -1069,20 +1068,20 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, /* Set pquantizer */ framehdr->pquantizer = 1; - if (simplehdr->quantizer == GST_VC1_QUANTIZER_IMPLICITLY) + if (structc->quantizer == GST_VC1_QUANTIZER_IMPLICITLY) framehdr->pquantizer = framehdr->pqindex < 9; - else if (simplehdr->quantizer == GST_VC1_QUANTIZER_NON_UNIFORM) + else if (structc->quantizer == GST_VC1_QUANTIZER_NON_UNIFORM) framehdr->pquantizer = 0; - if (simplehdr->quantizer == GST_VC1_QUANTIZER_EXPLICITLY) + if (structc->quantizer == GST_VC1_QUANTIZER_EXPLICITLY) READ_UINT8 (br, framehdr->pquantizer, 1); - if (simplehdr->extended_mv == 1) { + if (structc->extended_mv == 1) { pic->mvrange = get_unary (br, 0, 3); GST_DEBUG ("mvrange %u", pic->mvrange); } - if (simplehdr->multires && (framehdr->ptype == GST_VC1_PICTURE_TYPE_P || + if (structc->multires && (framehdr->ptype == GST_VC1_PICTURE_TYPE_P || framehdr->ptype == GST_VC1_PICTURE_TYPE_I)) { READ_UINT8 (br, pic->respic, 2); GST_DEBUG ("Respic %u", pic->respic); @@ -1132,7 +1131,7 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, parse_vopdquant (br, framehdr, framehdr->dquant); } - if (simplehdr->vstransform) { + if (structc->vstransform) { READ_UINT8 (br, pic->ttmbf, 1); GST_DEBUG ("ttmbf %u", pic->ttmbf); @@ -1163,7 +1162,7 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, if (framehdr->dquant) parse_vopdquant (br, framehdr, framehdr->dquant); - if (simplehdr->vstransform) { + if (structc->vstransform) { READ_UINT8 (br, pic->ttmbf, 1); if (pic->ttmbf) { @@ -1190,6 +1189,130 @@ failed: return GST_VC1_PARSER_ERROR; } +static GstVC1ParserResult +parse_sequence_header_struct_a (GstBitReader * br, GstVC1SeqStructA * structa) +{ + if (gst_bit_reader_get_remaining (br) < 64) { + GST_WARNING ("Failed to parse struct A"); + + return GST_VC1_PARSER_ERROR; + } + + structa->vert_size = gst_bit_reader_get_bits_uint32_unchecked (br, 32); + structa->horiz_size = gst_bit_reader_get_bits_uint32_unchecked (br, 32); + + return GST_VC1_PARSER_OK; +} + +static GstVC1ParserResult +parse_sequence_header_struct_b (GstBitReader * br, GstVC1SeqStructB * structb) +{ + if (gst_bit_reader_get_remaining (br) < 96) { + GST_WARNING ("Failed to parse sequence header"); + + return GST_VC1_PARSER_ERROR; + } + + structb->level = gst_bit_reader_get_bits_uint8_unchecked (br, 3); + structb->cbr = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + + /* res4 */ + gst_bit_reader_skip_unchecked (br, 4); + + structb->hrd_buffer = gst_bit_reader_get_bits_uint32_unchecked (br, 24); + structb->hrd_rate = gst_bit_reader_get_bits_uint32_unchecked (br, 32); + structb->framerate = gst_bit_reader_get_bits_uint32_unchecked (br, 32); + + return GST_VC1_PARSER_OK; +} + +static GstVC1ParserResult +parse_sequence_header_struct_c (GstBitReader * br, GstVC1SeqStructC * structc) +{ + guint8 old_interlaced_mode, tmp; + + READ_UINT8 (br, tmp, 2); + structc->profile = tmp; + + if (structc->profile == GST_VC1_PROFILE_ADVANCED) + return GST_VC1_PARSER_OK; + + GST_DEBUG ("Parsing sequence header in simple or main mode"); + + if (gst_bit_reader_get_remaining (br) < 29) + goto failed; + + /* Reserved bits */ + old_interlaced_mode = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + if (old_interlaced_mode) + GST_WARNING ("Old interlaced mode used"); + + structc->wmvp = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + if (structc->wmvp) + GST_DEBUG ("WMVP mode"); + + structc->frmrtq_postproc = gst_bit_reader_get_bits_uint8_unchecked (br, 3); + structc->bitrtq_postproc = gst_bit_reader_get_bits_uint8_unchecked (br, 5); + structc->loop_filter = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + + calculate_framerate_bitrate (structc->frmrtq_postproc, + structc->bitrtq_postproc, &structc->framerate, &structc->bitrate); + + /* Skipping reserved3 bit */ + gst_bit_reader_skip_unchecked (br, 1); + + structc->multires = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + + /* Skipping reserved4 bit */ + gst_bit_reader_skip_unchecked (br, 1); + + structc->fastuvmc = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + structc->extended_mv = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + structc->dquant = gst_bit_reader_get_bits_uint8_unchecked (br, 2); + structc->vstransform = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + + /* Skipping reserved5 bit */ + gst_bit_reader_skip_unchecked (br, 1); + + structc->overlap = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + structc->syncmarker = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + structc->rangered = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + structc->maxbframes = gst_bit_reader_get_bits_uint8_unchecked (br, 3); + structc->quantizer = gst_bit_reader_get_bits_uint8_unchecked (br, 2); + structc->finterpflag = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + + GST_DEBUG ("frmrtq_postproc %u, bitrtq_postproc %u, loop_filter %u, " + "multires %u, fastuvmc %u, extended_mv %u, dquant %u, vstransform %u, " + "overlap %u, syncmarker %u, rangered %u, maxbframes %u, quantizer %u, " + "finterpflag %u", structc->frmrtq_postproc, structc->bitrtq_postproc, + structc->loop_filter, structc->multires, structc->fastuvmc, + structc->extended_mv, structc->dquant, structc->vstransform, + structc->overlap, structc->syncmarker, structc->rangered, + structc->maxbframes, structc->quantizer, structc->finterpflag); + + if (structc->wmvp) { + if (gst_bit_reader_get_remaining (br) < 29) + goto failed; + + structc->coded_width = gst_bit_reader_get_bits_uint16_unchecked (br, 11); + structc->coded_height = gst_bit_reader_get_bits_uint16_unchecked (br, 11); + structc->framerate = gst_bit_reader_get_bits_uint8_unchecked (br, 5); + gst_bit_reader_skip_unchecked (br, 1); + structc->slice_code = gst_bit_reader_get_bits_uint8_unchecked (br, 1); + + GST_DEBUG ("coded_width %u, coded_height %u, framerate %u slice_code %u", + structc->coded_width, structc->coded_height, structc->framerate, + structc->slice_code); + } + + return GST_VC1_PARSER_OK; + +failed: + GST_WARNING ("Failed to struct C"); + + return GST_VC1_PARSER_ERROR; +} + /**** API ****/ /** * gst_vc1_identify_next_bdu: @@ -1230,7 +1353,7 @@ gst_vc1_identify_next_bdu (const guint8 * data, gsize size, GstVC1BDU * bdu) bdu->type = (GstVC1StartCode) (data[bdu->offset - 1]); if (bdu->type == GST_VC1_END_OF_SEQ) { - GST_DEBUG ("End-of-Sequence BDU found"); + GST_DEBUG ("End-of-Seq BDU found"); bdu->size = 0; return GST_VC1_PARSER_OK; } @@ -1252,10 +1375,135 @@ gst_vc1_identify_next_bdu (const guint8 * data, gsize size, GstVC1BDU * bdu) } /** - * gst_vc1_parse_sequence_header: + * gst_vc1_parse_sequence_layer: * @data: The data to parse * @size: the size of @data - * @seqhdr: The #GstVC1SeqHdr to set. + * @structa: The #GstVC1SeqLayer to set. + * + * Parses @data, and fills @seqlayer fields. + * + * Returns: a #GstVC1ParserResult + */ +GstVC1ParserResult +gst_vc1_parse_sequence_layer (const guint8 * data, gsize size, + GstVC1SeqLayer * seqlayer) +{ + guint32 tmp; + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (seqlayer != NULL, GST_VC1_PARSER_ERROR); + + ensure_debug_category (); + + READ_UINT32 (&br, tmp, 8); + if (tmp != 0xC5) + goto failed; + + READ_UINT32 (&br, seqlayer->numframes, 24); + + if (parse_sequence_header_struct_c (&br, &seqlayer->struct_c) == + GST_VC1_PARSER_ERROR) + goto failed; + + READ_UINT32 (&br, tmp, 32); + if (tmp != 0x04) + goto failed; + + if (parse_sequence_header_struct_a (&br, &seqlayer->struct_a) == + GST_VC1_PARSER_ERROR) + goto failed; + + READ_UINT32 (&br, tmp, 32); + if (tmp != 0x0C) + goto failed; + + if (parse_sequence_header_struct_b (&br, &seqlayer->struct_b) == + GST_VC1_PARSER_ERROR) + goto failed; + + return GST_VC1_PARSER_OK; + +failed: + GST_WARNING ("Failed to parse sequence layer"); + + return GST_VC1_PARSER_ERROR; +} + +/** + * gst_vc1_parse_sequence_header_struct_a: + * @data: The data to parse + * @size: the size of @data + * @structa: The #GstVC1SeqStructA to set. + * + * Parses @data, and fills @structa fields. + * + * Returns: a #GstVC1ParserResult + */ +GstVC1ParserResult +gst_vc1_parse_sequence_header_struct_a (const guint8 * data, + gsize size, GstVC1SeqStructA * structa) +{ + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (structa != NULL, GST_VC1_PARSER_ERROR); + + ensure_debug_category (); + + + return parse_sequence_header_struct_a (&br, structa); +} + +/** + * gst_vc1_parse_sequence_header_struct_b: + * @data: The data to parse + * @size: the size of @data + * @structa: The #GstVC1SeqStructB to set. + * + * Parses @data, and fills @structb fields. + * + * Returns: a #GstVC1ParserResult + */ +GstVC1ParserResult +gst_vc1_parse_sequence_header_struct_b (const guint8 * data, + gsize size, GstVC1SeqStructB * structb) +{ + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (structb != NULL, GST_VC1_PARSER_ERROR); + + ensure_debug_category (); + + return parse_sequence_header_struct_b (&br, structb); +} + +/** + * gst_vc1_parse_sequence_header_struct_c: + * @data: The data to parse + * @size: the size of @data + * @structc: The #GstVC1SeqStructC to set. + * + * Parses @data, and fills @structc fields. + * + * Returns: a #GstVC1ParserResult + */ +GstVC1ParserResult +gst_vc1_parse_sequence_header_struct_c (const guint8 * data, gsize size, + GstVC1SeqStructC * structc) +{ + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (structc != NULL, GST_VC1_PARSER_ERROR); + + ensure_debug_category (); + + return parse_sequence_header_struct_c (&br, structc); +} + +/** +* gst_vc1_parse_sequence_header: +* @data: The data to parse +* @size: the size of @data +* @seqhdr: The #GstVC1SeqHdr to set. * * Parses @data, and fills @seqhdr fields. * @@ -1265,92 +1513,25 @@ GstVC1ParserResult gst_vc1_parse_sequence_header (const guint8 * data, gsize size, GstVC1SeqHdr * seqhdr) { - GstBitReader br; - guint8 old_interlaced_mode; - GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr->profile.simplemain; + GstBitReader br = GST_BIT_READER_INIT (data, size); g_return_val_if_fail (seqhdr != NULL, GST_VC1_PARSER_ERROR); ensure_debug_category (); - gst_bit_reader_init (&br, data, size); - - READ_UINT8 (&br, seqhdr->profiletype, 2); - - if (seqhdr->profiletype == GST_VC1_PROFILE_ADVANCED) { - return parse_sequence_header_advanced (seqhdr, &br); - } - - GST_DEBUG ("Parsing sequence header in simple or main mode"); - - if (gst_bit_reader_get_remaining (&br) < 29) + if (parse_sequence_header_struct_c (&br, &seqhdr->struct_c) == + GST_VC1_PARSER_ERROR) goto failed; - /* Reserved bits */ - old_interlaced_mode = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - if (old_interlaced_mode) - GST_WARNING ("Old interlaced mode used"); + /* Convenience field */ + seqhdr->profile = seqhdr->struct_c.profile; - simplehdr->wmvp = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - if (simplehdr->wmvp) - GST_DEBUG ("WMVP mode"); - - seqhdr->frmrtq_postproc = gst_bit_reader_get_bits_uint8_unchecked (&br, 3); - seqhdr->bitrtq_postproc = gst_bit_reader_get_bits_uint8_unchecked (&br, 5); - simplehdr->loop_filter = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - calculate_framerate_bitrate (seqhdr); - - /* Skipping reserved3 bit */ - gst_bit_reader_skip_unchecked (&br, 1); - - simplehdr->multires = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - - /* Skipping reserved4 bit */ - gst_bit_reader_skip_unchecked (&br, 1); - - simplehdr->fastuvmc = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - simplehdr->extended_mv = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - simplehdr->dquant = gst_bit_reader_get_bits_uint8_unchecked (&br, 2); - simplehdr->vstransform = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - - /* Skipping reserved5 bit */ - gst_bit_reader_skip_unchecked (&br, 1); - - simplehdr->overlap = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - simplehdr->syncmarker = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - simplehdr->rangered = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - simplehdr->maxbframes = gst_bit_reader_get_bits_uint8_unchecked (&br, 3); - simplehdr->quantizer = gst_bit_reader_get_bits_uint8_unchecked (&br, 2); - seqhdr->finterpflag = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - - GST_DEBUG ("frmrtq_postproc %u, bitrtq_postproc %u, loop_filter %u, " - "multires %u, fastuvmc %u, extended_mv %u, dquant %u, vstransform %u, " - "overlap %u, syncmarker %u, rangered %u, maxbframes %u, quantizer %u, " - "finterpflag %u", seqhdr->frmrtq_postproc, seqhdr->bitrtq_postproc, - simplehdr->loop_filter, simplehdr->multires, simplehdr->fastuvmc, - simplehdr->extended_mv, simplehdr->dquant, simplehdr->vstransform, - simplehdr->overlap, simplehdr->syncmarker, simplehdr->rangered, - simplehdr->maxbframes, simplehdr->quantizer, seqhdr->finterpflag); - - if (simplehdr->wmvp) { - if (gst_bit_reader_get_remaining (&br) < 29) - goto failed; - - simplehdr->coded_width = gst_bit_reader_get_bits_uint16_unchecked (&br, 11); - simplehdr->coded_height = - gst_bit_reader_get_bits_uint16_unchecked (&br, 11); - simplehdr->framerate = gst_bit_reader_get_bits_uint8_unchecked (&br, 5); - gst_bit_reader_skip_unchecked (&br, 1); - simplehdr->slice_code = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); - - GST_DEBUG ("coded_width %u, coded_height %u, framerate %u slice_code %u", - simplehdr->coded_width, simplehdr->coded_height, simplehdr->framerate, - simplehdr->slice_code); - } + if (seqhdr->profile == GST_VC1_PROFILE_ADVANCED) + return parse_sequence_header_advanced (seqhdr, &br); /* compute height and width */ - seqhdr->mb_height = (simplehdr->coded_height + 15) >> 4; - seqhdr->mb_width = (simplehdr->coded_width + 15) >> 4; + seqhdr->mb_height = (seqhdr->struct_c.coded_height + 15) >> 4; + seqhdr->mb_width = (seqhdr->struct_c.coded_width + 15) >> 4; return GST_VC1_PARSER_OK; @@ -1377,7 +1558,7 @@ gst_vc1_parse_entry_point_header (const guint8 * data, gsize size, { GstBitReader br; guint8 i; - GstVC1AdvancedSeqHdr *advanced = &seqhdr->profile.advanced; + GstVC1AdvancedSeqHdr *advanced = &seqhdr->advanced; g_return_val_if_fail (entrypoint != NULL, GST_VC1_PARSER_ERROR); @@ -1401,8 +1582,7 @@ gst_vc1_parse_entry_point_header (const guint8 * data, gsize size, entrypoint->quantizer = gst_bit_reader_get_bits_uint8_unchecked (&br, 2); if (advanced->hrd_param_flag) { - for (i = 0; i < seqhdr->profile.advanced.hrd_param.hrd_num_leaky_buckets; - i++) + for (i = 0; i < seqhdr->advanced.hrd_param.hrd_num_leaky_buckets; i++) READ_UINT8 (&br, entrypoint->hrd_full[MAX_HRD_NUM_LEAKY_BUCKETS], 8); } @@ -1459,7 +1639,7 @@ gst_vc1_parse_frame_header (const guint8 * data, gsize size, gst_bit_reader_init (&br, data, size); - if (seqhdr->profiletype == GST_VC1_PROFILE_ADVANCED) + if (seqhdr->profile == GST_VC1_PROFILE_ADVANCED) result = parse_frame_header_advanced (&br, framehdr, seqhdr); else result = parse_frame_header (&br, framehdr, seqhdr); diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index aad83fa557..fd792649f8 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -129,10 +129,15 @@ typedef enum typedef struct _GstVC1SeqHdr GstVC1SeqHdr; typedef struct _GstVC1AdvancedSeqHdr GstVC1AdvancedSeqHdr; -typedef struct _GstVC1SimpleMainSeqHdr GstVC1SimpleMainSeqHdr; typedef struct _GstVC1HrdParam GstVC1HrdParam; typedef struct _GstVC1EntryPointHdr GstVC1EntryPointHdr; +typedef struct _GstVC1SeqLayer GstVC1SeqLayer; + +typedef struct _GstVC1SeqStructA GstVC1SeqStructA; +typedef struct _GstVC1SeqStructB GstVC1SeqStructB; +typedef struct _GstVC1SeqStructC GstVC1SeqStructC; + /* Pictures Structures */ typedef struct _GstVC1FrameHdr GstVC1FrameHdr; typedef struct _GstVC1PicAdvanced GstVC1PicAdvanced; @@ -152,37 +157,6 @@ struct _GstVC1HrdParam guint16 hrd_buffer[MAX_HRD_NUM_LEAKY_BUCKETS]; }; -/** - * GstVC1SimpleMainSeqHdr: - * - * Structure for simple and main profile sequence headers specific parameters. - */ -struct _GstVC1SimpleMainSeqHdr -{ - guint8 res_sprite; - guint8 loop_filter; - guint8 multires; - guint8 fastuvmc; - guint8 extended_mv; - guint8 dquant; - guint8 vstransform; - guint8 overlap; - guint8 syncmarker; - guint8 rangered; - guint8 maxbframes; - guint8 quantizer; - - /* This should be filled by user if previously known */ - guint16 coded_width; - /* This should be filled by user if previously known */ - guint16 coded_height; - - /* Wmvp specific */ - guint8 wmvp; /* Specify if the stream is wmp or not */ - guint8 framerate; - guint8 slice_code; -}; - /** * GstVC1EntryPointHdr: * @@ -221,12 +195,15 @@ struct _GstVC1EntryPointHdr struct _GstVC1AdvancedSeqHdr { guint8 level; + guint8 frmrtq_postproc; + guint8 bitrtq_postproc; guint8 postprocflag; guint16 max_coded_width; guint16 max_coded_height; guint8 pulldown; guint8 interlace; guint8 tfcntrflag; + guint8 finterpflag; guint8 psf; guint8 display_ext; guint16 disp_horiz_size; @@ -245,13 +222,80 @@ struct _GstVC1AdvancedSeqHdr guint8 transfer_char; guint8 matrix_coef; guint8 hrd_param_flag; + guint8 colordiff_format; GstVC1HrdParam hrd_param; + /* computed */ + guint framerate; /* Around in fps, 0 if unknown*/ + guint bitrate; /* Around in kpbs, 0 if unknown*/ + /* The last parsed entry point */ GstVC1EntryPointHdr entrypoint; }; +struct _GstVC1SeqStructA +{ + guint32 vert_size; + guint32 horiz_size; +}; + +struct _GstVC1SeqStructB +{ + guint8 level; + guint8 cbr; + guint32 framerate; + + /* In simple and main profiles only */ + guint32 hrd_buffer; + guint32 hrd_rate; +}; + +struct _GstVC1SeqStructC +{ + GstVC1Profile profile; + + /* Only in simple and main profiles */ + guint8 frmrtq_postproc; + guint8 bitrtq_postproc; + guint8 res_sprite; + guint8 loop_filter; + guint8 multires; + guint8 fastuvmc; + guint8 extended_mv; + guint8 dquant; + guint8 vstransform; + guint8 overlap; + guint8 syncmarker; + guint8 rangered; + guint8 maxbframes; + guint8 quantizer; + guint8 finterpflag; + + /* Computed */ + guint framerate; /* Around in fps, 0 if unknown*/ + guint bitrate; /* Around in kpbs, 0 if unknown*/ + + /* This should be filled by user if previously known */ + guint16 coded_width; + /* This should be filled by user if previously known */ + guint16 coded_height; + + /* Wmvp specific */ + guint8 wmvp; /* Specify if the stream is wmp or not */ + /* In the wmvp case, the framerate is not computed but in the bistream */ + guint8 slice_code; +}; + +struct _GstVC1SeqLayer +{ + guint32 numframes; + + GstVC1SeqStructA struct_a; + GstVC1SeqStructB struct_b; + GstVC1SeqStructC struct_c; +}; + /** * GstVC1SeqHdr: * @@ -259,22 +303,15 @@ struct _GstVC1AdvancedSeqHdr */ struct _GstVC1SeqHdr { - guint8 profiletype; - guint8 colordiff_format; - guint8 frmrtq_postproc; - guint8 bitrtq_postproc; - guint8 finterpflag; + GstVC1Profile profile; + + GstVC1SeqStructC struct_c; /* calculated */ - guint framerate; /* Around in fps, 0 if unknown*/ - guint bitrate; /* Around in kpbs, 0 if unknown*/ guint mb_height; guint mb_width; - union { - GstVC1AdvancedSeqHdr advanced; - GstVC1SimpleMainSeqHdr simplemain; - } profile; + GstVC1AdvancedSeqHdr advanced; }; @@ -466,6 +503,24 @@ GstVC1ParserResult gst_vc1_parse_entry_point_header (const guint8 *data, GstVC1EntryPointHdr * entrypoint, GstVC1SeqHdr *seqhdr); +GstVC1ParserResult gst_vc1_parse_sequence_layer (const guint8 *data, + gsize size, + GstVC1SeqLayer * seqlayer); + +GstVC1ParserResult +gst_vc1_parse_sequence_header_struct_a (const guint8 *data, + gsize size, + GstVC1SeqStructA *structa); +GstVC1ParserResult +gst_vc1_parse_sequence_header_struct_b (const guint8 *data, + gsize size, + GstVC1SeqStructB *structb); + +GstVC1ParserResult +gst_vc1_parse_sequence_header_struct_c (const guint8 *data, + gsize size, + GstVC1SeqStructC *structc); + GstVC1ParserResult gst_vc1_parse_frame_header (const guint8 *data, gsize size, GstVC1FrameHdr * framehdr, diff --git a/tests/check/libs/vc1parser.c b/tests/check/libs/vc1parser.c index 1fd9e39a65..0553efc3f6 100644 --- a/tests/check/libs/vc1parser.c +++ b/tests/check/libs/vc1parser.c @@ -799,10 +799,10 @@ GST_START_TEST (test_vc1_identify_bdu) res = gst_vc1_parse_sequence_header (bdu.data + bdu.offset, bdu.size, &hdr); assert_equals_int (res, GST_VC1_PARSER_OK); - assert_equals_int (hdr.profiletype, GST_VC1_PROFILE_ADVANCED); + assert_equals_int (hdr.profile, GST_VC1_PROFILE_ADVANCED); - assert_equals_int (hdr.profile.advanced.level, GST_VC1_LEVEL_L1); - assert_equals_int (hdr.colordiff_format, 1); + assert_equals_int (hdr.advanced.level, GST_VC1_LEVEL_L1); + assert_equals_int (hdr.advanced.colordiff_format, 1); res = gst_vc1_identify_next_bdu (sequence_fullframe + bdu.sc_offset + bdu.size, sizeof (sequence_fullframe) - bdu.sc_offset - bdu.size, &bdu); @@ -822,29 +822,29 @@ GST_START_TEST (test_vc1_parse_p_frame_header_main) GstVC1FrameHdr framehdr; GstVC1SeqHdr seqhdr; - GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain; + GstVC1SeqStructC *structc = &seqhdr.struct_c; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; - simplehdr->coded_height = 240; - simplehdr->coded_width = 320; + structc->coded_height = 240; + structc->coded_width = 320; assert_equals_int (gst_vc1_parse_sequence_header (pframe_header_main, sizeof (pframe_header_main), &seqhdr), GST_VC1_PARSER_OK); - assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN); + assert_equals_int (seqhdr.profile, GST_VC1_PROFILE_MAIN); - assert_equals_int (seqhdr.frmrtq_postproc, 7); - assert_equals_int (seqhdr.bitrtq_postproc, 2); - assert_equals_int (simplehdr->loop_filter, 1); - assert_equals_int (simplehdr->multires, 0); - assert_equals_int (simplehdr->extended_mv, 0); - assert_equals_int (simplehdr->rangered, 0); - assert_equals_int (simplehdr->vstransform, 1); - assert_equals_int (simplehdr->overlap, 1); - assert_equals_int (simplehdr->syncmarker, 0); - assert_equals_int (simplehdr->dquant, 1); - assert_equals_int (simplehdr->quantizer, 0); - assert_equals_int (simplehdr->maxbframes, 1); + assert_equals_int (structc->frmrtq_postproc, 7); + assert_equals_int (structc->bitrtq_postproc, 2); + assert_equals_int (structc->loop_filter, 1); + assert_equals_int (structc->multires, 0); + assert_equals_int (structc->extended_mv, 0); + assert_equals_int (structc->rangered, 0); + assert_equals_int (structc->vstransform, 1); + assert_equals_int (structc->overlap, 1); + assert_equals_int (structc->syncmarker, 0); + assert_equals_int (structc->dquant, 1); + assert_equals_int (structc->quantizer, 0); + assert_equals_int (structc->maxbframes, 1); assert_equals_int (gst_vc1_parse_frame_header (pframe_main, sizeof (pframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK); @@ -866,31 +866,31 @@ GST_START_TEST (test_vc1_parse_b_frame_header_main) GstVC1FrameHdr framehdr; GstVC1SeqHdr seqhdr; - GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain; + GstVC1SeqStructC *structc = &seqhdr.struct_c; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; - simplehdr->coded_height = 240; - simplehdr->coded_width = 320; + structc->coded_height = 240; + structc->coded_width = 320; assert_equals_int (gst_vc1_parse_sequence_header (bframe_header_main, sizeof (bframe_header_main), &seqhdr), GST_VC1_PARSER_OK); - assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN); + assert_equals_int (seqhdr.profile, GST_VC1_PROFILE_MAIN); assert_equals_int (seqhdr.mb_height, 15); assert_equals_int (seqhdr.mb_width, 20); - assert_equals_int (seqhdr.frmrtq_postproc, 7); - assert_equals_int (seqhdr.bitrtq_postproc, 3); - assert_equals_int (simplehdr->loop_filter, 1); - assert_equals_int (simplehdr->multires, 0); - assert_equals_int (simplehdr->extended_mv, 0); - assert_equals_int (simplehdr->rangered, 0); - assert_equals_int (simplehdr->vstransform, 1); - assert_equals_int (simplehdr->overlap, 1); - assert_equals_int (simplehdr->syncmarker, 0); - assert_equals_int (simplehdr->dquant, 1); - assert_equals_int (simplehdr->quantizer, 0); - assert_equals_int (simplehdr->maxbframes, 1); + assert_equals_int (structc->frmrtq_postproc, 7); + assert_equals_int (structc->bitrtq_postproc, 3); + assert_equals_int (structc->loop_filter, 1); + assert_equals_int (structc->multires, 0); + assert_equals_int (structc->extended_mv, 0); + assert_equals_int (structc->rangered, 0); + assert_equals_int (structc->vstransform, 1); + assert_equals_int (structc->overlap, 1); + assert_equals_int (structc->syncmarker, 0); + assert_equals_int (structc->dquant, 1); + assert_equals_int (structc->quantizer, 0); + assert_equals_int (structc->maxbframes, 1); assert_equals_int (gst_vc1_parse_frame_header (bframe_main, sizeof (bframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK); @@ -915,28 +915,28 @@ GST_START_TEST (test_vc1_parse_bi_frame_header_main) GstVC1FrameHdr framehdr; GstVC1SeqHdr seqhdr; - GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain; + GstVC1SeqStructC *structc = &seqhdr.struct_c; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; - simplehdr->coded_height = 240; - simplehdr->coded_width = 320; + structc->coded_height = 240; + structc->coded_width = 320; assert_equals_int (gst_vc1_parse_sequence_header (i_bi_frame_header, sizeof (i_bi_frame_header), &seqhdr), GST_VC1_PARSER_OK); - assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN); - assert_equals_int (seqhdr.frmrtq_postproc, 7); - assert_equals_int (seqhdr.bitrtq_postproc, 7); - assert_equals_int (simplehdr->loop_filter, 1); - assert_equals_int (simplehdr->multires, 0); - assert_equals_int (simplehdr->extended_mv, 0); - assert_equals_int (simplehdr->rangered, 0); - assert_equals_int (simplehdr->vstransform, 1); - assert_equals_int (simplehdr->overlap, 1); - assert_equals_int (simplehdr->syncmarker, 0); - assert_equals_int (simplehdr->dquant, 1); - assert_equals_int (simplehdr->quantizer, 0); - assert_equals_int (simplehdr->maxbframes, 1); + assert_equals_int (seqhdr.profile, GST_VC1_PROFILE_MAIN); + assert_equals_int (structc->frmrtq_postproc, 7); + assert_equals_int (structc->bitrtq_postproc, 7); + assert_equals_int (structc->loop_filter, 1); + assert_equals_int (structc->multires, 0); + assert_equals_int (structc->extended_mv, 0); + assert_equals_int (structc->rangered, 0); + assert_equals_int (structc->vstransform, 1); + assert_equals_int (structc->overlap, 1); + assert_equals_int (structc->syncmarker, 0); + assert_equals_int (structc->dquant, 1); + assert_equals_int (structc->quantizer, 0); + assert_equals_int (structc->maxbframes, 1); assert_equals_int (gst_vc1_parse_frame_header (biframe_main, sizeof (biframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK); @@ -958,28 +958,28 @@ GST_START_TEST (test_vc1_parse_i_frame_header_main) GstVC1FrameHdr framehdr; GstVC1SeqHdr seqhdr; - GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain; + GstVC1SeqStructC *structc = &seqhdr.struct_c; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; - simplehdr->coded_height = 240; - simplehdr->coded_width = 320; + structc->coded_height = 240; + structc->coded_width = 320; assert_equals_int (gst_vc1_parse_sequence_header (i_bi_frame_header, sizeof (i_bi_frame_header), &seqhdr), GST_VC1_PARSER_OK); - assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN); - assert_equals_int (seqhdr.frmrtq_postproc, 7); - assert_equals_int (seqhdr.bitrtq_postproc, 7); - assert_equals_int (simplehdr->loop_filter, 1); - assert_equals_int (simplehdr->multires, 0); - assert_equals_int (simplehdr->extended_mv, 0); - assert_equals_int (simplehdr->rangered, 0); - assert_equals_int (simplehdr->vstransform, 1); - assert_equals_int (simplehdr->overlap, 1); - assert_equals_int (simplehdr->syncmarker, 0); - assert_equals_int (simplehdr->dquant, 1); - assert_equals_int (simplehdr->quantizer, 0); - assert_equals_int (simplehdr->maxbframes, 1); + assert_equals_int (seqhdr.profile, GST_VC1_PROFILE_MAIN); + assert_equals_int (structc->frmrtq_postproc, 7); + assert_equals_int (structc->bitrtq_postproc, 7); + assert_equals_int (structc->loop_filter, 1); + assert_equals_int (structc->multires, 0); + assert_equals_int (structc->extended_mv, 0); + assert_equals_int (structc->rangered, 0); + assert_equals_int (structc->vstransform, 1); + assert_equals_int (structc->overlap, 1); + assert_equals_int (structc->syncmarker, 0); + assert_equals_int (structc->dquant, 1); + assert_equals_int (structc->quantizer, 0); + assert_equals_int (structc->maxbframes, 1); assert_equals_int (gst_vc1_parse_frame_header (iframe_main, sizeof (iframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK); @@ -1001,23 +1001,23 @@ GST_START_TEST (test_vc1_parse_i_frame_header_adv) GstVC1FrameHdr framehdr; GstVC1SeqHdr seqhdr; - GstVC1AdvancedSeqHdr *advhdr = &seqhdr.profile.advanced; + GstVC1AdvancedSeqHdr *advhdr = &seqhdr.advanced; GstVC1EntryPointHdr *entrypt = &advhdr->entrypoint; GstVC1PicAdvanced *pic = &framehdr.pic.advanced; assert_equals_int (gst_vc1_parse_sequence_header (iframe_adv_hdr, sizeof (iframe_adv_hdr), &seqhdr), GST_VC1_PARSER_OK); - assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_ADVANCED); + assert_equals_int (seqhdr.profile, GST_VC1_PROFILE_ADVANCED); assert_equals_int (advhdr->level, GST_VC1_LEVEL_L3); - assert_equals_int (seqhdr.frmrtq_postproc, 7); - assert_equals_int (seqhdr.bitrtq_postproc, 31); + assert_equals_int (advhdr->frmrtq_postproc, 7); + assert_equals_int (advhdr->bitrtq_postproc, 31); assert_equals_int (advhdr->postprocflag, 0); assert_equals_int (advhdr->max_coded_width, 1920); assert_equals_int (advhdr->max_coded_height, 1080); assert_equals_int (advhdr->interlace, 1); assert_equals_int (advhdr->tfcntrflag, 0); - assert_equals_int (seqhdr.finterpflag, 0); + assert_equals_int (advhdr->finterpflag, 0); assert_equals_int (advhdr->display_ext, 1); assert_equals_int (advhdr->disp_horiz_size, 1920); @@ -1062,23 +1062,23 @@ GST_START_TEST (test_vc1_parse_b_frame_header_adv) GstVC1FrameHdr framehdr; GstVC1SeqHdr seqhdr; - GstVC1AdvancedSeqHdr *advhdr = &seqhdr.profile.advanced; + GstVC1AdvancedSeqHdr *advhdr = &seqhdr.advanced; GstVC1EntryPointHdr *entrypt = &advhdr->entrypoint; GstVC1PicAdvanced *pic = &framehdr.pic.advanced; assert_equals_int (gst_vc1_parse_sequence_header (iframe_adv_hdr, sizeof (iframe_adv_hdr), &seqhdr), GST_VC1_PARSER_OK); - assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_ADVANCED); + assert_equals_int (seqhdr.profile, GST_VC1_PROFILE_ADVANCED); assert_equals_int (advhdr->level, GST_VC1_LEVEL_L3); - assert_equals_int (seqhdr.frmrtq_postproc, 7); - assert_equals_int (seqhdr.bitrtq_postproc, 31); + assert_equals_int (advhdr->frmrtq_postproc, 7); + assert_equals_int (advhdr->bitrtq_postproc, 31); assert_equals_int (advhdr->postprocflag, 0); assert_equals_int (advhdr->max_coded_width, 1920); assert_equals_int (advhdr->max_coded_height, 1080); assert_equals_int (advhdr->interlace, 1); assert_equals_int (advhdr->tfcntrflag, 0); - assert_equals_int (seqhdr.finterpflag, 0); + assert_equals_int (advhdr->finterpflag, 0); assert_equals_int (advhdr->display_ext, 1); assert_equals_int (advhdr->disp_horiz_size, 1920); @@ -1132,23 +1132,23 @@ GST_START_TEST (test_vc1_parse_p_frame_header_adv) GstVC1FrameHdr framehdr; GstVC1SeqHdr seqhdr; - GstVC1AdvancedSeqHdr *advhdr = &seqhdr.profile.advanced; + GstVC1AdvancedSeqHdr *advhdr = &seqhdr.advanced; GstVC1EntryPointHdr *entrypt = &advhdr->entrypoint; GstVC1PicAdvanced *pic = &framehdr.pic.advanced; assert_equals_int (gst_vc1_parse_sequence_header (iframe_adv_hdr, sizeof (iframe_adv_hdr), &seqhdr), GST_VC1_PARSER_OK); - assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_ADVANCED); + assert_equals_int (seqhdr.profile, GST_VC1_PROFILE_ADVANCED); assert_equals_int (advhdr->level, GST_VC1_LEVEL_L3); - assert_equals_int (seqhdr.frmrtq_postproc, 7); - assert_equals_int (seqhdr.bitrtq_postproc, 31); + assert_equals_int (advhdr->frmrtq_postproc, 7); + assert_equals_int (advhdr->bitrtq_postproc, 31); assert_equals_int (advhdr->postprocflag, 0); assert_equals_int (advhdr->max_coded_width, 1920); assert_equals_int (advhdr->max_coded_height, 1080); assert_equals_int (advhdr->interlace, 1); assert_equals_int (advhdr->tfcntrflag, 0); - assert_equals_int (seqhdr.finterpflag, 0); + assert_equals_int (advhdr->finterpflag, 0); assert_equals_int (advhdr->display_ext, 1); assert_equals_int (advhdr->disp_horiz_size, 1920); From 1a1935dacffe4796701fbf202898923ba1300f56 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Wed, 5 Oct 2011 16:40:47 -0300 Subject: [PATCH 13/26] codecparsers: VC1: Implement FrameLayer parsing --- gst-libs/gst/codecparsers/gstvc1parser.c | 41 ++++++++++++++++++++++++ gst-libs/gst/codecparsers/gstvc1parser.h | 17 ++++++++++ 2 files changed, 58 insertions(+) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index aad915d8b8..fe24d4e6fb 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -1617,6 +1617,47 @@ failed: return GST_VC1_PARSER_ERROR; } +/** + * gst_vc1_parse_frame_layer: + * @data: The data to parse + * @size: the size of @data + * @framelayer: The #GstVC1FrameLayer to fill. + * + * Parses @data, and fills @framelayer fields. + * + * Returns: a #GstVC1ParserResult + */ +GstVC1ParserResult +gst_vc1_parse_frame_layer (const guint8 * data, gsize size, + GstVC1FrameLayer * framelayer) +{ + GstBitReader br = GST_BIT_READER_INIT (data, size); + + if (gst_bit_reader_get_remaining (&br) < 64) { + GST_WARNING ("Could not parse frame layer"); + + return GST_VC1_PARSER_ERROR; + } + + /* set default values */ + framelayer->skiped_p_frame = 0; + + framelayer->key = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + gst_bit_reader_skip_unchecked (&br, 7); + + framelayer->framesize = gst_bit_reader_get_bits_uint32_unchecked (&br, 24); + + if (framelayer->framesize == 0 || framelayer->framesize == 1) + framelayer->skiped_p_frame = 1; + + /* compute next_framelayer_offset */ + framelayer->next_framelayer_offset = framelayer->framesize + 8; + + framelayer->timestamp = gst_bit_reader_get_bits_uint32_unchecked (&br, 32); + + return GST_VC1_PARSER_OK; +} + /** * gst_vc1_parse_frame_header: * @data: The data to parse diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index fd792649f8..d058f0ff4d 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -139,6 +139,7 @@ typedef struct _GstVC1SeqStructB GstVC1SeqStructB; typedef struct _GstVC1SeqStructC GstVC1SeqStructC; /* Pictures Structures */ +typedef struct _GstVC1FrameLayer GstVC1FrameLayer; typedef struct _GstVC1FrameHdr GstVC1FrameHdr; typedef struct _GstVC1PicAdvanced GstVC1PicAdvanced; typedef struct _GstVC1PicSimpleMain GstVC1PicSimpleMain; @@ -438,6 +439,18 @@ struct _GstVC1VopDquant }; +struct _GstVC1FrameLayer +{ + guint8 key; + guint32 framesize; + + guint32 timestamp; + + /* calculated */ + guint32 next_framelayer_offset; + guint8 skiped_p_frame; +}; + /** * GstVC1FrameHdr: * @@ -521,6 +534,10 @@ gst_vc1_parse_sequence_header_struct_c (const guint8 *data, gsize size, GstVC1SeqStructC *structc); +GstVC1ParserResult gst_vc1_parse_frame_layer (const guint8 *data, + gsize size, + GstVC1FrameLayer * framelayer); + GstVC1ParserResult gst_vc1_parse_frame_header (const guint8 *data, gsize size, GstVC1FrameHdr * framehdr, From 52d8510ee0914fadb97312b27b5399d3a8922ec9 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Tue, 4 Oct 2011 11:57:37 +0200 Subject: [PATCH 14/26] codecparsers: vc1: fix VLC decoding. --- gst-libs/gst/codecparsers/gstvc1parser.c | 265 ++++++++++++----------- 1 file changed, 137 insertions(+), 128 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index fe24d4e6fb..a3231508da 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -100,6 +100,13 @@ ensure_debug_category (void) } \ } G_STMT_END +typedef struct _VLCTable +{ + guint value; + guint cword; + guint cbits; +} VLCTable; + const guint8 vc1_pquant_table[3][32] = { { /* Implicit quantizer */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 6, 7, 8, 9, 10, 11, 12, @@ -140,30 +147,34 @@ const guint8 mvmode2_table[2][4] = { GST_VC1_MVMODE_1MV_HPEL_BILINEAR} }; -static const guint bfraction_vlc_table[] = { - 0x00, 3, 128, - 0x01, 3, 85, - 0x02, 3, 170, - 0x03, 3, 64, - 0x04, 3, 192, - 0x05, 3, 51, - 0x06, 3, 102, - 0x70, 3, 153, - 0x71, 7, 204, - 0x72, 7, 43, - 0x73, 7, 215, - 0x74, 7, 37, - 0x75, 7, 74, - 0x76, 7, 111, - 0x77, 7, 148, - 0x78, 7, 185, - 0x79, 7, 222, - 0x7a, 7, 32, - 0x7b, 7, 96, - 0x7c, 7, 160, - 0x7d, 7, 224, - 0x7e, 7, 0, /* Indicate sthat it is smtpe reserved */ - 0x7f, 7, GST_VC1_PICTURE_TYPE_BI +#define GST_VC1_BFRACTION_RESERVED (GST_VC1_BFRACTION_BASIS + 1) +#define GST_VC1_BFRACTION_PTYPE_BI (GST_VC1_BFRACTION_BASIS + 2) + +/* Table 40: BFRACTION VLC Table */ +static const VLCTable vc1_bfraction_vlc_table[] = { + {GST_VC1_BFRACTION_BASIS / 2, 0x00, 3}, + {GST_VC1_BFRACTION_BASIS / 3, 0x01, 3}, + {(GST_VC1_BFRACTION_BASIS * 2) / 3, 0x02, 3}, + {GST_VC1_BFRACTION_BASIS / 4, 0x02, 3}, + {(GST_VC1_BFRACTION_BASIS * 3) / 4, 0x04, 3}, + {GST_VC1_BFRACTION_BASIS / 5, 0x05, 3}, + {(GST_VC1_BFRACTION_BASIS * 2) / 5, 0x06, 3}, + {(GST_VC1_BFRACTION_BASIS * 3) / 5, 0x70, 7}, + {(GST_VC1_BFRACTION_BASIS * 4) / 5, 0x71, 7}, + {GST_VC1_BFRACTION_BASIS / 6, 0x72, 7}, + {(GST_VC1_BFRACTION_BASIS * 5) / 6, 0x73, 7}, + {GST_VC1_BFRACTION_BASIS / 7, 0x74, 7}, + {(GST_VC1_BFRACTION_BASIS * 2) / 7, 0x75, 7}, + {(GST_VC1_BFRACTION_BASIS * 3) / 7, 0x76, 7}, + {(GST_VC1_BFRACTION_BASIS * 4) / 7, 0x77, 7}, + {(GST_VC1_BFRACTION_BASIS * 5) / 7, 0x78, 7}, + {(GST_VC1_BFRACTION_BASIS * 6) / 7, 0x79, 7}, + {GST_VC1_BFRACTION_BASIS / 8, 0x7a, 7}, + {(GST_VC1_BFRACTION_BASIS * 3) / 8, 0x7b, 7}, + {(GST_VC1_BFRACTION_BASIS * 5) / 8, 0x7c, 7}, + {(GST_VC1_BFRACTION_BASIS * 7) / 8, 0x7d, 7}, + {GST_VC1_BFRACTION_RESERVED, 0x7e, 7}, + {GST_VC1_BFRACTION_PTYPE_BI, 0x7f, 7} }; /* Imode types */ @@ -178,88 +189,91 @@ enum IMODE_COLSKIP }; -static const guint imode_vlc_table[] = { - 0x02, 2, IMODE_NORM2, /* 10 */ - 0x03, 2, IMODE_NORM6, /* 11 */ - 0x02, 3, IMODE_ROWSKIP, /* 010 */ - 0x03, 3, IMODE_COLSKIP, /* 011 */ - 0x01, 3, IMODE_DIFF2, /* 001 */ - 0x01, 4, IMODE_DIFF6, /* 0001 */ - 0x00, 4, IMODE_RAW /* 0000 */ +/* Table 69: IMODE VLC Codetable */ +static const VLCTable vc1_imode_vlc_table[] = { + {IMODE_NORM2, 0x02, 2}, + {IMODE_NORM6, 0x03, 2}, + {IMODE_ROWSKIP, 0x02, 3}, + {IMODE_COLSKIP, 0x03, 3}, + {IMODE_DIFF2, 0x01, 3}, + {IMODE_DIFF6, 0x01, 4}, + {IMODE_RAW, 0x00, 4} }; -const guint vc1_norm2_codes_vlc_table[] = { - 0x00, 1, 1, - 0x03, 2, 3, - 0x04, 3, 3, - 0x05, 3, 2 +/* Table 80: Norm-2/Diff-2 Code Table */ +static const VLCTable vc1_norm2_vlc_table[4] = { + {0, 0, 1}, + {2, 4, 3}, + {1, 5, 3}, + {3, 3, 2} }; -const guint norm6_vlc_table[256] = { - 0x001, 1, 0, - 0x002, 4, 0, - 0x003, 4, 0, - 0x004, 4, 0, - 0x005, 4, 0, - 0x006, 4, 0, - 0x007, 4, 0, - 0x007, 6, 0, - 0x000, 8, 0, - 0x001, 8, 0, - 0x002, 8, 0, - 0x003, 8, 0, - 0x004, 8, 0, - 0x005, 8, 0, - 0x006, 8, 0, - 0x007, 8, 0, - 0x008, 8, 0, - 0x009, 8, 0, - 0x00A, 8, 0, - 0x00B, 8, 0, - 0x00C, 8, 0, - 0x00D, 8, 0, - 0x00E, 8, 0, - 0x037, 9, 0, - 0x036, 9, 0, - 0x035, 9, 0, - 0x034, 9, 0, - 0x033, 9, 0, - 0x032, 9, 0, - 0x047, 10, 0, - 0x04B, 10, 0, - 0x04D, 10, 0, - 0x04E, 10, 0, - 0x30E, 13, 0, - 0x053, 10, 0, - 0x055, 10, 0, - 0x056, 10, 0, - 0x30D, 13, 0, - 0x059, 10, 0, - 0x05A, 10, 0, - 0x30C, 13, 0, - 0x05C, 10, 0, - 0x30B, 13, 0, - 0x30A, 13, 0, - 0x043, 10, 0, - 0x045, 10, 0, - 0x046, 10, 0, - 0x309, 13, 0, - 0x049, 10, 0, - 0x04A, 10, 0, - 0x308, 13, 0, - 0x04C, 10, 0, - 0x307, 13, 0, - 0x306, 13, 0, - 0x051, 10, 0, - 0x052, 10, 0, - 0x305, 13, 0, - 0x054, 10, 0, - 0x304, 13, 0, - 0x303, 13, 0, - 0x058, 10, 0, - 0x302, 13, 0, - 0x301, 13, 0, - 0x300, 13, 0 +/* Table 81: Code table for 3x2 and 2x3 tiles */ +static const VLCTable vc1_norm6_vlc_table[64] = { + {0, 1, 1}, + {1, 2, 4}, + {2, 3, 4}, + {3, 0, 8}, + {4, 4, 4}, + {5, 1, 8}, + {6, 2, 8}, + {7, (2 << 5) | 7, 10}, + {8, 5, 4}, + {9, 3, 8}, + {10, 4, 8}, + {11, (2 << 5) | 11, 10}, + {12, 5, 8}, + {13, (2 << 5) | 13, 10}, + {14, (2 << 5) | 14, 10}, + {15, (3 << 8) | 14, 13}, + {16, 6, 4}, + {17, 6, 8}, + {18, 7, 8}, + {19, (2 << 5) | 19, 10}, + {20, 8, 8}, + {21, (2 << 5) | 21, 10}, + {22, (2 << 5) | 22, 10}, + {23, (3 << 8) | 13, 13}, + {24, 9, 8}, + {25, (2 << 5) | 25, 10}, + {26, (2 << 5) | 26, 10}, + {27, (3 << 8) | 12, 13}, + {28, (2 << 5) | 28, 10}, + {29, (3 << 8) | 11, 13}, + {30, (3 << 8) | 10, 13}, + {31, (3 << 4) | 7, 9}, + {32, 7, 4}, + {33, 10, 8}, + {34, 11, 8}, + {35, (2 << 5) | 3, 10}, + {36, 12, 8}, + {37, (2 << 5) | 5, 10}, + {38, (2 << 5) | 6, 10}, + {39, (3 << 8) | 9, 13}, + {40, 13, 8}, + {41, (2 << 5) | 9, 10}, + {42, (2 << 5) | 10, 10}, + {43, (3 << 8) | 8, 13}, + {44, (2 << 5) | 12, 10}, + {45, (3 << 8) | 7, 13}, + {46, (3 << 8) | 6, 13}, + {47, (3 << 4) | 6, 9}, + {48, 14, 8}, + {49, (2 << 5) | 17, 10}, + {50, (2 << 5) | 18, 10}, + {51, (3 << 8) | 5, 13}, + {52, (2 << 5) | 20, 10}, + {53, (3 << 8) | 4, 13}, + {54, (3 << 8) | 3, 13}, + {55, (3 << 4) | 5, 9}, + {56, (2 << 5) | 24, 10}, + {57, (3 << 8) | 2, 13}, + {58, (3 << 8) | 1, 13}, + {59, (3 << 4) | 4, 9}, + {60, (3 << 8) | 0, 13}, + {61, (3 << 4) | 3, 9}, + {62, (3 << 4) | 2, 9}, + {63, (3 << 1) | 1, 6} }; static inline guint8 @@ -345,32 +359,26 @@ calculate_nb_pan_scan_win (GstVC1AdvancedSeqHdr * advseqhdr, } } - -/** - * table should look like: - * {Value, nbBits, Meaning, - * ... - * } nbBits must be increasing - */ static gboolean -decode_vlc (GstBitReader * br, guint * res, const guint * table, guint length) +decode_vlc (GstBitReader * br, guint * res, const VLCTable * table, + guint length) { guint8 i; guint cbits = 0; guint32 value = 0; - for (i = 0; i < length; i += 3) { - if (cbits != table[i + 1]) { - cbits = table[i + 1]; + for (i = 0; i < length; i++) { + if (cbits != table[i].cbits) { + cbits = table[i].cbits; if (!gst_bit_reader_peek_bits_uint32 (br, &value, cbits)) { goto failed; } } - if (value == table[i]) { + if (value == table[i].cword) { SKIP (br, cbits); if (res) - *res = table[i + 2]; + *res = table[i].value; return TRUE; } @@ -393,7 +401,8 @@ bitplane_decoding (GstBitReader * br, guint height, guint i, j, offset = 0; SKIP (br, 1); - if (!decode_vlc (br, &imode, imode_vlc_table, G_N_ELEMENTS (imode_vlc_table))) + if (!decode_vlc (br, &imode, vc1_imode_vlc_table, + G_N_ELEMENTS (vc1_imode_vlc_table))) goto failed; switch (imode) { @@ -415,8 +424,8 @@ bitplane_decoding (GstBitReader * br, guint height, for (i = offset; i < height * width; i += 2) { /*guint x; */ - if (!decode_vlc (br, NULL, vc1_norm2_codes_vlc_table, - G_N_ELEMENTS (vc1_norm2_codes_vlc_table))) { + if (!decode_vlc (br, NULL, vc1_norm2_vlc_table, + G_N_ELEMENTS (vc1_norm2_vlc_table))) { goto failed; } } @@ -431,8 +440,8 @@ bitplane_decoding (GstBitReader * br, guint height, for (i = 0; i < height; i += 3) { for (j = width & 1; j < width; j += 2) { - if (!decode_vlc (br, NULL, norm6_vlc_table, - G_N_ELEMENTS (norm6_vlc_table))) { + if (!decode_vlc (br, NULL, vc1_norm6_vlc_table, + G_N_ELEMENTS (vc1_norm6_vlc_table))) { goto failed; } } @@ -440,8 +449,8 @@ bitplane_decoding (GstBitReader * br, guint height, } else { for (i = height & 1; i < height; i += 2) { for (j = width % 3; j < width; j += 3) { - if (!decode_vlc (br, NULL, norm6_vlc_table, - G_N_ELEMENTS (norm6_vlc_table))) { + if (!decode_vlc (br, NULL, vc1_norm6_vlc_table, + G_N_ELEMENTS (vc1_norm6_vlc_table))) { goto failed; } } @@ -806,13 +815,13 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, } if (framehdr->ptype == GST_VC1_PICTURE_TYPE_B) { - if (!decode_vlc (br, (guint *) & pic->bfraction, bfraction_vlc_table, - G_N_ELEMENTS (bfraction_vlc_table))) + if (!decode_vlc (br, (guint *) & pic->bfraction, vc1_bfraction_vlc_table, + G_N_ELEMENTS (vc1_bfraction_vlc_table))) goto failed; GST_DEBUG ("bfraction %u", pic->bfraction); - if (pic->bfraction == GST_VC1_PICTURE_TYPE_BI) { + if (pic->bfraction == GST_VC1_BFRACTION_PTYPE_BI) { framehdr->ptype = GST_VC1_PICTURE_TYPE_BI; } @@ -1033,11 +1042,11 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, if (framehdr->ptype == GST_VC1_PICTURE_TYPE_B) { - if (!decode_vlc (br, (guint *) & pic->bfraction, bfraction_vlc_table, - G_N_ELEMENTS (bfraction_vlc_table))) + if (!decode_vlc (br, (guint *) & pic->bfraction, vc1_bfraction_vlc_table, + G_N_ELEMENTS (vc1_bfraction_vlc_table))) goto failed; - if (pic->bfraction == GST_VC1_PICTURE_TYPE_BI) { + if (pic->bfraction == GST_VC1_BFRACTION_PTYPE_BI) { framehdr->ptype = GST_VC1_PICTURE_TYPE_BI; } GST_DEBUG ("bfraction= %d", pic->bfraction); From ac552a4f82f170fb314d42e5919395f2af2fc555 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Tue, 4 Oct 2011 14:04:42 +0200 Subject: [PATCH 15/26] codecparsers: vc1: fix BFRACTION parser (values range + overflow). --- gst-libs/gst/codecparsers/gstvc1parser.c | 15 ++++++++------- gst-libs/gst/codecparsers/gstvc1parser.h | 9 ++++++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index a3231508da..0c4455ed4a 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -147,9 +147,6 @@ const guint8 mvmode2_table[2][4] = { GST_VC1_MVMODE_1MV_HPEL_BILINEAR} }; -#define GST_VC1_BFRACTION_RESERVED (GST_VC1_BFRACTION_BASIS + 1) -#define GST_VC1_BFRACTION_PTYPE_BI (GST_VC1_BFRACTION_BASIS + 2) - /* Table 40: BFRACTION VLC Table */ static const VLCTable vc1_bfraction_vlc_table[] = { {GST_VC1_BFRACTION_BASIS / 2, 0x00, 3}, @@ -815,10 +812,12 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, } if (framehdr->ptype == GST_VC1_PICTURE_TYPE_B) { - if (!decode_vlc (br, (guint *) & pic->bfraction, vc1_bfraction_vlc_table, + guint bfraction; + if (!decode_vlc (br, &bfraction, vc1_bfraction_vlc_table, G_N_ELEMENTS (vc1_bfraction_vlc_table))) goto failed; + pic->bfraction = bfraction; GST_DEBUG ("bfraction %u", pic->bfraction); if (pic->bfraction == GST_VC1_BFRACTION_PTYPE_BI) { @@ -1041,15 +1040,17 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, if (framehdr->ptype == GST_VC1_PICTURE_TYPE_B) { - - if (!decode_vlc (br, (guint *) & pic->bfraction, vc1_bfraction_vlc_table, + guint bfraction; + if (!decode_vlc (br, &bfraction, vc1_bfraction_vlc_table, G_N_ELEMENTS (vc1_bfraction_vlc_table))) goto failed; + pic->bfraction = bfraction; + GST_DEBUG ("bfraction %d", pic->bfraction); + if (pic->bfraction == GST_VC1_BFRACTION_PTYPE_BI) { framehdr->ptype = GST_VC1_PICTURE_TYPE_BI; } - GST_DEBUG ("bfraction= %d", pic->bfraction); } if (framehdr->ptype == GST_VC1_PICTURE_TYPE_I || diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index d058f0ff4d..08293e54f8 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -37,7 +37,10 @@ G_BEGIN_DECLS * @GST_VC1_BFRACTION_BASIS: The @bfraction variable should be divided * by this constant to have the actual value. */ -#define GST_VC1_BFRACTION_BASIS 256 +#define GST_VC1_BFRACTION_BASIS 840 + +#define GST_VC1_BFRACTION_RESERVED (GST_VC1_BFRACTION_BASIS + 1) +#define GST_VC1_BFRACTION_PTYPE_BI (GST_VC1_BFRACTION_BASIS + 2) typedef enum { GST_VC1_END_OF_SEQ = 0x0A, @@ -350,7 +353,7 @@ struct _GstVC1PicSimpleMain /* B and BI picture only * Should be divided by #GST_VC1_BFRACTION_BASIS * to get the real value. */ - guint8 bfraction; + guint16 bfraction; /* Biplane value, those fields only mention the fact * that the bitplane is in raw mode or not */ @@ -392,7 +395,7 @@ struct _GstVC1PicAdvanced /* B and BI picture only * Should be divided by #GST_VC1_BFRACTION_BASIS * to get the real value. */ - guint8 bfraction; + guint16 bfraction; /* ppic */ guint8 mvmode2; From ef5b8ef5811fbc1ffdc0d10330fb432dfc4ce122 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Tue, 4 Oct 2011 15:16:04 +0200 Subject: [PATCH 16/26] codecparsers: vc1: Implement bitplanes handling properly Add a new GstVC1BitPlanes API. --- docs/libs/gst-plugins-bad-libs-sections.txt | 4 + gst-libs/gst/codecparsers/gstvc1parser.c | 333 +++++++++++++++----- gst-libs/gst/codecparsers/gstvc1parser.h | 23 ++ tests/check/libs/vc1parser.c | 25 +- 4 files changed, 304 insertions(+), 81 deletions(-) diff --git a/docs/libs/gst-plugins-bad-libs-sections.txt b/docs/libs/gst-plugins-bad-libs-sections.txt index 4b5e221eac..7976c25777 100644 --- a/docs/libs/gst-plugins-bad-libs-sections.txt +++ b/docs/libs/gst-plugins-bad-libs-sections.txt @@ -81,6 +81,10 @@ gst_vc1_parse_sequence_header_struct_b gst_vc1_parse_sequence_header_struct_c gst_vc1_parse_entry_point_header gst_vc1_parse_frame_header +gst_vc1_bitplanes_new +gst_vc1_bitplanes_free +gst_vc1_bitplanes_free_1 +gst_vc1_bitplanes_ensure_size diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 0c4455ed4a..bf555f239b 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -273,49 +273,69 @@ static const VLCTable vc1_norm6_vlc_table[64] = { {63, (3 << 1) | 1, 6} }; -static inline guint8 -decode_colskip (GstBitReader * br, guint width, guint height) +static inline gboolean +decode_colskip (GstBitReader * br, guint8 * data, guint width, guint height, + guint stride) { - guint i; + guint x, y; guint8 colskip; - GST_DEBUG ("Colskip rowskip"); + GST_DEBUG ("Parsing colskip"); - for (i = 0; i < height; i++) { + for (x = 0; x < width; x++) { READ_UINT8 (br, colskip, 1); - if (colskip) - SKIP (br, width); + if (data) { + if (colskip) { + for (y = 0; y < height; y++) + READ_UINT8 (br, data[y * stride], 1); + } else { + for (y = 0; y < height; y++) + data[y * stride] = 0; + } + data++; + } else if (colskip) + SKIP (br, height); } - return 1; + return TRUE; failed: GST_WARNING ("Failed to parse colskip"); - return 0; + return FALSE; } -static inline guint8 -decode_rowskip (GstBitReader * br, guint width, guint height) +static inline gboolean +decode_rowskip (GstBitReader * br, guint8 * data, guint width, guint height, + guint stride) { - guint i; + guint x, y; guint8 rowskip; GST_DEBUG ("Parsing rowskip"); - for (i = 0; i < height; i++) { + for (y = 0; y < height; y++) { READ_UINT8 (br, rowskip, 1); - if (rowskip) + if (data) { + if (!rowskip) + memset (data, 0, width); + else { + for (x = 0; x < width; x++) + READ_UINT8 (br, data[x], 1); + } + data += stride; + } else if (rowskip) SKIP (br, width); } - return 1; + + return TRUE; failed: GST_WARNING ("Failed to parse rowskip"); - return 0; + return FALSE; } static inline gint8 @@ -389,15 +409,21 @@ failed: } } -/*** bitplane decoding ***/ -static gint -bitplane_decoding (GstBitReader * br, guint height, - guint width, guint8 * is_raw) +/*** bitplanes decoding ***/ +static gboolean +bitplane_decoding (GstBitReader * br, guint8 * data, + GstVC1SeqHdr * seqhdr, guint8 * is_raw) { - guint imode; - guint i, j, offset = 0; + const guint width = seqhdr->mb_width; + const guint height = seqhdr->mb_height; + const guint stride = seqhdr->mb_stride; + guint imode, invert, invert_mask; + guint x, y, v; + guint8 *pdata = data; + + GET_BITS (br, 1, &invert); + invert_mask = -invert; - SKIP (br, 1); if (!decode_vlc (br, &imode, vc1_imode_vlc_table, G_N_ELEMENTS (vc1_imode_vlc_table))) goto failed; @@ -411,68 +437,125 @@ bitplane_decoding (GstBitReader * br, guint height, return TRUE; case IMODE_DIFF2: + invert_mask = 0; + // fall-through case IMODE_NORM2: GST_DEBUG ("Parsing IMODE_DIFF2 or IMODE_NORM2 biplane"); + x = 0; if ((height * width) & 1) { - SKIP (br, 1); + GET_BITS (br, 1, &v); + if (pdata) { + *pdata++ = v; + if (++x == width) { + x = 0; + pdata += stride - width; + } + } } - for (i = offset; i < height * width; i += 2) { - /*guint x; */ - if (!decode_vlc (br, NULL, vc1_norm2_vlc_table, - G_N_ELEMENTS (vc1_norm2_vlc_table))) { + for (y = 0; y < height * width; y += 2) { + if (!decode_vlc (br, &v, vc1_norm2_vlc_table, + G_N_ELEMENTS (vc1_norm2_vlc_table))) goto failed; + if (pdata) { + *pdata++ = v >> 1; + if (++x == width) { + x = 0; + pdata += stride - width; + } + *pdata++ = v & 1; + if (++x == width) { + x = 0; + pdata += stride - width; + } } } break; case IMODE_DIFF6: + invert_mask = 0; + // fall-through case IMODE_NORM6: GST_DEBUG ("Parsing IMODE_DIFF6 or IMODE_NORM6 biplane"); - if (!(height % 3) && (width % 3)) { // use 2x3 decoding - - for (i = 0; i < height; i += 3) { - for (j = width & 1; j < width; j += 2) { - if (!decode_vlc (br, NULL, vc1_norm6_vlc_table, - G_N_ELEMENTS (vc1_norm6_vlc_table))) { + if (!(height % 3) && (width % 3)) { /* decode 2x3 "vertical" tiles */ + for (y = 0; y < height; y += 3) { + for (x = width & 1; x < width; x += 2) { + if (!decode_vlc (br, &v, vc1_norm6_vlc_table, + G_N_ELEMENTS (vc1_norm6_vlc_table))) goto failed; + + if (pdata) { + v ^= invert_mask; + pdata[x + 0] = v & 1; + pdata[x + 1] = (v >> 1) & 1; + pdata[x + 0 + stride] = (v >> 2) & 1; + pdata[x + 1 + stride] = (v >> 3) & 1; + pdata[x + 0 + stride * 2] = (v >> 4) & 1; + pdata[x + 1 + stride * 2] = (v >> 5) & 1; } } + if (pdata) + pdata += 3 * stride; } - } else { - for (i = height & 1; i < height; i += 2) { - for (j = width % 3; j < width; j += 3) { - if (!decode_vlc (br, NULL, vc1_norm6_vlc_table, - G_N_ELEMENTS (vc1_norm6_vlc_table))) { + + x = width & 1; + y = 0; + } else { /* decode 3x2 "horizontal" tiles */ + + if (pdata) + pdata += (height & 1) * width; + for (y = height & 1; y < height; y += 2) { + for (x = width % 3; x < width; x += 3) { + if (!decode_vlc (br, &v, vc1_norm6_vlc_table, + G_N_ELEMENTS (vc1_norm6_vlc_table))) goto failed; + + if (pdata) { + v ^= invert_mask; + pdata[x + 0] = v & 1; + pdata[x + 1] = (v >> 1) & 1; + pdata[x + 2] = (v >> 2) & 1; + pdata[x + 0 + stride] = (v >> 3) & 1; + pdata[x + 1 + stride] = (v >> 4) & 1; + pdata[x + 2 + stride] = (v >> 5) & 1; } } + if (pdata) + pdata += 2 * stride; } - j = width % 3; - if (j) - decode_colskip (br, height, width); + x = width % 3; + y = height & 1; + } - if (height & 1) - decode_rowskip (br, height, width); + if (x) { + if (data) + pdata = data + y * stride; + decode_colskip (br, pdata, x, height, stride); + } + + if (y) { + if (data) + pdata = data + x; + decode_rowskip (br, pdata, width, y, stride); } break; case IMODE_ROWSKIP: GST_DEBUG ("Parsing IMODE_ROWSKIP biplane"); - if (!decode_rowskip (br, width, height)) + if (!decode_rowskip (br, data, width, height, stride)) goto failed; break; case IMODE_COLSKIP: GST_DEBUG ("Parsing IMODE_COLSKIP biplane"); - if (decode_colskip (br, width, height)) + if (!decode_colskip (br, data, width, height, stride)) goto failed; break; } @@ -597,6 +680,14 @@ calculate_framerate_bitrate (guint8 frmrtq_postproc, guint8 bitrtq_postproc, } } +static inline void +calculate_mb_size (GstVC1SeqHdr * seqhdr, guint width, guint height) +{ + seqhdr->mb_width = (width + 15) >> 4; + seqhdr->mb_height = (height + 15) >> 4; + seqhdr->mb_stride = seqhdr->mb_width + 1; +} + static GstVC1ParserResult parse_hrd_param_flag (GstBitReader * br, GstVC1HrdParam * hrd_param) { @@ -662,8 +753,8 @@ parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) gst_bit_reader_get_bits_uint16_unchecked (br, 12); advanced->max_coded_width = (advanced->max_coded_width + 1) << 1; advanced->max_coded_height = (advanced->max_coded_height + 1) << 1; - seqhdr->mb_height = (advanced->max_coded_height + 15) >> 4; - seqhdr->mb_width = (advanced->max_coded_width + 15) >> 4; + calculate_mb_size (seqhdr, advanced->max_coded_width, + advanced->max_coded_height); advanced->pulldown = gst_bit_reader_get_bits_uint8_unchecked (br, 1); advanced->interlace = gst_bit_reader_get_bits_uint8_unchecked (br, 1); advanced->tfcntrflag = gst_bit_reader_get_bits_uint8_unchecked (br, 1); @@ -733,14 +824,12 @@ failed: static GstVC1ParserResult parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, - GstVC1SeqHdr * seqhdr) + GstVC1SeqHdr * seqhdr, GstVC1BitPlanes * bitplanes) { GstVC1AdvancedSeqHdr *advhdr = &seqhdr->advanced; GstVC1PicAdvanced *pic = &framehdr->pic.advanced; GstVC1EntryPointHdr *entrypthdr = &advhdr->entrypoint; guint8 mvmodeidx; - guint width = seqhdr->mb_width; - guint height = seqhdr->mb_height; GST_DEBUG ("Parsing Frame header advanced %u", advhdr->interlace); @@ -861,7 +950,8 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, switch (framehdr->ptype) { case GST_VC1_PICTURE_TYPE_I: case GST_VC1_PICTURE_TYPE_BI: - if (!bitplane_decoding (br, height, width, &pic->acpred)) + if (!bitplane_decoding (br, bitplanes ? bitplanes->acpred : NULL, + seqhdr, &pic->acpred)) goto failed; if (entrypthdr->overlap && framehdr->pquant <= 8) { @@ -871,9 +961,10 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, goto failed; else if (pic->condover == GST_VC1_CONDOVER_SELECT) { - - if (!bitplane_decoding (br, height, width, &pic->overflags)) + if (!bitplane_decoding (br, bitplanes ? bitplanes->overflags : NULL, + seqhdr, &pic->overflags)) goto failed; + GST_DEBUG ("overflags %u", pic->overflags); } } @@ -899,10 +990,12 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, READ_UINT8 (br, pic->mvmode, 1); - if (!bitplane_decoding (br, height, width, &pic->directmb)) + if (!bitplane_decoding (br, bitplanes ? bitplanes->directmb : NULL, + seqhdr, &pic->directmb)) goto failed; - if (!bitplane_decoding (br, height, width, &pic->skipmb)) + if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, + seqhdr, &pic->skipmb)) goto failed; READ_UINT8 (br, pic->mvtab, 2); @@ -950,15 +1043,18 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV || (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP && pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) { - if (!bitplane_decoding (br, height, width, &pic->mvtypemb)) + if (!bitplane_decoding (br, bitplanes ? bitplanes->mvtypemb : NULL, + seqhdr, &pic->mvtypemb)) goto failed; GST_DEBUG ("mvtypemb %u", pic->mvtypemb); } - if (!bitplane_decoding (br, height, width, &pic->skipmb) || - gst_bit_reader_get_remaining (br) < 4) + if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, + seqhdr, &pic->skipmb)) goto failed; + if (gst_bit_reader_get_remaining (br) < 4) + goto failed; pic->mvtab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); pic->cbptab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); @@ -994,7 +1090,7 @@ failed: static GstVC1ParserResult parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, - GstVC1SeqHdr * seqhdr) + GstVC1SeqHdr * seqhdr, GstVC1BitPlanes * bitplanes) { guint8 mvmodeidx; GstVC1PicSimpleMain *pic = &framehdr->pic.simple; @@ -1127,11 +1223,13 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV || (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP && pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) { - if (!bitplane_decoding (br, height, width, &pic->mvtypemb)) + if (!bitplane_decoding (br, bitplanes ? bitplanes->mvtypemb : NULL, + seqhdr, &pic->mvtypemb)) goto failed; GST_DEBUG ("mvtypemb %u", pic->mvtypemb); } - if (!bitplane_decoding (br, height, width, &pic->skipmb)) + if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, + seqhdr, &pic->skipmb)) goto failed; READ_UINT8 (br, pic->mvtab, 2); @@ -1161,9 +1259,12 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, case GST_VC1_PICTURE_TYPE_B: READ_UINT8 (br, pic->mvmode, 1); - if (!bitplane_decoding (br, height, width, &pic->directmb)) + if (!bitplane_decoding (br, bitplanes ? bitplanes->directmb : NULL, + seqhdr, &pic->directmb)) goto failed; - if (!bitplane_decoding (br, height, width, &pic->skipmb) == -1) + + if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, + seqhdr, &pic->skipmb)) goto failed; READ_UINT8 (br, pic->mvtab, 2); @@ -1539,9 +1640,9 @@ gst_vc1_parse_sequence_header (const guint8 * data, gsize size, if (seqhdr->profile == GST_VC1_PROFILE_ADVANCED) return parse_sequence_header_advanced (seqhdr, &br); - /* compute height and width */ - seqhdr->mb_height = (seqhdr->struct_c.coded_height + 15) >> 4; - seqhdr->mb_width = (seqhdr->struct_c.coded_width + 15) >> 4; + /* Compute MB height and width */ + calculate_mb_size (seqhdr, seqhdr->struct_c.coded_width, + seqhdr->struct_c.coded_height); return GST_VC1_PARSER_OK; @@ -1602,8 +1703,8 @@ gst_vc1_parse_entry_point_header (const guint8 * data, gsize size, READ_UINT16 (&br, entrypoint->coded_height, 12); entrypoint->coded_height = (entrypoint->coded_height + 1) << 1; entrypoint->coded_width = (entrypoint->coded_width + 1) << 1; - seqhdr->mb_height = (entrypoint->coded_height + 15) >> 4; - seqhdr->mb_width = (entrypoint->coded_width + 15) >> 4; + calculate_mb_size (seqhdr, entrypoint->coded_width, + entrypoint->coded_height); } if (entrypoint->extended_mv) @@ -1674,6 +1775,7 @@ gst_vc1_parse_frame_layer (const guint8 * data, gsize size, * @size: the size of @data * @entrypoint: The #GstVC1EntryPointHdr to set. * @seqhdr: The #GstVC1SeqHdr currently being parsed + * @bitplanes: The #GstVC1BitPlanes to store bitplanes in or %NULL * * Parses @data, and fills @entrypoint fields. * @@ -1681,7 +1783,8 @@ gst_vc1_parse_frame_layer (const guint8 * data, gsize size, */ GstVC1ParserResult gst_vc1_parse_frame_header (const guint8 * data, gsize size, - GstVC1FrameHdr * framehdr, GstVC1SeqHdr * seqhdr) + GstVC1FrameHdr * framehdr, GstVC1SeqHdr * seqhdr, + GstVC1BitPlanes * bitplanes) { GstBitReader br; GstVC1ParserResult result; @@ -1691,10 +1794,96 @@ gst_vc1_parse_frame_header (const guint8 * data, gsize size, gst_bit_reader_init (&br, data, size); if (seqhdr->profile == GST_VC1_PROFILE_ADVANCED) - result = parse_frame_header_advanced (&br, framehdr, seqhdr); + result = parse_frame_header_advanced (&br, framehdr, seqhdr, bitplanes); else - result = parse_frame_header (&br, framehdr, seqhdr); + result = parse_frame_header (&br, framehdr, seqhdr, bitplanes); framehdr->header_size = gst_bit_reader_get_pos (&br); return result; } + +/** + * gst_vc1_bitplanes_new: + * @seqhdr: The #GstVC1SeqHdr from which to set @bitplanes + * + * Creates a new #GstVC1BitPlanes. It should be freed with + * gst_vc1_bitplanes_free() after use. + * + * Returns: a new #GstVC1BitPlanes + */ +GstVC1BitPlanes * +gst_vc1_bitplanes_new (void) +{ + return g_slice_new0 (GstVC1BitPlanes); +} + +/** + * gst_vc1_bitplane_free: + * @bitplanes: the #GstVC1BitPlanes to free + * + * Frees @bitplanes. + */ +void +gst_vc1_bitplanes_free (GstVC1BitPlanes * bitplanes) +{ + gst_vc1_bitplanes_free_1 (bitplanes); + g_slice_free (GstVC1BitPlanes, bitplanes); +} + +/** + * gst_vc1_bitplane_free_1: + * @bitplanes: The #GstVC1BitPlanes to free + * + * Frees @bitplanes fields. + */ +void +gst_vc1_bitplanes_free_1 (GstVC1BitPlanes * bitplanes) +{ + g_free (bitplanes->acpred); + g_free (bitplanes->overflags); + g_free (bitplanes->mvtypemb); + g_free (bitplanes->skipmb); + g_free (bitplanes->directmb); +} + +/** + * gst_vc1_bitplanes_ensure_size: + * @bitplanes: The #GstVC1BitPlanes to reset + * @seqhdr: The #GstVC1SeqHdr from which to set @bitplanes + * + * Fills the @bitplanes structure from @seqhdr, this function + * should be called after #gst_vc1_parse_sequence_header if + * in simple or main mode, or after #gst_vc1_parse_entry_point_header + * if in advanced mode. + * + * Returns: %TRUE if everything went fine, %FALSE otherwize + */ +gboolean +gst_vc1_bitplanes_ensure_size (GstVC1BitPlanes * bitplanes, + GstVC1SeqHdr * seqhdr) +{ + g_return_val_if_fail (bitplanes != NULL, FALSE); + g_return_val_if_fail (seqhdr != NULL, FALSE); + + if (bitplanes->size) { + bitplanes->size = seqhdr->mb_height * seqhdr->mb_stride; + bitplanes->acpred = + g_realloc_n (bitplanes->acpred, bitplanes->size, sizeof (guint8)); + bitplanes->overflags = + g_realloc_n (bitplanes->overflags, bitplanes->size, sizeof (guint8)); + bitplanes->mvtypemb = + g_realloc_n (bitplanes->mvtypemb, bitplanes->size, sizeof (guint8)); + bitplanes->skipmb = + g_realloc_n (bitplanes->skipmb, bitplanes->size, sizeof (guint8)); + bitplanes->directmb = + g_realloc_n (bitplanes->directmb, bitplanes->size, sizeof (guint8)); + } else { + bitplanes->size = seqhdr->mb_height * seqhdr->mb_stride; + bitplanes->acpred = g_malloc0 (bitplanes->size * sizeof (guint8)); + bitplanes->overflags = g_malloc0 (bitplanes->size * sizeof (guint8)); + bitplanes->mvtypemb = g_malloc0 (bitplanes->size * sizeof (guint8)); + bitplanes->skipmb = g_malloc0 (bitplanes->size * sizeof (guint8)); + bitplanes->directmb = g_malloc0 (bitplanes->size * sizeof (guint8)); + } + return TRUE; +} diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index 08293e54f8..8cdb60c0b3 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -150,6 +150,8 @@ typedef struct _GstVC1Picture GstVC1Picture; typedef struct _GstVC1VopDquant GstVC1VopDquant; +typedef struct _GstVC1BitPlanes GstVC1BitPlanes; + typedef struct _GstVC1BDU GstVC1BDU; struct _GstVC1HrdParam @@ -314,6 +316,7 @@ struct _GstVC1SeqHdr /* calculated */ guint mb_height; guint mb_width; + guint mb_stride; GstVC1AdvancedSeqHdr advanced; @@ -416,6 +419,16 @@ struct _GstVC1PicAdvanced guint8 directmb; }; +struct _GstVC1BitPlanes +{ + guint8 *acpred; + guint8 *overflags; + guint8 *mvtypemb; + guint8 *skipmb; + guint8 *directmb; + + guint size; /* Size of the arrays */ +}; struct _GstVC1VopDquant { @@ -544,6 +557,16 @@ GstVC1ParserResult gst_vc1_parse_frame_layer (const guint8 *data, GstVC1ParserResult gst_vc1_parse_frame_header (const guint8 *data, gsize size, GstVC1FrameHdr * framehdr, + GstVC1SeqHdr *seqhdr, + GstVC1BitPlanes *bitplanes); + +GstVC1BitPlanes * gst_vc1_bitplanes_new (void); + +void gst_vc1_bitplanes_free (GstVC1BitPlanes *bitplanes); + +void gst_vc1_bitplanes_free_1 (GstVC1BitPlanes *bitplanes); + +gboolean gst_vc1_bitplanes_ensure_size (GstVC1BitPlanes *bitplanes, GstVC1SeqHdr *seqhdr); G_END_DECLS diff --git a/tests/check/libs/vc1parser.c b/tests/check/libs/vc1parser.c index 0553efc3f6..1136fac3c3 100644 --- a/tests/check/libs/vc1parser.c +++ b/tests/check/libs/vc1parser.c @@ -847,7 +847,7 @@ GST_START_TEST (test_vc1_parse_p_frame_header_main) assert_equals_int (structc->maxbframes, 1); assert_equals_int (gst_vc1_parse_frame_header (pframe_main, - sizeof (pframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK); + sizeof (pframe_main), &framehdr, &seqhdr, NULL), GST_VC1_PARSER_OK); assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_P); assert_equals_int (framehdr.interpfrm, 0); assert_equals_int (pic->frmcnt, 1); @@ -865,6 +865,7 @@ GST_START_TEST (test_vc1_parse_b_frame_header_main) { GstVC1FrameHdr framehdr; GstVC1SeqHdr seqhdr; + GstVC1BitPlanes b = { 0, }; GstVC1SeqStructC *structc = &seqhdr.struct_c; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; @@ -879,6 +880,10 @@ GST_START_TEST (test_vc1_parse_b_frame_header_main) assert_equals_int (seqhdr.mb_height, 15); assert_equals_int (seqhdr.mb_width, 20); + gst_vc1_bitplanes_ensure_size (&b, &seqhdr); + + assert_equals_int (b.size, 315); + assert_equals_int (structc->frmrtq_postproc, 7); assert_equals_int (structc->bitrtq_postproc, 3); assert_equals_int (structc->loop_filter, 1); @@ -893,7 +898,7 @@ GST_START_TEST (test_vc1_parse_b_frame_header_main) assert_equals_int (structc->maxbframes, 1); assert_equals_int (gst_vc1_parse_frame_header (bframe_main, - sizeof (bframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK); + sizeof (bframe_main), &framehdr, &seqhdr, &b), GST_VC1_PARSER_OK); assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_B); assert_equals_int (framehdr.interpfrm, 0); @@ -906,6 +911,8 @@ GST_START_TEST (test_vc1_parse_b_frame_header_main) assert_equals_int (framehdr.pquant, 7); assert_equals_int (framehdr.halfqp, 0); assert_equals_int (framehdr.pquantizer, 0); + + gst_vc1_bitplanes_free_1 (&b); } GST_END_TEST; @@ -939,7 +946,7 @@ GST_START_TEST (test_vc1_parse_bi_frame_header_main) assert_equals_int (structc->maxbframes, 1); assert_equals_int (gst_vc1_parse_frame_header (biframe_main, - sizeof (biframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK); + sizeof (biframe_main), &framehdr, &seqhdr, NULL), GST_VC1_PARSER_OK); assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_BI); assert_equals_int (framehdr.interpfrm, 0); @@ -982,7 +989,7 @@ GST_START_TEST (test_vc1_parse_i_frame_header_main) assert_equals_int (structc->maxbframes, 1); assert_equals_int (gst_vc1_parse_frame_header (iframe_main, - sizeof (iframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK); + sizeof (iframe_main), &framehdr, &seqhdr, NULL), GST_VC1_PARSER_OK); assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_I); assert_equals_int (framehdr.interpfrm, 0); @@ -1041,7 +1048,7 @@ GST_START_TEST (test_vc1_parse_i_frame_header_adv) assert_equals_int (entrypt->coded_width, 1920); assert_equals_int (gst_vc1_parse_frame_header (iframe_adv, - sizeof (iframe_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK); + sizeof (iframe_adv), &framehdr, &seqhdr, NULL), GST_VC1_PARSER_OK); assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_I); assert_equals_int (framehdr.pqindex, 3); @@ -1100,7 +1107,7 @@ GST_START_TEST (test_vc1_parse_b_frame_header_adv) assert_equals_int (entrypt->quantizer, 0); assert_equals_int (gst_vc1_parse_frame_header (bframe_adv, - sizeof (bframe_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK); + sizeof (bframe_adv), &framehdr, &seqhdr, NULL), GST_VC1_PARSER_OK); assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_B); assert_equals_int (framehdr.pqindex, 1); @@ -1112,7 +1119,7 @@ GST_START_TEST (test_vc1_parse_b_frame_header_adv) assert_equals_int (framehdr.transacfrm, 1); assert_equals_int (gst_vc1_parse_frame_header (bframe2_adv, - sizeof (bframe2_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK); + sizeof (bframe2_adv), &framehdr, &seqhdr, NULL), GST_VC1_PARSER_OK); assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_B); assert_equals_int (framehdr.pqindex, 4); assert_equals_int (framehdr.pquant, 4); @@ -1172,7 +1179,7 @@ GST_START_TEST (test_vc1_parse_p_frame_header_adv) assert_equals_int (gst_vc1_parse_frame_header (pframe_adv, - sizeof (pframe_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK); + sizeof (pframe_adv), &framehdr, &seqhdr, NULL), GST_VC1_PARSER_OK); assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_P); assert_equals_int (framehdr.pqindex, 1); assert_equals_int (framehdr.pquant, 1); @@ -1183,7 +1190,7 @@ GST_START_TEST (test_vc1_parse_p_frame_header_adv) assert_equals_int (pic->mvrange, 0); assert_equals_int (gst_vc1_parse_frame_header (pframe2_adv, - sizeof (pframe2_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK); + sizeof (pframe2_adv), &framehdr, &seqhdr, NULL), GST_VC1_PARSER_OK); assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_P); assert_equals_int (framehdr.pqindex, 1); assert_equals_int (framehdr.pquant, 1); From 80906275816a27abd2943b7e4fce9f78d5062654 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 4 Oct 2011 17:39:00 -0300 Subject: [PATCH 17/26] codecparsers: VC1: Some cosmetics and debug logging enhancements --- gst-libs/gst/codecparsers/gstvc1parser.c | 15 ++++++++++----- gst-libs/gst/codecparsers/gstvc1parser.h | 6 +++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index bf555f239b..b724a9e628 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -401,9 +401,11 @@ decode_vlc (GstBitReader * br, guint * res, const VLCTable * table, } } + GST_DEBUG ("Did not find code"); + failed: { - GST_DEBUG ("Could not decode VLC returning -1"); + GST_WARNING ("Could not decode VLC returning"); return FALSE; } @@ -421,6 +423,8 @@ bitplane_decoding (GstBitReader * br, guint8 * data, guint x, y, v; guint8 *pdata = data; + *is_raw = FALSE; + GET_BITS (br, 1, &invert); invert_mask = -invert; @@ -438,7 +442,7 @@ bitplane_decoding (GstBitReader * br, guint8 * data, case IMODE_DIFF2: invert_mask = 0; - // fall-through + /* fall-through */ case IMODE_NORM2: GST_DEBUG ("Parsing IMODE_DIFF2 or IMODE_NORM2 biplane"); @@ -476,7 +480,7 @@ bitplane_decoding (GstBitReader * br, guint8 * data, case IMODE_DIFF6: invert_mask = 0; - // fall-through + /* fall-through */ case IMODE_NORM6: GST_DEBUG ("Parsing IMODE_DIFF6 or IMODE_NORM6 biplane"); @@ -1773,13 +1777,13 @@ gst_vc1_parse_frame_layer (const guint8 * data, gsize size, * gst_vc1_parse_frame_header: * @data: The data to parse * @size: the size of @data - * @entrypoint: The #GstVC1EntryPointHdr to set. + * @framehdr: The #GstVC1FrameHdr to fill. * @seqhdr: The #GstVC1SeqHdr currently being parsed * @bitplanes: The #GstVC1BitPlanes to store bitplanes in or %NULL * * Parses @data, and fills @entrypoint fields. * - * Returns: a #GstVC1EntryPointHdr + * Returns: a #GstVC1ParserResult */ GstVC1ParserResult gst_vc1_parse_frame_header (const guint8 * data, gsize size, @@ -1885,5 +1889,6 @@ gst_vc1_bitplanes_ensure_size (GstVC1BitPlanes * bitplanes, bitplanes->skipmb = g_malloc0 (bitplanes->size * sizeof (guint8)); bitplanes->directmb = g_malloc0 (bitplanes->size * sizeof (guint8)); } + return TRUE; } diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index 8cdb60c0b3..dc0dc6f957 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -82,9 +82,9 @@ typedef enum typedef enum { - GST_VC1_LEVEL_LOW = 0, /* Simple/Main profile low level */ - GST_VC1_LEVELMEDIUM = 1, /* Simple/Main profile medium level */ - GST_VC1_LEVELHIGH = 2, /* Main profile high level */ + GST_VC1_LEVEL_LOW = 0, /* Simple/Main profile low level */ + GST_VC1_LEVEL_MEDIUM = 1, /* Simple/Main profile medium level */ + GST_VC1_LEVEL_HIGH = 2, /* Main profile high level */ GST_VC1_LEVEL_L0 = 0, /* Advanced profile level 0 */ GST_VC1_LEVEL_L1 = 1, /* Advanced profile level 1 */ From ce71fdae1b2259bed05a79d50a1e2e888e085d77 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 4 Oct 2011 17:39:42 -0300 Subject: [PATCH 18/26] codecparsers: VC1: Implement bitplanes diff operator --- gst-libs/gst/codecparsers/gstvc1parser.c | 28 ++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index b724a9e628..1725347962 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -485,7 +485,7 @@ bitplane_decoding (GstBitReader * br, guint8 * data, GST_DEBUG ("Parsing IMODE_DIFF6 or IMODE_NORM6 biplane"); - if (!(height % 3) && (width % 3)) { /* decode 2x3 "vertical" tiles */ + if (!(height % 3) && (width % 3)) { /* decode 2x3 "vertical" tiles */ for (y = 0; y < height; y += 3) { for (x = width & 1; x < width; x += 2) { if (!decode_vlc (br, &v, vc1_norm6_vlc_table, @@ -508,7 +508,7 @@ bitplane_decoding (GstBitReader * br, guint8 * data, x = width & 1; y = 0; - } else { /* decode 3x2 "horizontal" tiles */ + } else { /* decode 3x2 "horizontal" tiles */ if (pdata) pdata += (height & 1) * width; @@ -564,6 +564,30 @@ bitplane_decoding (GstBitReader * br, guint8 * data, break; } + if (!data) + return TRUE; + + /* Applying diff operator */ + if (imode == IMODE_DIFF2 || imode == IMODE_DIFF6) { + pdata = data; + pdata[0] ^= invert; + + for (x = 1; x < width; x++) + pdata[x] ^= pdata[x - 1]; + + for (y = 1; y < height; y++) { + pdata[stride] ^= pdata[0]; + + for (x = 1; x < width; x++) { + if (pdata[stride + x - 1] != pdata[x]) + pdata[stride + x] ^= invert; + else + pdata[stride + x] ^= pdata[stride + x - 1]; + } + pdata += stride; + } + } + return TRUE; failed: From b23f7eb38d8fc407e054a91229468d1667eeb5b1 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Wed, 5 Oct 2011 17:39:59 +0200 Subject: [PATCH 19/26] codecparsers: vc1: handle skipped pictures gracefully. --- gst-libs/gst/codecparsers/gstvc1parser.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 1725347962..6a77409469 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -876,9 +876,6 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, framehdr->ptype = get_unary (br, 0, 4); - if (framehdr->ptype == GST_VC1_PICTURE_TYPE_SKIPPED) - goto failed; - if (advhdr->tfcntrflag) { READ_UINT8 (br, pic->tfcntr, 8); GST_DEBUG ("tfcntr %u", pic->tfcntr); @@ -916,6 +913,9 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, } } + if (framehdr->ptype == GST_VC1_PICTURE_TYPE_SKIPPED) + return GST_VC1_PARSER_OK; + READ_UINT8 (br, pic->rndctrl, 1); if (advhdr->interlace) { From 4280a61a237ad8ff1d4b7cd3acae7915e4f2eb3e Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Fri, 7 Oct 2011 13:59:29 +0200 Subject: [PATCH 20/26] codecparsers: vc1: fix MVMODE and MVMODE2 parsing. --- gst-libs/gst/codecparsers/gstvc1parser.c | 43 ++++++++++++------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 6a77409469..ba40ffd659 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -119,32 +119,36 @@ const guint8 vc1_pquant_table[3][32] = { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 31} }; -const guint8 mvmode_table[2][5] = { - { - GST_VC1_MVMODE_1MV_HPEL_BILINEAR, - GST_VC1_MVMODE_1MV, - GST_VC1_MVMODE_1MV_HPEL, - GST_VC1_MVMODE_MIXED_MV, - GST_VC1_MVMODE_INTENSITY_COMP}, +static const guint8 vc1_mvmode_table[2][5] = { + /* Table 47: P Picture High rate (PQUANT <= 12) MVMODE code table */ { GST_VC1_MVMODE_1MV, GST_VC1_MVMODE_MIXED_MV, GST_VC1_MVMODE_1MV_HPEL, GST_VC1_MVMODE_INTENSITY_COMP, - GST_VC1_MVMODE_1MV_HPEL_BILINEAR} -}; - -const guint8 mvmode2_table[2][4] = { + GST_VC1_MVMODE_1MV_HPEL_BILINEAR}, + /* Table 46: P Picture Low rate (PQUANT > 12) MVMODE code table */ { GST_VC1_MVMODE_1MV_HPEL_BILINEAR, GST_VC1_MVMODE_1MV, GST_VC1_MVMODE_1MV_HPEL, - GST_VC1_MVMODE_MIXED_MV}, + GST_VC1_MVMODE_INTENSITY_COMP, + GST_VC1_MVMODE_MIXED_MV} +}; + +static const guint8 vc1_mvmode2_table[2][4] = { + /* Table 50: P Picture High rate (PQUANT <= 12) MVMODE2 code table */ { GST_VC1_MVMODE_1MV, GST_VC1_MVMODE_MIXED_MV, GST_VC1_MVMODE_1MV_HPEL, - GST_VC1_MVMODE_1MV_HPEL_BILINEAR} + GST_VC1_MVMODE_1MV_HPEL_BILINEAR}, + /* Table 49: P Picture Low rate (PQUANT > 12) MVMODE2 code table */ + { + GST_VC1_MVMODE_1MV_HPEL_BILINEAR, + GST_VC1_MVMODE_1MV, + GST_VC1_MVMODE_1MV_HPEL, + GST_VC1_MVMODE_MIXED_MV} }; /* Table 40: BFRACTION VLC Table */ @@ -1056,15 +1060,13 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, else pic->mvrange = 0; - mvmodeidx = framehdr->pquant > 12 ? 0 : 1; - pic->mvmode = mvmode_table[mvmodeidx][get_unary (br, 1, 4)]; + mvmodeidx = framehdr->pquant > 12; + pic->mvmode = vc1_mvmode_table[mvmodeidx][get_unary (br, 1, 4)]; if (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP) { - - pic->mvmode2 = mvmode2_table[mvmodeidx][get_unary (br, 1, 4)]; + pic->mvmode2 = vc1_mvmode2_table[mvmodeidx][get_unary (br, 1, 3)]; READ_UINT8 (br, pic->lumscale, 6); READ_UINT8 (br, pic->lumshift, 6); - GST_DEBUG ("lumscale %u lumshift %u", pic->lumscale, pic->lumshift); } @@ -1238,11 +1240,10 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, case GST_VC1_PICTURE_TYPE_P: mvmodeidx = framehdr->pquant > 12; - - pic->mvmode = mvmode_table[mvmodeidx][get_unary (br, 1, 4)]; + pic->mvmode = vc1_mvmode_table[mvmodeidx][get_unary (br, 1, 4)]; if (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP) { - pic->mvmode2 = mvmode2_table[mvmodeidx][get_unary (br, 1, 4)]; + pic->mvmode2 = vc1_mvmode2_table[mvmodeidx][get_unary (br, 1, 3)]; READ_UINT8 (br, pic->lumscale, 6); READ_UINT8 (br, pic->lumshift, 6); GST_DEBUG ("lumscale %u lumshift %u", pic->lumscale, pic->lumshift); From 839acd54f6aead26edd542523cb159bb6f108bf0 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Fri, 7 Oct 2011 15:21:34 +0200 Subject: [PATCH 21/26] codecparsers: vc1: fix bitplanes decoding (INVERT mode). --- gst-libs/gst/codecparsers/gstvc1parser.c | 38 ++++++++++++++---------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index ba40ffd659..f39b7c355a 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -279,23 +279,26 @@ static const VLCTable vc1_norm6_vlc_table[64] = { static inline gboolean decode_colskip (GstBitReader * br, guint8 * data, guint width, guint height, - guint stride) + guint stride, guint invert) { guint x, y; - guint8 colskip; + guint8 colskip, v; GST_DEBUG ("Parsing colskip"); + invert &= 1; for (x = 0; x < width; x++) { READ_UINT8 (br, colskip, 1); if (data) { if (colskip) { - for (y = 0; y < height; y++) - READ_UINT8 (br, data[y * stride], 1); + for (y = 0; y < height; y++) { + READ_UINT8 (br, v, 1); + data[y * stride] = v ^ invert; + } } else { for (y = 0; y < height; y++) - data[y * stride] = 0; + data[y * stride] = invert; } data++; } else if (colskip) @@ -312,22 +315,25 @@ failed: static inline gboolean decode_rowskip (GstBitReader * br, guint8 * data, guint width, guint height, - guint stride) + guint stride, guint invert) { guint x, y; - guint8 rowskip; + guint8 rowskip, v; GST_DEBUG ("Parsing rowskip"); + invert &= 1; for (y = 0; y < height; y++) { READ_UINT8 (br, rowskip, 1); if (data) { if (!rowskip) - memset (data, 0, width); + memset (data, invert, width); else { - for (x = 0; x < width; x++) - READ_UINT8 (br, data[x], 1); + for (x = 0; x < width; x++) { + READ_UINT8 (br, v, 1); + data[x] = v ^ invert; + } } data += stride; } else if (rowskip) @@ -448,6 +454,7 @@ bitplane_decoding (GstBitReader * br, guint8 * data, invert_mask = 0; /* fall-through */ case IMODE_NORM2: + invert_mask &= 3; GST_DEBUG ("Parsing IMODE_DIFF2 or IMODE_NORM2 biplane"); @@ -455,7 +462,7 @@ bitplane_decoding (GstBitReader * br, guint8 * data, if ((height * width) & 1) { GET_BITS (br, 1, &v); if (pdata) { - *pdata++ = v; + *pdata++ = (v ^ invert_mask) & 1; if (++x == width) { x = 0; pdata += stride - width; @@ -468,6 +475,7 @@ bitplane_decoding (GstBitReader * br, guint8 * data, G_N_ELEMENTS (vc1_norm2_vlc_table))) goto failed; if (pdata) { + v ^= invert_mask; *pdata++ = v >> 1; if (++x == width) { x = 0; @@ -543,27 +551,27 @@ bitplane_decoding (GstBitReader * br, guint8 * data, if (x) { if (data) pdata = data + y * stride; - decode_colskip (br, pdata, x, height, stride); + decode_colskip (br, pdata, x, height, stride, invert_mask); } if (y) { if (data) pdata = data + x; - decode_rowskip (br, pdata, width, y, stride); + decode_rowskip (br, pdata, width, y, stride, invert_mask); } break; case IMODE_ROWSKIP: GST_DEBUG ("Parsing IMODE_ROWSKIP biplane"); - if (!decode_rowskip (br, data, width, height, stride)) + if (!decode_rowskip (br, data, width, height, stride, invert_mask)) goto failed; break; case IMODE_COLSKIP: GST_DEBUG ("Parsing IMODE_COLSKIP biplane"); - if (!decode_colskip (br, data, width, height, stride)) + if (!decode_colskip (br, data, width, height, stride, invert_mask)) goto failed; break; } From 40a1ed8288be68470242e9449091a573dc4e9373 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Fri, 7 Oct 2011 17:42:17 +0200 Subject: [PATCH 22/26] codecparsers: vc1: fix bitplanes decoding (check for errors). --- gst-libs/gst/codecparsers/gstvc1parser.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index f39b7c355a..673dfc167c 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -551,13 +551,15 @@ bitplane_decoding (GstBitReader * br, guint8 * data, if (x) { if (data) pdata = data + y * stride; - decode_colskip (br, pdata, x, height, stride, invert_mask); + if (!decode_colskip (br, pdata, x, height, stride, invert_mask)) + goto failed; } if (y) { if (data) pdata = data + x; - decode_rowskip (br, pdata, width, y, stride, invert_mask); + if (!decode_rowskip (br, pdata, width, y, stride, invert_mask)) + goto failed; } break; case IMODE_ROWSKIP: From 7a689b68051b0efb00a3faa63cdb7b428c8494f1 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Fri, 7 Oct 2011 13:11:55 -0300 Subject: [PATCH 23/26] codecparsers: VC1: Use enums when possible Add GstVC1FrameCodingMode and use it for the fcm field Use GstVC1PictureType as variable type for ptype Use GstVC1Level as variable type for level --- gst-libs/gst/codecparsers/gstvc1parser.c | 24 ++++++++++++++++++------ gst-libs/gst/codecparsers/gstvc1parser.h | 17 +++++++++++++---- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 673dfc167c..3d0b757d78 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -770,10 +770,12 @@ static GstVC1ParserResult parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) { GstVC1AdvancedSeqHdr *advanced = &seqhdr->advanced; + guint8 tmp; GST_DEBUG ("Parsing sequence header in advanced mode"); - READ_UINT8 (br, advanced->level, 3); + READ_UINT8 (br, tmp, 3); + advanced->level = tmp; READ_UINT8 (br, advanced->colordiff_format, 2); READ_UINT8 (br, advanced->frmrtq_postproc, 3); @@ -888,7 +890,7 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, pic->fcm = (guint8) fcm; } - framehdr->ptype = get_unary (br, 0, 4); + framehdr->ptype = (guint8) get_unary (br, 0, 4); if (advhdr->tfcntrflag) { READ_UINT8 (br, pic->tfcntr, 8); @@ -1118,6 +1120,10 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, pic->mvmode, pic->mvtab, pic->cbptab, pic->skipmb); break; + + default: + goto failed; + break; } return GST_VC1_PARSER_OK; @@ -1132,7 +1138,7 @@ static GstVC1ParserResult parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, GstVC1SeqHdr * seqhdr, GstVC1BitPlanes * bitplanes) { - guint8 mvmodeidx; + guint8 mvmodeidx, tmp; GstVC1PicSimpleMain *pic = &framehdr->pic.simple; GstVC1SeqStructC *structc = &seqhdr->struct_c; @@ -1154,12 +1160,14 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, } /* Figuring out the picture type */ - READ_UINT8 (br, framehdr->ptype, 1); + READ_UINT8 (br, tmp, 1); + framehdr->ptype = tmp; + if (structc->maxbframes) { if (!framehdr->ptype) { - READ_UINT8 (br, framehdr->ptype, 1); + READ_UINT8 (br, tmp, 1); - if (framehdr->ptype) + if (tmp) framehdr->ptype = GST_VC1_PICTURE_TYPE_I; else framehdr->ptype = GST_VC1_PICTURE_TYPE_B; @@ -1329,6 +1337,10 @@ parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr, pic->directmb, pic->skipmb); break; + + default: + goto failed; + break; } return GST_VC1_PARSER_OK; diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index dc0dc6f957..8709aa2fde 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -130,6 +130,13 @@ typedef enum GST_VC1_MVMODE_INTENSITY_COMP } GstVC1MvMode; +typedef enum +{ + GST_VC1_FRAME_PROGRESSIVE = 0x0, + GST_VC1_FRAME_INTERLACE = 0x10, + GST_VC1_FIELD_INTERLACE = 0x11 +} GstVC1FrameCodingMode; + typedef struct _GstVC1SeqHdr GstVC1SeqHdr; typedef struct _GstVC1AdvancedSeqHdr GstVC1AdvancedSeqHdr; typedef struct _GstVC1HrdParam GstVC1HrdParam; @@ -200,7 +207,8 @@ struct _GstVC1EntryPointHdr */ struct _GstVC1AdvancedSeqHdr { - guint8 level; + GstVC1Level level; + guint8 frmrtq_postproc; guint8 bitrtq_postproc; guint8 postprocflag; @@ -248,7 +256,8 @@ struct _GstVC1SeqStructA struct _GstVC1SeqStructB { - guint8 level; + GstVC1Level level; + guint8 cbr; guint32 framerate; @@ -372,7 +381,7 @@ struct _GstVC1PicSimpleMain */ struct _GstVC1PicAdvanced { - guint8 fcm; + GstVC1FrameCodingMode fcm; guint8 tfcntr; guint8 rptfrm; @@ -477,7 +486,7 @@ struct _GstVC1FrameLayer struct _GstVC1FrameHdr { /* common fields */ - guint8 ptype; + GstVC1PictureType ptype; guint8 interpfrm; guint8 halfqp; guint8 transacfrm; From 88766dc738e45b234d97071596ec3f827d4888ab Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 10 Oct 2011 10:14:12 -0300 Subject: [PATCH 24/26] codecparsers: VC1: Handle interlaced frames properly --- gst-libs/gst/codecparsers/gstvc1parser.c | 101 ++++++++++++++++++----- gst-libs/gst/codecparsers/gstvc1parser.h | 24 +++++- 2 files changed, 99 insertions(+), 26 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 3d0b757d78..ef0dee6a01 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -994,6 +994,12 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, switch (framehdr->ptype) { case GST_VC1_PICTURE_TYPE_I: case GST_VC1_PICTURE_TYPE_BI: + if (pic->fcm == GST_VC1_FRAME_INTERLACE) { + if (!bitplane_decoding (br, bitplanes ? bitplanes->fieldtx : NULL, + seqhdr, &pic->fieldtx)) + goto failed; + } + if (!bitplane_decoding (br, bitplanes ? bitplanes->acpred : NULL, seqhdr, &pic->acpred)) goto failed; @@ -1032,7 +1038,14 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, else pic->mvrange = 0; - READ_UINT8 (br, pic->mvmode, 1); + if (pic->fcm == GST_VC1_FRAME_INTERLACE) { + if (entrypthdr->extended_dmv) + 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, seqhdr, &pic->directmb)) @@ -1042,8 +1055,20 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, seqhdr, &pic->skipmb)) goto failed; - READ_UINT8 (br, pic->mvtab, 2); - READ_UINT8 (br, pic->cbptab, 2); + if (pic->fcm == GST_VC1_FRAME_INTERLACE) { + if (gst_bit_reader_get_remaining (br) < 11) + goto failed; + + pic->mbmodetab = 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->mvbptab2 = gst_bit_reader_get_bits_uint8_unchecked (br, 2); + pic->mvbptab4 = gst_bit_reader_get_bits_uint8_unchecked (br, 2); + + } else { + READ_UINT8 (br, pic->mvtab, 2); + READ_UINT8 (br, pic->cbptab, 2); + } if (framehdr->dquant) { parse_vopdquant (br, framehdr, framehdr->dquant); @@ -1072,33 +1097,61 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, else pic->mvrange = 0; - mvmodeidx = framehdr->pquant > 12; - pic->mvmode = vc1_mvmode_table[mvmodeidx][get_unary (br, 1, 4)]; + if (pic->fcm == GST_VC1_FRAME_INTERLACE) { + if (entrypthdr->extended_dmv) + pic->dmvrange = get_unary (br, 0, 3); - if (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP) { - pic->mvmode2 = vc1_mvmode2_table[mvmodeidx][get_unary (br, 1, 3)]; - READ_UINT8 (br, pic->lumscale, 6); - READ_UINT8 (br, pic->lumshift, 6); - GST_DEBUG ("lumscale %u lumshift %u", pic->lumscale, pic->lumshift); - } + READ_UINT8 (br, pic->mvswitch4, 1); + READ_UINT8 (br, pic->intcomp, 1); - if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV || - (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP && - pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) { - if (!bitplane_decoding (br, bitplanes ? bitplanes->mvtypemb : NULL, - seqhdr, &pic->mvtypemb)) - goto failed; - GST_DEBUG ("mvtypemb %u", pic->mvtypemb); + if (pic->intcomp) { + READ_UINT8 (br, pic->lumscale, 6); + READ_UINT8 (br, pic->lumshift, 6); + } + } else { + + mvmodeidx = framehdr->pquant > 12; + pic->mvmode = vc1_mvmode_table[mvmodeidx][get_unary (br, 1, 4)]; + + if (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP) { + pic->mvmode2 = vc1_mvmode2_table[mvmodeidx][get_unary (br, 1, 3)]; + READ_UINT8 (br, pic->lumscale, 6); + READ_UINT8 (br, pic->lumshift, 6); + GST_DEBUG ("lumscale %u lumshift %u", pic->lumscale, pic->lumshift); + } + + if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV || + (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP && + pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) { + if (!bitplane_decoding (br, bitplanes ? bitplanes->mvtypemb : NULL, + seqhdr, &pic->mvtypemb)) + goto failed; + GST_DEBUG ("mvtypemb %u", pic->mvtypemb); + } } if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, seqhdr, &pic->skipmb)) goto failed; - if (gst_bit_reader_get_remaining (br) < 4) - goto failed; - pic->mvtab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); - pic->cbptab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); + if (pic->fcm == GST_VC1_FRAME_INTERLACE) { + if (gst_bit_reader_get_remaining (br) < 9) + goto failed; + + pic->mbmodetab = 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->mvbptab2 = gst_bit_reader_get_bits_uint8_unchecked (br, 2); + + if (pic->mvswitch4) + READ_UINT8 (br, pic->mvbptab4, 2); + + } else { + if (gst_bit_reader_get_remaining (br) < 4) + goto failed; + pic->mvtab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); + pic->cbptab = gst_bit_reader_get_bits_uint8_unchecked (br, 2); + } if (framehdr->dquant) { parse_vopdquant (br, framehdr, framehdr->dquant); @@ -1891,6 +1944,7 @@ void gst_vc1_bitplanes_free_1 (GstVC1BitPlanes * bitplanes) { g_free (bitplanes->acpred); + g_free (bitplanes->fieldtx); g_free (bitplanes->overflags); g_free (bitplanes->mvtypemb); g_free (bitplanes->skipmb); @@ -1920,6 +1974,8 @@ gst_vc1_bitplanes_ensure_size (GstVC1BitPlanes * bitplanes, bitplanes->size = seqhdr->mb_height * seqhdr->mb_stride; bitplanes->acpred = g_realloc_n (bitplanes->acpred, bitplanes->size, sizeof (guint8)); + bitplanes->fieldtx = + g_realloc_n (bitplanes->fieldtx, bitplanes->size, sizeof (guint8)); bitplanes->overflags = g_realloc_n (bitplanes->overflags, bitplanes->size, sizeof (guint8)); bitplanes->mvtypemb = @@ -1931,6 +1987,7 @@ gst_vc1_bitplanes_ensure_size (GstVC1BitPlanes * bitplanes, } else { bitplanes->size = seqhdr->mb_height * seqhdr->mb_stride; bitplanes->acpred = g_malloc0 (bitplanes->size * sizeof (guint8)); + bitplanes->fieldtx = g_malloc0 (bitplanes->size * sizeof (guint8)); bitplanes->overflags = g_malloc0 (bitplanes->size * sizeof (guint8)); bitplanes->mvtypemb = g_malloc0 (bitplanes->size * sizeof (guint8)); bitplanes->skipmb = g_malloc0 (bitplanes->size * sizeof (guint8)); diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index 8709aa2fde..874d2f79ec 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -209,15 +209,15 @@ struct _GstVC1AdvancedSeqHdr { GstVC1Level level; - guint8 frmrtq_postproc; - guint8 bitrtq_postproc; + guint8 frmrtq_postproc; + guint8 bitrtq_postproc; guint8 postprocflag; guint16 max_coded_width; guint16 max_coded_height; guint8 pulldown; guint8 interlace; guint8 tfcntrflag; - guint8 finterpflag; + guint8 finterpflag; guint8 psf; guint8 display_ext; guint16 disp_horiz_size; @@ -236,7 +236,7 @@ struct _GstVC1AdvancedSeqHdr guint8 transfer_char; guint8 matrix_coef; guint8 hrd_param_flag; - guint8 colordiff_format; + guint8 colordiff_format; GstVC1HrdParam hrd_param; @@ -426,11 +426,27 @@ struct _GstVC1PicAdvanced guint8 mvtypemb; guint8 skipmb; guint8 directmb; + + /* For interlaced pictures only */ + guint8 fieldtx; + + /* P and B pictures */ + guint8 intcomp; + guint8 dmvrange; + guint8 mbmodetab; + guint8 imvtab; + guint8 icbptab; + guint8 mvbptab2; + guint8 mvbptab4; /* If 4mvswitch in ppic */ + + /* P picture */ + guint8 mvswitch4; }; struct _GstVC1BitPlanes { guint8 *acpred; + guint8 *fieldtx; guint8 *overflags; guint8 *mvtypemb; guint8 *skipmb; From 14590f06a011fb02cd084977eafbfb19dadb1c88 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 10 Oct 2011 14:19:48 -0300 Subject: [PATCH 25/26] codecparsers: VC1: Handle interlaced fields --- gst-libs/gst/codecparsers/gstvc1parser.c | 229 +++++++++++++++++++---- gst-libs/gst/codecparsers/gstvc1parser.h | 20 ++ 2 files changed, 214 insertions(+), 35 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index ef0dee6a01..9c9f743867 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -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 decode_vlc (GstBitReader * br, guint * res, const VLCTable * table, guint length) @@ -868,7 +905,7 @@ failed: static GstVC1ParserResult parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, - GstVC1SeqHdr * seqhdr, GstVC1BitPlanes * bitplanes) + GstVC1SeqHdr * seqhdr, GstVC1BitPlanes * bitplanes, gboolean field2) { GstVC1AdvancedSeqHdr *advhdr = &seqhdr->advanced; GstVC1PicAdvanced *pic = &framehdr->pic.advanced; @@ -888,9 +925,44 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, goto failed; 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) { READ_UINT8 (br, pic->tfcntr, 8); @@ -937,6 +1009,11 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, if (advhdr->interlace) { READ_UINT8 (br, pic->uvsamp, 1); 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) { @@ -944,8 +1021,12 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, 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; + if (!decode_vlc (br, &bfraction, vc1_bfraction_vlc_table, G_N_ELEMENTS (vc1_bfraction_vlc_table))) goto failed; @@ -1038,32 +1119,47 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, else pic->mvrange = 0; - if (pic->fcm == GST_VC1_FRAME_INTERLACE) { + if (pic->fcm != GST_VC1_FRAME_PROGRESSIVE) { if (entrypthdr->extended_dmv) 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, - seqhdr, &pic->directmb)) - goto failed; + if (pic->fcm == GST_VC1_FRAME_INTERLACE) + READ_UINT8 (br, pic->intcomp, 1); + else + READ_UINT8 (br, pic->mvmode, 1); - if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, - seqhdr, &pic->skipmb)) - goto failed; + if (pic->fcm == GST_VC1_FIELD_INTERLACE) { - if (pic->fcm == GST_VC1_FRAME_INTERLACE) { - if (gst_bit_reader_get_remaining (br) < 11) + if (!bitplane_decoding (br, bitplanes ? bitplanes->forwardmb : NULL, + 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; pic->mbmodetab = 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->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 { READ_UINT8 (br, pic->mvtab, 2); @@ -1092,15 +1188,24 @@ parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr, break; 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) pic->mvrange = get_unary (br, 0, 3); else pic->mvrange = 0; - if (pic->fcm == GST_VC1_FRAME_INTERLACE) { + if (pic->fcm != GST_VC1_FRAME_PROGRESSIVE) { if (entrypthdr->extended_dmv) pic->dmvrange = get_unary (br, 0, 3); + } + if (pic->fcm == GST_VC1_FRAME_INTERLACE) { READ_UINT8 (br, pic->mvswitch4, 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) { 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->lumshift, 6); 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 || - (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP && - pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) { - if (!bitplane_decoding (br, bitplanes ? bitplanes->mvtypemb : NULL, - seqhdr, &pic->mvtypemb)) - goto failed; - GST_DEBUG ("mvtypemb %u", pic->mvtypemb); + if (pic->fcm == GST_VC1_FRAME_PROGRESSIVE) { + if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV || + (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP && + pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) { + + if (!bitplane_decoding (br, bitplanes ? bitplanes->mvtypemb : NULL, + seqhdr, &pic->mvtypemb)) + goto failed; + + GST_DEBUG ("mvtypemb %u", pic->mvtypemb); + } } } - if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, - seqhdr, &pic->skipmb)) - goto failed; + if (pic->fcm != GST_VC1_FIELD_INTERLACE) { + if (!bitplane_decoding (br, bitplanes ? bitplanes->skipmb : NULL, + seqhdr, &pic->skipmb)) + goto failed; + } - if (pic->fcm == GST_VC1_FRAME_INTERLACE) { - if (gst_bit_reader_get_remaining (br) < 9) + if (pic->fcm != GST_VC1_FRAME_PROGRESSIVE) { + if (gst_bit_reader_get_remaining (br) < 7) goto failed; pic->mbmodetab = 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->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); } else { @@ -1898,7 +2023,8 @@ gst_vc1_parse_frame_header (const guint8 * data, gsize size, gst_bit_reader_init (&br, data, size); 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 result = parse_frame_header (&br, framehdr, seqhdr, bitplanes); @@ -1906,6 +2032,35 @@ gst_vc1_parse_frame_header (const guint8 * data, gsize size, 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: * @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->skipmb); 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)); bitplanes->directmb = g_realloc_n (bitplanes->directmb, bitplanes->size, sizeof (guint8)); + bitplanes->forwardmb = + g_realloc_n (bitplanes->forwardmb, bitplanes->size, sizeof (guint8)); } else { bitplanes->size = seqhdr->mb_height * seqhdr->mb_stride; 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->skipmb = g_malloc0 (bitplanes->size * sizeof (guint8)); bitplanes->directmb = g_malloc0 (bitplanes->size * sizeof (guint8)); + bitplanes->forwardmb = g_malloc0 (bitplanes->size * sizeof (guint8)); } return TRUE; diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index 874d2f79ec..0cf2b455f6 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -426,6 +426,7 @@ struct _GstVC1PicAdvanced guint8 mvtypemb; guint8 skipmb; guint8 directmb; + guint8 forwardmb; /* B pic interlace field only */ /* For interlaced pictures only */ guint8 fieldtx; @@ -441,6 +442,18 @@ struct _GstVC1PicAdvanced /* P picture */ 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 @@ -451,6 +464,7 @@ struct _GstVC1BitPlanes guint8 *mvtypemb; guint8 *skipmb; guint8 *directmb; + guint8 *forwardmb; guint size; /* Size of the arrays */ }; @@ -585,6 +599,12 @@ GstVC1ParserResult gst_vc1_parse_frame_header (const guint8 *data, GstVC1SeqHdr *seqhdr, 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); void gst_vc1_bitplanes_free (GstVC1BitPlanes *bitplanes); From 73d847ba24792ca2143c738b716b948e55ad193b Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Fri, 14 Oct 2011 11:07:00 -0300 Subject: [PATCH 26/26] codecparsers: VC1: Compute par and fps in advanced profile --- gst-libs/gst/codecparsers/gstvc1parser.c | 63 ++++++++++++++++++++++++ gst-libs/gst/codecparsers/gstvc1parser.h | 4 ++ 2 files changed, 67 insertions(+) diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c index 9c9f743867..654c1a7bb0 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.c +++ b/gst-libs/gst/codecparsers/gstvc1parser.c @@ -277,6 +277,51 @@ static const VLCTable vc1_norm6_vlc_table[64] = { {63, (3 << 1) | 1, 6} }; +/* SMPTE 421M Table 7 */ +typedef struct +{ + gint par_n, par_d; +} PAR; + +static PAR aspect_ratios[] = { + {0, 0}, + {1, 1}, + {12, 11}, + {10, 11}, + {16, 11}, + {40, 33}, + {24, 11}, + {20, 11}, + {32, 11}, + {80, 33}, + {18, 11}, + {15, 11}, + {64, 33}, + {160, 99}, + {0, 0}, + {0, 0} +}; + +/* SMPTE 421M Table 8 */ +static const guint framerates_n[] = { + 0, + 24 * 1000, + 25 * 1000, + 30 * 1000, + 50 * 1000, + 60 * 1000, + 48 * 1000, + 72 * 1000 +}; + +/* SMPTE 421M Table 9 */ +static const guint framerates_d[] = { + 0, + 1000, + 1001 +}; + + static inline gboolean decode_colskip (GstBitReader * br, guint8 * data, guint width, guint height, guint stride, guint invert) @@ -813,6 +858,10 @@ parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) READ_UINT8 (br, tmp, 3); advanced->level = tmp; + advanced->par_n = 0; + advanced->par_d = 0; + advanced->fps_n = 0; + advanced->fps_d = 0; READ_UINT8 (br, advanced->colordiff_format, 2); READ_UINT8 (br, advanced->frmrtq_postproc, 3); @@ -867,6 +916,11 @@ parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) if (advanced->aspect_ratio == 15) { READ_UINT8 (br, advanced->aspect_horiz_size, 8); READ_UINT8 (br, advanced->aspect_vert_size, 8); + advanced->par_n = advanced->aspect_horiz_size; + advanced->par_d = advanced->aspect_vert_size; + } else { + advanced->par_n = aspect_ratios[advanced->aspect_ratio].par_n; + advanced->par_d = aspect_ratios[advanced->aspect_ratio].par_d; } } READ_UINT8 (br, advanced->framerate_flag, 1); @@ -879,6 +933,15 @@ parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br) } else { READ_UINT16 (br, advanced->framerateexp, 16); } + if (advanced->frameratenr > 0 && + advanced->frameratenr < 8 && + advanced->frameratedr > 0 && advanced->frameratedr < 3) { + advanced->fps_n = framerates_n[advanced->frameratenr]; + advanced->fps_d = framerates_d[advanced->frameratedr]; + } else { + advanced->fps_n = advanced->framerateexp + 1; + advanced->fps_d = 32; + } } READ_UINT8 (br, advanced->color_format_flag, 1); diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h index 0cf2b455f6..ce463d7237 100644 --- a/gst-libs/gst/codecparsers/gstvc1parser.h +++ b/gst-libs/gst/codecparsers/gstvc1parser.h @@ -243,6 +243,10 @@ struct _GstVC1AdvancedSeqHdr /* computed */ guint framerate; /* Around in fps, 0 if unknown*/ guint bitrate; /* Around in kpbs, 0 if unknown*/ + guint par_n; + guint par_d; + guint fps_n; + guint fps_d; /* The last parsed entry point */ GstVC1EntryPointHdr entrypoint;