Commit 41bcd8c6 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont
Browse files

Remove libmpeg2 copy for XvMC

parent a2180073
/* $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 <stddef.h>
#include <inttypes.h>
#include <stdlib.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(__x86_64__) || (!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 (not needed on x86_64) */
#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
#ifndef __x86_64__ /* x86_64 supports the cpuid op */
__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;
#endif
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 <stddef.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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_vout.h>
#include "xxmc-config.h"
#include <inttypes.h>
#include "mpeg2.h"
#include "attributes.h"
#include "mpeg2_internal.h"
#include "xvmc_vld.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( (unsigned int) (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, 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
{
copied = copy_chunk (mpeg2dec, size_chunk);
if( !copied )
{
/* filled the chunk buffer without finding a start code */
mpeg2dec->bytes_since_tag += size_chunk;
mpeg2dec->code = 0xb4;
mpeg2dec->action = mpeg2_seek_header;
return STATE_INVALID;
}
}
mpeg2dec->bytes_since_tag += copied;
if( process_header[mpeg2dec->code & 0x0b](mpeg2dec) )
{
mpeg2dec->code = mpeg2dec->buf_start[-1];
mpeg2dec->action = mpeg2_seek_header;
return STATE_INVALID;
}
mpeg2dec->code = mpeg2dec->buf_start[-1];
switch( RECEIVED(mpeg2dec->code, mpeg2dec->state) )
{
/* state transition after a sequence header */
case RECEIVED (0x00, STATE_SEQUENCE):
mpeg2dec->action = mpeg2_header_picture_start;
case RECEIVED (0xb8, STATE_SEQUENCE):
mpeg2_header_sequence_finalize( mpeg2dec );
break;
/* other legal state transitions */
case RECEIVED (0x00, STATE_GOP):
mpeg2_header_gop_finalize( mpeg2dec );
mpeg2dec->action = mpeg2_header_picture_start;
break;
case RECEIVED (0x01, STATE_PICTURE):
case RECEIVED (0x01, STATE_PICTURE_2ND):
mpeg2_header_picture_finalize( mpeg2dec, mpeg2_accels );
mpeg2dec->action = mpeg2_header_slice_start;
break;
/* legal headers within a given state */
case RECEIVED (0xb2, STATE_SEQUENCE):
case RECEIVED (0xb2, STATE_GOP):
case RECEIVED (0xb2, STATE_PICTURE):
case RECEIVED (0xb2, STATE_PICTURE_2ND):
case RECEIVED (0xb5, STATE_SEQUENCE):
case RECEIVED (0xb5, STATE_PICTURE):
case RECEIVED (0xb5, STATE_PICTURE_2ND):
mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
continue;
default:
mpeg2dec->action = mpeg2_seek_header;
return STATE_INVALID;
}
mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
mpeg2dec->user_data_len = 0;