[g3dvl] Implement MPEG2 VLD

Based uppon xine's slice_xvmc.c.
This gets VDPAU up and running.
This commit is contained in:
Christian König 2011-05-04 18:56:32 +02:00
parent f20608b951
commit c888fe027c
9 changed files with 2246 additions and 35 deletions

View File

@ -153,6 +153,7 @@ C_SOURCES = \
vl/vl_mpeg12_decoder.c \
vl/vl_compositor.c \
vl/vl_csc.c \
vl/vl_mpeg12_bitstream.c \
vl/vl_zscan.c \
vl/vl_idct.c \
vl/vl_mc.c \

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
/**************************************************************************
*
* Copyright 2011 Christian König.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef vl_mpeg12_bitstream_h
#define vl_mpeg12_bitstream_h
#include "vl_defines.h"
#include "vl_vlc.h"
struct vl_mpg12_bs
{
unsigned width, height;
struct vl_vlc vlc;
unsigned *num_ycbcr_blocks;
struct pipe_ycbcr_block *ycbcr_stream[VL_MAX_PLANES];
short *ycbcr_buffer[VL_MAX_PLANES];
struct pipe_motionvector *mv_stream[VL_MAX_REF_FRAMES];
};
void
vl_mpg12_bs_init(struct vl_mpg12_bs *bs, unsigned width, unsigned height);
void
vl_mpg12_bs_set_buffers(struct vl_mpg12_bs *bs, struct pipe_ycbcr_block *ycbcr_stream[VL_MAX_PLANES],
short *ycbcr_buffer[VL_MAX_PLANES], struct pipe_motionvector *mv_stream[VL_MAX_REF_FRAMES]);
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]);
#endif /* vl_mpeg12_bitstream_h */

View File

@ -346,6 +346,19 @@ vl_mpeg12_buffer_map(struct pipe_video_decode_buffer *buffer)
buf->texels[i] = dec->pipe->transfer_map(dec->pipe, buf->tex_transfer[i]);
}
if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
struct pipe_ycbcr_block *ycbcr_stream[VL_MAX_PLANES];
struct pipe_motionvector *mv_stream[VL_MAX_REF_FRAMES];
for (i = 0; i < VL_MAX_PLANES; ++i)
ycbcr_stream[i] = vl_vb_get_ycbcr_stream(&buf->vertex_stream, i);
for (i = 0; i < VL_MAX_REF_FRAMES; ++i)
mv_stream[i] = vl_vb_get_mv_stream(&buf->vertex_stream, i);
vl_mpg12_bs_set_buffers(&buf->bs, ycbcr_stream, buf->texels, mv_stream);
}
}
static struct pipe_ycbcr_block *
@ -389,6 +402,17 @@ vl_mpeg12_buffer_get_mv_stream(struct pipe_video_decode_buffer *buffer, int ref_
return vl_vb_get_mv_stream(&buf->vertex_stream, ref_frame);
}
static void
vl_mpeg12_buffer_decode_bitstream(struct pipe_video_decode_buffer *buffer,
unsigned num_bytes, const void *data,
struct pipe_mpeg12_picture_desc *picture,
unsigned num_ycbcr_blocks[3])
{
struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
vl_mpg12_bs_decode(&buf->bs, num_bytes, data, picture, num_ycbcr_blocks);
}
static void
vl_mpeg12_buffer_unmap(struct pipe_video_decode_buffer *buffer)
{
@ -462,6 +486,7 @@ vl_mpeg12_create_buffer(struct pipe_video_decoder *decoder)
buffer->base.get_ycbcr_buffer = vl_mpeg12_buffer_get_ycbcr_buffer;
buffer->base.get_mv_stream_stride = vl_mpeg12_buffer_get_mv_stream_stride;
buffer->base.get_mv_stream = vl_mpeg12_buffer_get_mv_stream;
buffer->base.decode_bitstream = vl_mpeg12_buffer_decode_bitstream;
buffer->base.unmap = vl_mpeg12_buffer_unmap;
if (!vl_vb_init(&buffer->vertex_stream, dec->pipe,
@ -479,6 +504,9 @@ vl_mpeg12_create_buffer(struct pipe_video_decoder *decoder)
if (!init_zscan_buffer(buffer))
goto error_zscan;
if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM)
vl_mpg12_bs_init(&buffer->bs, dec->base.width, dec->base.height);
return &buffer->base;
error_zscan:

View File

@ -30,6 +30,7 @@
#include <pipe/p_video_context.h>
#include "vl_mpeg12_bitstream.h"
#include "vl_zscan.h"
#include "vl_idct.h"
#include "vl_mc.h"
@ -80,6 +81,7 @@ struct vl_mpeg12_buffer
struct pipe_video_buffer *idct_source;
struct pipe_video_buffer *mc_source;
struct vl_mpg12_bs bs;
struct vl_zscan_buffer zscan[VL_MAX_PLANES];
struct vl_idct_buffer idct[VL_MAX_PLANES];
struct vl_mc_buffer mc[VL_MAX_PLANES];

View File

@ -0,0 +1,138 @@
/**************************************************************************
*
* Copyright 2011 Christian König.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/**
* 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
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 */
};
static inline void
vl_vlc_restart(struct vl_vlc *vlc)
{
vlc->buf = (vlc->ptr[0] << 24) | (vlc->ptr[1] << 16) | (vlc->ptr[2] << 8) | vlc->ptr[3];
vlc->bits = -16;
vlc->ptr += 4;
}
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);
}
static inline bool
vl_vlc_getbyte(struct vl_vlc *vlc)
{
vlc->buf <<= 8;
vlc->buf |= vlc->ptr[0];
vlc->ptr++;
return vlc->ptr < vlc->max;
}
#define vl_vlc_getword(vlc, shift) \
do { \
(vlc)->buf |= (((vlc)->ptr[0] << 8) | (vlc)->ptr[1]) << (shift); \
(vlc)->ptr += 2; \
} while (0)
/* 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)
/* make sure that the full 32 bit of the buffer are valid */
static inline void
vl_vlc_need32bits(struct vl_vlc *vlc)
{
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++;
}
}
/* remove num valid bits from bit_buf */
#define vl_vlc_dumpbits(vlc, num) \
do { \
(vlc)->buf <<= (num); \
(vlc)->bits += (num); \
} while (0)
/* 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)))
/* 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)))
#endif /* vl_vlc_h */

