summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl-Anton Ingmarsson <ca.ingmarsson@gmail.com>2009-06-04 18:11:06 +0200
committerJan Schmidt <thaytan@noraisin.net>2009-06-20 15:21:40 +0100
commit127765d19c268724de21ea97038e380acdefd2a2 (patch)
tree224e61f7c572125d67e15824a0bb8a39885881ef
parent426a6eaba9776157f43da280d37b81ac49cccd72 (diff)
downloadgst-plugins-bad-127765d19c268724de21ea97038e380acdefd2a2.tar.gz
gst-plugins-bad-127765d19c268724de21ea97038e380acdefd2a2.tar.bz2
gst-plugins-bad-127765d19c268724de21ea97038e380acdefd2a2.zip
vdpaumpegdec: use GstBitReader to parse bitstream
-rw-r--r--sys/vdpau/gstvdpmpegdecoder.c213
-rw-r--r--sys/vdpau/mpegutil.c426
-rw-r--r--sys/vdpau/mpegutil.h59
3 files changed, 405 insertions, 293 deletions
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 <gst/gst.h>
+#include <gst/base/gstbytereader.h>
+#include <gst/base/gstbitreader.h>
#include <string.h>
#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 <gst/base/gstbitreader.h>
#include <string.h>
#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 <gst/gst.h>
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
+