From 127765d19c268724de21ea97038e380acdefd2a2 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 4 Jun 2009 18:11:06 +0200 Subject: vdpaumpegdec: use GstBitReader to parse bitstream --- sys/vdpau/gstvdpmpegdecoder.c | 213 +++++++++++++++------ sys/vdpau/mpegutil.c | 426 +++++++++++++++++++++--------------------- sys/vdpau/mpegutil.h | 59 ++++-- 3 files changed, 405 insertions(+), 293 deletions(-) (limited to 'sys') diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 006e6d41..fc7aa5a6 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -36,6 +36,8 @@ #endif #include +#include +#include #include #include "mpegutil.h" @@ -80,14 +82,82 @@ static void gst_vdp_mpeg_decoder_set_property (GObject * object, static void gst_vdp_mpeg_decoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +guint8 * +mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end) +{ + guint32 code; + + if (G_UNLIKELY (cur == NULL)) + return NULL; + + code = *sync_word; + + while (cur < end) { + code <<= 8; + + if (code == 0x00000100) { + /* Reset the sync word accumulator */ + *sync_word = 0xffffffff; + return cur; + } + + /* Add the next available byte to the collected sync word */ + code |= *cur++; + } + + *sync_word = code; + return NULL; +} + +typedef struct +{ + GstBuffer *buffer; + guint8 *cur; + guint8 *end; +} GstVdpMpegPacketizer; + +static GstBuffer * +gst_vdp_mpeg_packetizer_get_next_packet (GstVdpMpegPacketizer * packetizer) +{ + guint32 sync_word = 0xffffff; + guint8 *packet_start; + guint8 *packet_end; + + if (!packetizer->cur) + return NULL; + + packet_start = packetizer->cur - 3; + packetizer->cur = packet_end = mpeg_util_find_start_code (&sync_word, + packetizer->cur, packetizer->end); + + if (packet_end) + packet_end -= 3; + else + packet_end = packetizer->end; + + return gst_buffer_create_sub (packetizer->buffer, + packet_start - GST_BUFFER_DATA (packetizer->buffer), + packet_end - packet_start); +} + +static void +gst_vdp_mpeg_packetizer_init (GstVdpMpegPacketizer * packetizer, + GstBuffer * buffer) +{ + guint32 sync_word = 0xffffffff; + + packetizer->buffer = buffer; + packetizer->end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); + packetizer->cur = mpeg_util_find_start_code (&sync_word, + GST_BUFFER_DATA (buffer), packetizer->end); +} + static gboolean gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) { GstVdpMpegDecoder *mpeg_dec; GstStructure *structure; const GValue *value; - GstBuffer *codec_data; - MPEGSeqHdr hdr = { 0, }; VdpDecoderProfile profile; GstVdpDevice *device; VdpStatus status; @@ -100,25 +170,44 @@ gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) profile = VDP_DECODER_PROFILE_MPEG1; value = gst_structure_get_value (structure, "codec_data"); - codec_data = gst_value_get_buffer (value); - mpeg_util_parse_sequence_hdr (&hdr, GST_BUFFER_DATA (codec_data), - GST_BUFFER_DATA (codec_data) + GST_BUFFER_SIZE (codec_data)); - if (mpeg_dec->version != 1) { - switch (hdr.profile) { - case 5: - profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; - break; - default: - profile = VDP_DECODER_PROFILE_MPEG2_MAIN; - break; + if (value) { + GstBuffer *codec_data, *buf; + GstVdpMpegPacketizer packetizer; + + codec_data = gst_value_get_buffer (value); + gst_vdp_mpeg_packetizer_init (&packetizer, codec_data); + if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { + MPEGSeqHdr hdr; + + mpeg_util_parse_sequence_hdr (&hdr, buf); + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &hdr.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &hdr.non_intra_quantizer_matrix, 64); + + gst_buffer_unref (buf); + + if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { + MPEGSeqExtHdr ext; + + mpeg_util_parse_sequence_extension (&ext, buf); + if (mpeg_dec->version != 1) { + switch (ext.profile) { + case 5: + profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; + break; + default: + profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + break; + } + } + + gst_buffer_unref (buf); + } } } - memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, - &hdr.intra_quantizer_matrix, 64); - memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, - &hdr.non_intra_quantizer_matrix, 64); - device = dec->device; if (mpeg_dec->decoder != VDP_INVALID_HANDLE) { @@ -224,7 +313,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, static gboolean gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) + GstBuffer * buffer) { GstVdpDecoder *dec; MPEGPictureExt pic_ext; @@ -233,7 +322,7 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, dec = GST_VDP_DECODER (mpeg_dec); info = &mpeg_dec->vdp_info; - if (!mpeg_util_parse_picture_coding_extension (&pic_ext, data, end)) + if (!mpeg_util_parse_picture_coding_extension (&pic_ext, buffer)) return FALSE; memcpy (&mpeg_dec->vdp_info.f_code, &pic_ext.f_code, 4); @@ -252,16 +341,17 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, static gboolean gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) + GstBuffer * buffer) { GstVdpDecoder *dec; MPEGSeqHdr hdr; dec = GST_VDP_DECODER (mpeg_dec); - if (!mpeg_util_parse_sequence_hdr (&hdr, data, end)) + if (!mpeg_util_parse_sequence_hdr (&hdr, buffer)) return FALSE; + g_debug ("här"); memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, &hdr.intra_quantizer_matrix, 64); memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, @@ -272,14 +362,14 @@ gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, static gboolean gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) + GstBuffer * buffer) { GstVdpDecoder *dec; MPEGPictureHdr pic_hdr; dec = GST_VDP_DECODER (mpeg_dec); - if (!mpeg_util_parse_picture_hdr (&pic_hdr, data, end)) + if (!mpeg_util_parse_picture_hdr (&pic_hdr, buffer)) return FALSE; if (pic_hdr.pic_type != I_FRAME @@ -309,12 +399,12 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, } static gboolean -gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, guint8 * data, - guint8 * end) +gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, + GstBuffer * buffer) { - MPEGPictureGOP gop; + MPEGGop gop; - if (!mpeg_util_parse_picture_gop (&gop, data, end)) + if (!mpeg_util_parse_gop (&gop, buffer)) return FALSE; mpeg_dec->broken_gop = gop.broken_gop; @@ -324,11 +414,11 @@ gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, guint8 * data, static gboolean gst_vdp_mpeg_decoder_parse_quant_matrix (GstVdpMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) + GstBuffer * buffer) { MPEGQuantMatrix qm; - if (!mpeg_util_parse_quant_matrix (&qm, data, end)) + if (!mpeg_util_parse_quant_matrix (&qm, buffer)) return FALSE; memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, @@ -355,8 +445,8 @@ static GstFlowReturn gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) { GstVdpMpegDecoder *mpeg_dec; - guint8 *data, *end; - guint32 sync_word = 0xffffffff; + GstVdpMpegPacketizer packetizer; + GstBuffer *buf; GstFlowReturn ret = GST_FLOW_OK; mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); @@ -367,69 +457,70 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) return GST_FLOW_OK; } - data = GST_BUFFER_DATA (buffer); - end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); + gst_vdp_mpeg_packetizer_init (&packetizer, buffer); + while ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { + GstBitReader b_reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); + guint32 sync_code; + guint8 start_code; - while ((data = mpeg_util_find_start_code (&sync_word, data, end))) { - guint8 *packet_start; - guint8 *packet_end; + /* skip sync_code */ + gst_bit_reader_get_bits_uint32 (&b_reader, &sync_code, 8 * 3); - packet_start = data - 3; - packet_end = mpeg_util_find_start_code (&sync_word, data, end); - if (packet_end) - packet_end -= 3; - else - packet_end = end; - - if (data[0] >= MPEG_PACKET_SLICE_MIN && data[0] <= MPEG_PACKET_SLICE_MAX) { - GstBuffer *subbuf; + /* start_code */ + gst_bit_reader_get_bits_uint8 (&b_reader, &start_code, 8); + if (start_code >= MPEG_PACKET_SLICE_MIN + && start_code <= MPEG_PACKET_SLICE_MAX) { GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); - subbuf = - gst_buffer_create_sub (buffer, - packet_start - GST_BUFFER_DATA (buffer), packet_end - packet_start); - gst_adapter_push (mpeg_dec->adapter, subbuf); + + gst_buffer_ref (buf); + gst_adapter_push (mpeg_dec->adapter, buf); mpeg_dec->vdp_info.slice_count++; } - switch (data[0]) { + switch (start_code) { case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - if (!gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, packet_start, - packet_end)) { + if (!gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, buf)) { return GST_FLOW_OK; } break; case MPEG_PACKET_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); - gst_vdp_mpeg_decoder_parse_sequence (mpeg_dec, packet_start, - packet_end); + gst_vdp_mpeg_decoder_parse_sequence (mpeg_dec, buf); break; case MPEG_PACKET_EXTENSION: + { + guint8 ext_code; + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); - switch (read_bits (data + 1, 0, 4)) { + + /* ext_code */ + gst_bit_reader_get_bits_uint8 (&b_reader, &ext_code, 4); + switch (ext_code) { case MPEG_PACKET_EXT_PICTURE_CODING: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_PICTURE_CODING"); - gst_vdp_mpeg_decoder_parse_picture_coding (mpeg_dec, packet_start, - packet_end); + gst_vdp_mpeg_decoder_parse_picture_coding (mpeg_dec, buf); break; case MPEG_PACKET_EXT_QUANT_MATRIX: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); - gst_vdp_mpeg_decoder_parse_quant_matrix (mpeg_dec, packet_start, - packet_end); + gst_vdp_mpeg_decoder_parse_quant_matrix (mpeg_dec, buf); break; default: break; } break; + } case MPEG_PACKET_GOP: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); - gst_vdp_mpeg_decoder_parse_gop (mpeg_dec, packet_start, packet_end); + gst_vdp_mpeg_decoder_parse_gop (mpeg_dec, buf); break; default: break; } + + gst_buffer_unref (buf); } if (mpeg_dec->vdp_info.slice_count > 0) diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 08ae5c53..c35ad9fb 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -18,6 +18,7 @@ * Boston, MA 02111-1307, USA. */ +#include #include #include "mpegutil.h" @@ -53,58 +54,6 @@ guint8 mpeg2_scan[64] = { 53, 60, 61, 54, 47, 55, 62, 63 }; -guint8 bits[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; - -guint32 -read_bits (guint8 * buf, gint start_bit, gint n_bits) -{ - gint i; - guint32 ret = 0x00; - - buf += start_bit / 8; - start_bit %= 8; - - for (i = 0; i < n_bits; i++) { - guint32 tmp; - - tmp = ((*buf & bits[start_bit]) >> (7 - start_bit)); - ret = (ret | (tmp << (n_bits - i - 1))); - if (++start_bit == 8) { - buf += 1; - start_bit = 0; - } - } - - return ret; -} - -guint8 * -mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end) -{ - guint32 code; - - if (G_UNLIKELY (cur == NULL)) - return NULL; - - code = *sync_word; - - while (cur < end) { - code <<= 8; - - if (code == 0x00000100) { - /* Reset the sync word accumulator */ - *sync_word = 0xffffffff; - return cur; - } - - /* Add the next available byte to the collected sync word */ - code |= *cur++; - } - - *sync_word = code; - return NULL; -} - static void set_fps_from_code (MPEGSeqHdr * hdr, guint8 fps_code) { @@ -150,157 +99,169 @@ set_par_from_dar (MPEGSeqHdr * hdr, guint8 asr_code) } } -static gboolean -mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) +gboolean +mpeg_util_parse_sequence_extension (MPEGSeqExtHdr * hdr, GstBuffer * buffer) { - guint8 ext_code; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);; - if (G_UNLIKELY (data >= end)) - return FALSE; /* short extension packet */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - ext_code = read_bits (data, 0, 4); + /* skip extension code */ + if (!gst_bit_reader_skip (&reader, 4)) + return FALSE; - switch (ext_code) { - case MPEG_PACKET_EXT_SEQUENCE: - { - /* Parse a Sequence Extension */ - guint8 horiz_size_ext, vert_size_ext; - guint8 fps_n_ext, fps_d_ext; + /* skip profile and level escape bit */ + if (!gst_bit_reader_skip (&reader, 1)) + return FALSE; - if (G_UNLIKELY ((end - data) < 6)) - /* need at least 10 bytes, minus 4 for the start code 000001b5 */ - return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->profile, 3)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->level, 4)) + return FALSE; - hdr->profile = read_bits (data, 7, 3); + /* progressive */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->progressive, 1)) + return FALSE; + + /* chroma format */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->chroma_format, 2)) + return FALSE; - horiz_size_ext = read_bits (data + 1, 7, 2); - vert_size_ext = read_bits (data + 2, 1, 2); + /* resolution extension */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->horiz_size_ext, 2)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->vert_size_ext, 2)) + return FALSE; - fps_n_ext = read_bits (data + 5, 1, 2); - fps_d_ext = read_bits (data + 5, 3, 5); + /* skip to framerate extension */ + if (!gst_bit_reader_skip (&reader, 22)) + return FALSE; - hdr->fps_n *= (fps_n_ext + 1); - hdr->fps_d *= (fps_d_ext + 1); - hdr->width += (horiz_size_ext << 12); - hdr->height += (vert_size_ext << 12); - break; - } - default: - break; - } + /* framerate extension */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->fps_n_ext, 2)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->fps_d_ext, 2)) + return FALSE; return TRUE; } gboolean -mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) +mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, GstBuffer * buffer) { - guint32 code; - guint8 dar_idx, fps_idx; - guint32 sync_word = 0xffffffff; - gboolean constrained_flag; - gboolean load_intra_flag; - gboolean load_non_intra_flag; - gint i; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); + guint8 dar_idx, par_idx; + guint8 load_intra_flag, load_non_intra_flag; - if (G_UNLIKELY ((end - data) < 12)) - return FALSE; /* Too small to be a sequence header */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - code = GST_READ_UINT32_BE (data); - if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_SEQUENCE))) + /* resolution */ + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->width, 12)) + return FALSE; + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->height, 12)) return FALSE; - /* Skip the sync word */ - data += 4; + /* aspect ratio */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &dar_idx, 4)) + return FALSE; + set_par_from_dar (hdr, dar_idx); - /* Parse the MPEG 1 bits */ - hdr->mpeg_version = 1; + /* framerate */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &par_idx, 4)) + return FALSE; + set_fps_from_code (hdr, par_idx); - code = GST_READ_UINT32_BE (data); - hdr->width = read_bits (data, 0, 12); - hdr->height = read_bits (data + 1, 4, 12); + /* bitrate */ + if (!gst_bit_reader_get_bits_uint32 (&reader, &hdr->bitrate, 18)) + return FALSE; - dar_idx = read_bits (data + 3, 0, 4); - set_par_from_dar (hdr, dar_idx); - fps_idx = read_bits (data + 3, 4, 4); - set_fps_from_code (hdr, fps_idx); + if (!gst_bit_reader_skip (&reader, 1)) + return FALSE; + + /* VBV buffer size */ + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->vbv_buffer, 10)) + return FALSE; - constrained_flag = read_bits (data + 7, 5, 1); + /* constrained parameters flag */ + if (!gst_bit_reader_get_bits_uint8 (&reader, + &hdr->constrained_parameters_flag, 1)) + return FALSE; - load_intra_flag = read_bits (data + 7, 6, 1); + /* intra quantizer matrix */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &load_intra_flag, 1)) + return FALSE; if (load_intra_flag) { - if (G_UNLIKELY ((end - data) < 64)) - return FALSE; + gint i; for (i = 0; i < 64; i++) { - hdr->intra_quantizer_matrix[mpeg2_scan[i]] = - read_bits (data + 7 + i, 7, 8); + if (!gst_bit_reader_get_bits_uint8 (&reader, + &hdr->intra_quantizer_matrix[mpeg2_scan[i]], 8)) + return FALSE; } - data += 64; - } else memcpy (hdr->intra_quantizer_matrix, default_intra_quantizer_matrix, 64); - load_non_intra_flag = read_bits (data + 7, 7 + load_intra_flag, 1); + /* non intra quantizer matrix */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &load_non_intra_flag, 1)) + return FALSE; if (load_non_intra_flag) { - if (G_UNLIKELY ((end - data) < 64)) - return FALSE; - for (i = 0; i < 64; i++) - hdr->non_intra_quantizer_matrix[mpeg2_scan[i]] = - read_bits (data + 8 + i, 1 + load_intra_flag, 8); - } else - memset (hdr->non_intra_quantizer_matrix, 16, 64); - - /* Advance past the rest of the MPEG-1 header */ - data += 8; - - /* Read MPEG-2 sequence extensions */ - data = mpeg_util_find_start_code (&sync_word, data, end); - while (data != NULL) { - if (G_UNLIKELY (data >= end)) - return FALSE; - - /* data points at the last byte of the start code */ - if (data[0] == MPEG_PACKET_EXTENSION) { - if (!mpeg_util_parse_extension_packet (hdr, data + 1, end)) + gint i; + for (i = 0; i < 64; i++) { + if (!gst_bit_reader_get_bits_uint8 (&reader, + &hdr->non_intra_quantizer_matrix[mpeg2_scan[i]], 8)) return FALSE; - - hdr->mpeg_version = 2; } - data = mpeg_util_find_start_code (&sync_word, data, end); - } + } else + memset (hdr->non_intra_quantizer_matrix, 16, 64); return TRUE; } gboolean -mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) +mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, GstBuffer * buffer) { - guint32 code; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); - if (G_UNLIKELY ((end - data) < 8)) - return FALSE; /* Packet too small */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - code = GST_READ_UINT32_BE (data); - if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_PICTURE))) + /* temperal sequence number */ + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->tsn, 10)) return FALSE; - /* Skip the sync word */ - data += 4; + /* frame type */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->pic_type, 3)) + return FALSE; - hdr->pic_type = (data[1] >> 3) & 0x07; if (hdr->pic_type == 0 || hdr->pic_type > 4) return FALSE; /* Corrupted picture packet */ + /* VBV delay */ + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->vbv_delay, 16)) + return FALSE; + if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) { - if (G_UNLIKELY ((end - data) < 5)) - return FALSE; /* packet too small */ - hdr->full_pel_forward_vector = read_bits (data + 3, 5, 1); - hdr->f_code[0][0] = hdr->f_code[0][1] = read_bits (data + 3, 6, 3); + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->full_pel_forward_vector, + 1)) + return FALSE; + + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->f_code[0][0], 3)) + return FALSE; + hdr->f_code[0][1] = hdr->f_code[0][0]; if (hdr->pic_type == B_FRAME) { - hdr->full_pel_backward_vector = read_bits (data + 4, 1, 1); - hdr->f_code[1][0] = hdr->f_code[1][1] = read_bits (data + 4, 2, 3); + if (!gst_bit_reader_get_bits_uint8 (&reader, + &hdr->full_pel_backward_vector, 1)) + return FALSE; + + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->f_code[1][0], 3)) + return FALSE; + hdr->f_code[1][1] = hdr->f_code[1][0]; } else hdr->full_pel_backward_vector = 0; } else { @@ -312,104 +273,143 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) } gboolean -mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, guint8 * data, - guint8 * end) +mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, + GstBuffer * buffer) { - guint32 code; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); - if (G_UNLIKELY ((end - data) < 9)) - return FALSE; /* Packet too small */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - code = GST_READ_UINT32_BE (data); + /* skip extension code */ + if (!gst_bit_reader_skip (&reader, 4)) + return FALSE; - if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_EXTENSION)))) + /* f_code */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->f_code[0][0], 4)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->f_code[0][1], 4)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->f_code[1][0], 4)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->f_code[1][1], 4)) return FALSE; - /* Skip the sync word */ - data += 4; + /* intra DC precision */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->intra_dc_precision, 2)) + return FALSE; - ext->f_code[0][0] = read_bits (data, 4, 4); - ext->f_code[0][1] = read_bits (data + 1, 0, 4); - ext->f_code[1][0] = read_bits (data + 1, 4, 4); - ext->f_code[1][1] = read_bits (data + 2, 0, 4); + /* picture structure */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->picture_structure, 2)) + return FALSE; - ext->intra_dc_precision = read_bits (data + 2, 4, 2); - ext->picture_structure = read_bits (data + 2, 6, 2); - ext->top_field_first = read_bits (data + 3, 0, 1); - ext->frame_pred_frame_dct = read_bits (data + 3, 1, 1); - ext->concealment_motion_vectors = read_bits (data + 3, 2, 1); - ext->q_scale_type = read_bits (data + 3, 3, 1); - ext->intra_vlc_format = read_bits (data + 3, 4, 1); - ext->alternate_scan = read_bits (data + 3, 5, 1); + /* top field first */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->top_field_first, 1)) + return FALSE; + + /* frame pred frame dct */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->frame_pred_frame_dct, 1)) + return FALSE; + + /* concealment motion vectors */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->concealment_motion_vectors, + 1)) + return FALSE; + + /* q scale type */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->q_scale_type, 1)) + return FALSE; + + /* intra vlc format */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->intra_vlc_format, 1)) + return FALSE; + + /* alternate scan */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->alternate_scan, 1)) + return FALSE; + + /* repeat first field */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->repeat_first_field, 1)) + return FALSE; return TRUE; } gboolean -mpeg_util_parse_picture_gop (MPEGPictureGOP * gop, guint8 * data, guint8 * end) +mpeg_util_parse_gop (MPEGGop * gop, GstBuffer * buffer) { - guint32 code; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); - if (G_UNLIKELY ((end - data) < 8)) - return FALSE; /* Packet too small */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - code = GST_READ_UINT32_BE (data); + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->drop_frame_flag, 1)) + return FALSE; - if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_GOP)))) + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->hour, 5)) return FALSE; - /* Skip the sync word */ - data += 4; + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->minute, 6)) + return FALSE; + + /* skip unused bit */ + if (!gst_bit_reader_skip (&reader, 1)) + return FALSE; - gop->drop_frame_flag = read_bits (data, 0, 1); + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->second, 6)) + return FALSE; - gop->hour = read_bits (data, 1, 5); - gop->minute = read_bits (data, 6, 6); - gop->second = read_bits (data + 1, 4, 6); - gop->frame = read_bits (data + 2, 3, 6); + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->frame, 6)) + return FALSE; + + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->closed_gop, 1)) + return FALSE; - gop->closed_gop = read_bits (data + 3, 1, 1); - gop->broken_gop = read_bits (data + 3, 2, 1); + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->broken_gop, 1)) + return FALSE; return TRUE; } gboolean -mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, guint8 * data, guint8 * end) +mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, GstBuffer * buffer) { - guint32 code; - gboolean load_intra_flag, load_non_intra_flag; - gint i; - - if (G_UNLIKELY ((end - data) < 5)) - return FALSE; /* Packet too small */ + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); + guint8 load_intra_flag, load_non_intra_flag; - code = GST_READ_UINT32_BE (data); - - if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_EXTENSION)))) + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) return FALSE; - /* Skip the sync word */ - data += 4; + /* skip extension code */ + if (!gst_bit_reader_skip (&reader, 4)) + return FALSE; - load_intra_flag = read_bits (data, 4, 1); + /* intra quantizer matrix */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &load_intra_flag, 1)) + return FALSE; if (load_intra_flag) { - if (G_UNLIKELY ((end - data) < 64)) - return FALSE; - for (i = 0; i < 64; i++) - qm->intra_quantizer_matrix[mpeg2_scan[i]] = read_bits (data + i, 5, 8); - - data += 64; + gint i; + for (i = 0; i < 64; i++) { + if (!gst_bit_reader_get_bits_uint8 (&reader, + &qm->intra_quantizer_matrix[mpeg2_scan[i]], 8)) + return FALSE; + } } else memcpy (qm->intra_quantizer_matrix, default_intra_quantizer_matrix, 64); - load_non_intra_flag = read_bits (data, 5 + load_intra_flag, 1); + /* non intra quantizer matrix */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &load_non_intra_flag, 1)) + return FALSE; if (load_non_intra_flag) { - if (G_UNLIKELY ((end - data) < 64)) - return FALSE; - for (i = 0; i < 64; i++) - qm->non_intra_quantizer_matrix[mpeg2_scan[i]] = - read_bits (data + i, 6 + load_intra_flag, 8); + gint i; + for (i = 0; i < 64; i++) { + if (!gst_bit_reader_get_bits_uint8 (&reader, + &qm->non_intra_quantizer_matrix[mpeg2_scan[i]], 8)) + return FALSE; + } } else memset (qm->non_intra_quantizer_matrix, 16, 64); diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h index 43f34a59..4e5a656a 100644 --- a/sys/vdpau/mpegutil.h +++ b/sys/vdpau/mpegutil.h @@ -24,9 +24,10 @@ #include typedef struct MPEGSeqHdr MPEGSeqHdr; +typedef struct MPEGSeqExtHdr MPEGSeqExtHdr; typedef struct MPEGPictureHdr MPEGPictureHdr; typedef struct MPEGPictureExt MPEGPictureExt; -typedef struct MPEGPictureGOP MPEGPictureGOP; +typedef struct MPEGGop MPEGGop; typedef struct MPEGQuantMatrix MPEGQuantMatrix; /* Packet ID codes for different packet types we @@ -53,27 +54,45 @@ typedef struct MPEGQuantMatrix MPEGQuantMatrix; struct MPEGSeqHdr { - /* 0 for unknown, else 1 or 2 */ - guint8 mpeg_version; - /* Pixel-Aspect Ratio from DAR code via set_par_from_dar */ - gint par_w, par_h; + guint par_w, par_h; /* Width and Height of the video */ - gint width, height; + guint16 width, height; /* Framerate */ - gint fps_n, fps_d; + guint fps_n, fps_d; - /* mpeg2 decoder profile */ - gint profile; + guint32 bitrate; + guint16 vbv_buffer; + guint8 constrained_parameters_flag; + guint8 intra_quantizer_matrix[64]; guint8 non_intra_quantizer_matrix[64]; }; +struct MPEGSeqExtHdr +{ + + /* mpeg2 decoder profile */ + guint8 profile; + /* mpeg2 decoder level */ + guint8 level; + + guint8 progressive; + guint8 chroma_format; + + guint8 horiz_size_ext, vert_size_ext; + + guint8 fps_n_ext, fps_d_ext; + +}; + struct MPEGPictureHdr { + guint16 tsn; guint8 pic_type; - + guint16 vbv_delay; + guint8 full_pel_forward_vector, full_pel_backward_vector; guint8 f_code[2][2]; @@ -91,9 +110,10 @@ struct MPEGPictureExt guint8 q_scale_type; guint8 intra_vlc_format; guint8 alternate_scan; + guint8 repeat_first_field; }; -struct MPEGPictureGOP +struct MPEGGop { guint8 drop_frame_flag; @@ -109,18 +129,19 @@ struct MPEGQuantMatrix guint8 non_intra_quantizer_matrix[64]; }; -gboolean mpeg_util_parse_sequence_hdr (MPEGSeqHdr *hdr, - guint8 *data, guint8 *end); +gboolean mpeg_util_parse_sequence_hdr (MPEGSeqHdr *hdr, GstBuffer *buffer); -gboolean mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end); +gboolean mpeg_util_parse_sequence_extension (MPEGSeqExtHdr *hdr, + GstBuffer *buffer); -gboolean mpeg_util_parse_picture_coding_extension (MPEGPictureExt *ext, guint8 *data, guint8 *end); +gboolean mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, GstBuffer *buffer); -gboolean mpeg_util_parse_picture_gop (MPEGPictureGOP * gop, guint8 * data, guint8 * end); +gboolean mpeg_util_parse_picture_coding_extension (MPEGPictureExt *ext, + GstBuffer *buffer); -gboolean mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, guint8 * data, guint8 * end); +gboolean mpeg_util_parse_gop (MPEGGop * gop, GstBuffer *buffer); -guint8 *mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end); -guint32 read_bits (guint8 * buf, gint start_bit, gint n_bits); +gboolean mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, GstBuffer *buffer); #endif + -- cgit v1.2.1