View File

@ -199,14 +199,13 @@ struct pipe_video_decode_buffer
*/
struct pipe_motionvector *(*get_mv_stream)(struct pipe_video_decode_buffer *decbuf, int ref_frame);
#if 0
/**
* decode a bitstream
*/
void (*decode_bitstream)(struct pipe_video_decode_buffer *decbuf,
unsigned num_bufs,
struct pipe_buffer **bitstream_buf);
#endif
unsigned num_bytes, const void *data,
struct pipe_mpeg12_picture_desc *picture,
unsigned num_ycbcr_blocks[3]);
/**
* unmap decoder buffer before flushing

View File

@ -99,37 +99,43 @@ struct pipe_ycbcr_block
enum pipe_mpeg12_dct_type coding:8;
};
#if 0
struct pipe_picture_desc
{
enum pipe_video_format format;
enum pipe_video_profile profile;
};
struct pipe_mpeg12_picture_desc
{
struct pipe_picture_desc base;
/* TODO: Use bitfields where possible? */
struct pipe_surface *forward_reference;
struct pipe_surface *backward_reference;
unsigned picture_coding_type;
unsigned fcode;
unsigned intra_dc_precision;
unsigned picture_structure;
unsigned top_field_first;
unsigned frame_pred_frame_dct;
unsigned concealment_motion_vectors;
unsigned q_scale_type;
unsigned intra_vlc_format;
unsigned alternate_scan;
unsigned intra_dc_precision;
unsigned intra_vlc_format;
unsigned concealment_motion_vectors;
unsigned f_code[2][2];
bool mpeg1;
uint8_t *intra_quantizer_matrix;
uint8_t *non_intra_quantizer_matrix;
/* predictor for DC coefficients in intra blocks */
int16_t dc_dct_pred[3];
int quantizer_scale;
#if 0
/* TODO: Use bitfields where possible? */
unsigned top_field_first;
unsigned full_pel_forward_vector;
unsigned full_pel_backward_vector;
struct pipe_buffer *intra_quantizer_matrix;
struct pipe_buffer *non_intra_quantizer_matrix;
struct pipe_buffer *chroma_intra_quantizer_matrix;
struct pipe_buffer *chroma_non_intra_quantizer_matrix;
};
#endif
};
#ifdef __cplusplus
}

