mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 17:20:36 +00:00
vdpaumpegdec: use GstBitReader to parse bitstream
This commit is contained in:
parent
426a6eaba9
commit
127765d19c
3 changed files with 413 additions and 301 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
horiz_size_ext = read_bits (data + 1, 7, 2);
|
||||
vert_size_ext = read_bits (data + 2, 1, 2);
|
||||
/* chroma format */
|
||||
if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->chroma_format, 2))
|
||||
return FALSE;
|
||||
|
||||
fps_n_ext = read_bits (data + 5, 1, 2);
|
||||
fps_d_ext = read_bits (data + 5, 3, 5);
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
/* skip to framerate extension */
|
||||
if (!gst_bit_reader_skip (&reader, 22))
|
||||
return FALSE;
|
||||
|
||||
/* 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 */
|
||||
|
||||
code = GST_READ_UINT32_BE (data);
|
||||
if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_SEQUENCE)))
|
||||
/* skip sync word */
|
||||
if (!gst_bit_reader_skip (&reader, 8 * 4))
|
||||
return FALSE;
|
||||
|
||||
/* Skip the sync word */
|
||||
data += 4;
|
||||
/* 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;
|
||||
|
||||
/* Parse the MPEG 1 bits */
|
||||
hdr->mpeg_version = 1;
|
||||
|
||||
code = GST_READ_UINT32_BE (data);
|
||||
hdr->width = read_bits (data, 0, 12);
|
||||
hdr->height = read_bits (data + 1, 4, 12);
|
||||
|
||||
dar_idx = read_bits (data + 3, 0, 4);
|
||||
/* aspect ratio */
|
||||
if (!gst_bit_reader_get_bits_uint8 (&reader, &dar_idx, 4))
|
||||
return FALSE;
|
||||
set_par_from_dar (hdr, dar_idx);
|
||||
fps_idx = read_bits (data + 3, 4, 4);
|
||||
set_fps_from_code (hdr, fps_idx);
|
||||
|
||||
constrained_flag = read_bits (data + 7, 5, 1);
|
||||
/* framerate */
|
||||
if (!gst_bit_reader_get_bits_uint8 (&reader, &par_idx, 4))
|
||||
return FALSE;
|
||||
set_fps_from_code (hdr, par_idx);
|
||||
|
||||
load_intra_flag = read_bits (data + 7, 6, 1);
|
||||
/* bitrate */
|
||||
if (!gst_bit_reader_get_bits_uint32 (&reader, &hdr->bitrate, 18))
|
||||
return FALSE;
|
||||
|
||||
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 parameters flag */
|
||||
if (!gst_bit_reader_get_bits_uint8 (&reader,
|
||||
&hdr->constrained_parameters_flag, 1))
|
||||
return FALSE;
|
||||
|
||||
/* 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);
|
||||
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;
|
||||
}
|
||||
} 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))
|
||||
return FALSE;
|
||||
|
||||
hdr->mpeg_version = 2;
|
||||
}
|
||||
data = mpeg_util_find_start_code (&sync_word, data, end);
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
code = GST_READ_UINT32_BE (data);
|
||||
if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_PICTURE)))
|
||||
/* skip sync word */
|
||||
if (!gst_bit_reader_skip (&reader, 8 * 4))
|
||||
return FALSE;
|
||||
|
||||
/* Skip the sync word */
|
||||
data += 4;
|
||||
/* temperal sequence number */
|
||||
if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->tsn, 10))
|
||||
return FALSE;
|
||||
|
||||
/* 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 */
|
||||
|
||||
if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) {
|
||||
if (G_UNLIKELY ((end - data) < 5))
|
||||
return FALSE; /* packet too small */
|
||||
/* VBV delay */
|
||||
if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->vbv_delay, 16))
|
||||
return FALSE;
|
||||
|
||||
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 (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) {
|
||||
|
||||
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 */
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
/* intra DC precision */
|
||||
if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->intra_dc_precision, 2))
|
||||
return FALSE;
|
||||
|
||||
/* picture structure */
|
||||
if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->picture_structure, 2))
|
||||
return FALSE;
|
||||
|
||||
/* 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 */
|
||||
|
||||
code = GST_READ_UINT32_BE (data);
|
||||
|
||||
if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_GOP))))
|
||||
/* skip sync word */
|
||||
if (!gst_bit_reader_skip (&reader, 8 * 4))
|
||||
return FALSE;
|
||||
|
||||
/* Skip the sync word */
|
||||
data += 4;
|
||||
if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->drop_frame_flag, 1))
|
||||
return FALSE;
|
||||
|
||||
gop->drop_frame_flag = read_bits (data, 0, 1);
|
||||
if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->hour, 5))
|
||||
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->minute, 6))
|
||||
return FALSE;
|
||||
|
||||
gop->closed_gop = read_bits (data + 3, 1, 1);
|
||||
gop->broken_gop = read_bits (data + 3, 2, 1);
|
||||
/* skip unused bit */
|
||||
if (!gst_bit_reader_skip (&reader, 1))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->second, 6))
|
||||
return FALSE;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
|
||||
guint8 load_intra_flag, load_non_intra_flag;
|
||||
|
||||
if (G_UNLIKELY ((end - data) < 5))
|
||||
return FALSE; /* Packet too small */
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue