codecparsers: mpeg2: add slice header parsing API.

Add API to parse the Slice header. This also calculates the macroblock
position as specified in 6.3.16.

https://bugzilla.gnome.org/show_bug.cgi?id=664274

Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
Sreerenj Balachandran 2013-01-30 16:56:15 +02:00 committed by Gwenole Beauchesne
parent 2adfbe36f1
commit 9a2ed78532
2 changed files with 164 additions and 0 deletions

View file

@ -78,6 +78,49 @@ static const guint8 mpeg_zigzag_8x8[64] = {
53, 60, 61, 54, 47, 55, 62, 63
};
enum
{
GST_MPEG_VIDEO_MACROBLOCK_ESCAPE = G_MAXUINT,
};
/* Table B-1: Variable length codes for macroblock_address_increment */
static const VLCTable mpeg2_mbaddr_vlc_table[] = {
{1, 0x01, 1},
{2, 0x03, 3},
{3, 0x02, 3},
{4, 0x03, 4},
{5, 0x02, 4},
{6, 0x03, 5},
{7, 0x02, 5},
{8, 0x07, 7},
{9, 0x06, 7},
{10, 0x0b, 8},
{11, 0x0a, 8},
{12, 0x09, 8},
{13, 0x08, 8},
{14, 0x07, 8},
{15, 0x06, 8},
{16, 0x17, 10},
{17, 0x16, 10},
{18, 0x15, 10},
{19, 0x14, 10},
{20, 0x13, 10},
{21, 0x12, 10},
{22, 0x23, 11},
{23, 0x22, 11},
{24, 0x21, 11},
{25, 0x20, 11},
{26, 0x1f, 11},
{27, 0x1e, 11},
{28, 0x1d, 11},
{29, 0x1c, 11},
{30, 0x1b, 11},
{31, 0x1a, 11},
{32, 0x19, 11},
{33, 0x18, 11},
{GST_MPEG_VIDEO_MACROBLOCK_ESCAPE, 0x08, 11}
};
GST_DEBUG_CATEGORY (mpegvideo_parser_debug);
#define GST_CAT_DEFAULT mpegvideo_parser_debug
@ -893,6 +936,95 @@ failed:
return FALSE;
}
/**
* gst_mpeg_video_packet_parse_slice_header:
* @packet: The #GstMpegVideoPacket that carries the data
* @slice_hdr: (out): The #GstMpegVideoSliceHdr structure to fill
* @seqhdr: The #GstMpegVideoSequenceHdr header
* @seqscaleext: The #GstMpegVideoSequenceScalableExt header
*
* Parses the @GstMpegVideoSliceHdr structure members from @data
*
* Returns: %TRUE if the slice could be parsed correctly, %FALSE otherwize.
*
* Since: 1.2
*/
gboolean
gst_mpeg_video_packet_parse_slice_header (const GstMpegVideoPacket * packet,
GstMpegVideoSliceHdr * slice_hdr, GstMpegVideoSequenceHdr * seqhdr,
GstMpegVideoSequenceScalableExt * seqscaleext)
{
GstBitReader br;
guint height;
guint mb_inc;
guint8 bits, extra_bits;
guint8 vertical_position, vertical_position_extension = 0;
g_return_val_if_fail (seqhdr != NULL, FALSE);
if (packet->size < 5)
return FALSE;
gst_bit_reader_init (&br, &packet->data[packet->offset], packet->size);
if (packet->type < GST_MPEG_VIDEO_PACKET_SLICE_MIN ||
packet->type > GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
GST_DEBUG ("Not parsing a slice");
return FALSE;
}
vertical_position = packet->type - GST_MPEG_VIDEO_PACKET_SLICE_MIN;
height = seqhdr->height;
if (height > 2800)
READ_UINT8 (&br, vertical_position_extension, 3);
if (seqscaleext)
if (seqscaleext->scalable_mode ==
GST_MPEG_VIDEO_SEQ_SCALABLE_MODE_DATA_PARTITIONING)
READ_UINT8 (&br, slice_hdr->priority_breakpoint, 7);
READ_UINT8 (&br, slice_hdr->quantiser_scale_code, 5);
READ_UINT8 (&br, extra_bits, 1);
if (!extra_bits)
slice_hdr->intra_slice = 0;
else {
READ_UINT8 (&br, slice_hdr->intra_slice, 1);
SKIP (&br, 1);
READ_UINT8 (&br, slice_hdr->slice_picture_id, 6);
READ_UINT8 (&br, bits, 1);
while (bits) {
READ_UINT8 (&br, extra_bits, 8);
READ_UINT8 (&br, bits, 1);
}
}
slice_hdr->header_size = gst_bit_reader_get_pos (&br);
if (height > 2800)
slice_hdr->mb_row = (vertical_position_extension << 7) + vertical_position;
else
slice_hdr->mb_row = vertical_position;
slice_hdr->mb_column = -1;
do {
if (!decode_vlc (&br, &mb_inc, mpeg2_mbaddr_vlc_table,
G_N_ELEMENTS (mpeg2_mbaddr_vlc_table))) {
GST_WARNING ("failed to decode first macroblock_address_increment");
goto failed;
}
slice_hdr->mb_column +=
mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE ? 33 : mb_inc;
} while (mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE);
return TRUE;
failed:
GST_WARNING ("error parsing \"Slice\"");
return FALSE;
}
/**
* gst_mpeg_video_quant_matrix_get_raster_from_zigzag:
* @out_quant: (out): The resulting quantization matrix

View file

@ -197,6 +197,7 @@ typedef struct _GstMpegVideoPictureHdr GstMpegVideoPictureHdr;
typedef struct _GstMpegVideoGop GstMpegVideoGop;
typedef struct _GstMpegVideoPictureExt GstMpegVideoPictureExt;
typedef struct _GstMpegVideoQuantMatrixExt GstMpegVideoQuantMatrixExt;
typedef struct _GstMpegVideoSliceHdr GstMpegVideoSliceHdr;
typedef struct _GstMpegVideoPacket GstMpegVideoPacket;
/**
@ -438,6 +439,32 @@ struct _GstMpegVideoGop
guint8 broken_link;
};
/**
* GstMpegVideoSliceHdr:
* @slice_vertical_position_extension: Extension to slice_vertical_position
* @priority_breakpoint: Point where the bitstream shall be partitioned
* @quantiser_scale_code: Quantiser value (range: 1-31)
* @intra_slice: Equal to one if all the macroblocks are intra macro blocks.
* @slice_picture_id: Intended to aid recovery on severe bursts of
* errors for certain types of applications
*
* The Mpeg2 Video Slice Header structure.
*
* Since: 1.2
*/
struct _GstMpegVideoSliceHdr
{
guint8 priority_breakpoint;
guint8 quantiser_scale_code;
guint8 intra_slice;
guint8 slice_picture_id;
/* Calculated values */
guint header_size; /* slice_header size in bits */
gint mb_row; /* macroblock row */
gint mb_column; /* macroblock column */
};
/**
* GstMpegVideoTypeOffsetSize:
* @type: the type of the packet that start at @offset
@ -479,6 +506,11 @@ gboolean gst_mpeg_video_packet_parse_picture_extension (const GstMpegVideoPacke
gboolean gst_mpeg_video_packet_parse_gop (const GstMpegVideoPacket * packet,
GstMpegVideoGop * gop);
gboolean gst_mpeg_video_packet_parse_slice_header (const GstMpegVideoPacket * packet,
GstMpegVideoSliceHdr * slice_hdr,
GstMpegVideoSequenceHdr * seq_hdr,
GstMpegVideoSequenceScalableExt * seqscaleext);
gboolean gst_mpeg_video_packet_parse_quant_matrix_extension (const GstMpegVideoPacket * packet,
GstMpegVideoQuantMatrixExt * quant);