View File

@ -146,40 +146,56 @@ vlVdpDecoderRenderMpeg2(struct pipe_video_decoder *decoder,
uint32_t bitstream_buffer_count,
VdpBitstreamBuffer const *bitstream_buffers)
{
struct pipe_mpeg12_picture_desc picture;
struct pipe_video_buffer *ref_frames[2];
unsigned num_ycbcr_blocks[3] = { 0, 0, 0 };
unsigned i;
debug_printf("[VDPAU] Decoding MPEG2\n");
/* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
if (picture_info->backward_reference == VDP_INVALID_HANDLE)
if (picture_info->forward_reference == VDP_INVALID_HANDLE)
ref_frames[0] = NULL;
else {
ref_frames[0] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer;
ref_frames[0] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer;
if (!ref_frames[0])
return VDP_STATUS_INVALID_HANDLE;
}
if (picture_info->forward_reference == VDP_INVALID_HANDLE)
if (picture_info->backward_reference == VDP_INVALID_HANDLE)
ref_frames[1] = NULL;
else {
ref_frames[1] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer;
ref_frames[1] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer;
if (!ref_frames[1])
return VDP_STATUS_INVALID_HANDLE;
}
//if (vlVdpMPEG2BitstreamToMacroblock(vpipe->screen, bitstream_buffers, bitstream_buffer_count,
// &num_macroblocks, &pipe_macroblocks))
//{
// debug_printf("[VDPAU] Error in frame-header. Skipping.\n");
//
// ret = VDP_STATUS_OK;
// goto skip_frame;
//}
memset(&picture, 0, sizeof(picture));
picture.picture_coding_type = picture_info->picture_coding_type;
picture.picture_structure = picture_info->picture_structure;
picture.frame_pred_frame_dct = picture_info->frame_pred_frame_dct;
picture.q_scale_type = picture_info->q_scale_type;
picture.alternate_scan = picture_info->alternate_scan;
picture.intra_dc_precision = picture_info->intra_dc_precision;
picture.intra_vlc_format = picture_info->intra_vlc_format;
picture.concealment_motion_vectors = picture_info->concealment_motion_vectors;
picture.f_code[0][0] = picture_info->f_code[0][0] - 1;
picture.f_code[0][1] = picture_info->f_code[0][1] - 1;
picture.f_code[1][0] = picture_info->f_code[1][0] - 1;
picture.f_code[1][1] = picture_info->f_code[1][1] - 1;
// TODO
//vpipe->set_decode_target(vpipe,t_surf);
//vpipe->decode_macroblocks(vpipe, p_surf, f_surf, num_macroblocks,
// (struct pipe_macroblock *)pipe_macroblocks, NULL);
picture.intra_quantizer_matrix = picture_info->intra_quantizer_matrix;
picture.non_intra_quantizer_matrix = picture_info->non_intra_quantizer_matrix;
buffer->map(buffer);
for (i = 0; i < bitstream_buffer_count; ++i)
buffer->decode_bitstream(buffer, bitstream_buffers[i].bitstream_bytes,
bitstream_buffers[i].bitstream, &picture, num_ycbcr_blocks);
buffer->unmap(buffer);
decoder->flush_buffer(buffer, num_ycbcr_blocks, ref_frames, target);
return VDP_STATUS_OK;
}
@ -218,8 +234,8 @@ vlVdpDecoderRender(VdpDecoder decoder,
switch (vldecoder->decoder->profile) {
case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
return vlVdpDecoderRenderMpeg2(vldecoder->decoder, vldecoder->buffer,
vlsurf, (VdpPictureInfoMPEG1Or2 *)picture_info,
return vlVdpDecoderRenderMpeg2(vldecoder->decoder, vldecoder->buffer, vlsurf->video_buffer,
(VdpPictureInfoMPEG1Or2 *)picture_info,
bitstream_buffer_count,bitstream_buffers);
break;