g3dvl: Rewrite the mpeg 1&2 bitstream parser

Based on work of Maarten Lankhorst this time.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Younes Manton <younes.m@gmail.com>
This commit is contained in:
Christian König 2011-08-24 22:51:31 +02:00
parent 31096e13f8
commit 9765dede75
5 changed files with 1034 additions and 1851 deletions

File diff suppressed because it is too large Load diff

View file

@ -30,32 +30,25 @@
#include "vl_defines.h"
#include "vl_vlc.h"
#include "vl_vertex_buffers.h"
struct vl_mpg12_bs
{
unsigned width, height;
struct pipe_video_decoder *decoder;
struct pipe_mpeg12_picture_desc desc;
struct dct_coeff *intra_dct_tbl;
struct vl_vlc vlc;
unsigned block_num;
unsigned *num_ycbcr_blocks;
struct vl_ycbcr_block *ycbcr_stream[VL_MAX_PLANES];
short *ycbcr_buffer;
struct vl_motionvector *mv_stream[VL_MAX_REF_FRAMES];
short pred_dc[3];
};
void
vl_mpg12_bs_init(struct vl_mpg12_bs *bs, unsigned width, unsigned height);
vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_decoder *decoder);
void
vl_mpg12_bs_set_buffers(struct vl_mpg12_bs *bs, struct vl_ycbcr_block *ycbcr_stream[VL_MAX_PLANES],
short *ycbcr_buffer, struct vl_motionvector *mv_stream[VL_MAX_REF_FRAMES]);
vl_mpg12_bs_set_picture_desc(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc *picture);
void
vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, unsigned num_bytes, const void *buffer,
struct pipe_mpeg12_picture_desc *picture, unsigned num_ycbcr_blocks[3]);
vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, unsigned num_bytes, const uint8_t *buffer);
#endif /* vl_mpeg12_bitstream_h */

View file

