Commit 3f8b6306 authored by Jean-Paul Saman's avatar Jean-Paul Saman

Support for X11 Unichrome and XvMC extensions. The patch includes hw codec and...

Support for X11 Unichrome and XvMC extensions. The patch includes hw codec and video_output module for testing on VIA boards (CLE266). Patch by Christophe Burgalat <c.burgalat _at_ broadcastavenue _dot_ com>

This patch is not tested yet and is disabled by default.
parent d3217fc7
......@@ -39,6 +39,7 @@ Cédric Cocquebert - Misc opengl effects for the OpenGL Video Output. "Panoramix
Chris Clepper - OpenGL fix
Christian Henz - libupnp service discovery plugin, CyberLink UPnP fixes
Christof Baumgaertner - dbox web intf
Christophe Burgalat <c.burgalat _at_ broadcastavenue _dot_ com> - XVMC (cle266) patch for VIA boards
Christophe Mutricy <xtophe at nxtelevision dot com> - many fixes (preferences, M3U, ...)
Christopher Johnson <cjohnson at mint.net> - Qt fix in vlc.spec
Colin Simmonds <colin_simmonds at Mac.lover.org> - compile fix for Mac OS X
......
SOURCES_xvmc = \
xxmc.c \
alloc.c \
cpu_accel.c \
cpu_state.c \
decode.c \
header.c \
motion_comp.c \
motion_comp_mmx.c \
slice.c \
slice_xvmc_vld.c \
accel_xvmc.h \
attributes.h \
xxmc-config.h \
mpeg2.h \
mpeg2_internal.h \
vlc.h \
xvmc_vld.h \
$(NULL)
/*****************************************************************************
* xvmc.c : Common acceleration definitions for XvMC
*****************************************************************************
* Copyright (C) 2006 VideoLAN
* $Id$
*
* Authors: Christophe Burgalat <c _dot_ burgalat _at_ broadcastavenue _dot_ com>
* Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
*
* This program 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.
*
* This program 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, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
/*
* Common acceleration definitions for XvMC
*
*
*/
#ifndef HAVE_VLC_ACCEL_H
#define HAVE_VLC_ACCEL_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct vlc_macroblock_s
{
short *blockptr; /* pointer to current dct block */
short *blockbaseptr; /* pointer to base of dct block array in blocks */
short xvmc_accel; /* type of acceleration supported */
} vlc_macroblocks_t;
typedef struct vlc_vld_frame_s
{
int version; /* Backward compatibility */
int mv_ranges[2][2];
int picture_structure;
int picture_coding_type;
int intra_dc_precision;
int mpeg_coding;
int progressive_sequence;
int scan;
int pred_dct_frame;
int concealment_motion_vectors;
int q_scale_type;
int intra_vlc_format;
int second_field;
int load_intra_quantizer_matrix;
int load_non_intra_quantizer_matrix;
uint8_t intra_quantizer_matrix[64];
uint8_t non_intra_quantizer_matrix[64];
picture_t *backward_reference_picture;
picture_t *forward_reference_picture;
} vlc_vld_frame_t;
typedef struct vlc_xvmc_s
{
vlc_macroblocks_t *macroblocks;
void (*proc_macro_block)(int x,int y,int mb_type,
int motion_type,int (*mv_field_sel)[2],
int *dmvector,int cbp,int dct_type,
picture_t *current_picture,picture_t *forward_ref_picture,
picture_t *backward_ref_picture,int picture_structure,
int second_field,int (*f_mot_pmv)[2],int (*b_mot_pmv)[2]);
} vlc_xvmc_t ;
typedef struct vlc_xxmc_s
{
/*
* We inherit the xine_xvmc_t properties.
*/
vlc_xvmc_t xvmc;
unsigned mpeg;
unsigned acceleration;
vlc_fourcc_t fallback_format;
vlc_vld_frame_t vld_frame;
uint8_t *slice_data;
unsigned slice_data_size;
unsigned slice_code;
int result;
int decoded;
float sleep;
void (*proc_xxmc_update_frame) (picture_t *picture_gen,
uint32_t width, uint32_t height, double ratio,
int format, int flags);
void (*proc_xxmc_begin) (picture_t *vo_img);
void (*proc_xxmc_slice) (picture_t *vo_img);
void (*proc_xxmc_flush) (picture_t *vo_img);
void (*proc_xxmc_flushsync) (picture_t *vo_img);
} vlc_xxmc_t;
#define VLC_IMGFMT_XXMC VLC_FOURCC('X','x','M','C')
/*
* Register XvMC stream types here.
*/
#define VLC_XVMC_MPEG_1 0x00000001
#define VLC_XVMC_MPEG_2 0x00000002
#define VLC_XVMC_MPEG_4 0x00000004
/*
* Register XvMC acceleration levels here.
*/
#define VLC_XVMC_ACCEL_MOCOMP 0x00000001
#define VLC_XVMC_ACCEL_IDCT 0x00000002
#define VLC_XVMC_ACCEL_VLD 0x00000004
/* xvmc acceleration types */
#define VLC_VO_MOTION_ACCEL 1
#define VLC_VO_IDCT_ACCEL 2
#define VLC_VO_SIGNED_INTRA 4
/* motion types */
#define VLC_MC_FIELD 1
#define VLC_MC_FRAME 2
#define VLC_MC_16X8 2
#define VLC_MC_DMV 3
/* picture coding type */
#define VLC_PICT_I_TYPE 1
#define VLC_PICT_P_TYPE 2
#define VLC_PICT_B_TYPE 3
#define VLC_PICT_D_TYPE 4
/* macroblock modes */
#define VLC_MACROBLOCK_INTRA 1
#define VLC_MACROBLOCK_PATTERN 2
#define VLC_MACROBLOCK_MOTION_BACKWARD 4
#define VLC_MACROBLOCK_MOTION_FORWARD 8
#define VLC_MACROBLOCK_QUANT 16
#define VLC_MACROBLOCK_DCT_TYPE_INTERLACED 32
#ifdef __cplusplus
}
#endif
#endif
/* $Id:$
* alloc.c
* Copyright (C) 2000-2003 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
*/
#include <stdlib.h>
#include <inttypes.h>
#include "mpeg2.h"
static void * (* malloc_hook) (unsigned size, mpeg2_alloc_t reason) = NULL;
static int (* free_hook) (void * buf) = NULL;
void * mpeg2_malloc( unsigned size, mpeg2_alloc_t reason )
{
char *buf = NULL;
if (malloc_hook)
{
buf = (char *) malloc_hook (size, reason);
if (buf)
return buf;
}
if (size)
{
buf = (char *) malloc (size + 63 + sizeof (void **));
if (buf)
{
char * align_buf = NULL;
align_buf = buf + 63 + sizeof (void **);
align_buf -= (long)align_buf & 63;
*(((void **)align_buf) - 1) = buf;
return align_buf;
}
}
return NULL;
}
void mpeg2_free( void * buf )
{
if (free_hook && free_hook (buf))
return;
if (buf)
free (*(((void **)buf) - 1));
}
void mpeg2_malloc_hooks( void * malloc (unsigned, mpeg2_alloc_t),
int free (void *) )
{
malloc_hook = malloc;
free_hook = free;
}
/* $Id:$
* attributes.h
* Copyright (C) 2000-2003 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
*/
/* use gcc attribs to align critical data structures */
#ifdef ATTRIBUTE_ALIGNED_MAX
# define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align)))
#else
# define ATTR_ALIGN(align)
#endif
#ifdef HAVE_BUILTIN_EXPECT
# define likely(x) __builtin_expect ((x) != 0, 1)
# define unlikely(x) __builtin_expect ((x) != 0, 0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
#endif
/* $Id:$
* cpu_accel.c
* Copyright (C) 2000-2003 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
*/
#include <inttypes.h>
#include "mpeg2.h"
#include "attributes.h"
#include "mpeg2_internal.h"
static inline uint32_t arch_accel( void )
{
uint32_t eax, ebx, ecx, edx;
int AMD;
uint32_t caps;
#if !defined(PIC) && !defined(__PIC__)
#define cpuid(op,eax,ebx,ecx,edx) \
__asm__ ("cpuid" \
: "=a" (eax), \
"=b" (ebx), \
"=c" (ecx), \
"=d" (edx) \
: "a" (op) \
: "cc")
#else /* PIC version : save ebx */
#define cpuid(op,eax,ebx,ecx,edx) \
__asm__ ("push %%ebx\n\t" \
"cpuid\n\t" \
"movl %%ebx,%1\n\t" \
"pop %%ebx" \
: "=a" (eax), \
"=r" (ebx), \
"=c" (ecx), \
"=d" (edx) \
: "a" (op) \
: "cc")
#endif
__asm__ ("pushf\n\t"
"pushf\n\t"
"pop %0\n\t"
"movl %0,%1\n\t"
"xorl $0x200000,%0\n\t"
"push %0\n\t"
"popf\n\t"
"pushf\n\t"
"pop %0\n\t"
"popf"
: "=r" (eax),
"=r" (ebx)
:
: "cc");
if (eax == ebx) /* no cpuid */
return 0;
cpuid (0x00000000, eax, ebx, ecx, edx);
if (!eax) /* vendor string only */
return 0;
AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
cpuid (0x00000001, eax, ebx, ecx, edx);
if (! (edx & 0x00800000)) /* no MMX */
return 0;
caps = MPEG2_ACCEL_X86_MMX;
if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */
caps = MPEG2_ACCEL_X86_MMX | MPEG2_ACCEL_X86_MMXEXT;
cpuid (0x80000000, eax, ebx, ecx, edx);
if (eax < 0x80000001) /* no extended capabilities */
return caps;
cpuid (0x80000001, eax, ebx, ecx, edx);
if (edx & 0x80000000)
caps |= MPEG2_ACCEL_X86_3DNOW;
if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */
caps |= MPEG2_ACCEL_X86_MMXEXT;
return caps;
}
uint32_t mpeg2_detect_accel (void)
{
uint32_t accel;
accel = 0;
accel = arch_accel ();
return accel;
}
/* $Id:$
* cpu_state.c
* Copyright (C) 2000-2003 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
*/
#include "xxmc-config.h"
#include <stdlib.h>
#include <inttypes.h>
#include "mpeg2.h"
#include "attributes.h"
#include "mpeg2_internal.h"
#ifdef ARCH_X86
# include "mmx.h"
#endif
void (* mpeg2_cpu_state_save) (cpu_state_t * state) = NULL;
void (* mpeg2_cpu_state_restore) (cpu_state_t * state) = NULL;
static void state_restore_mmx (cpu_state_t * state)
{
emms ();
}
void mpeg2_cpu_state_init (uint32_t accel)
{
if (accel & MPEG2_ACCEL_X86_MMX)
{
mpeg2_cpu_state_restore = state_restore_mmx;
}
}
/* $Id:$
* decode.c
* Copyright (C) 2000-2003 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
*/
#include "xxmc-config.h"
#include <string.h> /* memcmp/memset, try to remove */
#include <stdlib.h>
#include <inttypes.h>
#include "mpeg2.h"
#include "attributes.h"
#include "mpeg2_internal.h"
static int mpeg2_accels = 0;
#define BUFFER_SIZE (1194 * 1024)
const mpeg2_info_t *mpeg2_info( mpeg2dec_t * mpeg2dec )
{
return &(mpeg2dec->info);
}
static inline int skip_chunk( mpeg2dec_t * mpeg2dec, int bytes )
{
uint8_t *current = NULL;
uint32_t shift;
uint8_t *limit = NULL;
uint8_t byte;
if (!bytes)
return 0;
current = mpeg2dec->buf_start;
shift = mpeg2dec->shift;
limit = current + bytes;
do {
byte = *current++;
if (shift == 0x00000100)
{
int skipped;
mpeg2dec->shift = 0xffffff00;
skipped = current - mpeg2dec->buf_start;
mpeg2dec->buf_start = current;
return skipped;
}
shift = (shift | byte) << 8;
} while (current < limit);
mpeg2dec->shift = shift;
mpeg2dec->buf_start = current;
return 0;
}
static inline int copy_chunk( mpeg2dec_t * mpeg2dec, int bytes )
{
uint8_t *current = NULL;
uint32_t shift;
uint8_t *chunk_ptr = NULL;
uint8_t *limit = NULL;
uint8_t byte;
if (!bytes)
return 0;
current = mpeg2dec->buf_start;
shift = mpeg2dec->shift;
chunk_ptr = mpeg2dec->chunk_ptr;
limit = current + bytes;
do {
byte = *current++;
if (shift == 0x00000100)
{
int copied;
mpeg2dec->shift = 0xffffff00;
mpeg2dec->chunk_size = chunk_ptr - mpeg2dec->chunk_start - 3;
mpeg2dec->chunk_ptr = chunk_ptr + 1;
copied = current - mpeg2dec->buf_start;
mpeg2dec->buf_start = current;
return copied;
}
shift = (shift | byte) << 8;
*chunk_ptr++ = byte;
} while (current < limit);
mpeg2dec->shift = shift;
mpeg2dec->buf_start = current;
return 0;
}
void mpeg2_buffer( mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end )
{
mpeg2dec->buf_start = start;
mpeg2dec->buf_end = end;
}
int mpeg2_getpos( mpeg2dec_t * mpeg2dec )
{
return mpeg2dec->buf_end - mpeg2dec->buf_start;
}
static inline mpeg2_state_t seek_chunk( mpeg2dec_t * mpeg2dec )
{
int size, skipped;
size = mpeg2dec->buf_end - mpeg2dec->buf_start;
skipped = skip_chunk (mpeg2dec, size);
if (!skipped)
{
mpeg2dec->bytes_since_tag += size;
return STATE_BUFFER;
}
mpeg2dec->bytes_since_tag += skipped;
mpeg2dec->code = mpeg2dec->buf_start[-1];
return (mpeg2_state_t)-1;
}
mpeg2_state_t mpeg2_seek_header( mpeg2dec_t * mpeg2dec )
{
while( (mpeg2dec->code != 0xb3) &&
(((mpeg2dec->code != 0xb7) &&
(mpeg2dec->code != 0xb8) &&
mpeg2dec->code ) ||
(mpeg2dec->sequence.width == (unsigned)-1)) )
{
if (seek_chunk (mpeg2dec) == STATE_BUFFER)
return STATE_BUFFER;
}
mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
mpeg2dec->user_data_len = 0;
return (mpeg2dec->code ? mpeg2_parse_header (mpeg2dec) :
mpeg2_header_picture_start (mpeg2dec));
}
#define RECEIVED(code,state) (((state) << 8) + (code))
mpeg2_state_t mpeg2_parse( mpeg2dec_t * mpeg2dec )
{
int size_buffer, size_chunk, copied;
if (mpeg2dec->action)
{
mpeg2_state_t state;
state = mpeg2dec->action (mpeg2dec);
if ((int)state >= 0)
return state;
}
while(1)
{
while( (unsignedint) (mpeg2dec->code - mpeg2dec->first_decode_slice)
< mpeg2dec->nb_decode_slices )
{
size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
mpeg2dec->chunk_ptr);
if (size_buffer <= size_chunk)
{
copied = copy_chunk (mpeg2dec, size_buffer);
if (!copied)
{
mpeg2dec->bytes_since_tag += size_buffer;
mpeg2dec->chunk_ptr += size_buffer;
return STATE_BUFFER;
}
}
else
{
copied = copy_chunk (mpeg2dec, size_chunk);
if( !copied )
{
/* filled the chunk buffer without finding a start code */
mpeg2dec->bytes_since_tag += size_chunk;
mpeg2dec->action = seek_chunk;
return STATE_INVALID;
}
}
mpeg2dec->bytes_since_tag += copied;
mpeg2_xxmc_slice( &(mpeg2dec->decoder), NULL,
mpeg2dec->code,mpeg2dec->chunk_start,
mpeg2dec->chunk_size);
mpeg2dec->prev_code = mpeg2dec->code;
mpeg2dec->code = mpeg2dec->buf_start[-1];
mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
}
if( (unsigned int) (mpeg2dec->code - 1) >= (0xb0 - 1) )
break;
if( seek_chunk (mpeg2dec) == STATE_BUFFER )
return STATE_BUFFER;
}
switch( mpeg2dec->code )
{
case 0x00:
mpeg2dec->action = mpeg2_header_picture_start;
return mpeg2dec->state;
case 0xb7:
mpeg2dec->action = mpeg2_header_end;
break;
case 0xb3:
case 0xb8:
mpeg2dec->action = mpeg2_parse_header;
break;
default:
mpeg2dec->action = seek_chunk;
return STATE_INVALID;
}
return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID;
}
mpeg2_state_t mpeg2_parse_header( mpeg2dec_t * mpeg2dec )
{
static int (* process_header[]) (mpeg2dec_t * mpeg2dec) =
{
mpeg2_header_picture,
mpeg2_header_extension,
mpeg2_header_user_data,
mpeg2_header_sequence,
NULL,
NULL,
NULL,
NULL,
mpeg2_header_gop
};
int size_buffer, size_chunk, copied;
mpeg2dec->action = mpeg2_parse_header;
mpeg2dec->info.user_data = NULL;
mpeg2dec->info.user_data_len = 0;
while( 1 )
{
size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
mpeg2dec->chunk_ptr);
if( size_buffer <= size_chunk )
{
copied = copy_chunk (mpeg2dec, size_buffer);
if( !copied )
{
mpeg2dec->bytes_since_tag += size_buffer;
mpeg2dec->chunk_ptr += size_buffer;
return STATE_BUFFER;
}
}
else
{