Commit b99aa8d3 authored by Aaron Holtzman's avatar Aaron Holtzman

Major cleanup and cruft removal before I put in the motion_comp_mmx

updates. The libmpeg2 sources are now in the libmpeg2 directory now as
well.

cheers,
aaron
parent dda3f8b7
mpeg2dec-0.1.7
-added Xv support
-major cruft removal
-cleanup on motion_comp
mpeg2dec-0.1.6 Wed Mar 22 09:45:44 PST 2000
-enhanced g200
......
......@@ -2,9 +2,9 @@
AUTOMAKE_OPTIONS = 1.3 foreign no-dependencies
SUBDIRS = tools drivers
SUBDIRS = libmpeg2 tools drivers
EXTRA_DIST = Changelog autogen.sh soft_video.c
EXTRA_DIST = Changelog autogen.sh
CFLAGS = -Wall -O3 -g @CFLAGS@ @X_CFLAGS@ -I/usr/src/linux
......@@ -14,30 +14,13 @@ endif
mpeg2dec_SOURCES = mpeg2dec.c
mpeg2dec_DEPENDENCIES = libmpeg2.la @CONFIG_OBJS@
mpeg2dec_LDADD= libmpeg2.la @CONFIG_OBJS@ @X_PRE_LIBS@ @X_LIBS@ -lXext\
mpeg2dec_LDADD= libmpeg2/libmpeg2.la @CONFIG_OBJS@ @X_PRE_LIBS@ @X_LIBS@ -lXext\
-L/usr/X11R6/lib -lX11 @X_EXTRA_LIBS@ -lm
EXTRA_mpeg2dec_SOURCES = display_gatos.c display_mga_vid.c display_x11.c\
display_xil.c idct_mmx.c idct_block_mmx.S idct_mlib.c\
motion_comp_mmx.c motion_comp_mlib.c yuv2rgb.c yuv2rgb_mlib.c
if HAVE_X
lib_LTLIBRARIES = libmpeg2.la
endif
libmpeg2_la_LIBADD = @LIB_CONFIG_OBJS@
libmpeg2_la_SOURCES = getvlc.c mb_buffer.c motion.c parse.c stats.c\
idct.c motion_comp.c inv_quantize.c decode.c bitstream.c debug.c
libmpeg2_la_DEPENDENCIES = @LIB_CONFIG_OBJS@
libmpeg2_la_LDFLAGS = -version-info 1:6:1
noinst_HEADERS = config.h getvlc.h stats.h parse.h slice.h mb_buffer.h\
motion_comp.h inv_quantize.h mpeg2.h mpeg2_internal.h display.h idct.h\
old_config.h global.h old_crap.h mpeg2dec.h debug.h bitstream.h\
idct_mmx.h idct_mlib.h motion_comp_mmx.h motion_comp_mlib.h\
yuv2rgb.h yuv2rgb_mlib.h
yuv2rgb.c yuv2rgb_mlib.c
noinst_HEADERS = config.h display.h yuv2rgb.h yuv2rgb_mlib.h
prof:
$(MAKE) mpeg2dec CFLAGS="-pg $(CFLAGS)"
......@@ -46,7 +29,6 @@ prof:
x11:
$(MAKE) -e mpeg2dec mpeg2dec_LDADD="display_x11.o idct_block_mmx.S motion_comp_mmx.c idct_mmx.c"
mostlyclean-generic:
-rm -f *~ \#* .*~ .\#* $(distdir).tar.gz
-rm -rf $(distdir)
......
......@@ -10,6 +10,7 @@ Contributions by:
H}kan Hjort <d95hjort@dtek.chalmers.se> - Solaris fixes
Didier Gautheron <dgautheron@magic.fr> - bug fixes
Gerd Knorr <kraxel@goldbach.in-berlin.de> - Xv support
Michel LESPINASSE <walken@windriver.com> - motion comp cleanup et al.
(let me know if I've forgotten anyone)
First of all, this is very early code. If you're not interested
......@@ -25,15 +26,16 @@ read and understand. I'd love to have some feedback on the design.
Here's a hierarchy of how the code fits together:
decode.c
|--parse.c
|-----bitstream.c
|-----getvlc.c
|-----stats.c
|--mb_buffer.c
|--idct.c
|--motion_comp.c
|--display_*.c
libmpeg2/decode.c
|--parse.c
|-----bitstream.c
|-----getvlc.c
|-----stats.c
|--mb_buffer.c
|--idct.c
|--motion_comp.c
display_*.c
mpeg2dec.c
For each frame, decode.c uses parse.c to stuff macroblocks into the
macroblock buffer (mb_buffer.c). When this buffer is full or the frame
......@@ -47,17 +49,11 @@ supported (like 3dnow or SSE). The philosophy is "one binary->one
architecture".
Stuff that works
- I-type Frame pictures
-pretty much everything
Stuff that is broken
- field based pictures
- P,B type pictures (motion_comp.c needs some filling in)
Stuff that needs to be done
- fix the broken stuff (see above)
- the MSSG getvlc.c needs to be sanitized and turned into vlc.c
- motion.c need to be sanitized and pulled into parse.c
(in cvs 'bp_frames_branch')
- make it really fast :)
Patches
......@@ -90,7 +86,6 @@ as well as RAM size). RAM size autodetect was only tested on a G200,
8MB so far... Also it should draw some nice 256x256 images for you,
if all is working well.
Documentation
If you need the mpeg-2 video spec, you can get it on www.wotsit.org
......@@ -98,4 +93,6 @@ If you need the mpeg-2 video spec, you can get it on www.wotsit.org
Aaron Holtzman,
December 1999
April 2000
......@@ -2,11 +2,11 @@ dnl Autoconf configuration script mpeg2dec
dnl
dnl Aaron Holtzman - May 1999
dnl
AC_INIT(parse.c)
AC_INIT(mpeg2dec.c)
AC_CANONICAL_HOST
AC_PREREQ(2.13)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(mpeg2dec, 0.1.7)
AM_INIT_AUTOMAKE(mpeg2dec, 0.1.7-cvs)
AM_MAINTAINER_MODE
AC_PROG_CC
......@@ -136,4 +136,4 @@ ppc-*) AC_DEFINE(__ppc__);;
*) echo "$host is not currently supported by mpeg2dec"; exit 1;;
esac
AC_OUTPUT( tools/Makefile drivers/Makefile Makefile )
AC_OUTPUT( libmpeg2/Makefile tools/Makefile drivers/Makefile Makefile )
......@@ -29,9 +29,10 @@
#include <fcntl.h>
#include <sys/mman.h>
#include "debug.h"
#include "mpeg2.h"
#include "mpeg2_internal.h"
#include "libmpeg2/debug.h"
#include "libmpeg2/mpeg2.h"
//FIXME
#include "libmpeg2/mpeg2_internal.h"
#include "drivers/mga_vid.h"
#include "display.h"
......
/*
* inv_quantize.c
*
* Copyright (C) Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - Nov 1999
*
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
*
* 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, 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 GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation,
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "mpeg2.h"
#include "mpeg2_internal.h"
#include "mb_buffer.h"
#include "inv_quantize.h"
static uint_8 default_intra_quantization_matrix[64] =
{
8, 16, 19, 22, 26, 27, 29, 34,
16, 16, 22, 24, 27, 29, 34, 37,
19, 22, 26, 27, 29, 34, 34, 38,
22, 22, 26, 27, 29, 34, 37, 40,
22, 26, 27, 29, 32, 35, 40, 48,
26, 27, 29, 32, 35, 40, 48, 58,
26, 27, 29, 34, 38, 46, 56, 69,
27, 29, 35, 38, 46, 56, 69, 83
};
static uint_8 default_non_intra_quantization_matrix[64] =
{
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16
};
//FIXME this should go
//it stays until I get this working
static inline sint_16 clip(sint_16 x)
{
if(x > 2047)
x = 2047;
else if(x < -2048)
x = -2048;
// if (x != 0)
// x = (x - 1) | 1;
return x;
}
static void
inv_quantize_intra_mb(const picture_t *picture,macroblock_t *mb)
{
uint_8 *quant_matrix;
uint_32 i;
sint_16 *block;
//choose the appropriate quantization matrix
if(picture->use_custom_intra_quantizer_matrix)
quant_matrix = picture->custom_intra_quantization_matrix;
else
quant_matrix = default_intra_quantization_matrix;
block = mb->y_blocks;
for(i=1;i<64;i++)
{
block[i] = (block[i] * (sint_16) quant_matrix[i]) / 16;
block[i] = clip(block[i]);
}
block = mb->y_blocks + 64;
for(i=1;i<64;i++)
{
block[i] = (block[i] * quant_matrix[i]) / 16;
block[i] = clip(block[i]);
}
block = mb->y_blocks + 64 * 2;
for(i=1;i<64;i++)
{
block[i] = (block[i] * quant_matrix[i]) / 16;
block[i] = clip(block[i]);
}
block = mb->y_blocks + 64 * 3;
for(i=1;i<64;i++)
{
block[i] = (block[i] * quant_matrix[i]) / 16;
block[i] = clip(block[i]);
}
block = mb->cr_blocks;
for(i=1;i<64;i++)
{
block[i] = (block[i] * quant_matrix[i]) / 16;
block[i] = clip(block[i]);
}
block = mb->cb_blocks;
for(i=1;i<64;i++)
{
block[i] = (block[i] * quant_matrix[i]) / 16;
block[i] = clip(block[i]);
}
}
static void
inv_quantize_non_intra_mb(picture_t *picture,macroblock_t *mb)
{
uint_8 *quant_matrix;
uint_32 i;
sint_16 *block;
//choose the appropriate quantization matrix
if(picture->use_custom_non_intra_quantizer_matrix)
quant_matrix = picture->custom_non_intra_quantization_matrix;
else
quant_matrix = default_non_intra_quantization_matrix;
//FIXME we can optimize this so that we load the quantization
//coeff once and use it on all 6 blocks at once
block = mb->y_blocks;
for(i=0;i<64;i++)
block[i] = (block[i] * quant_matrix[i]) / 32;
block = mb->y_blocks + 64;
for(i=0;i<64;i++)
block[i] = (block[i] * quant_matrix[i]) / 32;
block = mb->y_blocks + 64 * 2;
for(i=0;i<64;i++)
block[i] = (block[i] * quant_matrix[i]) / 32;
block = mb->y_blocks + 64 * 3;
for(i=0;i<64;i++)
block[i] = (block[i] * quant_matrix[i]) / 32;
block = mb->cr_blocks;
for(i=0;i<64;i++)
block[i] = (block[i] * quant_matrix[i]) / 32;
block = mb->cb_blocks;
for(i=0;i<64;i++)
block[i] = (block[i] * quant_matrix[i]) / 32;
}
void
inv_quantize(picture_t *picture,mb_buffer_t *mb_buffer)
{
uint_32 i;
macroblock_t *mb = mb_buffer->macroblocks;
uint_32 num_blocks = mb_buffer->num_blocks;
for(i=0;i<num_blocks;i++)
{
#if 1
sint_16 *block;
uint_32 j;
block = mb[i].y_blocks;
if(i == 0)
{
fprintf(stderr,"block_before\n");
for(j=0;j<64;j++)
{
fprintf(stderr,"%06d, ",block[j]);
if(!((j+1)%8))
fprintf(stderr,"\n");
}
fprintf(stderr,"\n\n");
}
#endif
if(mb[i].macroblock_type & MACROBLOCK_INTRA)
inv_quantize_intra_mb(picture,&mb[i]);
else
inv_quantize_non_intra_mb(picture,&mb[i]);
#if 1
if(i == 0)
{
fprintf(stderr,"block_after\n");
for(j=0;j<64;j++)
{
fprintf(stderr,"%06d, ",block[j]);
if(!((j+1)%8))
fprintf(stderr,"\n");
}
fprintf(stderr,"\n\n");
}
#endif
}
}
/*
* inv_quantize.c
*
* Copyright (C) Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - Nov 1999
*
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
*
* 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, 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 GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation,
*
*/
void inv_quantize(picture_t *picture,mb_buffer_t *mb_buffer);
/* config.h. Generated automatically by configure. */
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
/* #undef WORDS_BIGENDIAN */
/* Define if the X Window System is missing or not being used. */
/* #undef X_DISPLAY_MISSING */
/* Name of package */
#define PACKAGE "mpeg2dec"
/* Version number of package */
#define VERSION "0.1.7-cvs"
/* Architecture defines */
#define __i386__ 1
/* #undef __alpha__ */
/* #undef __ppc__ */
/* #undef __sparc__ */
/* Extension defines */
/* #undef HAVE_MLIB */
......@@ -30,7 +30,6 @@
#include <errno.h>
#include "config.h"
#include "old_crap.h"
#include "mpeg2.h"
#include "mpeg2_internal.h"
......@@ -40,7 +39,6 @@
#include "idct.h"
#include "parse.h"
#include "display.h"
#include "inv_quantize.h"
//this is where we keep the state of the decoder
static picture_t picture;
......@@ -52,7 +50,6 @@ mpeg2_config_t config;
//frame structure to pass back to caller
mpeg2_frame_t mpeg2_frame;
static uint_32 is_display_initialized = 0;
static uint_32 is_sequence_needed = 1;
static void find_next_start_code()
......@@ -220,12 +217,6 @@ mpeg2_decode_frame (char *new_data, u_int new_data_len)
last_mba = ((picture.coded_picture_height * picture.coded_picture_width) >> 8) - 1;
mb_width = picture.coded_picture_width >> 4;
//we can't initialize the display until we know how big the picture is
if(!is_display_initialized)
{
display_init(picture.coded_picture_width,picture.coded_picture_height);
is_display_initialized = 1;
}
do
{
......@@ -287,6 +278,7 @@ mpeg2_decode_frame (char *new_data, u_int new_data_len)
prev_macroblock_type = mb->macroblock_type & (MACROBLOCK_MOTION_FORWARD | MACROBLOCK_MOTION_BACKWARD);
mb = mb_buffer_increment();
if(!mb)
decode_flush_buffer();
}
......@@ -310,6 +302,9 @@ mpeg2_decode_frame (char *new_data, u_int new_data_len)
mpeg2_frame.frame[2] = picture.forward_reference_frame[2];
}
mpeg2_frame.width = picture.coded_picture_width;
mpeg2_frame.height = picture.coded_picture_height;
if(bitstream_show(32) == SEQUENCE_END_CODE)
is_sequence_needed = 1;
......
......@@ -29,7 +29,8 @@
#include <stdio.h>
#include "global.h"
#include "mpeg2.h"
#include "mpeg2_internal.h"
#include "config.h"
#include "bitstream.h"
#include "getvlc.h"
......@@ -39,10 +40,10 @@ int Quiet_Flag = 0;
/* private prototypes */
/* generic picture macroblock type processing functions */
static int Get_I_macroblock_type _ANSI_ARGS_((void));
static int Get_P_macroblock_type _ANSI_ARGS_((void));
static int Get_B_macroblock_type _ANSI_ARGS_((void));
static int Get_D_macroblock_type _ANSI_ARGS_((void));
static int Get_I_macroblock_type (void);
static int Get_P_macroblock_type (void);
static int Get_B_macroblock_type (void);
static int Get_D_macroblock_type (void);
int Get_macroblock_type(int picture_coding_type)
{
......
......@@ -43,6 +43,8 @@ typedef struct {
char run, level, len;
} DCTtab;
#define ERROR -1
/* Table B-3, macroblock_type in P-pictures, codes 001..1xx */
static VLCtab PMBtab0[8] = {
{ERROR,0},
......
......@@ -117,14 +117,12 @@ static void idct_row(sint_16 *blk)
x6 = blk[5];
x7 = blk[3];
#if 0
/* shortcut */
if (!(x1 | x2 | x3 | x4 | x5 | x6 | x7 ))
{
blk[0]=blk[1]=blk[2]=blk[3]=blk[4]=blk[5]=blk[6]=blk[7]=blk[0]<<3;
return;
}
#endif
x0 = (blk[0]<<11) + 128; /* for proper rounding in the fourth stage */
......@@ -177,9 +175,7 @@ static void idct_row(sint_16 *blk)
* c[1..7] = (1/1024)*sqrt(2)
*/
/* FIXME something odd is going on with inlining this
* procedure. Things break if it isn't inlined */
static void idct_col(sint_16 *blk)
static void idct_col_s16(sint_16 *blk)
{
int x0, x1, x2, x3, x4, x5, x6, x7, x8;
......@@ -192,14 +188,12 @@ static void idct_col(sint_16 *blk)
x6 = blk[8*5];
x7 = blk[8*3];
#if 0
if (!(x1 | x2 | x3 | x4 | x5 | x6 | x7 ))
{
blk[8*0]=blk[8*1]=blk[8*2]=blk[8*3]=blk[8*4]=blk[8*5]=blk[8*6]=blk[8*7]=
clip[(blk[8*0]+32)>>6];
return;
}
#endif
x0 = (blk[8*0]<<8) + 8192;
......@@ -256,7 +250,6 @@ idct_c(mb_buffer_t *mb_buffer)
if(mb[k].skipped)
continue;
//XXX only 4:2:0 supported here
for(i=0;i<4;i++)
{
blk = mb[k].y_blocks + 64*i;
......@@ -267,7 +260,7 @@ idct_c(mb_buffer_t *mb_buffer)
idct_row(blk + 8*j);
for (j=0; j<8; j++)
idct_col(blk + j);
idct_col_s16(blk + j);
}
}
......@@ -279,7 +272,7 @@ idct_c(mb_buffer_t *mb_buffer)
idct_row(blk + 8*j);
for (j=0; j<8; j++)
idct_col(blk + j);
idct_col_s16(blk + j);
}
if(mb[k].coded_block_pattern & 0x1)
......@@ -290,7 +283,7 @@ idct_c(mb_buffer_t *mb_buffer)
idct_row(blk + 8*j);
for (j=0; j<8; j++)
idct_col(blk + j);
idct_col_s16(blk + j);
}
}
}
......
<
/*
* motion_comp.c
*
* Copyright (C) Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - Nov 1999
*
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
*
* 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, 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 GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation,
*
*/
//
// This will get amusing in a few months I'm sure
//
// motion_comp.c rewrite counter: 5
//
#include <stdlib.h>
#include <stdio.h>
#include "config.h"
#include "mpeg2.h"
#include "mpeg2_internal.h"
#include "debug.h"
#include "mb_buffer.h"
#include "motion_comp.h"
//#include "motion_comp_mmx.h"
//#include "motion_comp_mlib.h"
static uint_8 clip_lut[1024];
#define clip_to_u8(x) clip_lut[(x)+384]
static void
motion_comp_idct_copy (uint_8 * dst, sint_16 * block, uint_32 stride)
{
int x, y;
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
dst[x] = clip_to_u8 (block[x]);
dst += stride;
block += 8;
}
}
static void
motion_comp_idct_add (uint_8 * dst, sint_16 * block, uint_32 stride)
{
int x, y;
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
dst[x] = clip_to_u8 (dst[x] + block[x]);
dst += stride;
block += 8;
}
}
void
motion_comp_init (void)
{
sint_32 i;
for ( i =-384; i < 640; i++)
clip_lut[i+384] = i < 0 ? 0 : (i > 255 ? 255 : i);
//FIXME turn mmx back on
//#ifdef __i386__
#if 0
if (config.flags & MPEG2_MMX_ENABLE)
motion_comp = motion_comp_mmx;
#if HAVE_MLIB
else if(1 || config.flags & MPEG2_MLIB_ENABLE) // FIXME
motion_comp = motion_comp_mlib;
#endif
else
#endif
//FIXME fill in function table here
}
static void (* put_table [8]) (uint_8 *, uint_8 *, sint_32, sint_32) =
{
motion_comp_put_16x16, motion_comp_put_x_16x16,
motion_comp_put_y_16x16, motion_comp_put_xy_16x16,
motion_comp_put_8x8, motion_comp_put_x_8x8,
motion_comp_put_y_8x8, motion_comp_put_xy_8x8,
};
static void (* ave_table [8]) (uint_8 *, uint_8 *, sint_32, sint_32) =
{
motion_comp_avg_16x16, motion_comp_avg_x_16x16,
motion_comp_avg_y_16x16, motion_comp_avg_xy_16x16,
motion_comp_avg_8x8, motion_comp_avg_x_8x8,
motion_comp_avg_y_8x8, motion_comp_avg_xy_8x8,
};
void motion_block (void (** table) (uint_8 *, uint_8 *, sint_32, sint_32),
int x_pred, int y_pred, int field_select,
uint_8 * dst_y, uint_8 * dst_cr, uint_8 * dst_cb,
uint_8 * refframe[3], int pitch, int height)
{
int xy_half;
uint_8 *src1, *src2;