@ -450,9 +450,7 @@ vl_mpeg12_create_buffer(struct pipe_video_decoder *decoder)
goto error_zscan;
if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM)
vl_mpg12_bs_init(&buffer->bs,
dec->base.width / MACROBLOCK_WIDTH,
dec->base.height / MACROBLOCK_HEIGHT);
vl_mpg12_bs_init(&buffer->bs, decoder);
return buffer;
@ -614,7 +612,7 @@ vl_mpeg12_begin_frame(struct pipe_video_decoder *decoder)
buf->mv_stream[i] = vl_vb_get_mv_stream(&buf->vertex_stream, i);
if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
vl_mpg12_bs_set_buffers(&buf->bs, buf->ycbcr_stream, buf->texels, buf->mv_stream);
vl_mpg12_bs_set_picture_desc(&buf->bs, &dec->picture_desc);
} else {
@ -708,7 +706,7 @@ vl_mpeg12_decode_bitstream(struct pipe_video_decoder *decoder,
vl_zscan_set_layout(&buf->zscan[i], dec->picture_desc.alternate_scan ?
dec->zscan_alternate : dec->zscan_normal);
vl_mpg12_bs_decode(&buf->bs, num_bytes, data, &dec->picture_desc, buf->num_ycbcr_blocks);
vl_mpg12_bs_decode(&buf->bs, num_bytes, data);
}
static void

View file

@ -25,116 +25,147 @@
*
**************************************************************************/
/**
* This file is based uppon slice_xvmc.c and vlc.h from the xine project,
* which in turn is based on mpeg2dec. The following is the original copyright:
*
* Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
*
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
* See http://libmpeg2.sourceforge.net/ for updates.
*
* mpeg2dec is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpeg2dec is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef vl_vlc_h
#define vl_vlc_h
#include "pipe/p_compiler.h"
#include <assert.h>
#include <pipe/p_compiler.h>
#include <util/u_math.h>
struct vl_vlc
{
uint32_t buf; /* current 32 bit working set of buffer */
int bits; /* used bits in working set */
const uint8_t *ptr; /* buffer with stream data */
const uint8_t *max; /* ptr+len of buffer */
uint64_t buffer;
unsigned valid_bits;
uint32_t *data;
uint32_t *end;
};
struct vl_vlc_entry
{
int8_t length;
int8_t value;
};
struct vl_vlc_compressed
{
uint16_t bitcode;
struct vl_vlc_entry entry;
};
static INLINE void
vl_vlc_restart(struct vl_vlc *vlc)
vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_vlc_compressed *src, unsigned src_size)
{
vlc->buf = (vlc->ptr[0] << 24) | (vlc->ptr[1] << 16) | (vlc->ptr[2] << 8) | vlc->ptr[3];
vlc->bits = -16;
vlc->ptr += 4;
unsigned i, bits = util_logbase2(dst_size);
for (i=0;i<dst_size;++i) {
dst[i].length = 0;
dst[i].value = 0;
}
for(; src_size > 0; --src_size, ++src) {
for(i=0; i<(1 << (bits - src->entry.length)); ++i)
dst[src->bitcode >> (16 - bits) | i] = src->entry;
}
}
static INLINE void
vl_vlc_fillbits(struct vl_vlc *vlc)
{
if (vlc->valid_bits < 32) {
uint32_t value = *vlc->data;
//assert(vlc->data <= vlc->end);
#ifndef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
vlc->buffer |= (uint64_t)value << (32 - vlc->valid_bits);
++vlc->data;
vlc->valid_bits += 32;
}
}
static INLINE void
vl_vlc_init(struct vl_vlc *vlc, const uint8_t *data, unsigned len)
{
vlc->ptr = data;
vlc->max = data + len;
vl_vlc_restart(vlc);
assert(vlc);
assert(data && len);
vlc->buffer = 0;
vlc->valid_bits = 0;
/* align the data pointer */
while((uint64_t)data & 3) {
vlc->buffer |= (uint64_t)*data << (56 - vlc->valid_bits);
++data;
--len;
vlc->valid_bits += 8;
}
vlc->data = (uint32_t*)data;
vlc->end = (uint32_t*)(data + len);
vl_vlc_fillbits(vlc);
vl_vlc_fillbits(vlc);
}
static INLINE bool
vl_vlc_getbyte(struct vl_vlc *vlc)
static INLINE unsigned
vl_vlc_bytes_left(struct vl_vlc *vlc)
{
vlc->buf <<= 8;
vlc->buf |= vlc->ptr[0];
vlc->ptr++;
return vlc->ptr < vlc->max;
return ((uint8_t*)vlc->end)-((uint8_t*)vlc->data);
}
#define vl_vlc_getword(vlc, shift) \
do { \
(vlc)->buf |= (((vlc)->ptr[0] << 8) | (vlc)->ptr[1]) << (shift); \
(vlc)->ptr += 2; \
} while (0)
static INLINE unsigned
vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits)
{
//assert(vlc->valid_bits >= num_bits);
/* make sure that there are at least 16 valid bits in bit_buf */
#define vl_vlc_needbits(vlc) \
do { \
if ((vlc)->bits >= 0) { \
vl_vlc_getword(vlc, (vlc)->bits); \
(vlc)->bits -= 16; \
} \
} while (0)
return vlc->buffer >> (64 - num_bits);
}
/* make sure that the full 32 bit of the buffer are valid */
static INLINE void
vl_vlc_need32bits(struct vl_vlc *vlc)
vl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits)
{
vl_vlc_needbits(vlc);
if (vlc->bits > -8) {
unsigned n = -vlc->bits;
vlc->buf <<= n;
vlc->buf |= *vlc->ptr << 8;
vlc->bits = -8;
vlc->ptr++;
}
if (vlc->bits > -16) {
unsigned n = -vlc->bits - 8;
vlc->buf <<= n;
vlc->buf |= *vlc->ptr;
vlc->bits = -16;
vlc->ptr++;
}
//assert(vlc->valid_bits > num_bits);
vlc->buffer <<= num_bits;
vlc->valid_bits -= num_bits;
}
/* remove num valid bits from bit_buf */
#define vl_vlc_dumpbits(vlc, num) \
do { \
(vlc)->buf <<= (num); \
(vlc)->bits += (num); \
} while (0)
static INLINE unsigned
vl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits)
{
unsigned value;
/* take num bits from the high part of bit_buf and zero extend them */
#define vl_vlc_ubits(vlc, num) (((uint32_t)((vlc)->buf)) >> (32 - (num)))
//assert(vlc->valid_bits >= num_bits);
/* take num bits from the high part of bit_buf and sign extend them */
#define vl_vlc_sbits(vlc, num) (((int32_t)((vlc)->buf)) >> (32 - (num)))
value = vlc->buffer >> (64 - num_bits);
vl_vlc_eatbits(vlc, num_bits);
return value;
}
static INLINE signed
vl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits)
{
signed value;
//assert(vlc->valid_bits >= num_bits);
value = ((int64_t)vlc->buffer) >> (64 - num_bits);
vl_vlc_eatbits(vlc, num_bits);
return value;
}
static INLINE int8_t
vl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct vl_vlc_entry *tbl, unsigned num_bits)
{
tbl += vl_vlc_peekbits(vlc, num_bits);
vl_vlc_eatbits(vlc, tbl->length);
return tbl->value;
}
#endif /* vl_vlc_h */

View file

@ -43,6 +43,17 @@ struct pipe_video_rect
unsigned x, y, w, h;
};
/*
* see table 6-12 in the spec
*/
enum pipe_mpeg12_picture_coding_type
{
PIPE_MPEG12_PICTURE_CODING_TYPE_I = 0x01,
PIPE_MPEG12_PICTURE_CODING_TYPE_P = 0x02,
PIPE_MPEG12_PICTURE_CODING_TYPE_B = 0x03,
PIPE_MPEG12_PICTURE_CODING_TYPE_D = 0x04
};
/*
* see table 6-14 in the spec
*/