Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 1064 → Rev 1063

/shark/trunk/ports/mpeg/makefile
0,0 → 1,52
#
# The mpeg library
#
 
# (see sources for copyrights)
 
ifndef BASE
BASE=../..
endif
 
include $(BASE)/config/config.mk
 
LIBRARY = mpeg
 
OBJS_PATH = $(BASE)/ports/mpeg
 
DECODER_SRC = util.c \
video.c \
parseblock.c \
motionvector.c \
decoders.c \
jrevdct.c \
wrapper.c \
gdith.c \
gdithmni.c \
readfile.c \
16bit.c
 
DITHER_SRC = fs2.c \
fs2fast.c \
fs4.c \
hybrid.c \
hybriderr.c \
2x2.c \
gray.c \
mono.c \
ordered.c \
ordered2.c \
mb_ordered.c
 
SRCS= $(DECODER_SRC) $(DITHER_SRC)
 
OBJS= $(patsubst %.c,%.o,$(SRCS))
 
C_WARN += -Wno-unused -Wno-uninitialized -Wno-implicit-function-declaration \
-Wno-switch -Wno-return-type
 
C_DEF += -DNOCONTROLS
C_INC += -I.
 
include $(BASE)/config/lib.mk
 
/shark/trunk/ports/mpeg/fs2.h
0,0 → 1,27
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
typedef struct {
unsigned char value;
int e1;
int e3;
} FS2DithVal;
 
/shark/trunk/ports/mpeg/imakefil.pro
0,0 → 1,29
/* See Makefile.proto for flags to define */
DESTDIR = /usr/pkg/video
NDEBUG = /* -DNDEBUG */
/*ANALYSIS = -DANALYSIS */
SHMEM = -DSH_MEM
EXTRA_DEFINES = $(NDEBUG) $(ANALYSIS) $(SHMEM)
DEPLIBS = $(DEPXLIB)
LOCAL_LIBRARIES = $(XLIB)
SYS_LIBRARIES = -lm -lc
 
PROGRAM = mpeg_play
 
SRCS1 = util.c video.c parseblock.c motionvector.c decoders.c \
main.c gdith.c fs2.c fs2fast.c fs4.c hybrid.c hybriderr.c \
2x2.c gray.c jrevdct.c 16bit.c util32.c ordered.c mono.c \
mb_ordered.c ordered2.c readfile.c floatdct.c ctrlbar.c
 
OBJS1 = util.o video.o parseblock.o motionvector.o decoders.o \
fs2.o fs2fast.o fs4.o hybrid.o hybriderr.o 2x2.o \
gdith.o gray.o main.o jrevdct.o 16bit.o util32.o ordered.o mono.o \
mb_ordered.o ordered2.o readfile.o floatdct.o ctrlbar.o
 
PROGRAMS = $(PROGRAM)
 
ComplexProgramTarget_1($(PROGRAM),$(LOCAL_LIBRARIES),)
 
 
 
 
/shark/trunk/ports/mpeg/fs4.h
0,0 → 1,29
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
typedef struct {
unsigned char value;
int e1;
int e2;
int e3;
int e4;
} FS4Dither;
 
/shark/trunk/ports/mpeg/gray.c
0,0 → 1,336
/*
* gray.c --
*
* More procedures to dither grey-scale images.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "proto.h"
#include "dither.h"
 
/*
*--------------------------------------------------------------
*
* GrayDitherImage --
*
* Dithers image into 128 gray scales. Simply maps luminance
* value into 1 of 128 gray scale colors (divide by two, essentially).
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
GrayDitherImage(lum, cr, cb, out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int w, h;
{
 
int i, max = w*h/16;
 
for (i=0; i<max; i++) {
out[0] = pixel[lum[0]];
out[1] = pixel[lum[1]];
out[2] = pixel[lum[2]];
out[3] = pixel[lum[3]];
out[4] = pixel[lum[4]];
out[5] = pixel[lum[5]];
out[6] = pixel[lum[6]];
out[7] = pixel[lum[7]];
out[8] = pixel[lum[8]];
out[9] = pixel[lum[9]];
out[10] = pixel[lum[10]];
out[11] = pixel[lum[11]];
out[12] = pixel[lum[12]];
out[13] = pixel[lum[13]];
out[14] = pixel[lum[14]];
out[15] = pixel[lum[15]];
out += 16;
lum += 16;
}
}
 
 
void
Gray16DitherImage(lum, cr, cb, p_out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *p_out;
int w, h;
{
 
unsigned short *out = (unsigned short *)p_out;
 
int i, max = w*h/16;
 
for (i=0; i<max; i++) {
out[0] = wpixel[lum[0]];
out[1] = wpixel[lum[1]];
out[2] = wpixel[lum[2]];
out[3] = wpixel[lum[3]];
out[4] = wpixel[lum[4]];
out[5] = wpixel[lum[5]];
out[6] = wpixel[lum[6]];
out[7] = wpixel[lum[7]];
out[8] = wpixel[lum[8]];
out[9] = wpixel[lum[9]];
out[10] = wpixel[lum[10]];
out[11] = wpixel[lum[11]];
out[12] = wpixel[lum[12]];
out[13] = wpixel[lum[13]];
out[14] = wpixel[lum[14]];
out[15] = wpixel[lum[15]];
out += 16;
lum += 16;
}
}
 
void
Gray32DitherImage(lum, cr, cb, p_out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *p_out;
int w, h;
{
 
unsigned int *out = (unsigned int *)p_out;
int i, max = w*h/16;
 
for (i=0; i<max; i++) {
out[0] = wpixel[lum[0]];
out[1] = wpixel[lum[1]];
out[2] = wpixel[lum[2]];
out[3] = wpixel[lum[3]];
out[4] = wpixel[lum[4]];
out[5] = wpixel[lum[5]];
out[6] = wpixel[lum[6]];
out[7] = wpixel[lum[7]];
out[8] = wpixel[lum[8]];
out[9] = wpixel[lum[9]];
out[10] = wpixel[lum[10]];
out[11] = wpixel[lum[11]];
out[12] = wpixel[lum[12]];
out[13] = wpixel[lum[13]];
out[14] = wpixel[lum[14]];
out[15] = wpixel[lum[15]];
out += 16;
lum += 16;
}
}
 
/*
*--------------------------------------------------------------
*
* Gray2DitherImage --
*
* Dithers image into 128 gray scales. Simply maps luminance
* value into 1 of 128 gray scale colors (divide by two, essentially).
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
Gray2DitherImage(lum, cr, cb, p_out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *p_out;
int w, h;
{
 
int x, y;
unsigned short *out = (unsigned short *)p_out;
unsigned short *out2 = out + w;
 
for (y=0; y<h; y++) {
for (x=0; x<w; x+=16) {
out[0] = out2[0] = wpixel[lum[0]];
out[1] = out2[1] = wpixel[lum[1]];
out[2] = out2[2] = wpixel[lum[2]];
out[3] = out2[3] = wpixel[lum[3]];
out[4] = out2[4] = wpixel[lum[4]];
out[5] = out2[5] = wpixel[lum[5]];
out[6] = out2[6] = wpixel[lum[6]];
out[7] = out2[7] = wpixel[lum[7]];
out[8] = out2[8] = wpixel[lum[8]];
out[9] = out2[9] = wpixel[lum[9]];
out[10] = out2[10] = wpixel[lum[10]];
out[11] = out2[11] = wpixel[lum[11]];
out[12] = out2[12] = wpixel[lum[12]];
out[13] = out2[13] = wpixel[lum[13]];
out[14] = out2[14] = wpixel[lum[14]];
out[15] = out2[15] = wpixel[lum[15]];
out += 16;
out2 += 16;
lum += 16;
}
out += w;
out2 += w;
}
}
 
void
Gray216DitherImage(lum, cr, cb, p_out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *p_out;
int w, h;
{
 
int x, y;
unsigned int *out = (unsigned int *)p_out;
unsigned int *out2 = out + w;
 
for (y=0; y<h; y++) {
for (x=0; x<w; x+=16) {
out[0] = out2[0] = wpixel[lum[0]];
out[1] = out2[1] = wpixel[lum[1]];
out[2] = out2[2] = wpixel[lum[2]];
out[3] = out2[3] = wpixel[lum[3]];
out[4] = out2[4] = wpixel[lum[4]];
out[5] = out2[5] = wpixel[lum[5]];
out[6] = out2[6] = wpixel[lum[6]];
out[7] = out2[7] = wpixel[lum[7]];
out[8] = out2[8] = wpixel[lum[8]];
out[9] = out2[9] = wpixel[lum[9]];
out[10] = out2[10] = wpixel[lum[10]];
out[11] = out2[11] = wpixel[lum[11]];
out[12] = out2[12] = wpixel[lum[12]];
out[13] = out2[13] = wpixel[lum[13]];
out[14] = out2[14] = wpixel[lum[14]];
out[15] = out2[15] = wpixel[lum[15]];
out += 16;
out2 += 16;
lum += 16;
}
out += w;
out2 += w;
}
}
 
#ifndef SIXTYFOUR_BIT
 
void
Gray232DitherImage(lum, cr, cb, p_out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *p_out;
int w, h;
{
 
int x, y;
unsigned int *out = (unsigned int *)p_out;
unsigned int *out2 = out + w * 2;
 
for (y=0; y<h; y++) {
for (x=0; x<w; x+=16) {
out[0] = out2[0] = out[1] = out2[1] = wpixel[lum[0]];
out[2] = out2[2] = out[3] = out2[3] = wpixel[lum[1]];
out[4] = out2[4] = out[5] = out2[5] = wpixel[lum[2]];
out[6] = out2[6] = out[7] = out2[7] = wpixel[lum[3]];
out[8] = out2[8] = out[9] = out2[9] = wpixel[lum[4]];
out[10] = out2[10] = out[11] = out2[11] = wpixel[lum[5]];
out[12] = out2[12] = out[13] = out2[13] = wpixel[lum[6]];
out[14] = out2[14] = out[15] = out2[15] = wpixel[lum[7]];
out[16] = out2[16] = out[17] = out2[17] = wpixel[lum[8]];
out[18] = out2[18] = out[19] = out2[19] = wpixel[lum[9]];
out[20] = out2[20] = out[21] = out2[21] = wpixel[lum[10]];
out[22] = out2[22] = out[23] = out2[23] = wpixel[lum[11]];
out[24] = out2[24] = out[25] = out2[25] = wpixel[lum[12]];
out[26] = out2[26] = out[27] = out2[27] = wpixel[lum[13]];
out[28] = out2[28] = out[29] = out2[29] = wpixel[lum[14]];
out[30] = out2[30] = out[31] = out2[31] = wpixel[lum[15]];
out += 32;
out2 += 32;
lum += 16;
}
out += w * 2;
out2 += w * 2;
}
}
 
#else /* def SIXTYFOUR_BIT */
 
void
Gray232DitherImage(lum, cr, cb, p_out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *p_out;
int w, h;
{
 
int x, y;
unsigned long *out = (unsigned long *)p_out;
unsigned long *out2 = out + w;
 
for (y=0; y<h; y++) {
for (x=0; x<w; x+=16) {
out[0] = out2[0] = wpixel[lum[0]];
out[2] = out2[2] = wpixel[lum[1]];
out[4] = out2[4] = wpixel[lum[2]];
out[6] = out2[6] = wpixel[lum[3]];
out[8] = out2[8] = wpixel[lum[4]];
out[10] = out2[10] = wpixel[lum[5]];
out[12] = out2[12] = wpixel[lum[6]];
out[14] = out2[14] = wpixel[lum[7]];
out[16] = out2[16] = wpixel[lum[8]];
out[18] = out2[18] = wpixel[lum[9]];
out[20] = out2[20] = wpixel[lum[10]];
out[22] = out2[22] = wpixel[lum[11]];
out[24] = out2[24] = wpixel[lum[12]];
out[26] = out2[26] = wpixel[lum[13]];
out[28] = out2[28] = wpixel[lum[14]];
out[30] = out2[30] = wpixel[lum[15]];
out += 16;
out2 += 16;
lum += 16;
}
out += w;
out2 += w;
}
}
 
#endif /* def SIXTYFOUR_BIT */
/shark/trunk/ports/mpeg/animdisp.c
0,0 → 1,268
/*
* Copyright 1995, Brown University, Providence, RI
*
* Permission to use and modify this software and its documentation for
* any purpose other than its incorporation into a commercial product is
* hereby granted without fee. Permission to copy and distribute this
* software and its documentation only for non-commercial use is also
* granted without fee, provided, however, that the above copyright notice
* appear in all copies, that both that copyright notice and this permission
* notice appear in supporting documentation, that the name of Brown
* University not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission,
* and that the person doing the distribution notify Brown University of
* such distributions outside of his or her organization. Brown University
* makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
* Brown University requests notification of any modifications to this
* software or its documentation.
*
* Send the following redistribution information:
*
* Name:
* Organization:
* Address (postal and/or electronic):
*
* To:
* Software Librarian
* Computer Science Department, Box 1910
* Brown University
* Providence, RI 02912
*
* or
*
* brusd@cs.brown.edu
*
* We will acknowledge all electronic notifications.
*/
 
#include <stdio.h>
#include <iostream.h>
#include "ANIMdisplay.H"
 
// Constructor for first movie in a series
//
//
ANIMdisplay::ANIMdisplay(ANIMbase *movie, char* displayName,
Boolean loopMovie,
int allocateFrame, int starty)
: _movie(movie),
originalMovie(TRUE),
frameAllocated(FALSE),
loop(loopMovie),
movieEnded(FALSE),
_displayName(strdup(displayName))
{
 
//for first instance
xinfo.hints.x=0;
xinfo.hints.y=starty;
xinfo.cmap=0;
xinfo.gc=0;
xinfo.depth=24;
xinfo.ditherType=FULL_COLOR_DITHER;
xinfo.display=NULL;
xinfo.visual=NULL;
xinfo.ExistingWindow=0;
xinfo.hints.width=movie->Width;
xinfo.hints.height=movie->Height;
largy=-1;
init(allocateFrame);
 
XWindowAttributes winattr;
Display *display=xinfo.display;
 
displayWidth=DisplayWidth(display,XDefaultScreen(display));
XGetWindowAttributes(display, xinfo.window, &winattr);
 
_movie->InitDither(winattr.visual->red_mask,
winattr.visual->green_mask,
winattr.visual->blue_mask);
}
 
// Constructor for first movie in a series
//
//
ANIMdisplay::ANIMdisplay(ANIMbase *movie, ANIMdisplay *lastMovie,
Boolean loopMovie,
int allocateFrame)
: largy(lastMovie->largy),
frameAllocated(FALSE),
displayWidth(lastMovie->displayWidth),
_displayName(lastMovie->_displayName),
_movie(movie),
originalMovie(TRUE),
loop(loopMovie),
movieEnded(FALSE)
{
//for n>1 instance
/* get next X coordinates */
xinfo.hints.x= lastMovie->xinfo.hints.x+10+ lastMovie->_movie->Width;
/* Update the largest vertical size of a movie */
/* If we are off the right side of the screen, cont at left */
xinfo.hints.y=lastMovie->xinfo.hints.y;
if (xinfo.hints.x > displayWidth - 80) {
xinfo.hints.y+=largy+30;
largy=0;
xinfo.hints.x=0;
}
xinfo.ExistingWindow=0;
xinfo.display=lastMovie->xinfo.display;
xinfo.visual=lastMovie->xinfo.visual;
xinfo.cmap=lastMovie->xinfo.cmap;
xinfo.gc=lastMovie->xinfo.gc;
xinfo.ditherType=lastMovie->xinfo.ditherType;
xinfo.display=lastMovie->xinfo.display;
xinfo.depth=lastMovie->xinfo.depth;
xinfo.ditherType=lastMovie->xinfo.ditherType;
 
init(allocateFrame);
}
 
// Destructor
//
//
ANIMdisplay::~ANIMdisplay()
{
if (frameAllocated) {
free(xinfo.ximage->data);
xinfo.ximage->data=NULL;
}
if (xinfo.ximage!=NULL) XDestroyImage(xinfo.ximage);
// Add code re: xinfo.display - reference count
}
 
// Constructor helper code, also called when we switch movies
//
//
void
ANIMdisplay::init(Boolean allocateFrame)
{
const char *inputName=_movie->getName();
 
if (_movie->Height>largy) {
largy=_movie->Height;
}
xinfo.hints.width=_movie->Width;
xinfo.hints.height=_movie->Height;
 
xinfo.ximage=NULL;
xinfo.owncmFlag=FALSE;
 
if (inputName==NULL) {
// Should be.... different
xinfo.name="Display!";
} else if ((xinfo.name=strrchr(inputName,'/'))==NULL) {
xinfo.name=(char *) inputName;
} else xinfo.name++;
 
if (originalMovie) InitColorDisplay((char *) _displayName,&xinfo);
else {
XSetStandardProperties (xinfo.display, xinfo.window, xinfo.name,
xinfo.name, None, NULL, 0,
&xinfo.hints);
}
init_image(allocateFrame);
}
 
void
ANIMdisplay::init_image(Boolean allocateFrame) {
Display *display=xinfo.display;
Visual *fc_visual;
int depth, w,h;
char *where,dummy;
 
//XImage has to be on word boundary?
w = _movie->Width + (_movie->Width % 16);
h = _movie->Height + (_movie->Height % 16);
if (w+h==0) {
xinfo.ximage=NULL;
return;
}
frameAllocated=allocateFrame;
 
fc_visual = FindFullColorVisual(display, &depth);
if (allocateFrame) where=(char *) malloc(w*h*4);
else where=&dummy;
xinfo.ximage=XCreateImage(display,fc_visual,depth,ZPixmap,
0,where,w, h,32,0);
#ifdef LITTLE_ENDIAN_ARCHITECTURE
xinfo.ximage->byte_order = LSBFirst;
xinfo.ximage->bitmap_bit_order = LSBFirst;
#else
xinfo.ximage->byte_order = MSBFirst;
xinfo.ximage->bitmap_bit_order = MSBFirst;
#endif
}
 
void
ANIMdisplay::newMovie(const char *const newMovieName)
{
if (xinfo.ximage!=NULL) XDestroyImage(xinfo.ximage);
 
if (newMovieName!=NULL) {
_movie->newMovie(newMovieName);
_movie->open();
}
 
originalMovie=FALSE;
init(frameAllocated);
 
XResizeWindow(xinfo.display,xinfo.window,
_movie->Width,
_movie->Height);
XFlush(xinfo.display);
 
movieEnded=FALSE;
}
 
void
ANIMdisplay::display(char *frame) {
char *paramFrame, *tmpFrame;
Boolean moreFrames, newFrame;
 
// if frame is:
// !NULL - display frame already in xinfo
// NULL - get frame and then display it
if (frame==NULL) {
if (xinfo.ximage!=NULL) paramFrame=xinfo.ximage->data;
else paramFrame=NULL;
moreFrames=_movie->GetFrame(&paramFrame,&newFrame);
if (newFrame) {
// if there is no ximage so far, we are starting "anew"
if (xinfo.ximage==NULL) {
frameAllocated=TRUE; // Don't allocate a frame
newMovie(NULL);
}
tmpFrame=xinfo.ximage->data;
xinfo.ximage->data=paramFrame;
}
} else newFrame=TRUE;
 
if (newFrame) {
Display *display=xinfo.display;
if (frame!=NULL) xinfo.ximage->data=frame;
XPutImage(display, xinfo.window, xinfo.gc, xinfo.ximage,
0,0,0,0,
(unsigned int) xinfo.ximage->width,
(unsigned int) xinfo.ximage->height);
}
 
if (frame==NULL) {
// Don't copy NULL over new frame if unneeded
if (newFrame) xinfo.ximage->data=tmpFrame;
 
if (!moreFrames ) {
if (loop) _movie->rewind();
else movieEnded=TRUE;
}
}
}
 
Boolean ANIMdisplay::movieDone()
{
return movieEnded;
}
/shark/trunk/ports/mpeg/fs2fast.c
0,0 → 1,353
/*
* fs2fast.c --
*
* Procedures dealing with a fast version of Floyd-Steinberg
* dithering with 2 error values propagated.
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "proto.h"
#include "dither.h"
#ifdef __STDC__
#include <stdlib.h>
#else
#include <malloc.h>
#endif
 
 
/* Arrays containing error values for floyd-steinberg dithering. */
 
static int deltay[256];
static int deltau[256];
static int deltav[256];
static int deltay2[256];
static int deltau2[256];
static int deltav2[256];
 
/* Definitions governing number of bits used for luminance, cr, and cb. */
 
#define L_BITS 3
#define CR_BITS 2
#define CB_BITS 2
 
/* Masks for proper quantization of lum, cr, and cb values. */
 
#define L_MASK 0xe0
#define CR_MASK 0xc0
#define CB_MASK 0xc0
 
 
/*
*--------------------------------------------------------------
*
* InitFS2FastDither --
*
* Initializes structures and arrays neeeded for fast implementation
* of two error F-S dithering.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void InitFS2FastDither()
{
int i;
int lum_num, cr_num, cb_num;
 
for (i=0; i<256; i++) {
lum_num = (i >> (8-L_BITS));
cr_num = (i >> (8-CR_BITS));
cb_num = (i >> (8-CB_BITS));
 
/* These arrays contain the error values propogated for each pixel value
for each channel.
*/
 
deltay[i] = (i - ((int) lum_values[lum_num])) / 2;
deltau[i] = (i-((int) cr_values[cr_num])) / 2;
deltav[i] = (i-((int) cb_values[cb_num])) / 2;
deltay2[i] = (i - ((int) lum_values[lum_num])) - deltay[i];
deltau2[i] = (i - ((int) cr_values[cr_num])) - deltau[i];
deltav2[i] = (i - ((int) cb_values[cb_num])) - deltav[i];
 
}
 
}
 
/*
*--------------------------------------------------------------
*
* DitherImage --
*
* Dithers an image using floyd-steinberg.
* Assumptions made:
* 1) The color space is allocated y:cr:cb = 8:4:4
* 2) The spatial resolution of y:cr:cb is 4:1:1
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
FS2FastDitherImage (lum, cr, cb, out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int w, h;
{
int i, j, idx, idx2;
int y, u, v;
int dy, du, dv;
int code;
static int *yerr1;
static int *yerr2;
static int *uerr1;
static int *uerr2;
static int *verr1;
static int *verr2;
int *ye1, *ue1, *ve1;
int *ye2, *ue2, *ve2;
unsigned char *o, *l, *r, *b;
static int first = 1;
 
/* If first time called, allocate error arrays. */
 
if (first) {
first = 0;
yerr1 = (int *) malloc((w+5)*sizeof(int));
yerr2 = (int *) malloc((w+5)*sizeof(int));
uerr1 = (int *) malloc((w+5)*sizeof(int));
uerr2 = (int *) malloc((w+5)*sizeof(int));
verr1 = (int *) malloc((w+5)*sizeof(int));
verr2 = (int *) malloc((w+5)*sizeof(int));
}
 
/*
* Init error arrays and variables.
*/
memset ((char *)yerr1, 0, (w+5)*sizeof(int));
memset ((char *)yerr2, 0, (w+5)*sizeof(int));
memset ((char *)uerr1, 0, (w+5)*sizeof(int));
memset ((char *)uerr2, 0, (w+5)*sizeof(int));
memset ((char *)verr1, 0, (w+5)*sizeof(int));
memset ((char *)verr2, 0, (w+5)*sizeof(int));
du = dv = dy = 0;
 
for (j=0; j<h; j+=2) {
ye1 = yerr1;
ue1 = uerr1;
ve1 = verr1;
ye2 = yerr2;
ue2 = uerr2;
ve2 = verr2;
idx = j*w;
idx2 = idx/4;
o = out+idx;
l = lum+idx;
r = cr+idx2;
b = cb+idx2;
 
/* Do the top row in forward order. */
for (i=0; i<w; i+=2) {
/* Do left side of this pair... */
y = *l++ + dy + *ye1++;
u = *r + du + *ue1++;
v = *b + dv + *ve1++;
 
if (y < 0) {
y = 0;
} else if (y > 255) {
y = 255;
}
 
if (u < 0) {
u = 0;
} else if (u > 255) {
u = 255;
}
 
if (v < 0) {
v = 0;
} else if (v > 255) {
v = 255;
}
 
/*
* Construct a code using:
* high order 3 bits of y,
* high order 2 bits of u,
* high order 2 bits of v
*/
code = (((y & L_MASK) | ((u & CR_MASK) >> L_BITS) | (v >> (L_BITS+CR_BITS)))
>> (8-(L_BITS+CR_BITS+CB_BITS)));
*o++ = pixel[code];
*ye2++ = deltay[y];
*ue2++ = deltau[u];
*ve2++ = deltav[v];
dy = deltay2[y];
du = deltau2[u];
dv = deltav2[v];
 
/* Do right side of this pair... */
y = *l++ + dy + *ye1++;
u = *r++ + du + *ue1++;
v = *b++ + dv + *ve1++;
 
if (y < 0) {
y = 0;
} else if (y > 255) {
y = 255;
}
 
if (u < 0) {
u = 0;
} else if (u > 255) {
u = 255;
}
 
if (v < 0) {
v = 0;
} else if (v > 255) {
v = 255;
}
 
code = (((y & L_MASK) | ((u & CR_MASK) >> L_BITS) | (v >> (L_BITS+CR_BITS)))
>> (8-(L_BITS+CR_BITS+CB_BITS)));
*o++ = pixel[code];
*ye2++ = deltay[y];
*ue2++ = deltau[u];
*ve2++ = deltav[v];
dy = deltay2[y];
du = deltau2[u];
dv = deltav2[v];
 
}
ye1 = yerr1+w-1;
ue1 = uerr1+w-1;
ve1 = verr1+w-1;
ye2 = yerr2+w-1;
ue2 = uerr2+w-1;
ve2 = verr2+w-1;
l += w-1;
o += w-1;
r--;
b--;
dy = du = dv = 0;
 
/* Do bottom part of row, in right to left order. */
for (i=w-1; i>0; i-=2) {
/* Do right side of this pair... */
y = *l-- + dy + *ye2--;
u = *r + du + *ue2--;
v = *b + dv + *ve2--;
 
if (y < 0) {
y = 0;
} else if (y > 255) {
y = 255;
}
 
if (u < 0) {
u = 0;
} else if (u > 255) {
u = 255;
}
 
if (v < 0) {
v = 0;
} else if (v > 255) {
v = 255;
}
 
/*
* Construct a code using:
* high order 3 bits of y,
* high order 2 bits of u,
* high order 2 bits of v
*/
code = (((y & L_MASK) | ((u & CR_MASK) >> L_BITS) | (v >> (L_BITS+CR_BITS)))
>> (8-(L_BITS+CR_BITS+CB_BITS)));
*o-- = pixel[code];
*ye1-- = deltay[y];
*ue1-- = deltau[u];
*ve1-- = deltav[v];
dy = deltay2[y];
du = deltau2[u];
dv = deltav2[v];
 
/* Do left side of this pair... */
y = *l-- + dy + *ye2--;
u = *r-- + du + *ue2--;
v = *b-- + dv + *ve2--;
 
if (y < 0) {
y = 0;
} else if (y > 255) {
y = 255;
}
 
if (u < 0) {
u = 0;
} else if (u > 255) {
u = 255;
}
 
if (v < 0) {
v = 0;
} else if (v > 255) {
v = 255;
}
 
 
code = (((y & L_MASK) | ((u & CR_MASK) >> L_BITS) | (v >> (L_BITS+CR_BITS)))
>> (8-(L_BITS+CR_BITS+CB_BITS)));
*o-- = pixel[code];
*ye1-- = deltay[y];
*ue1-- = deltau[u];
*ve1-- = deltav[v];
dy = deltay2[y];
du = deltau2[u];
dv = deltav2[v];
 
}
}
}
 
 
 
 
 
/shark/trunk/ports/mpeg/proto.h
0,0 → 1,240
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#ifdef __STDC__
# define P(s) s
#include <stdlib.h> /* used by almost all modules */
#else
# define P(s) ()
#endif
 
/* util.c */
void correct_underflow P((VidStream *vid_stream ));
int next_bits P((int num , unsigned int mask , VidStream *vid_stream ));
char *get_ext_data P((VidStream *vid_stream ));
int next_start_code P((VidStream *vid_stream));
char *get_extra_bit_info P((VidStream *vid_stream ));
 
/* video.c */
void init_stats P((void ));
void PrintAllStats P((VidStream *vid_stream ));
double ReadSysClock P((void ));
void PrintTimeInfo P(( VidStream *vid_stream ));
void InitCrop P((void ));
VidStream *NewVidStream P((unsigned int buffer_len ));
#ifndef NOCONTROLS
void ResetVidStream P((VidStream *vid ));
#endif
void DestroyVidStream P((VidStream *astream, XInfo *xinfo ));
PictImage *NewPictImage P(( VidStream *vid_stream, XInfo *xinfo ));
void DestroyPictImage P((PictImage *apictimage, XInfo *xinfo ));
VidStream *mpegVidRsrc P((TimeStamp time_stamp,VidStream *vid_stream, int first , XInfo *xinfo));
void SetBFlag P((BOOLEAN val ));
void SetPFlag P((BOOLEAN val ));
 
/* parseblock.c */
void ParseReconBlock P((int n, VidStream *vid_stream ));
void ParseAwayBlock P((int n , VidStream *vid_stream ));
 
/* motionvector.c */
void ComputeForwVector P((int *recon_right_for_ptr , int *recon_down_for_ptr , VidStream *the_stream ));
void ComputeBackVector P((int *recon_right_back_ptr , int *recon_down_back_ptr, VidStream *the_stream ));
 
/* decoders.c */
void init_tables P((void ));
void decodeDCTDCSizeLum P((unsigned int *value ));
void decodeDCTDCSizeChrom P((unsigned int *value ));
void decodeDCTCoeffFirst P((unsigned int *run , int *level ));
void decodeDCTCoeffNext P((unsigned int *run , int *level ));
 
/* from main.c or equivalent */
void DoDitherImage P(( VidStream *vid_stream ));
 
/* gdith.c */
void InitColor P((void ));
/*int HandleXError P((Display *dpy , XErrorEvent *event ));
void InstallXErrorHandler P(( Display *display ));
void DeInstallXErrorHandler P(( Display *display ));*/
void ResizeDisplay P((unsigned int w , unsigned int h, XInfo *xinfo ));
void InitDisplay P((char *name , XInfo *xinfo ));
void InitGrayDisplay P((char *name, XInfo *xinfo ));
void InitGray256Display P((char *name, XInfo *xinfo ));
void InitMonoDisplay P((char *name, XInfo *xinfo ));
void InitColorDisplay P((char *name , XInfo *xinfo ));
#ifndef NOCONTROLS
void ExecuteDisplay P((VidStream *vid_stream , int frame_increment , XInfo *xinfo));
#else
void ExecuteDisplay P((VidStream *vid_stream, XInfo *xinfo ));
#endif
void ExecutePPM P((VidStream *vid_stream ));
#ifdef NO_GETTIMEOFDAY
struct timeval {long tv_sec, tv_usec;}; /* secs and usecs since 1-jan-1970 */
int gettimeofday P((struct timeval * retval, void * unused));
#endif
 
/* fs2.c */
void InitFS2Dither P((void ));
void FS2DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *disp , int rows , int cols ));
 
/* fs2fast.c */
void InitFS2FastDither P((void ));
void FS2FastDitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
 
/* fs4.c */
void InitFS4Dither P((void ));
void FS4DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *disp , int rows , int cols ));
 
/* hybrid.c */
void InitHybridDither P((void ));
void HybridDitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
 
/* hybriderr.c */
void InitHybridErrorDither P((void ));
void HybridErrorDitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
 
/* 2x2.c */
void Init2x2Dither P((void ));
void RandInit P((int h , int w ));
void PostInit2x2Dither P((void ));
void Twox2DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
 
/* gray.c */
void GrayDitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
void Gray2DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
void Gray16DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
void Gray216DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
void Gray32DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
void Gray232DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
 
/* mono.c */
void MonoThresholdImage(unsigned char *lum, unsigned char *cr, unsigned char *cb, unsigned char *out, int h, int w);
void MonoDitherImage(unsigned char *lum, unsigned char *cr, unsigned char *cb, unsigned char *out, int h, int w);
 
/* jrevdct.c */
void init_pre_idct P((void ));
void j_rev_dct_sparse P((DCTBLOCK data , int pos ));
void j_rev_dct P((DCTBLOCK data ));
void j_rev_dct_sparse P((DCTBLOCK data , int pos ));
void j_rev_dct P((DCTBLOCK data ));
 
/* floatdct.c */
void init_float_idct P((void ));
void float_idct P((short* block ));
 
/* 16bit.c */
void InitColorDither P((int ));
void Color16DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int rows , int cols ));
void Color32DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int rows , int cols ));
 
/* 16bit2x2.c */
void Twox2Color16DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int rows , int cols ));
void Twox2Color32DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int rows , int cols ));
 
/* util32.c */
/*Visual *FindFullColorVisual P((Display *dpy , int *depth ));
void CreateFullColorWindow P(( XInfo *xinfo));*/
 
/* ordered.c */
void InitOrderedDither P((void ));
void OrderedDitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
 
/* ordered2.c */
void InitOrdered2Dither P((void ));
void Ordered2DitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w ));
 
/* mb_ordered.c */
void InitMBOrderedDither P((void ));
void MBOrderedDitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int h , int w, char *ditherFlags ));
void MBOrderedDitherDisplayCopy P((VidStream *vid_stream , int mb_addr , int motion_forw , int r_right_forw , int r_down_forw , int motion_back , int r_right_back , int r_down_back , unsigned char *past , unsigned char *future ));
 
/* readfile.c */
void SeekStream P((VidStream *vid_stream ));
void clear_data_stream P(( VidStream *vid_stream));
int get_more_data P(( VidStream *vid_stream ));
int pure_get_more_data P((unsigned int *buf_start , int max_length , int *length_ptr , unsigned int **buf_ptr, VidStream *vid_stream ));
int read_sys P(( VidStream *vid_stream, unsigned int start ));
int ReadStartCode P(( unsigned int *startCode, VidStream *vid_stream ));
 
int ReadPackHeader P((
double *systemClockTime,
unsigned long *muxRate,
VidStream *vid_stream ));
 
int ReadSystemHeader P(( VidStream *vid_stream ));
 
int find_start_code P(( FILE *input ));
 
int ReadPacket P(( unsigned char packetID, VidStream *vid_stream ));
 
void ReadTimeStamp P((
unsigned char *inputBuffer,
unsigned char *hiBit,
unsigned long *low4Bytes));
 
void ReadSTD P((
unsigned char *inputBuffer,
unsigned char *stdBufferScale,
unsigned long *stdBufferSize));
 
void ReadRate P((
unsigned char *inputBuffer,
unsigned long *rate));
 
int MakeFloatClockTime P((
unsigned char hiBit,
unsigned long low4Bytes,
double *floatClockTime));
 
 
#ifndef NOCONTROLS
/* ctrlbar.c */
double StopWatch P((int action ));
Bool WindowMapped P((Display *dsp, XEvent *xev, char *window ));
Bool IfEventType P((Display *dsp, XEvent *xev, char *type ));
void MakeControlBar P(( XInfo *xinfo ));
void UpdateFrameTotal P((Display *display));
void UpdateControlDisplay P((Display *display));
void ControlBar P((VidStream **vid_stream, XInfo *xinfo, int numMovies ));
void ControlLoop P((VidStream **theStream, XInfo *xinfo, int numStreams ));
#endif /* !NOCONTROLS */
 
#undef P
/shark/trunk/ports/mpeg/animdisp.h
0,0 → 1,78
/*
* Copyright 1995, Brown University, Providence, RI
*
* Permission to use and modify this software and its documentation for
* any purpose other than its incorporation into a commercial product is
* hereby granted without fee. Permission to copy and distribute this
* software and its documentation only for non-commercial use is also
* granted without fee, provided, however, that the above copyright notice
* appear in all copies, that both that copyright notice and this permission
* notice appear in supporting documentation, that the name of Brown
* University not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission,
* and that the person doing the distribution notify Brown University of
* such distributions outside of his or her organization. Brown University
* makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
* Brown University requests notification of any modifications to this
* software or its documentation.
*
* Send the following redistribution information:
*
* Name:
* Organization:
* Address (postal and/or electronic):
*
* To:
* Software Librarian
* Computer Science Department, Box 1910
* Brown University
* Providence, RI 02912
*
* or
*
* brusd@cs.brown.edu
*
* We will acknowledge all electronic notifications.
*/
 
#include <stdio.h>
#include <iostream.h>
#include "ANIMmpeg.H"
 
extern unsigned long wpixel[256];
//extern int quietFlag;
 
class ANIMdisplay {
public:
//Constructor for first movie
ANIMdisplay(ANIMbase *movie, char *displayName,
Boolean loopMovie=TRUE,
int allocateFrame=1, int starty=5);
 
//Constructor for later movies
ANIMdisplay(ANIMbase *movie, ANIMdisplay *lastMovie,
Boolean loopMovie=TRUE,
int allocateFrame=1);
 
//Destructor
~ANIMdisplay();
 
//Replace with a new movie
void newMovie(const char * const movie);
 
void display(char *frame=NULL);
 
Boolean movieDone();
ANIMbase *_movie;
 
private:
ANIMdisplay& operator=(const ANIMdisplay& rhs); //disallow = operator
void init_image(Boolean allocateFrame);
void init(Boolean allocateFrame);
 
XInfo xinfo;
int largy, displayWidth;
Boolean originalMovie,frameAllocated, loop, movieEnded;
char *_displayName;
};
/shark/trunk/ports/mpeg/config.h
0,0 → 1,13
/* config.h. Generated automatically by configure. */
#define ENABLE_DITHER 1
#define STDC_HEADERS 1
#define HAVE_SYS_TIME_H 1
#define HAVE_UNISTD_H 1
#define TIME_WITH_SYS_TIME 1
#define HAVE_VPRINTF 1
#define HAVE_STRTOD 1
#define HAVE_STRTOL 1
#define HAVE_LRAND48 0
#define HAVE_GETRUSAGE 0
/* #undef CLK_TCK */
#define _HPUX_SOURCE 1
/shark/trunk/ports/mpeg/util.c
0,0 → 1,495
/*
* util.c --
*
* Miscellaneous utility procedures.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include <stdlib.h>
#include "video.h"
#include "proto.h"
#include "util.h"
#ifndef NOCONTROLS
#include "ctrlbar.h"
#endif
 
/*
Changes to make the code reentrant:
de-globalized: totNumFrames, realTimeStart, vid_stream, sys_layer,
bitOffset, bitLength, bitBuffer, curVidStream
setjmp/longjmp replaced
 
Additional changes:
only call DestroyVidStream up in mpegVidRsrc, not in correct_underflow
 
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* Bit masks used by bit i/o operations. */
 
unsigned int nBitMask[] = { 0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe};
 
unsigned int bitMask[] = { 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff,
0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
0x0000000f, 0x00000007, 0x00000003, 0x00000001};
 
unsigned int rBitMask[] = { 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
0xf0000000, 0xe0000000, 0xc0000000, 0x80000000};
 
unsigned int bitTest[] = { 0x80000000, 0x40000000, 0x20000000, 0x10000000,
0x08000000, 0x04000000, 0x02000000, 0x01000000,
0x00800000, 0x00400000, 0x00200000, 0x00100000,
0x00080000, 0x00040000, 0x00020000, 0x00010000,
0x00008000, 0x00004000, 0x00002000, 0x00001000,
0x00000800, 0x00000400, 0x00000200, 0x00000100,
0x00000080, 0x00000040, 0x00000020, 0x00000010,
0x00000008, 0x00000004, 0x00000002, 0x00000001};
 
/*
*--------------------------------------------------------------
*
* correct_underflow --
*
* Called when buffer does not have sufficient data to
* satisfy request for bits.
* Calls get_more_data, an application specific routine
* required to fill the buffer with more data.
*
* Results:
* None really.
*
* Side effects:
* buf_length and buffer fields may be changed.
*
*--------------------------------------------------------------
*/
 
void
correct_underflow(vid_stream)
VidStream *vid_stream;
{
 
int status;
 
status = get_more_data(vid_stream);
 
if (status < 0) {
if (!quietFlag) {
fprintf (stderr, "\n");
perror("Unexpected read error.");
}
exit(1);
}
else if ((status == 0) && (vid_stream->buf_length < 1)) {
if (!quietFlag) {
fprintf(stderr, "\nImproper or missing sequence end code.\n");
}
#ifdef ANALYSIS
PrintAllStats(vid_stream);
#endif
if (!quietFlag) {
PrintTimeInfo(vid_stream);
}
 
vid_stream->film_has_ended=TRUE;
#ifndef NOCONTROLS
/* Hmm, don't really know if this works or not... */
clear_data_stream(vid_stream);
return;
#else
if (loopFlag) {
clear_data_stream(vid_stream);
} /* destroy stream up in mpegVidRsrc */
return;
#endif /* !NOCONTROLS */
}
#ifdef UTIL2
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;
#else
vid_stream->curBits = *vid_stream->buffer;
#endif
 
}
 
/*
*--------------------------------------------------------------
*
* next_bits --
*
* Compares next num bits to low order position in mask.
* Buffer pointer is NOT advanced.
*
* Results:
* TRUE, FALSE, or error code.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
int next_bits(num, mask, vid_stream)
int num;
unsigned int mask;
VidStream *vid_stream;
{
unsigned int stream;
int ret_value;
 
/* If no current stream, return error. */
 
if (vid_stream == NULL)
return NO_VID_STREAM;
 
/* Get next num bits, no buffer pointer advance. */
 
show_bitsn(num, stream);
 
/* Compare bit stream and mask. Set return value toTRUE if equal, FALSE if
differs.
*/
 
if (mask == stream) {
ret_value = TRUE;
} else ret_value = FALSE;
 
/* Return return value. */
return ret_value;
}
 
/*
*--------------------------------------------------------------
*
* get_ext_data --
*
* Assumes that bit stream is at begining of extension
* data. Parses off extension data into dynamically
* allocated space until start code is hit.
*
* Results:
* Pointer to dynamically allocated memory containing
* extension data.
*
* Side effects:
* Bit stream irreversibly parsed.
*
*--------------------------------------------------------------
*/
 
char *get_ext_data (vid_stream)
VidStream *vid_stream;
{
unsigned int size, marker;
char *dataPtr;
unsigned int data;
 
/* Set initial ext data buffer size. */
 
size = EXT_BUF_SIZE;
 
/* Allocate ext data buffer. */
 
dataPtr = (char *) malloc(size);
 
/* Initialize marker to keep place in ext data buffer. */
 
marker = 0;
 
/* While next data is not start code... */
while (!next_bits(24, 0x000001, vid_stream)) {
 
/* Get next byte of ext data. */
 
get_bits8(data);
 
/* Put ext data into ext data buffer. Advance marker. */
 
dataPtr[marker] = (char) data;
marker++;
 
/* If end of ext data buffer reached, resize data buffer. */
 
if (marker == size) {
size += EXT_BUF_SIZE;
dataPtr = (char *) realloc(dataPtr, size);
}
}
 
/* Realloc data buffer to free any extra space. */
 
dataPtr = (char *) realloc(dataPtr, marker);
 
/* Return pointer to ext data buffer. */
return dataPtr;
}
 
/*
*--------------------------------------------------------------
*
* next_start_code --
*
* Parses off bitstream until start code reached. When done
* next 4 bytes of bitstream will be start code. Bit offset
* reset to 0.
*
* Results:
* Status code.
*
* Side effects:
* Bit stream irreversibly parsed.
*
*--------------------------------------------------------------
*/
 
int next_start_code(vid_stream)
VidStream *vid_stream;
{
int state;
int byteoff;
unsigned int data;
 
/* If no current stream, return error. */
 
if (vid_stream== NULL)
return NO_VID_STREAM;
 
/* If insufficient buffer length, correct underflow. */
 
if (vid_stream->buf_length < 4) {
correct_underflow(vid_stream);
}
 
/* If bit offset not zero, reset and advance buffer pointer. */
 
byteoff = vid_stream->bit_offset % 8;
 
if (byteoff != 0) {
flush_bits((8-byteoff));
}
 
/* Set state = 0. */
 
state = 0;
 
/* While buffer has data ... */
 
while(vid_stream->buf_length > 0) {
 
/* If insufficient data exists, correct underflow. */
 
if (vid_stream->buf_length < 4) {
correct_underflow(vid_stream);
}
 
/* If next byte is zero... */
 
get_bits8(data);
 
if (data == 0) {
 
/* If state < 2, advance state. */
 
if (state < 2) state++;
}
 
/* If next byte is one... */
 
else if (data == 1) {
 
/* If state == 2, advance state (i.e. start code found). */
 
if (state == 2) state++;
 
/* Otherwise, reset state to zero. */
 
else state = 0;
}
 
/* Otherwise byte is neither 1 or 0, reset state to 0. */
 
else {
state = 0;
}
 
/* If state == 3 (i.e. start code found)... */
 
if (state == 3) {
 
/* Set buffer pointer back and reset length & bit offsets so
* next bytes will be beginning of start code.
*/
 
vid_stream->bit_offset = vid_stream->bit_offset - 24;
 
#ifdef ANALYSIS
bitCount -= 24;
#endif
 
if (vid_stream->bit_offset < 0) {
vid_stream->bit_offset = 32 + vid_stream->bit_offset;
vid_stream->buf_length++;
vid_stream->buffer--;
#ifdef UTIL2
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;
#else
vid_stream->curBits = *vid_stream->buffer;
#endif
}
else {
#ifdef UTIL2
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;
#else
vid_stream->curBits = *vid_stream->buffer;
#endif
}
 
/* Return success. */
return OK;
}
}
 
/* Return underflow error. */
return STREAM_UNDERFLOW;
}
 
/*
*--------------------------------------------------------------
*
* get_extra_bit_info --
*
* Parses off extra bit info stream into dynamically
* allocated memory. Extra bit info is indicated by
* a flag bit set to 1, followed by 8 bits of data.
* This continues until the flag bit is zero. Assumes
* that bit stream set to first flag bit in extra
* bit info stream.
*
* Results:
* Pointer to dynamically allocated memory with extra
* bit info in it. Flag bits are NOT included.
*
* Side effects:
* Bit stream irreversibly parsed.
*
*--------------------------------------------------------------
*/
 
char *get_extra_bit_info(vid_stream)
VidStream *vid_stream;
{
unsigned int size, marker;
char *dataPtr;
unsigned int data;
 
/* Get first flag bit. */
get_bits1(data);
 
/* If flag is false, return NULL pointer (i.e. no extra bit info). */
 
if (!data) return NULL;
 
/* Initialize size of extra bit info buffer and allocate. */
 
size = EXT_BUF_SIZE;
dataPtr = (char *) malloc(size);
 
/* Reset marker to hold place in buffer. */
 
marker = 0;
 
/* While flag bit is true. */
 
while (data) {
 
/* Get next 8 bits of data. */
get_bits8(data);
 
/* Place in extra bit info buffer. */
 
dataPtr[marker] = (char) data;
marker++;
 
/* If buffer is full, reallocate. */
 
if (marker == size) {
size += EXT_BUF_SIZE;
dataPtr = (char *) realloc(dataPtr, size);
}
 
/* Get next flag bit. */
get_bits1(data);
}
 
/* Reallocate buffer to free extra space. */
 
dataPtr = (char *) realloc(dataPtr, marker);
 
/* Return pointer to extra bit info buffer. */
return dataPtr;
}
/shark/trunk/ports/mpeg/bugs
0,0 → 1,21
KNOWN BUGS
o IDCT sometimes doesn't generate IEEE-compliant values for sparse blocks
 
o seg faults when running more than one mpeg_play -loop with shared memory
on a multiprocessor machine w/Solaris 2.4. workaround: use -shmem_off
 
o The control panel sometimes gets confused at the end, knowing it is done
thus the "end" button, but still having a play state (and play button
highlighted), so a "rewind" instantly plays from start.
 
o -position ignores - offsets (ie -position -1-1)
 
o -position should be -geometry
 
o sometimes crashes on SPARC-10s under tvtwm, try -controls none
 
o If you compile with -DNDEBUG and some mpegs cause mpeg_play to crash, check
them out with mpeg_stat -verify
 
o The argument parsing is very shaky for more than one mpeg to play
 
/shark/trunk/ports/mpeg/util.h
0,0 → 1,393
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
Changes to make the code reentrant:
deglobalized: curBits, curVidStream
deglobalized: bitOffset, bitLength, bitBuffer in vid_stream, not used
here
Additional changes:
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* Status codes for bit stream i/o operations. */
 
#define NO_VID_STREAM (-1)
#define STREAM_UNDERFLOW (-2)
#define OK 1
 
/* Size increment of extension data buffers. */
 
#define EXT_BUF_SIZE 1024
 
/* External declarations for bitstream i/o operations. */
extern unsigned int bitMask[];
extern unsigned int nBitMask[];
extern unsigned int rBitMask[];
extern unsigned int bitTest[];
 
/* Macro for updating bit counter if analysis tool is on. */
#ifdef ANALYSIS
#define UPDATE_COUNT(numbits) bitCount += numbits
#else
#define UPDATE_COUNT(numbits)
#endif
 
#ifdef NO_SANITY_CHECKS
#define get_bits1(result) \
{ \
UPDATE_COUNT(1); \
result = ((vid_stream->curBits & 0x80000000) != 0); \
vid_stream->curBits <<= 1; \
vid_stream->bit_offset++; \
\
if (vid_stream->bit_offset & 0x20) { \
vid_stream->bit_offset = 0; \
vid_stream->buffer++; \
vid_stream->curBits = *vid_stream->buffer; \
vid_stream->buf_length--; \
} \
}
 
#define get_bits2(result) \
{ \
UPDATE_COUNT(2); \
vid_stream->bit_offset += 2; \
\
if (vid_stream->bit_offset & 0x20) { \
vid_stream->bit_offset -= 32; \
vid_stream->buffer++; \
vid_stream->buf_length--; \
if (vid_stream->bit_offset) { \
vid_stream->curBits |= \
(*vid_stream->buffer >> (2 - vid_stream->bit_offset)); \
} \
result = ((vid_stream->curBits & 0xc0000000) >> 30); \
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset; \
} \
\
result = ((vid_stream->curBits & 0xc0000000) >> 30); \
vid_stream->curBits <<= 2; \
}
 
#define get_bitsX(num, mask, shift, result) \
{ \
UPDATE_COUNT(num); \
vid_stream->bit_offset += num; \
\
if (vid_stream->bit_offset & 0x20) { \
vid_stream->bit_offset -= 32; \
vid_stream->buffer++; \
vid_stream->buf_length--; \
if (vid_stream->bit_offset) { \
vid_stream->curBits |= (*vid_stream->buffer >> \
(num - vid_stream->bit_offset)); \
} \
result = ((vid_stream->curBits & mask) >> shift); \
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset; \
} \
else { \
result = ((vid_stream->curBits & mask) >> shift); \
vid_stream->curBits <<= num; \
} \
}
#else
 
#define get_bits1(result) \
{ \
/* Check for underflow. */ \
\
if (vid_stream->buf_length < 2) { \
correct_underflow(vid_stream); \
} \
UPDATE_COUNT(1); \
result = ((vid_stream->curBits & 0x80000000) != 0); \
vid_stream->curBits <<= 1; \
vid_stream->bit_offset++; \
\
if (vid_stream->bit_offset & 0x20) { \
vid_stream->bit_offset = 0; \
vid_stream->buffer++; \
vid_stream->curBits = *vid_stream->buffer; \
vid_stream->buf_length--; \
} \
}
 
#define get_bits2(result) \
{ \
/* Check for underflow. */ \
\
if (vid_stream->buf_length < 2) { \
correct_underflow(vid_stream); \
} \
UPDATE_COUNT(2); \
vid_stream->bit_offset += 2; \
\
if (vid_stream->bit_offset & 0x20) { \
vid_stream->bit_offset -= 32; \
vid_stream->buffer++; \
vid_stream->buf_length--; \
if (vid_stream->bit_offset) { \
vid_stream->curBits |= (*vid_stream->buffer >> \
(2 - vid_stream->bit_offset)); \
} \
result = ((vid_stream->curBits & 0xc0000000) >> 30); \
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset; \
} \
\
result = ((vid_stream->curBits & 0xc0000000) >> 30); \
vid_stream->curBits <<= 2; \
}
 
#define get_bitsX(num, mask, shift, result) \
{ \
/* Check for underflow. */ \
\
if (vid_stream->buf_length < 2) { \
correct_underflow(vid_stream); \
} \
UPDATE_COUNT(num); \
vid_stream->bit_offset += num; \
\
if (vid_stream->bit_offset & 0x20) { \
vid_stream->bit_offset -= 32; \
vid_stream->buffer++; \
vid_stream->buf_length--; \
if (vid_stream->bit_offset) { \
vid_stream->curBits |= (*vid_stream->buffer >> \
(num - vid_stream->bit_offset)); \
} \
result = ((vid_stream->curBits & mask) >> shift); \
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset; \
} \
else { \
result = ((vid_stream->curBits & mask) >> shift); \
vid_stream->curBits <<= num; \
} \
}
#endif
 
#define get_bits3(result) get_bitsX(3, 0xe0000000, 29, result)
#define get_bits4(result) get_bitsX(4, 0xf0000000, 28, result)
#define get_bits5(result) get_bitsX(5, 0xf8000000, 27, result)
#define get_bits6(result) get_bitsX(6, 0xfc000000, 26, result)
#define get_bits7(result) get_bitsX(7, 0xfe000000, 25, result)
#define get_bits8(result) get_bitsX(8, 0xff000000, 24, result)
#define get_bits9(result) get_bitsX(9, 0xff800000, 23, result)
#define get_bits10(result) get_bitsX(10, 0xffc00000, 22, result)
#define get_bits11(result) get_bitsX(11, 0xffe00000, 21, result)
#define get_bits12(result) get_bitsX(12, 0xfff00000, 20, result)
#define get_bits14(result) get_bitsX(14, 0xfffc0000, 18, result)
#define get_bits16(result) get_bitsX(16, 0xffff0000, 16, result)
#define get_bits18(result) get_bitsX(18, 0xffffc000, 14, result)
#define get_bits32(result) get_bitsX(32, 0xffffffff, 0, result)
 
#define get_bitsn(num, result) get_bitsX((num), nBitMask[num], (32-(num)), result)
 
#ifdef NO_SANITY_CHECKS
#define show_bits32(result) \
{ \
if (vid_stream->bit_offset) { \
result = vid_stream->curBits | (*(vid_stream->buffer+1) >> \
(32 - vid_stream->bit_offset)); \
} \
else { \
result = vid_stream->curBits; \
} \
}
 
#define show_bitsX(num, mask, shift, result) \
{ \
int bO; \
bO = vid_stream->bit_offset + num; \
if (bO > 32) { \
bO -= 32; \
result = ((vid_stream->curBits & mask) >> shift) | \
(*(vid_stream->buffer+1) >> (shift + (num - bO))); \
} \
else { \
result = ((vid_stream->curBits & mask) >> shift); \
} \
}
 
#else
#define show_bits32(result) \
{ \
/* Check for underflow. */ \
if (vid_stream->buf_length < 2) { \
correct_underflow(vid_stream); \
} \
if (vid_stream->bit_offset) { \
result = vid_stream->curBits | (*(vid_stream->buffer+1) >> \
(32 - vid_stream->bit_offset)); \
} \
else { \
result = vid_stream->curBits; \
} \
}
 
#define show_bitsX(num, mask, shift, result) \
{ \
int bO; \
\
/* Check for underflow. */ \
if (vid_stream->buf_length < 2) { \
correct_underflow(vid_stream); \
} \
bO = vid_stream->bit_offset + num; \
if (bO > 32) { \
bO -= 32; \
result = ((vid_stream->curBits & mask) >> shift) | \
(*(vid_stream->buffer+1) >> (shift + (num - bO))); \
} \
else { \
result = ((vid_stream->curBits & mask) >> shift); \
} \
}
#endif
 
#define show_bits1(result) show_bitsX(1, 0x80000000, 31, result)
#define show_bits2(result) show_bitsX(2, 0xc0000000, 30, result)
#define show_bits3(result) show_bitsX(3, 0xe0000000, 29, result)
#define show_bits4(result) show_bitsX(4, 0xf0000000, 28, result)
#define show_bits5(result) show_bitsX(5, 0xf8000000, 27, result)
#define show_bits6(result) show_bitsX(6, 0xfc000000, 26, result)
#define show_bits7(result) show_bitsX(7, 0xfe000000, 25, result)
#define show_bits8(result) show_bitsX(8, 0xff000000, 24, result)
#define show_bits9(result) show_bitsX(9, 0xff800000, 23, result)
#define show_bits10(result) show_bitsX(10, 0xffc00000, 22, result)
#define show_bits11(result) show_bitsX(11, 0xffe00000, 21, result)
#define show_bits12(result) show_bitsX(12, 0xfff00000, 20, result)
#define show_bits13(result) show_bitsX(13, 0xfff80000, 19, result)
#define show_bits14(result) show_bitsX(14, 0xfffc0000, 18, result)
#define show_bits15(result) show_bitsX(15, 0xfffe0000, 17, result)
#define show_bits16(result) show_bitsX(16, 0xffff0000, 16, result)
#define show_bits17(result) show_bitsX(17, 0xffff8000, 15, result)
#define show_bits18(result) show_bitsX(18, 0xffffc000, 14, result)
#define show_bits19(result) show_bitsX(19, 0xffffe000, 13, result)
#define show_bits20(result) show_bitsX(20, 0xfffff000, 12, result)
#define show_bits21(result) show_bitsX(21, 0xfffff800, 11, result)
#define show_bits22(result) show_bitsX(22, 0xfffffc00, 10, result)
#define show_bits23(result) show_bitsX(23, 0xfffffe00, 9, result)
#define show_bits24(result) show_bitsX(24, 0xffffff00, 8, result)
#define show_bits25(result) show_bitsX(25, 0xffffff80, 7, result)
#define show_bits26(result) show_bitsX(26, 0xffffffc0, 6, result)
#define show_bits27(result) show_bitsX(27, 0xffffffe0, 5, result)
#define show_bits28(result) show_bitsX(28, 0xfffffff0, 4, result)
#define show_bits29(result) show_bitsX(29, 0xfffffff8, 3, result)
#define show_bits30(result) show_bitsX(30, 0xfffffffc, 2, result)
#define show_bits31(result) show_bitsX(31, 0xfffffffe, 1, result)
 
#define show_bitsn(num,result) show_bitsX((num), (0xffffffff << (32-(num))), (32-(num)), result)
 
#ifdef NO_SANITY_CHECKS
#define flush_bits32 \
{ \
UPDATE_COUNT(32); \
\
vid_stream->buffer++; \
vid_stream->buf_length--; \
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;\
}
 
 
#define flush_bits(num) \
{ \
vid_stream->bit_offset += num; \
\
UPDATE_COUNT(num); \
\
if (vid_stream->bit_offset & 0x20) { \
vid_stream->bit_offset -= 32; \
vid_stream->buffer++; \
vid_stream->buf_length--; \
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;\
} \
else { \
vid_stream->curBits <<= num; \
} \
}
#else
#define flush_bits32 \
{ \
if (vid_stream == NULL) { \
/* Deal with no vid stream here. */ \
} \
\
if (vid_stream->buf_length < 2) { \
correct_underflow(vid_stream); \
} \
\
UPDATE_COUNT(32); \
\
vid_stream->buffer++; \
vid_stream->buf_length--; \
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;\
}
 
#define flush_bits(num) \
{ \
if (vid_stream== NULL) { \
/* Deal with no vid stream here. */ \
} \
\
if (vid_stream->buf_length < 2) { \
correct_underflow(vid_stream); \
} \
\
UPDATE_COUNT(num); \
\
vid_stream->bit_offset += num; \
\
if (vid_stream->bit_offset & 0x20) { \
vid_stream->buf_length--; \
vid_stream->bit_offset -= 32; \
vid_stream->buffer++; \
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;\
} \
else { \
vid_stream->curBits <<= num; \
} \
}
#endif
 
#define UTIL2
/shark/trunk/ports/mpeg/readfile.ori
0,0 → 1,1065
/*
* readfile.c --
*
* Procedures concerned with reading data and parsing
* start codes from MPEG files.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "proto.h"
#include <sys/types.h>
/*#include <signal.h> TO FIX!!! */
#ifndef MIPS
#include <netinet/in.h>
#else
#include <bsd/netinet/in.h>
#endif
 
#include "util.h"
#include "dither.h"
 
#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
#endif
 
/*
Changes to make the code reentrant:
deglobalized: totNumFrames, realTimeStart, stream id vars, Prase_done,
swap, seekValue, input, EOF_flag, ReadPacket statics, sys_layer,
bitOffset, bitLength, bitBuffer, curVidStream
removed: [aud,sys,vid]Bytes
Additional changes:
get rid on ANSI C complaints about shifting
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* Silly Constants.... */
#define PACK_START_CODE ((unsigned int)0x000001ba)
#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)
#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00)
#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100)
#define ISO_11172_END_CODE ((unsigned int)0x000001b9)
#define PACK_HEADER_SIZE 8
#define STD_AUDIO_STREAM_ID ((unsigned char) 0xb8)
#define STD_VIDEO_STREAM_ID ((unsigned char) 0xb9)
#define MIN_STREAM_ID_ID ((unsigned char) 0xbc)
#define RESERVED_STREAM_ID ((unsigned char) 0xbc)
#define PRIVATE_STREAM_1_ID ((unsigned char) 0xbd)
#define PADDING_STREAM_ID ((unsigned char) 0xbe)
#define PRIVATE_STREAM_2_ID ((unsigned char) 0xbf)
#define STD_SYSTEM_CLOCK_FREQ (unsigned long)90000
#define MUX_RATE_SCALE_FACTOR 50
#define MAX_STREAMS 8
#define NOT_PACKET_ID ((unsigned char) 0xff)
#define KILL_BUFFER ((unsigned char) 0xfe)
/*
*--------------------------------------------------------------
*
* get_more_data --
*
* Called by get_more_data to read in more data from
* video MPG files (non-system-layer)
*
* Results:
* Input buffer updated, buffer length updated.
* Returns 1 if data read, 0 if EOF, -1 if error.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
int
get_more_data(vid_stream)
VidStream *vid_stream;
{
unsigned int **bs_ptr=&vid_stream->buf_start;
int *max_length=&vid_stream->max_buf_length;
int *length_ptr=&vid_stream->buf_length;
unsigned int **buf_ptr=&vid_stream->buffer;
int ioBytes, data, result;
unsigned char byte;
unsigned int *mark;
int sys_layer= vid_stream->sys_layer;
if (sys_layer == 0) {
return pure_get_more_data(*bs_ptr,
*max_length,
length_ptr,
buf_ptr,
vid_stream);
}
 
if (sys_layer == -1) {
/* Time to init ourselves */
vid_stream->swap = (htonl(1) != 1);
mark = *bs_ptr;
ioBytes = fread(&data, 1, 4, vid_stream->input);
 
if (ioBytes != 4) {
return 0;
}
 
data = ntohl(data);
if ( (data == PACK_START_CODE) || (data == SYSTEM_HEADER_START_CODE) ) {
got_sys:
/* Yow, a System Layer Stream. Much harder to parse. Call in the
specialist.... */
fprintf(stderr,"This is an MPEG System Layer Stream. ");
fprintf(stderr,"Audio is not played.\n");
vid_stream->sys_layer = 1;
result = read_sys(vid_stream,(unsigned int) data);
return result;
} else if (data == SEQ_START_CODE) {
got_seq:
/* No system Layer junk, just pretent we didn't peek,
and hereafter just call pure_get_more_data */
vid_stream->sys_layer = 0;
**bs_ptr = data;
*length_ptr = 1;
result = pure_get_more_data(*bs_ptr, *max_length,
length_ptr, buf_ptr, vid_stream);
*buf_ptr = *bs_ptr;
return result;
} else {
int state;
 
fprintf(stderr, "Junk at start of stream, searching for start code\n");
state = 0;
while (TRUE) {
if ((ioBytes = fread(&byte, 1, 1, vid_stream->input)) != 1) return 0;
if (byte == 0) {
if (state < 2) state++;
} else if ((byte == 1) && (state == 2)) {
state++;
} else {
state = 0;
}
if (state == 3) {
if ((ioBytes = fread(&byte, 1, 1, vid_stream->input)) != 1) return 0;
data = ((unsigned int) byte + 0x100);
switch (data) {
case SEQ_START_CODE:
goto got_seq;
case PACK_START_CODE:
case SYSTEM_HEADER_START_CODE:
goto got_sys;
default:
/* keep looking */
state=0;
}
}
}}
}
 
/* A system layer stream (called after the 1st time), call the specialist */
result = read_sys(vid_stream,0);
return result;
}
 
/*
*-------------------------------------------------------------
*
* clear_data_stream
*
* Empties out internal buffers
*
*-------------------------------------------------------------
*/
void
clear_data_stream(vid_stream)
VidStream *vid_stream;
{
/* Only internal buffer is in ReadPacket */
if (vid_stream->sys_layer) {
ReadPacket(KILL_BUFFER, vid_stream);
}
}
 
/*
*-------------------------------------------------------------
*
* SeekStream
*
* Goto an offset in the steam
*
*-------------------------------------------------------------
*/
void
SeekStream(vid_stream)
VidStream *vid_stream;
{
int errno;
int code;
if (vid_stream->seekValue < 0) return; /* done seeking */
#ifdef SEEK_SET
errno = fseek(vid_stream->input, vid_stream->seekValue, SEEK_SET);
#else
errno = fseek(vid_stream->input, vid_stream->seekValue, 0);
#endif
if (errno != 0) {
fprintf(stderr,"Error in seek (%d)\n",errno);
perror("mpeg_play");
}
vid_stream->seekValue = 0-vid_stream->seekValue;
vid_stream->totNumFrames = 0;
 
/* clear that buffer */
vid_stream->buffer = vid_stream->buf_start;
vid_stream->buf_length = 0;
vid_stream->bit_offset = 0;
 
/* Find a decent start code */
restart:
NO_ZEROS:
switch(fgetc(vid_stream->input)) {
case 0: goto ONE_ZERO;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
ONE_ZERO:
switch(fgetc(vid_stream->input)) {
case 0: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
TWO_ZEROS:
switch(fgetc(vid_stream->input)) {
case 0x01: goto CODE_FOUND;
case 0x00: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
CODE_FOUND:
code = 0x00000100+fgetc(vid_stream->input);
if (vid_stream->sys_layer) {
clear_data_stream(vid_stream);
if (((code & PACKET_START_CODE_MASK) == PACKET_START_CODE_PREFIX) &&
((code & 0xff) >= 0xbc)) {
read_sys(vid_stream, code);
while (TRUE) {
next_start_code(vid_stream);
show_bits32(code);
if ((code == SEQ_START_CODE) ||
(code == GOP_START_CODE)) return;
flush_bits32;
}
}
} else {
if ((code == SEQ_START_CODE) ||
(code == GOP_START_CODE)) {
*vid_stream->buffer = code;
vid_stream->buf_length = 1;
return;
}
}
goto restart;
 
EOF_FOUND: /* received EOF */
fprintf(stderr, "Hit EOF after seeking (offset %ld)\n",
ftell(vid_stream->input));
exit(1);
 
}
 
 
/*
*--------------------------------------------------------------
*
* pure_get_more_data --
* (get_more_data from ver 2.0 with swap added)
*
* Called by get_more_data to read in more data from
* video MPG files (non-system-layer)
*
* Results:
* Input buffer updated, buffer length updated.
* Returns 1 if data read, 0 if EOF, -1 if error.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
int
pure_get_more_data(buf_start, max_length, length_ptr, buf_ptr, vid_stream)
unsigned int *buf_start;
int max_length;
int *length_ptr;
unsigned int **buf_ptr;
VidStream *vid_stream;
{
int length, num_read, i;
unsigned int request;
unsigned char *buffer, *mark;
unsigned int *lmark;
BOOLEAN swap=vid_stream->swap;
if (vid_stream->EOF_flag) return 0;
length = *length_ptr;
buffer = (unsigned char *) *buf_ptr;
if (length > 0) {
memcpy((unsigned char *) buf_start, buffer, (unsigned int) (length*4));
mark = ((unsigned char *) (buf_start + length));
}
else {
mark = (unsigned char *) buf_start;
length = 0;
}
request = (max_length-length)*4;
num_read = fread(mark, 1, request, vid_stream->input);
/* Paulo Villegas - 26/1/1993: Correction for 4-byte alignment */
{
int num_read_rounded;
unsigned char *index;
num_read_rounded = 4*(num_read/4);
/* this can happen only if num_read<request; i.e. end of file reached */
if ( num_read_rounded < num_read ) {
num_read_rounded = 4*( num_read/4+1 );
 
/* fill in with zeros */
for( index=mark+num_read; index<mark+num_read_rounded; *(index++)=0 );
 
/* advance to the next 4-byte boundary */
num_read = num_read_rounded;
}
}
if (num_read < 0) {
return -1;
} else if (num_read == 0) {
*buf_ptr = buf_start;
/* Make 32 bits after end equal to 0 and 32
* bits after that equal to seq end code
* in order to prevent messy data from infinite
* recursion.
*/
*(buf_start + length) = 0x0;
*(buf_start + length+1) = SEQ_END_CODE;
vid_stream->EOF_flag = 1;
return 0;
}
lmark = (unsigned int *) mark;
num_read = num_read/4;
if (swap) {
for (i = 0; i < num_read; i++) {
*lmark = htonl(*lmark);
lmark++;
}
}
*buf_ptr = buf_start;
*length_ptr = length + num_read;
return 1;
}
 
 
 
 
/*
Here is the specialist....
Code is adapted from our program demux....
A bunch of this needs to be #ifdef ANALYSIS'ed
define __SYSREAD_LOGGING_ON__ to get an output file for debugging
*/
 
/* Brown - removed StreamID global variables */
#ifdef ANALYSIS
/* Statistics */
static int gNumAudioPackets;
static int gNumVideoPackets;
static int gNumPaddingPackets;
static int gNumReservedPackets;
static int gNumPrivate_1_Packets;
static int gNumPrivate_2_Packets;
#endif
 
/*
*----------------------------------------------------------
*
* read_sys
*
* Parse out a packet of the system layer MPEG file.
*
* Results: Returns 0 if error or EOF
* Returns 1 if more data read (could be just one int)
*
* Side Effects: ReadPacket can change *bs_ptr to be a new buffer
* buf_ptr will remain pointing at *length_ptr (at input)
* into the buffer
* *length_ptr will be changed to the new size
* *max_length can be changed if a new buffer is alloc'd
*
*----------------------------------------------------------
*/
int read_sys(vid_stream, start)
VidStream *vid_stream;
unsigned int start;
/* start is either a start code or 0 to indicate continued parsing */
{
unsigned int **bs_ptr=&vid_stream->buf_start;
int *max_length = &vid_stream->max_buf_length;
int *length_ptr=&vid_stream->buf_length;
unsigned int **buf_ptr=&vid_stream->buffer;
unsigned int startCode;
int errorCode, PacketReply;
unsigned char packetID;
double systemClockTime;
unsigned long muxRate;
/* Statistics */
#ifdef ANALYSIS
static int numPacks = 0;
static int numPackets = 0;
static int numSystemHeaders = 0;
#endif
BOOLEAN match;
if (!start) {
errorCode = ReadStartCode(&startCode,vid_stream);
if (vid_stream->EOF_flag) return 0;
if (errorCode != 0) {
fprintf(stderr, "Unable to read initial pack start code\n");
return 0;
}}
else {
errorCode = 0;
startCode = start;
}
while (1) {
match=FALSE;
if (startCode == PACK_START_CODE) {
#ifdef ANALYSIS
++numPacks;
#endif
match = TRUE;
errorCode = ReadPackHeader( &systemClockTime, &muxRate, vid_stream);
if (errorCode != 0) {
fprintf(stderr, "Error in reading pack header\n");
return 0;
}
errorCode = ReadStartCode( &startCode, vid_stream );
if (errorCode != 0) {
fprintf(stderr, "Error in reading start code\n");
return 0;
}
}
if (startCode == SYSTEM_HEADER_START_CODE) {
#ifdef ANALYSIS
++numSystemHeaders;
#endif
match = TRUE;
errorCode = ReadSystemHeader(vid_stream);
if (errorCode != 0) {
fprintf(stderr, "Error in reading system header\n");
return 0;
}
errorCode = ReadStartCode( &startCode, vid_stream );
if (errorCode != 0) {
fprintf(stderr,"Error in reading start code after system header\n");
return 0;
}
}
packetID = startCode & 0xff;
while (((startCode & PACKET_START_CODE_MASK) == PACKET_START_CODE_PREFIX) &&
(packetID >= 0xbc)) {
#ifdef ANALYSIS
++numPackets;
#endif
match = TRUE;
packetID = startCode & 0xff;
PacketReply = ReadPacket(packetID, vid_stream);
switch (PacketReply) {
case 2:
return 1;
case 1:
return 0;
default: /* do nothing */
break;
}
errorCode = ReadStartCode( &startCode, vid_stream );
if (errorCode != 0) {
fprintf(stderr,"Error in start code after packet\n");
return 0;
}
if (startCode == PACK_START_CODE || startCode == ISO_11172_END_CODE) {
break;
}
}
if (startCode == ISO_11172_END_CODE) {
match = TRUE;
if (vid_stream->Parse_done) {
return 1;
}
#ifdef ANALYSIS
fprintf(stderr, "Successful parse of MPEG system level\n");
fprintf(stderr, "%d system headers, %d packs, %d packets\n",
numSystemHeaders, numPacks, numPackets);
fprintf(stderr, "%d audio packets, %d video packets, %d padding packets\n",
gNumAudioPackets, gNumVideoPackets, gNumPaddingPackets);
fprintf(stderr, "%d reserved packets, %d/%d private type 1/2 packets\n",
gNumReservedPackets, gNumPrivate_1_Packets, gNumPrivate_2_Packets);
#endif
ReadPacket(NOT_PACKET_ID, vid_stream);
vid_stream->Parse_done = TRUE;
return 1;
}
if (errorCode != 0)
return 1;
if (! match) {
fprintf(stderr,"\nNo match found for start code %08x in system layer, skipping\n",startCode);
startCode = find_start_code(vid_stream->input);
if (startCode == EOF) {
vid_stream->EOF_flag = 1;
return 0;
}
}
}
}
 
/*
*-----------------------------------------------------------
*
* ReadStartCode
*
* Parses a start code out of the stream
*
* Results/Side Effects: Sets *startCode to the code, returns
* 1 on error, 0 on success
*
*-----------------------------------------------------------
*/
int ReadStartCode(startCode, vid_stream)
unsigned int *startCode;
VidStream *vid_stream;
{
int numRead;
numRead = fread((unsigned char *)startCode, 1, 4, vid_stream->input);
*startCode = htonl(*startCode);
if (numRead < 4) {
vid_stream->EOF_flag = 1;
return 1;
}
 
if ((*startCode&0xfffffe00) != 0) {
fprintf(stderr,"Problem with system layer parse, skipping to start code\n");
*startCode = find_start_code(vid_stream->input);
if (*startCode == EOF) {
vid_stream->EOF_flag = TRUE;
return 0;
}
}
 
return 0;
}
 
/*
*-----------------------------------------------------------
*
* find_start_code
*
* Parses a start code out of the stream by tossing bytes until it gets one
*
* Results/Side Effects: Parses bytes of the stream, returns code
* Returns EOF in case of end of file
*
*-----------------------------------------------------------
*/
int find_start_code(input)
FILE *input;
{
NO_ZEROS:
switch(fgetc(input)) {
case 0: goto ONE_ZERO;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
 
ONE_ZERO:
switch(fgetc(input)) {
case 0: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
 
TWO_ZEROS:
switch(fgetc(input)) {
case 0x01: goto CODE_FOUND;
case 0x00: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
 
CODE_FOUND:
return 0x00000100+fgetc(input);
 
EOF_FOUND: /* received EOF */
return EOF;
}
 
 
 
/*
*-----------------------------------------------------------------
*
* ReadPackHeader
*
* Parses out the PACK header
*
* Returns: 1 on error, 0 on success
*
*-------------------------------------------------------------------
*/
int ReadPackHeader(systemClockTime,muxRate, vid_stream)
double *systemClockTime;
unsigned long *muxRate;
VidStream *vid_stream;
{
int numRead;
unsigned char inputBuffer[PACK_HEADER_SIZE];
unsigned long systemClockRef;
unsigned char systemClockRefHiBit;
int errorCode;
numRead = fread(inputBuffer, 1, PACK_HEADER_SIZE, vid_stream->input);
if (numRead < PACK_HEADER_SIZE) {
vid_stream->EOF_flag = 1;
return 1;
}
ReadTimeStamp(inputBuffer, &systemClockRefHiBit, &systemClockRef);
errorCode = MakeFloatClockTime(systemClockRefHiBit, systemClockRef,
systemClockTime);
ReadRate(&inputBuffer[5], muxRate);
*muxRate *= MUX_RATE_SCALE_FACTOR;
return 0;
}
 
/*
*------------------------------------------------------------------
*
* ReadSystemHeader
*
* Parse out the system header, setup out stream IDs for parsing packets
*
* Results: Returns 1 on error, 0 on success.
* Sets gAudioStreamID and gVideoStreamID
*
*------------------------------------------------------------------
*/
int ReadSystemHeader(vid_stream)
VidStream *vid_stream;
{
unsigned char *inputBuffer = NULL;
int numRead;
int pos;
unsigned short headerSize;
unsigned char streamID;
numRead = fread((char *)&headerSize, 1, 2, vid_stream->input);
headerSize = ntohs(headerSize);
if (numRead != 2) {
vid_stream->EOF_flag = 1;
return 1;
}
inputBuffer = (unsigned char *) malloc((unsigned int) headerSize+1);
if (inputBuffer == NULL) {
return 1;
}
inputBuffer[headerSize]=0;
numRead = fread(inputBuffer, 1, headerSize, vid_stream->input);
/* Brown - get rid of Ansi C complaints */
if (numRead < (int) headerSize) {
vid_stream->EOF_flag = 1;
return 1;
}
pos = 6;
while ((inputBuffer[pos] & 0x80) == 0x80) {
streamID = inputBuffer[pos];
switch (streamID) {
case STD_VIDEO_STREAM_ID:
break;
case STD_AUDIO_STREAM_ID:
break;
case RESERVED_STREAM_ID:
break;
case PADDING_STREAM_ID:
break;
case PRIVATE_STREAM_1_ID:
break;
case PRIVATE_STREAM_2_ID:
break;
default:
if (streamID < MIN_STREAM_ID_ID) {
return 1;
}
switch (streamID >> 4) {
case 0xc:
case 0xd:
vid_stream->gAudioStreamID = streamID;
break;
case 0xe:
if ((vid_stream->gVideoStreamID != 0) &&
(vid_stream->gVideoStreamID!=streamID)) {
break;
}
vid_stream->gVideoStreamID = streamID;
break;
case 0xf:
/*Brown - deglobalized gReservedStreamID */
vid_stream->gReservedStreamID = streamID;
break;
}
break;
}
pos += 3;
}
if (inputBuffer != NULL)
free(inputBuffer);
return 0;
}
 
/*
*-----------------------------------------------------------------
*
* ReadPacket
*
* Reads a single packet out of the stream, and puts it in the
* buffer if it is video.
*
* Results:
* Changes the value of *length_ptr to be the new length (plus old)
* If the buffer is too small, can change *bs_ptr, *max_length, and
* buf_ptr to be correct for a newly allocated buffer.
*
* State:
* The buffer is in ints, but the packets can be an arbitrary number
* of bytes, so leftover bytes are kept in the VidStream variable and
* are added on the next call.
*
*-----------------------------------------------------------------
*/
#ifdef __STDC__
int ReadPacket(unsigned char packetID, VidStream *vid_stream)
#else
int ReadPacket(packetID, vid_stream)
unsigned char packetID;
VidStream *vid_stream;
#endif
 
/* Returns:
0 - no error, but not video packet we want
1 - error
2 - got video packet into buffer
*/
{
unsigned int **bs_ptr=&vid_stream->buf_start;
int *max_length = &vid_stream->max_buf_length;
int *length_ptr=&vid_stream->buf_length;
unsigned int **buf_ptr=&vid_stream->buffer;
int ioBytes;
unsigned char nextByte;
unsigned short packetLength;
unsigned char *packetBuffer = NULL;
int pos;
int numStuffBytes = 0;
unsigned int packetDataLength;
int byte_length;
unsigned char scratch[10];
/* Leftovers from previous video packets */
if (packetID == NOT_PACKET_ID) {
/* Gross hack to handle unread bytes before end of stream */
if (vid_stream->num_left != 0) {
/* Sigh, deal with previous leftovers */
*(*buf_ptr+*length_ptr) = vid_stream->leftover_bytes;
*(*buf_ptr+*length_ptr+1) = ISO_11172_END_CODE;
*length_ptr += 2;
} else {
*(*buf_ptr+*length_ptr) = ISO_11172_END_CODE;
*length_ptr += 1;
}
return 1;
} else if (packetID==KILL_BUFFER) {
vid_stream->num_left=0;
vid_stream->leftover_bytes=0;
return 0;
}
ioBytes = fread(&packetLength, 1, 2, vid_stream->input);
packetLength = htons(packetLength);
if (ioBytes < 2) {
return 1;
}
if (packetID == vid_stream->gAudioStreamID) {
#ifdef ANALYSIS
++gNumAudioPackets;
#endif
}
else if (packetID == vid_stream->gVideoStreamID) {
#ifdef ANALYSIS
++gNumVideoPackets;
#endif
}
else {
switch (packetID) {
case PADDING_STREAM_ID:
#ifdef ANALYSIS
++gNumPaddingPackets;
#endif
break;
case RESERVED_STREAM_ID:
#ifdef ANALYSIS
++gNumReservedPackets;
#endif
break;
case PRIVATE_STREAM_1_ID:
#ifdef ANALYSIS
++gNumPrivate_1_Packets;
#endif
break;
case PRIVATE_STREAM_2_ID:
#ifdef ANALYSIS
++gNumPrivate_2_Packets;
#endif
break;
default:
fprintf(stderr, "\nUnknown packet type encountered. P'bly audio? (%x) at %d\n",
packetID,(int) ftell(vid_stream->input));
}
if (packetID != vid_stream->gVideoStreamID) {/* changed by jim */
fseek(vid_stream->input, packetLength, 1);
return 0;
}
}
 
fread(&nextByte,1,1,vid_stream->input);
pos = 0;
while (nextByte & 0x80) {
++numStuffBytes;
++pos;
fread(&nextByte,1,1,vid_stream->input);
}
if ((nextByte >> 6) == 0x01) {
pos += 2;
fread(&nextByte,1,1,vid_stream->input);
fread(&nextByte,1,1,vid_stream->input);
}
if ((nextByte >> 4) == 0x02) {
scratch[0] = nextByte; /* jim */
fread(&scratch[1],1,4,vid_stream->input); /* jim */
fread(&nextByte,1,1,vid_stream->input);
pos += 5;
}
else if ((nextByte >> 4) == 0x03) {
scratch[0] = nextByte; /* jim */
fread(&scratch[1],1,9,vid_stream->input); /* jim */
fread(&nextByte,1,1,vid_stream->input);
pos += 10;
}
else {
fread(&nextByte,1,1,vid_stream->input);
pos += 1;
}
/* Read all the headers, now make room for packet */
if (*bs_ptr + *max_length < *buf_ptr+ packetLength/4 + *length_ptr) {
/* Brown - get rid of Ansi C complaints */
if (*max_length - *length_ptr < (int) packetLength/4) {
/* Buffer too small for a packet (plus whats there),
* time to enlarge it!
*/
unsigned int *old = *bs_ptr;
*max_length = *length_ptr + packetLength/2;
*bs_ptr=(unsigned int *)malloc(*max_length*4);
if (*bs_ptr == NULL) {
return 1;
}
memcpy((unsigned char *)*bs_ptr, *buf_ptr, (unsigned int) *length_ptr*4);
free(old);
*buf_ptr = *bs_ptr;
} else {
memcpy((unsigned char *)*bs_ptr, *buf_ptr, (unsigned int) *length_ptr*4);
*buf_ptr = *bs_ptr;
}}
byte_length = *length_ptr*4;
if (vid_stream->num_left != 0) {
/* Sigh, deal with previous leftovers */
byte_length += vid_stream->num_left;
*(*buf_ptr+*length_ptr) = vid_stream->leftover_bytes;
}
packetBuffer=((unsigned char *)*buf_ptr)+byte_length;
packetDataLength = packetLength - pos;
*packetBuffer++ = nextByte;
/* Brown - deglobalize gVideoStreamID */
if (packetID == vid_stream->gVideoStreamID) {
ioBytes = fread(packetBuffer, 1, packetDataLength-1, vid_stream->input);
if (ioBytes != packetDataLength-1) {
vid_stream->EOF_flag = 1;
return 1;
}
if (1 != ntohl(1)) {
unsigned int *mark = *buf_ptr+*length_ptr;
int i;
for (i=0; i < ((packetDataLength+
vid_stream->num_left)&0xfffffffc); i+=4) {
*mark=ntohl(*mark);
mark++;
}
}
byte_length = byte_length + packetDataLength;
vid_stream->num_left = byte_length % 4;
*length_ptr = byte_length / 4;
vid_stream->leftover_bytes = *(*buf_ptr + *length_ptr);
return 2;
}
else if (packetID == vid_stream->gAudioStreamID) {
packetBuffer = (unsigned char *)(*buf_ptr + *length_ptr + 1);
fread(packetBuffer, 1, packetDataLength - 1, vid_stream->input);
}
else /* Donno what it is, just nuke it */ {
/* This code should be unreachable */
packetBuffer = (unsigned char *)(*buf_ptr + *length_ptr + 1);
fread(packetBuffer, 1, packetDataLength - 1, vid_stream->input);
}
return 0;
}
 
 
/*
* The remaining procedures are formatting utility procedures.
*/
void ReadTimeStamp(inputBuffer,hiBit,low4Bytes)
unsigned char *inputBuffer, *hiBit;
unsigned long *low4Bytes;
{
*hiBit = ((unsigned long)inputBuffer[0] >> 3) & 0x01;
*low4Bytes = (((unsigned long)inputBuffer[0] >> 1) & 0x03) << 30;
*low4Bytes |= (unsigned long)inputBuffer[1] << 22;
*low4Bytes |= ((unsigned long)inputBuffer[2] >> 1) << 15;
*low4Bytes |= (unsigned long)inputBuffer[3] << 7;
*low4Bytes |= ((unsigned long)inputBuffer[4]) >> 1;
}
 
void ReadSTD(inputBuffer,stdBufferScale,stdBufferSize)
unsigned char *inputBuffer;
unsigned char *stdBufferScale;
unsigned long *stdBufferSize;
{
/* Brown - get rid of ANSI C complaints */
*stdBufferScale = ((int)(inputBuffer[0] & 0x20) >> 5);
*stdBufferSize = ((unsigned long)inputBuffer[0] & 0x1f) << 8;
*stdBufferSize |= (unsigned long)inputBuffer[1];
}
 
 
void ReadRate(inputBuffer,rate)
unsigned char *inputBuffer;
unsigned long *rate;
{
*rate = (inputBuffer[0] & 0x7f) << 15;
*rate |= inputBuffer[1] << 7;
/* Brown - get rid of ANSI C complaints */
*rate |= (int) (inputBuffer[2] & 0xfe) >> 1;
}
 
#define FLOAT_0x10000 (double)((unsigned long)1 << 16)
 
#ifdef __STDC__
int MakeFloatClockTime(unsigned char hiBit, unsigned long low4Bytes,
double * floatClockTime)
#else
int MakeFloatClockTime(hiBit,low4Bytes,floatClockTime)
unsigned char hiBit;
unsigned long low4Bytes;
double *floatClockTime;
#endif
{
if (hiBit != 0 && hiBit != 1) {
*floatClockTime = 0.0;
return 1;
}
*floatClockTime
= (double)hiBit*FLOAT_0x10000*FLOAT_0x10000 + (double)low4Bytes;
*floatClockTime /= (double)STD_SYSTEM_CLOCK_FREQ;
return 0;
}
/shark/trunk/ports/mpeg/util32.c
0,0 → 1,173
/*
* util32.c --
*
* Miscellaneous functions that deal with 32 bit color displays.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "video.h"
#include "proto.h"
 
/*
Changes to make the code reentrant:
deglobalized: matched_depth
use X variables in xinfo instead of globals
Additional changes:
#ifdef DISABLE_DITHER - don't compile dither code
fix parameter types for XCreateWindow call
-lsh@cs.brown.edu (Loring Holden)
*/
 
/*
*--------------------------------------------------------------
*
* FindFullColorVisual
*
* Returns a pointer to a full color bit visual on the display
*
* Results:
* See above.
*
* Side effects:
* Unknown.
*
*--------------------------------------------------------------
*/
Visual *
FindFullColorVisual (dpy, depth)
Display *dpy;
int *depth;
{
XVisualInfo vinfo;
XVisualInfo *vinfo_ret;
int numitems, maxdepth;
vinfo.class = TrueColor;
vinfo_ret = XGetVisualInfo(dpy, VisualClassMask, &vinfo, &numitems);
if (numitems == 0) return NULL;
 
maxdepth = 0;
while(numitems > 0) {
if (vinfo_ret[numitems-1].depth > maxdepth) {
maxdepth = vinfo_ret[numitems-1 ].depth;
}
numitems--;
}
XFree((void *) vinfo_ret);
 
if (maxdepth < 16) return NULL;
 
if (XMatchVisualInfo(dpy, DefaultScreen(dpy), maxdepth,
TrueColor, &vinfo)) {
*depth = maxdepth;
return vinfo.visual;
}
return NULL;
}
 
/*
*--------------------------------------------------------------
*
* CreateFullColorWindow
*
* Creates a window capable of handling 32 bit color.
*
* Results:
* See above.
*
* Side effects:
* Unknown.
*
*--------------------------------------------------------------
*/
void
CreateFullColorWindow (xinfo)
XInfo *xinfo;
{
int depth;
Visual *visual;
XSetWindowAttributes xswa;
unsigned long mask;
unsigned int class;
int screen;
Display *dpy=xinfo->display;
int x = xinfo->hints.x,
y = xinfo->hints.y;
unsigned int w = xinfo->hints.width,
h = xinfo->hints.height;
 
screen = XDefaultScreen(dpy);
class = InputOutput; /* Could be InputOnly */
if (xinfo->visual == NULL) {
xinfo->visual = visual = FindFullColorVisual (dpy, &depth);
xinfo->depth = depth;
} else {
visual=xinfo->visual;
depth=xinfo->depth;
}
 
if (visual == NULL) {
return;
}
mask = CWBackPixel | CWColormap | CWBorderPixel;
if (xinfo->cmap==0) {
xswa.colormap = XCreateColormap(dpy,
XRootWindow(dpy, screen),
visual, AllocNone);
} else xswa.colormap = xinfo->cmap;
xswa.background_pixel = BlackPixel(dpy, DefaultScreen(dpy));
xswa.border_pixel = WhitePixel(dpy, DefaultScreen(dpy));
 
xinfo->window = XCreateWindow(dpy, RootWindow(dpy, screen), x, y, w, h,
(unsigned int) 1, depth, class, visual, mask, &xswa);
}
/shark/trunk/ports/mpeg/netinet/in.h
0,0 → 1,2
 
#include <endian.h>
/shark/trunk/ports/mpeg/thread_m.h
0,0 → 1,156
/*
* Copyright 1995, Brown University, Providence, RI
*
* Permission to use and modify this software and its documentation for
* any purpose other than its incorporation into a commercial product is
* hereby granted without fee. Permission to copy and distribute this
* software and its documentation only for non-commercial use is also
* granted without fee, provided, however, that the above copyright notice
* appear in all copies, that both that copyright notice and this permission
* notice appear in supporting documentation, that the name of Brown
* University not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission,
* and that the person doing the distribution notify Brown University of
* such distributions outside of his or her organization. Brown University
* makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
* Brown University requests notification of any modifications to this
* software or its documentation.
*
* Send the following redistribution information:
*
* Name:
* Organization:
* Address (postal and/or electronic):
*
* To:
* Software Librarian
* Computer Science Department, Box 1910
* Brown University
* Providence, RI 02912
*
* or
*
* brusd@cs.brown.edu
*
* We will acknowledge all electronic notifications.
*/
 
/* -------------------------------------------------------------------------
Public THREAD include file
------------------------------------------------------------------------- */
 
// Original code by Tom Meyer
// Altered by Loring Holden to work with MPEGmovie object
 
/* $Id: thread_m.h,v 1.1.1.1 2002-03-29 14:12:59 pj Exp $ */
 
#ifndef THREAD_MP_HAS_BEEN_INCLUDED
#define THREAD_MP_HAS_BEEN_INCLUDED
 
#if defined(sol)
 
#ifdef CPLPLTHREADS
#include "/pro/threadtools/C++_mon/include/c++thread.h"
#else
#include <unistd.h>
#include <thread.h>
#endif
#include <string.h>
 
#elif defined(hp)
// No multithreading on the HPs
#elif defined(sgi)
#include <stdio.h>
#include <ulocks.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/prctl.h>
#endif
#include "queue_int.H"
 
#if defined(sgi)
void THREADprocessor_startup_func(void *proc);
#endif
#if defined(sol)
#ifndef CPLPLTHREADS
void *THREADprocessor_startup_func(void *proc);
#endif
#endif
 
#if defined(sol)
#if CPLPLTHREADS
class THREAD_processor : public Thread {
#else
class THREAD_processor {
#endif
#else
class THREAD_processor {
#endif
private:
void *(*_start_routine)(void *, void *);
void *_arg, *_arg2;
protected:
#if defined(sol)
#if CPLPLTHREADS
Semaphore *sema,*semaDone;
#else
thread_t thr;
sema_t sema,semaDone;
#endif
#elif defined(sgi)
pid_t pid;
usema_t *_sema,*semaDone;
#else
#endif
public:
void startup();
#if defined(sol)
#ifndef CPLPLTHREADS
virtual void startup_func();
THREAD_processor();
#endif
#endif
THREAD_processor(char *name = "", char *thrname = "");
virtual ~THREAD_processor() {}
 
virtual void start_execute(void *(*start_routine)(void *, void *),
void *arg, void *arg2);
virtual int wait_for_done();
virtual int still_running();
int running;
};
 
class THREAD_mp_manager {
protected:
int num_procs() const;
THREAD_mp_manager(int _procs = 0);
};
 
 
class THREADprocessor : public THREAD_processor {
protected:
public:
THREADprocessor(char *name = "", char *thrname = "")
: THREAD_processor(name, thrname) {};
virtual ~THREADprocessor() {}
};
 
class THREADmp_manager : public THREAD_mp_manager {
THREADprocessor **procs;
int _num_procs;
void THREADmp_initproc(int i);
static int procNum; // just for test
QUEUEint queue;
public:
THREADmp_manager(int _procs = 0);
virtual ~THREADmp_manager();
void enqThread(int threadNumber);
int deqThread();
int num_processes() const { return _num_procs; }
THREADprocessor *processor(int i) const { return procs[i]; }
void THREADmp_newproc();
};
 
#endif
/shark/trunk/ports/mpeg/ctrlbar.c
0,0 → 1,1295
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 
contributed by (but no rights held by):
 
Michael J. Donahue
National Institute of Standards and Technology
Gaithersburg MD USA
donahue@ulexite.nist.gov
 
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
Changes to make the code reentrant:
If using ANSI C, do prototyping for static functions
display not a global, must be passed to functions
display window now not a global, must be passed to functions via xinfo
struct
FILMState removed - now uses vid_stream->film_has_ended instead
use totNumFrames from vid_stream, not global
must pass vid_stream (EOF_flag, seekValue, etc. no longer global)
CONTROLS version now can deal with >1 movie
Additional changes:
Do prototyping for static functions
- lsh@cs.brown.edu (Loring Holden)
*/
 
#ifndef NOCONTROLS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dither.h"
#include "video.h"
#include "ctrlbar.h"
#include "proto.h"
 
#ifndef MIPS
#include <sys/time.h>
#else
#include <sys/types.h>
#include <sys/system.h>
#endif
 
/* Default is to play asap. If you want it to start paused, change to
CTRL_PAUSE
*/
#define INITIAL_STATE CTRL_PLAY
 
/* Global variable definitions */
int ControlShow = CTRLBAR_ON; /* ON => Show (display) control bar */
int ControlState = CTRL_UNDEFINED; /* Current control state */
int ControlMotion = CTRLMOTION_OFF; /* Pause mode */
long TotalFrameCount= 0; /* Total number of frames processed, including loops */
 
/* File statics */
static int CtrlBarWidth;
static int CtrlBarHeight = 31;
static int CtrlBarBorder = 4;
static int ChildBorder = 2;
static int ChildMargin = 6;
 
static Window ctrlwindow = 0;
static int screen = -1;
static XFontStruct* ctrlfont = NULL;
static int fontheight, fontwidth;
static unsigned long fgcolor, bgcolor;
 
static int ctrl_init = 0; /* 1 => Control windows have been initialized */
 
/* Support for WM_DELETE_WINDOW */
static Atom protocol_atom = (Atom)None;
static Atom delete_atom = (Atom)None;
 
/* Child windows */
static int ChildCount = 7;
static Window frametotalwin;
static int ftw_width, ftw_height;
static Window rewindwin;
static int rww_width, rww_height;
static Window pausewin;
static int psw_width, psw_height;
static Window playwin;
static int plw_width, plw_height;
static Window stepwin;
static int stw_width, stw_height;
static Window exitwin;
static int exw_width, exw_height;
static Window loopwin;
static int lpw_width, lpw_height;
 
/*
*--------------------------------------------------------------
*
* StopWatch --
*
* On/off timing routine (in real elapsed time).
*
* Results:
* If import is:
* STOPWATCH_START ---- Starts timing, returns 0.0.
* STOPWATCH_STOP ---- Stops timing, returns elapsed
* time in seconds.
* STOPWATCH_RESET ---- Resets timing, returns 0.0.
* STOPWATCH_READ ---- Returns elapsed time in seconds.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
double
StopWatch(action)
int action;
{
static struct timeval start,current; /* Working times */
static struct timeval elapsed; /* Previously accumulated time */
static int state = STOPWATCH_STOP;
double dtemp = 0.0;
long ltemp;
 
if (action == state) {
if (state == STOPWATCH_START) {
return 0.0;
}
else return elapsed.tv_sec + elapsed.tv_usec/1000000.0;
}
switch(action) {
case STOPWATCH_START:
state = STOPWATCH_START;
gettimeofday(&start, (struct timezone *)NULL);
break;
case STOPWATCH_STOP:
gettimeofday(&current, (struct timezone *)NULL);
state = STOPWATCH_STOP;
ltemp = elapsed.tv_usec + current.tv_usec - start.tv_usec;
elapsed.tv_sec += current.tv_sec-start.tv_sec + ltemp/1000000;
elapsed.tv_usec = ltemp % 1000000;
/* And fall through to STOPWATCH_READ */
case STOPWATCH_READ:
if (state == STOPWATCH_START) { /* Stopwatch is running */
gettimeofday(&current,(struct timezone *)NULL);
dtemp = (current.tv_sec-start.tv_sec + elapsed.tv_sec)
+ (current.tv_usec-start.tv_usec + elapsed.tv_usec) / 1000000.0;
}
else dtemp = elapsed.tv_sec + elapsed.tv_usec/1000000.0;
break;
case STOPWATCH_RESET:
state = STOPWATCH_STOP;
elapsed.tv_sec = elapsed.tv_usec = 0;
break;
default:
fprintf(stderr,"Illegal action (%d) requested of StopWatch()",action);
exit(1);
}
return dtemp;
}
 
/*
*--------------------------------------------------------------
*
* GetWindowOrigins --
*
* Determines window coordinates with respect to root window.
*
* Results:
* Sets (xwhole,ywhole) to root coordinates of upper lefthand corner
* of the specified window (including decorations), and (xclient,yclient)
* to the root coordinates of the client region.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
#ifdef __STDC__
static void GetWindowOrigins(XInfo *xinfo, int *xclient,
int *yclient, int *xwhole, int *ywhole)
#else
static void GetWindowOrigins(xinfo,xclient,yclient,xwhole,ywhole)
XInfo *xinfo;
int *xclient;
int *yclient;
int *xwhole;
int *ywhole;
#endif
{
Window dummy_window;
Window win=xinfo->window;
Display *display=xinfo->display;
 
/* First get coordinates for client "sub"-window */
XTranslateCoordinates(display,win,DefaultRootWindow(display),
0,0,xclient,yclient,&dummy_window);
if (dummy_window == None) { /* Shouldn't happen, but if so, then punt */
*xwhole = *xclient;
*ywhole = *yclient;
return;
}
 
/* Now dummy_window should be a direct child of root, so find */
/* its base coordinates. */
XTranslateCoordinates(display,dummy_window,DefaultRootWindow(display),
0,0,xwhole,ywhole,&dummy_window);
 
/* And finally, subtract 1 for good luck ;-) */
if ((*xwhole) > 0) {
(*xwhole)--;
}
if ((*ywhole) > 0) {
(*ywhole)--;
}
}
 
 
/*
*--------------------------------------------------------------
*
* WindowMapped --
*
* Check event to see if window is mapped. A procedure
* intended to be passed to XIfEvent().
*
* Results:
* Read the code.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
Bool WindowMapped(dsp,xev,window)
Display *dsp;
XEvent *xev;
char *window;
{
if (xev->type == MapNotify && xev->xmap.event == *((Window *)window))
return TRUE;
return FALSE;
}
 
/*
*--------------------------------------------------------------
*
* IfEventType --
*
* Check event type. A procedure intended to be passed to XIfEvent().
*
* Results:
* Read the code.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
Bool IfEventType(dsp,xev,type)
Display *dsp;
XEvent *xev;
char *type;
{
if (xev->type == *((int *)type)) {
return TRUE;
}
return FALSE;
}
 
 
/*
*--------------------------------------------------------------
* ShowHideControls---
*
* Maps or unmaps control bar as dictated by the value of the
* global variable ControlShow.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
#ifdef __STDC__
static void ShowHideControls(XInfo *xinfo)
#else
static void ShowHideControls(xinfo)
XInfo *xinfo;
#endif
{
if (ControlShow == CTRLBAR_ON) {
XEvent event;
XMapRaised(xinfo->display, ctrlwindow);
XIfEvent(xinfo->display, &event, WindowMapped, (char *)(&ctrlwindow));
/* Wait for map. */
}
else {
XUnmapWindow(xinfo->display, ctrlwindow);
}
}
 
 
/*
*--------------------------------------------------------------
*
* MakeControlBar --
*
* Creates and (possibly) displays Control Bar in root window
* at position (x,y) relative to video output window.
*
* Results:
* Sets ctrlwindow.
*
* Side effects:
* Sets ctrl_init to 1 if successful.
*
*--------------------------------------------------------------
*/
void MakeControlBar(xinfo)
XInfo *xinfo;
{
char *ctrlname = "MPEG Player Controls";
XSizeHints hint;
int xpos, ypos;
Display *display=xinfo->display;
 
if (ctrl_init) {
fprintf(stderr,
"Warning from MakeControlBar(): Controls already initialized\n");
return;
}
if (xinfo->ditherType == NO_DITHER) return;
if (display == (Display*)NULL) {
fprintf(stderr,
"Fatal error in MakeControlBar(): Display pointer not initialized\n");
exit(1);
}
 
/* Get font (used in window sizing) */
if ((ctrlfont = XLoadQueryFont(display, "fixed")) == NULL) {
fprintf(stderr,"Error: Unable to load font \"fixed\" for Control Bar\n");
exit(1);
}
fontheight = ctrlfont->ascent + ctrlfont->descent;
fontwidth = ctrlfont->max_bounds.width;
 
if (fontheight < 4 || fontheight > 75 || fontwidth < 2 || fontwidth > 30) {
fprintf(stderr,"Warning: Font size seems suspect...guessing\n");
fontheight = 20;
fontwidth = 10; /* Maybe 13 and 6 are better */
}
 
/* Set window sizes */
ftw_height = CtrlBarHeight-2*(ChildBorder+ChildMargin);
ftw_width = fontwidth * 21;
rww_height = ftw_height; rww_width = fontwidth * 8;
psw_height = rww_height; psw_width = fontwidth * 7;
stw_height = psw_height; stw_width = fontwidth * 6;
plw_height = stw_height; plw_width = fontwidth * 6;
lpw_height = plw_height; lpw_width = fontwidth * 10;
exw_height = lpw_height; exw_width = fontwidth * 6;
CtrlBarWidth = rww_width + psw_width + stw_width + plw_width + lpw_width
+ exw_width + ftw_width + ChildMargin
+ ChildCount*(ChildMargin + 2*ChildBorder);
 
/* Figure out how to place control bar just above display window */
GetWindowOrigins(xinfo,&xpos,&ypos,&hint.x,&hint.y);
 
/* Leave room for title bar decorations. Note this assumes */
/* control bar dec. same height as for display window */
hint.y = 2*hint.y - ypos;
 
hint.y -= (CtrlBarHeight + 2*CtrlBarBorder + 1); /* +1 for luck ;-) */
if (hint.y < 0) {
hint.y = 0;
}
hint.max_width = hint.base_width = hint.width = CtrlBarWidth;
hint.max_height = hint.base_height = hint.height = CtrlBarHeight;
hint.min_width = hint.min_height = 0;
hint.flags = PMinSize | PMaxSize | PBaseSize |
PPosition | PSize | USPosition;
 
screen = DefaultScreen (display);
fgcolor = BlackPixel(display, screen);
bgcolor = WhitePixel(display, screen);
 
/* Create main control window */
ctrlwindow = XCreateSimpleWindow (display,
DefaultRootWindow(display),
hint.x, hint.y,
hint.base_width, hint.base_height,
CtrlBarBorder, fgcolor, bgcolor);
 
/* Create child windows */
xpos = ChildMargin;
ypos = ChildMargin;
frametotalwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos,
ftw_width, ftw_height, ChildBorder, fgcolor, bgcolor);
xpos += ftw_width + 2*ChildBorder + ChildMargin;
rewindwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos,
rww_width, rww_height, ChildBorder, fgcolor, bgcolor);
xpos += rww_width + 2*ChildBorder + ChildMargin;
pausewin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos,
psw_width, psw_height, ChildBorder, fgcolor, bgcolor);
xpos += psw_width + 2*ChildBorder + ChildMargin;
stepwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos,
stw_width, stw_height, ChildBorder, fgcolor, bgcolor);
xpos += stw_width + 2*ChildBorder + ChildMargin;
playwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos,
plw_width, plw_height, ChildBorder, fgcolor, bgcolor);
xpos += plw_width + 2*ChildBorder + ChildMargin;
loopwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos,
lpw_width, lpw_height, ChildBorder, fgcolor, bgcolor);
xpos += lpw_width + 2*ChildBorder + ChildMargin;
exitwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos,
exw_width, exw_height, ChildBorder, fgcolor, bgcolor);
 
/* Set up windows */
XSelectInput(display, ctrlwindow, StructureNotifyMask);
XSetStandardProperties(display, ctrlwindow, ctrlname, ctrlname, None,
NULL, 0, &hint);
/*Safety*/
XResizeWindow(display,ctrlwindow, hint. base_width, hint. base_height);
 
XSelectInput(display, rewindwin, ExposureMask | ButtonPressMask);
XSelectInput(display, pausewin, ExposureMask | ButtonPressMask);
XSelectInput(display, stepwin, ExposureMask | ButtonPressMask);
XSelectInput(display, playwin, ExposureMask | ButtonPressMask);
XSelectInput(display, loopwin, ExposureMask | ButtonPressMask);
XSelectInput(display, exitwin, ExposureMask | ButtonPressMask);
XSelectInput(display, frametotalwin, ExposureMask );
 
/* Add "Delete" option to system menus */
protocol_atom = XInternAtom(display,"WM_PROTOCOLS",False);
delete_atom = XInternAtom(display,"WM_DELETE_WINDOW",False);
if ( protocol_atom != (Atom)None && delete_atom != (Atom)None) {
XSetWMProtocols(display, xinfo->window, &delete_atom, 1);/* Video window */
XSetWMProtocols(display, ctrlwindow, &delete_atom, 1); /* Control bar */
}
 
/* Map windows (or not ;-) */
XMapSubwindows(display, ctrlwindow);
ShowHideControls(xinfo);
 
ctrl_init = 1; /* Control Bar successfully initialized */
}
 
 
/*
*--------------------------------------------------------------
*
* Child window draw functions --
*
* (Re)draws child window
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
#if __STDC__
static void WriteCenteredText(Window win,
GC gc,
int winwidth,
int winheight,
char *str,
Display *display)
#else
static void WriteCenteredText(win,gc,winwidth,winheight,str,display)
Window win;
GC gc;
int winwidth, winheight;
char *str;
Display *display;
#endif
{
int xpos, ypos, len;
len = strlen(str);
ypos = (winheight + ctrlfont->ascent)/2 - 1; /* Ignore descenders */
xpos = (winwidth - len*fontwidth)/2;
XDrawImageString(display, win, gc, xpos, ypos, str, len);
}
 
#if __STDC__
static void ExposeWindow(Window win, Display *display)
#else
static void ExposeWindow(win,display)
Window win;
Display *display;
#endif
{
static XEvent event;
event.xexpose.type = Expose;
event.xexpose.serial = 0;
event.xexpose.send_event = TRUE;
event.xexpose.display = display;
event.xexpose.window = win;
event.xexpose.x = 0;
event.xexpose.y = 0;
event.xexpose.width = 0;
event.xexpose.height = 0;
event.xexpose.count = 0;
XSendEvent(display, win, FALSE, ExposureMask, &event);
}
 
#if __STDC__
static void NormalColors(GC gc, Display *display)
#else
static void NormalColors(gc,display)
GC gc;
Display *display;
#endif
{
XSetForeground(display, gc, fgcolor);
XSetBackground(display, gc, bgcolor);
}
 
#if __STDC__
static void InvertColors(GC gc, Display *display)
#else
static void InvertColors(gc,display)
GC gc;
Display *display;
#endif
{
XSetForeground(display, gc, bgcolor);
XSetBackground(display, gc, fgcolor);
}
 
#if __STDC__
static void DrawRewind(GC gc, Display *display)
#else
static void DrawRewind(gc,display)
GC gc;
Display *display;
#endif
{
if (ControlState == CTRL_REWIND) {
XFillRectangle(display, rewindwin, gc, 0, 0, rww_width, rww_height);
InvertColors(gc,display);
WriteCenteredText(rewindwin, gc, rww_width, rww_height, "Rewind",display);
NormalColors(gc,display);
}
else {
WriteCenteredText(rewindwin, gc, rww_width, rww_height, "Rewind",display);
}
}
 
#if __STDC__
static void DrawPause(GC gc, Display *display)
#else
static void DrawPause(gc,display)
GC gc;
Display *display;
#endif
{
if (ControlState == CTRL_EOF || ControlState == CTRL_FFWD
|| ControlState == CTRL_PAUSE) {
XFillRectangle(display,pausewin,gc,0,0,psw_width,psw_height);
InvertColors(gc,display);
switch(ControlState) {
case CTRL_EOF:
WriteCenteredText(pausewin,gc,psw_width,psw_height,"End",display);
break;
case CTRL_FFWD:
WriteCenteredText(pausewin,gc,psw_width,psw_height,"Wait",display);
break;
default:
WriteCenteredText(pausewin,gc,psw_width,psw_height,"Pause",display);
break;
}
NormalColors(gc,display);
}
else {
WriteCenteredText(pausewin,gc,psw_width,psw_height,"Pause",display);
}
}
 
#if __STDC__
static void DrawStep(GC gc, Display *display)
#else
static void DrawStep(gc,display)
GC gc;
Display *display;
#endif
{
if (ControlState == CTRL_STEP) {
XFillRectangle(display, stepwin, gc, 0, 0, stw_width, stw_height);
InvertColors(gc,display);
}
WriteCenteredText(stepwin, gc, stw_width, stw_height, "Step",display);
if (ControlState == CTRL_STEP) {
NormalColors(gc,display);
}
}
 
#if __STDC__
static void DrawPlay(GC gc, Display *display)
#else
static void DrawPlay(gc,display)
GC gc;
Display *display;
#endif
{
if (ControlState == CTRL_PLAY ||
(ControlState == CTRL_EOF && ControlMotion == CTRLMOTION_ON)) {
XFillRectangle(display, playwin, gc, 0, 0, plw_width, plw_height);
InvertColors(gc,display);
WriteCenteredText(playwin, gc, plw_width, plw_height, "Play",display);
NormalColors(gc,display);
}
else {
WriteCenteredText(playwin, gc, plw_width, plw_height, "Play",display);
}
}
 
#if __STDC__
static void DrawLoop(GC gc, Display *display)
#else
static void DrawLoop(gc,display)
GC gc;
Display *display;
#endif
{
if (loopFlag) {
XFillRectangle(display, loopwin, gc, 0, 0, lpw_width, lpw_height);
InvertColors(gc,display);
WriteCenteredText(loopwin, gc, lpw_width, lpw_height, "Loop ON",display);
NormalColors(gc,display);
}
else WriteCenteredText(loopwin, gc, lpw_width, lpw_height, "Loop OFF",
display);
}
 
#if __STDC__
static void DrawExit(GC gc, Display *display)
#else
static void DrawExit(gc,display)
GC gc;
Display *display;
#endif
{
if (ControlState == CTRL_EXIT) {
XFillRectangle(display,exitwin, gc, 0, 0, exw_width, exw_height);
InvertColors(gc,display);
}
WriteCenteredText(exitwin, gc, exw_width, exw_height, "Exit",display);
if (ControlState == CTRL_EXIT) {
NormalColors(gc,display);
}
}
 
void UpdateFrameTotal(display)
Display *display;
{
if (!ctrl_init) {
return;
}
ExposeWindow(frametotalwin,display);
}
 
void UpdateControlDisplay(display)
Display *display;
{
if (!ctrl_init) {
return;
}
ExposeWindow(rewindwin,display);
ExposeWindow(pausewin,display);
ExposeWindow(stepwin,display);
ExposeWindow(playwin,display);
ExposeWindow(loopwin,display);
ExposeWindow(exitwin,display);
ExposeWindow(frametotalwin,display);
}
 
#if __STDC__
static void DrawFrameTotal(GC gc, VidStream **vid_stream, Display *display,
int numMovies)
#else
static void DrawFrameTotal(gc, vid_stream, display, numMovies)
GC gc;
VidStream **vid_stream;
Display *display;
int numMovies;
#endif
{
char str[32];
double dtemp;
int totNumFrames=0, i;
 
dtemp = StopWatch(STOPWATCH_READ);
 
 
for (i=0;i<numMovies;i++) {
if ((vid_stream[i]!=NULL) &&
(vid_stream[i]->totNumFrames > totNumFrames)) {
totNumFrames= vid_stream[i]->totNumFrames;
}
}
 
if (dtemp > 0.0) {
sprintf(str, "Frame/Rate%4d/%4.1f",
totNumFrames, TotalFrameCount/dtemp);
}
else {
sprintf(str, "Frame/Rate%4d/----", totNumFrames);
}
WriteCenteredText(frametotalwin, gc, ftw_width, ftw_height, str, display);
}
 
#if __STDC__
static GC CreateCtrlGC(Display *display)
#else
static GC CreateCtrlGC(display)
Display *display;
#endif
{
XGCValues gcv;
GC gc;
gcv.foreground = BlackPixel(display, screen);
gcv.background = WhitePixel(display, screen);
gcv.font = ctrlfont->fid;
gcv.subwindow_mode = ClipByChildren;
/* gcv.subwindow_mode = IncludeInferiors; */
gc=XCreateGC(display, ctrlwindow,
GCForeground|GCBackground|GCFont|GCSubwindowMode, &gcv);
return gc;
}
 
/*
*--------------------------------------------------------------
*
* GetStateButton --
*
* Determines the window of the button associated with the
* import ctrlstate.
*
* Results:
* The associated window, if any; Otherwise 0.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
#if __STDC__
static Window GetStateButton(int ctrlstate)
#else
static Window GetStateButton(ctrlstate)
int ctrlstate;
#endif
{
switch(ctrlstate) {
case CTRL_REWIND:
return rewindwin;
case CTRL_PAUSE:
case CTRL_FFWD:
case CTRL_EOF:
return pausewin;
case CTRL_STEP:
return stepwin;
case CTRL_PLAY:
return playwin;
case CTRL_EXIT:
return exitwin;
default:
break;
}
return (Window)0;
}
 
/*
*--------------------------------------------------------------
*
* DrawButton --
*
* Calls the draw button function associated with the import
* window button.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
#if __STDC__
static void DrawButton(Window button, GC gc,
Display *display,
VidStream **vid_stream,
int num)
#else
static void DrawButton(button,gc,display,vid_stream, num)
Window button;
GC gc;
Display *display;
VidStream **vid_stream;
int num;
#endif
{
if (button == frametotalwin) DrawFrameTotal(gc,vid_stream,display,num);
else if (button == rewindwin) DrawRewind(gc,display);
else if (button == pausewin) DrawPause(gc,display);
else if (button == stepwin) DrawStep(gc,display);
else if (button == playwin) DrawPlay(gc,display);
else if (button == loopwin) DrawLoop(gc,display);
else if (button == exitwin) DrawExit(gc,display);
else fprintf(stderr, "DrawButton called with unknown button\n");
}
 
/*
*
* WindowSearch --
*
* Search window id's to see if an expose event is on a display window
*
*/
#if __STDC__
static int WindowSearch(XInfo *xinfo, Window win, int num)
#else
static int WindowSearch(xinfo, win, num)
XInfo *xinfo;
Window win;
int num;
#endif
{
int i;
 
for (i=0;(i<num) && (xinfo[i].window!=win);i++) {
}
if (i==num) return -1;
else return i;
}
 
 
/*
*--------------------------------------------------------------
*
* ControlBar --
*
* Checks XEvent queue for control commands.
*
* Results:
* Adjusts global variables ControlState, loopFlag as appropriate.
*
* Side effects:
* May adjust StopWatch state.
*
*--------------------------------------------------------------
*/
 
void ControlBar(vid_stream,xinfo,numMovies)
VidStream **vid_stream;
XInfo *xinfo;
int numMovies;
{
GC gc;
int gcflag, winNum;
Window oldbutton, newbutton;
XEvent event;
static int LastState = CTRL_UNDEFINED;
Display *display=xinfo[0].display;
 
gcflag = 0;
 
/* Check to see if ControlState was modified outside this function, */
/* and update control displays if it was. */
if (LastState != ControlState) {
if (!gcflag) {
gc = CreateCtrlGC(display);
gcflag = 1;
}
if ((oldbutton = GetStateButton(LastState)) != (Window)NULL) {
XClearWindow(display, oldbutton);
DrawButton(oldbutton, gc, display, vid_stream, numMovies);
if (LastState == CTRL_EOF) {
XClearWindow(display, playwin);
DrawButton(playwin, gc, display, vid_stream, numMovies);
}
}
DrawButton(GetStateButton(LastState = ControlState), gc,
display, vid_stream, numMovies);
}
 
/* Process events, if any */
if (XPending(display) < 1) { /* No events */
if (gcflag) {
XFreeGC(display, gc);
}
LastState = ControlState;
return;
}
 
if (!gcflag) {
gc=CreateCtrlGC(display);
gcflag=1;
}
do {
XNextEvent(display, &event);
#ifdef HAVE_XFILTEREVENT /* Define if needed; Some older X's don't have this */
if (XFilterEvent(&event, ctrlwindow)) continue;
#endif
switch(event.type) {
case ButtonPress:
/* Toggle Buttons */
if (event.xbutton.window == loopwin) {
if (loopFlag) {
XClearWindow(display,loopwin);
loopFlag = 0;
}
else {
loopFlag = 1;
if (ControlState == CTRL_EOF && ControlMotion == CTRLMOTION_ON) {
ControlState = CTRL_REWIND;
DrawRewind(gc,display);
XClearWindow(display, playwin);
DrawPlay(gc,display);
XClearWindow(display, pausewin);
DrawPause(gc,display);
}
}
DrawLoop(gc,display);
break;
}
/* Click in display window */
else if (WindowSearch(xinfo,event.xbutton.window,numMovies) != -1) {
if (ControlShow) {
ControlShow = CTRLBAR_OFF;
} else {
ControlShow = CTRLBAR_ON;
}
ShowHideControls(&xinfo[0]);
break;
}
/* ControlState buttons --- */
/* Get currently selected button */
oldbutton = GetStateButton(ControlState);
/* Update state */
if (event.xbutton.window == pausewin) {
if ((ControlState == CTRL_EOF || ControlState == CTRL_FFWD)
&& ControlMotion == CTRLMOTION_ON) {
ControlMotion = CTRLMOTION_OFF;
XClearWindow(display, playwin);
DrawPlay(gc,display);
}
else if (ControlState == CTRL_PLAY) {
ControlMotion = CTRLMOTION_OFF;
ControlState = CTRL_PAUSE;
}
else if (ControlState == CTRL_PAUSE) {
ControlMotion = CTRLMOTION_ON;
ControlState = CTRL_PLAY;
}
}
else if (event.xbutton.window == stepwin) {
if (ControlState == CTRL_PAUSE || ControlState == CTRL_PLAY)
ControlState = CTRL_STEP;
else if (ControlState == CTRL_EOF && loopFlag)
ControlState = CTRL_REWIND;
ControlMotion = CTRLMOTION_OFF;
}
else if (event.xbutton.window == playwin) {
ControlMotion = CTRLMOTION_ON;
if (ControlState == CTRL_EOF) {
if (loopFlag) {
ControlState = CTRL_REWIND;
}
DrawButton(playwin, gc, display, vid_stream, numMovies);
}
else if (ControlState == CTRL_PAUSE) {
ControlState = CTRL_PLAY;
}
}
else if (event.xbutton.window == rewindwin) {
ControlState = CTRL_REWIND;
}
else if (event.xbutton.window == exitwin) {
ControlState = CTRL_EXIT;
}
/* Get newly selected button */
newbutton = GetStateButton(ControlState);
if (LastState == ControlState) break;
/* Adjust stopwatch */
if (LastState == CTRL_PLAY)
StopWatch(STOPWATCH_STOP); /* Stop playing */
else if (ControlState == CTRL_PLAY)
StopWatch(STOPWATCH_START); /* Start playing */
/* Update button display */
if (oldbutton != (Window)NULL) {
XClearWindow(display,oldbutton);
DrawButton(oldbutton,gc,display,vid_stream,numMovies);
}
DrawButton(newbutton,gc,display,vid_stream,numMovies);
break;
case ClientMessage:
if (event.xclient.message_type != protocol_atom ||
event.xclient.data.l[0] != delete_atom ||
event.xclient.format != 32) break; /* Not WM_DELETE_WINDOW */
/* Otherwise drop through to DestroyNotify */
case DestroyNotify:
ControlState=CTRL_EXIT;
break;
case Expose:
if (event.xexpose.count > 0) {
break; /* Wait for last expose event */
}
if ((winNum=
WindowSearch(xinfo,event.xexpose.window, numMovies)) != -1) {
if ( vid_stream[winNum]->current != NULL) {
ExecuteDisplay(vid_stream[winNum],0,&xinfo[winNum]);
}
}
else {
DrawButton(event.xexpose.window,gc,display,vid_stream,numMovies);
}
break;
default:
break;
}
} while (XPending(display) > 0);
if (gcflag) {
XFreeGC(display, gc);
}
LastState = ControlState;
}
 
/*
*--------------------------------------------------------------
*
* ControlLoop --
*
* Main control loop. Intermixes video processing (as
* determined by ControlState) with user input.
*
* Results:
* None.
*
* Side effects:
* Adjusts StopWatch state, totNumFrames, ControlState.
* May also reset video state.
*
*--------------------------------------------------------------
*/
 
void ControlLoop(vid_stream,xinfo,numStreams)
VidStream **vid_stream;
XInfo *xinfo;
int numStreams;
{
int itemp, i, allMovies;
XEvent event;
Display *display=xinfo[0].display;
 
for (i=0;(display==NULL) && (i<numStreams); i++) {
display=xinfo[i].display;
}
 
if (!ctrl_init) {
fprintf(stderr,"ControlLoop() accessed without initialization\n");
exit(1);
}
StopWatch(STOPWATCH_RESET);
TotalFrameCount = 0;
StopWatch(STOPWATCH_START);
 
for (i=0;i<numStreams;i++) {
itemp = vid_stream[i]->totNumFrames;
while (vid_stream[i]->totNumFrames == itemp)
mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]); /* Advance to 1st frame */
}
if (startFrame > vid_stream[0]->totNumFrames) {
ControlState = CTRL_FFWD;
ControlMotion = CTRLMOTION_OFF;
StopWatch(STOPWATCH_STOP);
}
else if (ControlShow != CTRLBAR_ON || noDisplayFlag) {
ControlState = CTRL_PLAY;
ControlMotion = CTRLMOTION_ON;
}
else {
ControlState = INITIAL_STATE;
ControlMotion = CTRLMOTION_OFF;
if (ControlState == CTRL_PAUSE) {
StopWatch(STOPWATCH_STOP);
} else {
StopWatch(STOPWATCH_START);
}
}
 
while (1) {
ControlBar(vid_stream,&xinfo[0],numStreams);
if (ControlState == CTRL_PAUSE || ControlState == CTRL_EOF) {
XPeekEvent(display, &event); /* Block until user input */
}
else {
switch(ControlState) {
case CTRL_PLAY:
allMovies=1;
for (i=0;i<numStreams;i++) {
/* If Film end reached, don't play frames */
if ((vid_stream[i]!=NULL) && (!vid_stream[i]->film_has_ended)) {
itemp = vid_stream[i]->totNumFrames; /* Advance 1 frame */
while (vid_stream[i]->totNumFrames == itemp) {
mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]);
}
allMovies=allMovies && (vid_stream[i]->film_has_ended);
}
}
if (allMovies) { /* Film end reached for all movies*/
StopWatch(STOPWATCH_STOP);
XSync(display, FALSE); /* Kludge to update frametotalwin */
if (loopFlag) {
ControlState = CTRL_REWIND;
}
else {
ControlState = CTRL_EOF;
}
}
break;
case CTRL_FFWD:
allMovies=1;
for (i=0;i<numStreams;i++) {
if (vid_stream[i]!=NULL) {
mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]);
allMovies=allMovies && vid_stream[i]->film_has_ended;
}
}
for (i=0;(i<numStreams) && ((vid_stream[i]==NULL)
|| (startFrame <= vid_stream[i]->totNumFrames));i++) {
;
}
if (i==numStreams) {
if (ControlMotion == CTRLMOTION_ON) {
ControlState = CTRL_PLAY;
StopWatch(STOPWATCH_START);
} else {
ControlState = CTRL_PAUSE;
}
}
 
/* Film end just reached---Degenerate case */
if (allMovies) {
StopWatch(STOPWATCH_STOP);
if (loopFlag) {
ControlState = CTRL_REWIND;
}
else {
ControlState = CTRL_EOF;
}
}
break;
case CTRL_EOF:
if (loopFlag) {
ControlState = CTRL_REWIND;
}
break;
case CTRL_STEP:
StopWatch(STOPWATCH_START);
allMovies=1;
for (i=0;i<numStreams;i++) {
if ((vid_stream[i]!=NULL) && !vid_stream[i]->film_has_ended) {
itemp = vid_stream[i]->totNumFrames; /* Advance 1 frame */
while (vid_stream[i]->totNumFrames == itemp) {
mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]);
}
allMovies=allMovies && vid_stream[i]->film_has_ended;
}
}
StopWatch(STOPWATCH_STOP);
ControlState = CTRLMOTION_OFF;
/* Film end just reached for last ending movie */
if (allMovies)
ControlState = CTRL_EOF;
else
ControlState = CTRL_PAUSE;
break;
case CTRL_REWIND:
StopWatch(STOPWATCH_STOP);
for (i=0;i<numStreams;i++) {
rewind(vid_stream[i]->input);
}
ControlBar(vid_stream, &xinfo[0], numStreams);
for (i=0;i<numStreams;i++) {
if (vid_stream[i]!=NULL) {
ResetVidStream(vid_stream[i]);/* Reinitialize vid_stream pointers */
if (vid_stream[i]->seekValue < 0) {
vid_stream[i]->seekValue = 0 - vid_stream[i]->seekValue;
}
}
}
for (i=0; i<numStreams; i++) {
if (vid_stream[i] != NULL) {
/* Process start codes */
mpegVidRsrc(0, vid_stream[i], 1, &xinfo[i]);
}
}
if (startFrame > 0) {
ControlState = CTRL_FFWD;
}
else {
/* Do 1st frame */
for (i=0;i<numStreams;i++) {
if (vid_stream[i] != NULL) {
vid_stream[i]->realTimeStart = ReadSysClock();
while (vid_stream[i]->totNumFrames == 0) {
mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]);
}
}
}
/* Time like original pass */
StopWatch(STOPWATCH_START);
 
if (ControlMotion == CTRLMOTION_ON) {
ControlState = CTRL_PLAY;
} else {
ControlState = CTRL_PAUSE;
StopWatch(STOPWATCH_STOP);
}
}
break;
case CTRL_EXIT:
if (ctrlfont != NULL) {
XFreeFont(display, ctrlfont);
}
XDestroyWindow(display, ctrlwindow);
return;
default:
fprintf(stderr,"Code error: Illegal control state: %d (main())",
ControlState);
exit(1);
break;
}
}
}
}
#endif /* !NOCONTROLS */
/shark/trunk/ports/mpeg/animmpeg.c
0,0 → 1,833
/*
* Copyright (c) 1994 by Gregory P. Ward.
* All rights reserved.
*
* This file is part of the MNI front end of the Berkeley MPEG decoder.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
* UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER
* IS ON AN "AS IS" BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
*
* Original C version by Greg Ward <greg@pet.mni.mcgill.ca>,
* reentrant C++ version by Loring Holden <lsh@cs.brown.edu>
*
* All functions that have an "MNI Header" are rewritten from the original
* MNI C function
*
*/
 
#include "ANIMmpeg.H"
 
// These are MPEG decoder globals but shouldn't be, really;
int quietFlag=1, loopFlag=1,qualityFlag=0, requireKeypressFlag=0;
int framerate=0,gammaCorrectFlag=0, chromaCorrectFlag=0, noDisplayFlag=0;
int partialFlag=0,startFrame=-1, endFrame=-1;
double gammaCorrect = 1.0, chromaCorrect=1.0;
 
int ANIMmpeg::numMovies=0;
 
//
//Constructor
//
//
ANIMmpeg::ANIMmpeg(const char * const inFileName)
: vid_stream(NULL)
{
newMovie(inFileName);
init();
}
 
//
//Copy constructor
//
ANIMmpeg::ANIMmpeg(const ANIMmpeg& rhs)
: ANIMbase(rhs),
vid_stream(NULL)
{
newMovie(rhs.fileName);
init();
}
 
//
// Takes in read-only string that is the the name of the new movie,
// if NULL, then just deallocates memory
//
void
ANIMmpeg::newMovie(const char * const infile)
{
int stringLength = infile==NULL ? 0 : strlen(infile);
#ifndef NOTHREADS
Boolean tmpThreaded=MultiThreaded;
 
// In case we're decoding in another thread...
if (MultiThreaded && mp_man->processor(threadNumber)->running) {
mp_man->processor(threadNumber)->wait_for_done();
}
#endif
 
// Clean up after old movie
if (fileName) {
delete [] fileName;
}
if (filePtr) fclose(filePtr);
if (vid_stream) {
DestroyVidStream(vid_stream, NULL);
vid_stream=NULL;
}
if (frameBuffer) {
Buffer(FALSE);
}
#ifndef NOTHREADS
MultiThread(FALSE);
#endif
 
if (stringLength) {
fileName = new char[stringLength];
strcpy(fileName, infile);
filePtr = fopen(fileName,"r");
#ifndef NOTHREADS
MultiThread(tmpThreaded);
#endif
}
 
/* Initialize movie information */
Height=Width=BlockHeight=BlockWidth=Depth=PixelSize=Size=BitmapPad=0;
PictureRate=BitRate=0;
}
 
//
//Initialization used by all constructors
//
//
void
ANIMmpeg::init() {
thread_routine=RunDecode;
numMovies++;
if (numMovies==1) {
/* Allocate/initialize tables used for dithering (?) */
lum_values = (int *) malloc(LUM_RANGE*sizeof(int));
cr_values = (int *) malloc(CR_RANGE*sizeof(int));
cb_values = (int *) malloc(CB_RANGE*sizeof(int));
init_tables(); /* initialize decoding stuff */
InitCrop();
InitDither(); /* initializes dithering structures and */
/* colormap (i.e. this is where we do */
/* all dither-specific stuff) */
}
}
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : OpenMPEG
@INPUT : MPEGfile - pointer to a stream opened for reading, positioned
at the beginning of an MPEG stream
ImgInfo - pointer to an ImageDesc structure which will have
information such as frame height, width, depth
and size (total bytes per frame) put in it.
@OUTPUT :
@RETURNS :
@DESCRIPTION: Creates and initializes the variables needed to start
reading/decoding an MPEG stream.
 
This function is part of the MNI front end to the Berkeley
MPEG decoder, adapted from the original Berkeley code.
@METHOD :
@GLOBALS : LUM_RANGE, CR_RANGE, CB_RANGE
lum_values, cr_values, cb_values
@CALLS : GetMPEGInfo()
init_tables()
InitDither()
@CREATED : 94/6/16, Greg Ward (adapted from main() in the original
Berkeley source)
@MODIFIED : 95/10, Loring Holden (made reentrant and ported to C++)
---------------------------------------------------------------------------- */
Boolean ANIMmpeg::open()
{
Boolean okMovie;
/*
* Create the video stream and read the first chunk to get movie
* stats -- width and height in particular.
*/
#ifndef NOTHREADS
if (MultiThreaded && (mp_man->processor(threadNumber)->running)) {
#ifdef sol
fprintf(stderr,"%s: Decode running when open called\n",
fileName);
#else
fprintf(stderr,"%s: Decode running when open called\n",fileName);
#endif
fflush(stderr);
exit(2);
}
#endif
 
if (vid_stream==NULL) {
vid_stream =NewVidStream((unsigned int) BUF_LENGTH);
/* Initialize start time */
vid_stream->realTimeStart = ReadSysClock();
} else {
// clear_data_stream(vid_stream) already called in mpegVidRsrc
ResetVidStream(vid_stream);
allBuffered=FALSE;
// call buffer destructor
if (frameBuffer) Buffer(FALSE);
}
 
vid_stream->input = filePtr;
vid_stream->filename = (char *) fileName;
vid_stream->ditherType=FULL_COLOR_DITHER; /* default */
frames=0;
InitStream();
 
okMovie=(mpegVidRsrc(0, vid_stream, 1, NULL)!=NULL);
if (okMovie) {
GetInfo();
moreFrames=TRUE;
} else moreFrames=FALSE;
 
#ifndef NOTHREADS
if (!allBuffered && MultiThreaded && okMovie) {
// Should check that nothing is running, but assume rewind has been
// called
mp_man->processor(threadNumber)->start_execute(RunDecode,this,NULL);
}
#endif
return okMovie;
 
} /* OpenMPEG () */
 
 
// Destructor
/* ----------------------------- MNI Header -----------------------------------
@NAME : CloseMPEG
@INPUT : (none)
@OUTPUT : (none)
@RETURNS : (void)
@DESCRIPTION: Frees up some of the memory allocated by OpenMPEG() (some
is not freed because the Berkeley code doesn't take into
account the fact that somebody might want to, say, free
up the memory it allocates... someday, I'll probably have
to hack into it to fix that, but not today thanks.)
@METHOD :
@GLOBALS : lum_values
cr_values
cb_values
@CALLS : DestroyVidStream
@CREATED : 94/6/27, Greg Ward
@MODIFIED : 95/10, Loring Holden (made reentrant and ported to C++)
---------------------------------------------------------------------------- */
ANIMmpeg::~ANIMmpeg()
{
newMovie(NULL); //Like we are playing a new movie, but no new
//allocation
// These stay around for the life of the program
// free (lum_values);
// free (cr_values);
// free (cb_values);
}
 
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : RewindMPEG
@INPUT : MPEGfile - the input stream where the MPEG's coming from
Image - image descriptor (just passed to OpenMPEG ())
@OUTPUT : (none)
@RETURNS : (void)
@DESCRIPTION: Resets things so that the caller can start reading the MPEG
stream from the start again. Note that the caller does NOT
need to call OpenMPEG() again -- after a call to RewindMPEG(),
the next call to GetMPEGFrame() will return the first frame
of the MPEG.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 94/7/20, Greg Ward
@MODIFIED : 95/10, Loring Holden (made reentrant and ported to C++)
@COMMENTS :
---------------------------------------------------------------------------- */
void ANIMmpeg::rewind()
{
#ifndef NOTHREADS
if (MultiThreaded && (mp_man->processor(threadNumber)->running)) {
#ifdef sol
fprintf(stderr,"%s: Decode running when rewind called\n",
fileName);
#else
fprintf(stderr,"%s: Decode running when rewind called\n",fileName);
#endif
fflush(stderr);
exit(2);
}
#endif
 
if (!allBuffered) {
::rewind(filePtr);
open();
} else {
// do buffering stuff here
}
}
 
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : GetMPEGInfo
@INPUT : vid_stream - a video stream that is open and has had at
least one call to mpegVidRsrc() performed on it
Info - a pointer to an ImageDesc struct in the caller's
space (i.e., the argument to OpenMPEG()) where
the image information will be copied
@OUTPUT :
@RETURNS : (void)
@DESCRIPTION: From the video stream, determines the width, height, pixel
size and depth (in bits) and total image size (in bytes)
for an MPEG stream. Sets the global variable Info
(part of the interface between wrapper.c and globals.c),
and then copies that struct to the user application's
space via the Info pointer.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 94/6/17, Greg Ward: based on code from ExecuteDisplay() in the
original Berkeley source
@MODIFIED : 95/10, Loring Holden (made reentrant and ported to C++)
---------------------------------------------------------------------------- */
void ANIMmpeg::GetInfo()
{
#ifndef DISABLE_DITHER
switch (vid_stream->ditherType)
{
case Twox2_DITHER:
{
Height = vid_stream->v_size;
Width = vid_stream->h_size;
BlockHeight=vid_stream->mb_height;
BlockWidth=vid_stream->mb_width;
Depth = 8;
PixelSize = 8;
BitmapPad = 8;
break;
}
case FULL_COLOR_DITHER:
{
#endif
Height = vid_stream->v_size;
Width = vid_stream->h_size;
BlockHeight=vid_stream->mb_height;
BlockWidth=vid_stream->mb_width;
Depth = 24;
PixelSize = 32;
BitmapPad = 32;
#ifndef DISABLE_DITHER
break;
}
case MONO_DITHER:
case MONO_THRESHOLD:
{
Height = vid_stream->v_size;
Width = vid_stream->h_size;
Depth = 1;
PixelSize = 1;
BitmapPad = 8;
break;
}
default: /* including GRAY_DITHER and ORDERED_DITHER */
{
Height = vid_stream->v_size;
Width = vid_stream->h_size;
Depth = 8;
PixelSize = 8;
BitmapPad = 8;
break;
}
} /* switch on ditherType */
#endif
 
Size = (BlockHeight*16*BlockWidth*16*PixelSize) / 8;
PictureRate = vid_stream->picture_rate;
BitRate = vid_stream->bit_rate;
 
} /* GetMPEGInfo () */
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : GetMPEGFrame
@INPUT :
@OUTPUT : Frame - the image data, converted to RGB space, is
copied to the area pointed to by Frame. There must be
enough room for the entire image; the ImageDesc
structure returned by OpenMPEG() will tell you just how
much memory this is. The format of the data depends on
the dithering type; for full colour dithering, there are
four bytes per pixel: red, green, blue, and unused.
(Perfect for passing to lrectwrite() or XPutImage().)
@RETURNS : TRUE if there are still frames left to decode
FALSE if we have just decoded the last frame
@DESCRIPTION: Part of the MNI front end to the Berkeley MPEG decoder.
Essentially reads, decodes, and converts to RGB space the
next frame in the MPEG stream opened with OpenMPEG().
@METHOD :
@GLOBALS :
@CALLS : mpegVidRsrc ()
@CREATED : 94/6/16, Greg Ward
@MODIFIED : 95/10, Loring Holden (made reentrant and ported to C++)
---------------------------------------------------------------------------- */
void *ANIMmpeg::RunDecode(void *ptr, void *)
{
ANIMmpeg *movie=(ANIMmpeg *) ptr;
Boolean MovieDone = FALSE;
int frames;
 
#if 0
dprintf ("GetMPEGFrame: starting or continuing movie\n");
#endif
 
frames=movie->vid_stream->totNumFrames;
while (!MovieDone && (frames==movie->vid_stream->totNumFrames))
{
mpegVidRsrc(0,movie->vid_stream,0, NULL);
MovieDone = movie->vid_stream->film_has_ended;
}
 
return NULL;
 
} /* GetMPEGFrame () */
 
Boolean ANIMmpeg::GetFrame(char **Frame, Boolean *newFrame)
{
void *CurrentImage;
int looped;
 
if ((vid_stream==NULL) && !open()) {
*newFrame=FALSE;
return FALSE;
}
 
if (!allBuffered) {
#ifndef NOTHREADS
if (MultiThreaded) {
mp_man->processor(threadNumber)->wait_for_done();
} else {
ANIMmpeg::RunDecode(this,NULL);
}
#else
ANIMmpeg::RunDecode(this,NULL);
#endif
moreFrames=!vid_stream->film_has_ended;
CurrentImage=(void *) vid_stream->current->display;
if (buffering) {
// copy CurrentImage to the right place in the array
if (!frameBuffer->addToBuffer(CurrentImage)) {
// ran out of memory - can't buffer
Buffer(FALSE);
fflush(stdout);
fprintf(stderr,"%s: no more room to buffer\n",fileName);
fflush(stderr);
} else if (!moreFrames) {
allBuffered=TRUE;
moreFrames=TRUE;
}
}
#if 0
dprintf ("\nGetMPEGFrame: just received a finished frame: ",
"copying from %08X to %08X\n", CurrentImage, Frame);
#endif
memcpy ((void *) *Frame, CurrentImage, Size);
 
if (allBuffered) {
int totFrames=vid_stream->totNumFrames;
 
DestroyVidStream(vid_stream,NULL);
// This is a hack in order to use PrintTimeInfo
// - Create a NewVidStream just to use realTimeStart
// - all the image information is deallocated, so we do save space
vid_stream =NewVidStream((unsigned int) BUF_LENGTH);
vid_stream->totNumFrames=totFrames;
/* Initialize start time */
vid_stream->realTimeStart = ReadSysClock();
}
 
} else {
// set moreFrames
moreFrames=TRUE;
// set CurrentImage to point to the right place in the array
*Frame=(char *) frameBuffer->nextBufferItem(&looped);
if (looped) {
PrintTimeInfo(vid_stream);
vid_stream->realTimeStart = ReadSysClock();
}
}
 
#ifndef NOTHREADS
if (!allBuffered && MultiThreaded && moreFrames) {
mp_man->processor(threadNumber)->start_execute(RunDecode,this,NULL);
}
#endif
 
frames++;
*newFrame=TRUE;
return moreFrames;
}
 
#ifndef DISABLE_DITHER
/* ----------------------------- MNI Header -----------------------------------
@NAME : DoDitherImage
@INPUT : l, Cr, Cb - pointers to the luminance, Cr, and Cb planes
disp - ?
h, w - height and width of image (?)
@OUTPUT :
@RETURNS :
@DESCRIPTION: Called when image needs to be dithered. Selects correct
dither routine based on info in ditherType.
@METHOD :
@GLOBALS : ditherType
@CALLS : One of the following, depending on the value of ditherType:
HybridDitherImage (hybrid.c)
HybridErrorDitherImage (hybriderr.c)
FS2FastDitherImage (fs2fast.c)
FS2DitherImage (fs2.c)
FS4DitherImage (fs4.c)
Twox2DitherImage (2x2.c)
ColorDitherImage (16bit.c)
GrayDitherImage (gray.c)
OrderedDitherImage (ordered.c)
MonoDitherImage (mono.c)
MonoThresholdImage (mono.c)
Ordered2DitherImage (ordered2.c)
MBOrderedDitherImage (mb_ordered.c)
@CREATED : (taken from the original Berkeley code)
@MODIFIED :
---------------------------------------------------------------------------- */
void
DoDitherImage(VidStream *vid_stream)
{
unsigned char *l=vid_stream->current->luminance,
*Cr=vid_stream->current->Cr,
*Cb=vid_stream->current->Cb,
*disp=vid_stream->current->display;
int h=(int) vid_stream->mb_height * 16;
int w=(int) vid_stream->mb_width * 16;
int ditherType=vid_stream->ditherType;
int matched_depth=vid_stream->matched_depth;
 
switch(ditherType) {
case HYBRID_DITHER:
HybridDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case HYBRID2_DITHER:
HybridErrorDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FS2FAST_DITHER:
FS2FastDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FS2_DITHER:
FS2DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FS4_DITHER:
FS4DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case Twox2_DITHER:
Twox2DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FULL_COLOR_DITHER:
Color32DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case GRAY_DITHER:
GrayDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case NO_DITHER:
break;
 
case PPM_DITHER:
Color32DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case ORDERED_DITHER:
OrderedDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case MONO_DITHER:
MonoDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case MONO_THRESHOLD:
MonoThresholdImage(l, Cr, Cb, disp, h, w);
break;
 
case ORDERED2_DITHER:
Ordered2DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case MBORDERED_DITHER:
MBOrderedDitherImage(l, Cr, Cb, disp, h, w, vid_stream->ditherFlags);
break;
}
} /* DoDitherImage () */
#else
void
DoDitherImage(VidStream *vid_stream)
{
unsigned char *l=vid_stream->current->luminance,
*Cr=vid_stream->current->Cr,
*Cb=vid_stream->current->Cb,
*disp=vid_stream->current->display;
int h=(int) vid_stream->mb_height * 16;
int w=(int) vid_stream->mb_width * 16;
 
Color32DitherImage(l,Cr,Cb,disp,h,w);
}
#endif
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : InitColormap
@INPUT : (none)
@OUTPUT : *NumColors - number of entries in the newly-created colormap
*Map - an array of colourmap entries; each one contains a
red, green, and blue byte-values (0 .. 255).
*Map[i] gives the colour to display a pixel value i.
@RETURNS : (none)
@DESCRIPTION: Creates a colour map used for most dithering methods
(everything except full-colour, gray, and monochrome).
The colour map itself is pretty self-explanatory -- a
pixel with value i is to be displayed using the red, green
and blue values in *Map[i] after InitColormap() is done.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 95/3/4, Greg Ward: based on InitColorDisplay(), from gdith.c
in the original Berkeley player
@MODIFIED :
---------------------------------------------------------------------------- */
#ifndef DISABLE_DITHER
static void
InitColormap (int *NumColors, ColormapEntry **Map)
{
int i, lum_num, cr_num, cb_num;
 
*NumColors = LUM_RANGE*CB_RANGE*CR_RANGE;
*Map = (ColormapEntry *) malloc (*NumColors * sizeof (ColormapEntry));
 
for (i = 0; i < *NumColors; i++)
{
lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE;
cr_num = (i / CB_RANGE)%CR_RANGE;
cb_num = i % CB_RANGE;
/* ConvertColor(lum_values[lum_num], cr_values[cr_num], cb_values[cb_num],
&(*Map)[i].red, &(*Map)[i].green, &(*Map)[i].blue);
*/
pixel[i] = i;
}
}
#endif
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : InitGrayColormap
@INPUT : (none)
@OUTPUT : *NumColors - number of entries in the newly-created colormap
*Map - an array of colourmap entries
@RETURNS : (none)
@DESCRIPTION: Creates a colour map used for gray-scale dithering, i.e.
the red/green/blue values are the same for any given
pixel value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 95/3/4, Greg Ward: based on InitGrayDisplay(), from gdith.c
in the original Berkeley player
@MODIFIED :
---------------------------------------------------------------------------- */
#ifndef DISABLE_DITHER
static void
InitGrayColormap (int *NumColors, ColormapEntry **Map)
{
int i;
*NumColors = NUM_COLORS;
*Map = (ColormapEntry *) malloc (*NumColors * sizeof (ColormapEntry));
 
for (i = 0; i < *NumColors; i++)
{
(*Map)[i].red = (*Map)[i].green = (*Map)[i].blue = i;
pixel[i] = i;
}
}
#endif
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : InitDither
@INPUT : Image - pointer to the image descriptor for the current MPEG
@OUTPUT : ColormapSize, Colormap - the colour map for
this movie, as initialized by either InitColormap or
InitGrayColormap (unless the current dithering scheme
is full colour, in which case there is no colour map)
@RETURNS : (none)
@DESCRIPTION: Does all initialization particular to the type of dithering
being used. Basically, sets up the internal data structures
needed by the dithering code, and then sets up a colour map
needed to display the pixels output by the ditherers.
@METHOD :
@GLOBALS :
@CALLS : InitColor (for most dithering methods)
InitColormap (for most dithering methods)
InitGrayColormap (for gray-scale dithering)
Init(..)Dither (.. = the current dithering method)
@CREATED : 95/3/3, Greg Ward: taken mostly from main() in the original
Berkeley player
@MODIFIED :
---------------------------------------------------------------------------- */
void
ANIMmpeg::InitDither(unsigned long red,
unsigned long green,
unsigned long blue)
{
LUM_RANGE = 8;
CR_RANGE = 4;
CB_RANGE = 4;
#ifndef DISABLE_DITHER
switch (vid_stream->ditherType)
{
case HYBRID_DITHER:
InitColor ();
InitHybridDither ();
InitColormap (&ColormapSize, &Colormap);
break;
 
case HYBRID2_DITHER:
InitColor ();
InitHybridErrorDither ();
InitColormap (&ColormapSize, &Colormap);
break;
 
case FS4_DITHER:
InitColor ();
InitFS4Dither ();
InitColormap (&ColormapSize, &Colormap);
break;
 
case FS2_DITHER:
InitColor ();
InitFS2Dither ();
InitColormap (&ColormapSize, &Colormap);
break;
 
case FS2FAST_DITHER:
InitColor ();
InitFS2FastDither ();
InitColormap (&ColormapSize, &Colormap);
break;
 
case Twox2_DITHER:
InitColor ();
Init2x2Dither ();
InitColormap (&ColormapSize, &Colormap);
PostInit2x2Dither ();
break;
 
case GRAY_DITHER:
InitGrayColormap (&ColormapSize, &Colormap);
break;
case FULL_COLOR_DITHER:
#endif
wpixel[0]=red;
wpixel[1]=green;
wpixel[2]=blue;
InitColorDither(1);
#ifndef DISABLE_DITHER
break;
 
case NO_DITHER:
break;
 
case ORDERED_DITHER:
InitColor ();
InitOrderedDither ();
InitColormap (&ColormapSize, &Colormap);
break;
 
case MONO_DITHER:
case MONO_THRESHOLD:
break;
 
case ORDERED2_DITHER:
InitColor ();
InitColormap (&ColormapSize, &Colormap);
InitOrdered2Dither ();
break;
 
case MBORDERED_DITHER:
InitColor ();
InitColormap (&ColormapSize, &Colormap);
InitMBOrderedDither ();
break;
 
case PPM_DITHER:
ColormapSize = -1;
Colormap = NULL;
wpixel[0] = 0xff;
wpixel[1] = 0xff00;
wpixel[2] = 0xff0000;
vid_stream->matched_depth=24;
InitColorDither(TRUE);
break;
}
#endif
}
 
//
//
//
void
ANIMmpeg::InitStream()
{
if ((vid_stream->ditherType==FULL_COLOR_DITHER) ||
(vid_stream->ditherType==PPM_DITHER)) {
vid_stream->matched_depth=24;
// InitColorDither(1);
}
}
/shark/trunk/ports/mpeg/ctrlbar.h
0,0 → 1,97
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 
contributed by (but no rights held by):
 
Michael J. Donahue
National Institute of Standards and Technology
Gaithersburg MD USA
donahue@ulexite.nist.gov
 
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include <X11/Xlib.h>
#include <X11/Xutil.h>
 
/*
Changes to make the code reentrant:
deglobalize totNumFrames, realTimeStart, seekValue, EOF_flag
Additional changes:
none
-lsh@cs.brown.edu (Loring Holden)
*/
 
#define DISPLAY_WINDOW_BORDER 4
 
/* Control bar display flag */
extern int ControlShow;
#define CTRLBAR_OFF 0
#define CTRLBAR_ON 1
#define CTRLBAR_NONE 2 /* No control bar at all */
 
/* Video play states */
extern int ControlState;
#define CTRL_UNDEFINED -1
#define CTRL_PAUSE 0
#define CTRL_PLAY 1
#define CTRL_STEP 2
#define CTRL_EOF 3
#define CTRL_REWIND 4
#define CTRL_FFWD 5 /* Fast Forward (skips frames w/o display) */
#define CTRL_EXIT 6
 
/* ControlMotion tracks Play/Pause status (for resumption after e.g. Rewind) */
extern int ControlMotion;
#define CTRLMOTION_OFF 0 /* Pause */
#define CTRLMOTION_ON 1 /* Play */
 
/* StopWatch constants */
extern long TotalFrameCount; /* Total number of frames processed, with loops */
#define STOPWATCH_RESET 0 /* Resets timing, returns 0.0. */
#define STOPWATCH_START 1 /* Starts timing, returns 0.0. */
#define STOPWATCH_STOP 2 /* Stops timing, returns elapsed time in secs. */
#define STOPWATCH_READ 3 /* Returns elapsed time in seconds. */
 
/* Miscellaneous externals */
extern int loopFlag; /* Video loop flag */
extern int startFrame; /* != -1 => skip all frames up to this one */
extern int endFrame; /* Either last frame to display or else frame count,
* depending on the value of seekValue. */
/shark/trunk/ports/mpeg/gdith.c
0,0 → 1,246
/*
* gdith.c --
*
* Procedures dealing with grey-scale and mono dithering,
* as well as X Windows set up procedures.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include <math.h>
#include "video.h"
#include "proto.h"
#include "dither.h"
#ifndef NOCONTROLS
#include "ctrlbar.h"
#endif
#include <sys/time.h>
 
#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
#endif
 
/*
Changes to make the code reentrant:
X variables now passed in xinfo: display, ximage,cmap,window, gc, etc
De-globalized: ditherType, matched_depth, totNumFrames
vid_stream->film_has_ended instead of FilmState
 
Additional changes:
Now can name and position each movie window individually
DISABLE_DITHER cpp define - do not include dither code if defined
NOFRAMECOUNT cpp define - do not count frames when running without
controls
Short circuit InitColorDisplay if not displaying anything
ExistingWindow default now 0
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* Range values for lum, cr, cb. */
int LUM_RANGE;
int CR_RANGE;
int CB_RANGE;
 
/* Array that remaps color numbers to actual pixel values used by X server. */
 
unsigned char pixel[256];
unsigned long wpixel[256];
 
/* Arrays holding quantized value ranged for lum, cr, and cb. */
 
int *lum_values;
int *cr_values;
int *cb_values;
 
/* Declaration of global variable containing dither type. */
 
/* Frame Rate Info */
extern int framerate;
 
/* Video rates table */
/* Cheat on Vid rates, round to 30, and use 30 if illegal value
Except for 9, where Xing means 15, and given their popularity, we'll
be nice and do it */
static int VidRateNum[16]={30, 24, 24, 25, 30, 30, 50, 60,
60, 15, 30, 30, 30, 30, 30, 30};
 
/* Luminance and chrominance lookup tables */
static double *L_tab, *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
 
/*
*--------------------------------------------------------------
*
* InitColor --
*
* Initialize lum, cr, and cb quantized range value arrays.
* Also initializes the lookup tables for the possible
* values of lum, cr, and cb.
* Color values from ITU-R BT.470-2 System B, G and SMPTE 170M
* see InitColorDither in 16bits.c for more
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
InitColor()
{
int i, CR, CB;
 
L_tab = (double *)malloc(LUM_RANGE*sizeof(double));
Cr_r_tab = (double *)malloc(CR_RANGE*sizeof(double));
Cr_g_tab = (double *)malloc(CR_RANGE*sizeof(double));
Cb_g_tab = (double *)malloc(CB_RANGE*sizeof(double));
Cb_b_tab = (double *)malloc(CB_RANGE*sizeof(double));
 
if (L_tab == NULL || Cr_r_tab == NULL ||
Cr_g_tab == NULL || Cb_g_tab == NULL ||
Cb_b_tab == NULL) {
fprintf(stderr, "Could not alloc memory in InitColor\n");
exit(1);
}
 
for (i=0; i<LUM_RANGE; i++) {
lum_values[i] = ((i * 256) / (LUM_RANGE)) + (256/(LUM_RANGE*2));
L_tab[i] = lum_values[i];
if (gammaCorrectFlag) {
L_tab[i] = GAMMA_CORRECTION(L_tab[i]);
}
}
for (i=0; i<CR_RANGE; i++) {
register double tmp;
if (chromaCorrectFlag) {
tmp = ((i * 256) / (CR_RANGE)) + (256/(CR_RANGE*2));
Cr_r_tab[i] = (int) (0.419/0.299) * CHROMA_CORRECTION128D(tmp - 128.0);
Cr_g_tab[i] = (int) -(0.299/0.419) * CHROMA_CORRECTION128D(tmp - 128.0);
cr_values[i] = CHROMA_CORRECTION256(tmp);
} else {
tmp = ((i * 256) / (CR_RANGE)) + (256/(CR_RANGE*2));
Cr_r_tab[i] = (int) (0.419/0.299) * (tmp - 128.0);
Cr_g_tab[i] = (int) -(0.299/0.419) * (tmp - 128.0);
cr_values[i] = (int) tmp;
}
}
 
for (i=0; i<CB_RANGE; i++) {
register double tmp;
if (chromaCorrectFlag) {
tmp = ((i * 256) / (CB_RANGE)) + (256/(CB_RANGE*2));
Cb_g_tab[i] = (int) -(0.114/0.331) * CHROMA_CORRECTION128D(tmp - 128.0);
Cb_b_tab[i] = (int) (0.587/0.331) * CHROMA_CORRECTION128D(tmp - 128.0);
cb_values[i] = CHROMA_CORRECTION256(tmp);
} else {
tmp = ((i * 256) / (CB_RANGE)) + (256/(CB_RANGE*2));
Cb_g_tab[i] = (int) -(0.114/0.331) * (tmp - 128.0);
Cb_b_tab[i] = (int) (0.587/0.331) * (tmp - 128.0);
cb_values[i] = (int) tmp;
}
}
 
}
 
/*
*--------------------------------------------------------------
*
* ConvertColor --
*
* Given a l, cr, cb tuple, converts it to r,g,b.
*
* Results:
* r,g,b values returned in pointers passed as parameters.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
static void
ConvertColor(l, cr, cb, r, g, b)
unsigned int l, cr, cb;
unsigned char *r, *g, *b;
{
double fl, fcr, fcb, fr, fg, fb;
 
/*
* Old method w/o lookup table
*
* fl = 1.164*(((double) l)-16.0);
* fcr = ((double) cr) - 128.0;
* fcb = ((double) cb) - 128.0;
*
* fr = fl + (1.366 * fcr);
* fg = fl - (0.700 * fcr) - (0.334 * fcb);
* fb = fl + (1.732 * fcb);
*/
 
fl = L_tab[l];
 
fr = fl + Cr_r_tab[cr];
fg = fl + Cr_g_tab[cr] + Cb_g_tab[cb];
fb = fl + Cb_b_tab[cb];
 
if (fr < 0.0) fr = 0.0;
else if (fr > 255.0) fr = 255.0;
 
if (fg < 0.0) fg = 0.0;
else if (fg > 255.0) fg = 255.0;
 
if (fb < 0.0) fb = 0.0;
else if (fb > 255.0) fb = 255.0;
 
*r = (unsigned char) fr;
*g = (unsigned char) fg;
*b = (unsigned char) fb;
 
}
/shark/trunk/ports/mpeg/jrevdct.c
0,0 → 1,1715
/*
* jrevdct.c
*
* This file is part of the Independent JPEG Group's software.
* The IJG code is distributed under the terms reproduced here:
*
* LEGAL ISSUES
* ============
*
* In plain English:
*
* 1. We don't promise that this software works. (But if you find any bugs,
* please let us know!)
* 2. You can use this software for whatever you want. You don't have to
* pay us.
* 3. You may not pretend that you wrote this software. If you use it in a
* program, you must acknowledge somewhere in your documentation that
* you've used the IJG code.
*
* In legalese:
*
* The authors make NO WARRANTY or representation, either express or implied,
* with respect to this software, its quality, accuracy, merchantability, or
* fitness for a particular purpose. This software is provided "AS IS", and
* you, its user, assume the entire risk as to its quality and accuracy.
*
* This software is copyright (C) 1991, 1992, Thomas G. Lane.
* All Rights Reserved except as specified below.
*
* Permission is hereby granted to use, copy, modify, and distribute this
* software (or portions thereof) for any purpose, without fee, subject to
* these conditions:
* (1) If any part of the source code for this software is distributed, then
* this copyright and no-warranty notice must be included unaltered; and any
* additions, deletions, or changes to the original files must be clearly
* indicated in accompanying documentation.
* (2) If only executable code is distributed, then the accompanying
* documentation must state that "this software is based in part on the
* work of the Independent JPEG Group".
* (3) Permission for use of this software is granted only if the user
* accepts full responsibility for any undesirable consequences; the authors
* accept NO LIABILITY for damages of any kind.
*
* These conditions apply to any software derived from or based on the IJG
* code, not just to the unmodified library. If you use our work, you ought
* to acknowledge us.
*
* Permission is NOT granted for the use of any IJG author's name or company
* name in advertising or publicity relating to this software or products
* derived from it. This software may be referred to only as
* "the Independent JPEG Group's software".
*
* We specifically permit and encourage the use of this software as the
* basis of commercial products, provided that all warranty or liability
* claims are assumed by the product vendor.
*
*
* ARCHIVE LOCATIONS
* =================
*
* The "official" archive site for this software is ftp.uu.net (Internet
* address 192.48.96.9). The most recent released version can always be
* found there in directory graphics/jpeg. This particular version will
* be archived as graphics/jpeg/jpegsrc.v6a.tar.gz. If you are on the
* Internet, you can retrieve files from ftp.uu.net by standard anonymous
* FTP. If you don't have FTP access, UUNET's archives are also available
* via UUCP; contact help@uunet.uu.net for information on retrieving files
* that way.
*
* Numerous Internet sites maintain copies of the UUNET files. However,
* only ftp.uu.net is guaranteed to have the latest official version.
*
* You can also obtain this software in DOS-compatible "zip" archive
* format from the SimTel archives (ftp.coast.net:/SimTel/msdos/graphics/),
* or on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP),
* library 12 "JPEG Tools". Again, these versions may sometimes lag behind
* the ftp.uu.net release.
*
* The JPEG FAQ (Frequently Asked Questions) article is a useful source of
* general information about JPEG. It is updated constantly and therefore
* is not included in this distribution. The FAQ is posted every two weeks
* to Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
* You can always obtain the latest version from the news.answers archive
* at rtfm.mit.edu. By FTP, fetch /pub/usenet/news.answers/jpeg-faq/part1
* and .../part2. If you don't have FTP, send e-mail to
* mail-server@rtfm.mit.edu with body
* send usenet/news.answers/jpeg-faq/part1
* send usenet/news.answers/jpeg-faq/part2
*
* ==============
*
*
* This file contains the basic inverse-DCT transformation subroutine.
*
* This implementation is based on an algorithm described in
* C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
* Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
* Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
* The primary algorithm described there uses 11 multiplies and 29 adds.
* We use their alternate method with 12 multiplies and 32 adds.
* The advantage of this method is that no data path contains more than one
* multiplication; this allows a very simple and accurate implementation in
* scaled fixed-point arithmetic, with a minimal number of shifts.
*
*
* CHANGES FOR BERKELEY MPEG
* =========================
*
* This file has been altered to use the Berkeley MPEG header files,
* to add the capability to handle sparse DCT matrices efficiently,
* and to relabel the inverse DCT function as well as the file
* (formerly jidctint.c).
*
* I've made lots of modifications to attempt to take advantage of the
* sparse nature of the DCT matrices we're getting. Although the logic
* is cumbersome, it's straightforward and the resulting code is much
* faster.
*
* A better way to do this would be to pass in the DCT block as a sparse
* matrix, perhaps with the difference cases encoded.
*/
 
#include <string.h>
#include "video.h"
#include "proto.h"
 
#define GLOBAL /* a function referenced thru EXTERNs */
/* We assume that right shift corresponds to signed division by 2 with
* rounding towards minus infinity. This is correct for typical "arithmetic
* shift" instructions that shift in copies of the sign bit. But some
* C compilers implement >> with an unsigned shift. For these machines you
* must define RIGHT_SHIFT_IS_UNSIGNED.
* RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
* It is only applied with constant shift counts. SHIFT_TEMPS must be
* included in the variables of any routine using RIGHT_SHIFT.
*/
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define SHIFT_TEMPS INT32 shift_temp;
#define RIGHT_SHIFT(x,shft) \
((shift_temp = (x)) < 0 ? \
(shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
(shift_temp >> (shft)))
#else
#define SHIFT_TEMPS
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
#endif
 
/*
* This routine is specialized to the case DCTSIZE = 8.
*/
 
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
 
 
/*
* A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* The poop on this scaling stuff is as follows:
*
* Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
* larger than the true IDCT outputs. The final outputs are therefore
* a factor of N larger than desired; since N=8 this can be cured by
* a simple right shift at the end of the algorithm. The advantage of
* this arrangement is that we save two multiplications per 1-D IDCT,
* because the y0 and y4 inputs need not be divided by sqrt(N).
*
* We have to do addition and subtraction of the integer inputs, which
* is no problem, and multiplication by fractional constants, which is
* a problem to do in integer arithmetic. We multiply all the constants
* by CONST_SCALE and convert them to integer constants (thus retaining
* CONST_BITS bits of precision in the constants). After doing a
* multiplication we have to divide the product by CONST_SCALE, with proper
* rounding, to produce the correct output. This division can be done
* cheaply as a right shift of CONST_BITS bits. We postpone shifting
* as long as possible so that partial sums can be added together with
* full fractional precision.
*
* The outputs of the first pass are scaled up by PASS1_BITS bits so that
* they are represented to better-than-integral precision. These outputs
* require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
* with the recommended scaling. (To scale up 12-bit sample data further, an
* intermediate INT32 array would be needed.)
*
* To avoid overflow of the 32-bit intermediate results in pass 2, we must
* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
* shows that the values given below are the most effective.
*/
 
#ifdef EIGHT_BIT_SAMPLES
#define PASS1_BITS 2
#else
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
 
#define ONE ((INT32) 1)
 
#define CONST_SCALE (ONE << CONST_BITS)
 
/* Convert a positive real constant to an integer scaled by CONST_SCALE.
* IMPORTANT: if your compiler doesn't do this arithmetic at compile time,
* you will pay a significant penalty in run time. In that case, figure
* the correct integer constant values and insert them by hand.
*/
 
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
 
/* When adding two opposite-signed fixes, the 0.5 cancels */
#define FIX2(x) ((INT32) ((x) * CONST_SCALE))
 
/* Descale and correctly round an INT32 value that's scaled by N bits.
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
* the fudge factor is correct for either sign of X.
*/
 
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
 
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
* For 8-bit samples with the recommended scaling, all the variable
* and constant values involved are no more than 16 bits wide, so a
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply;
* this provides a useful speedup on many machines.
* There is no way to specify a 16x16->32 multiply in portable C, but
* some C compilers will do the right thing if you provide the correct
* combination of casts.
* NB: for 12-bit samples, a full 32-bit multiplication will be needed.
*/
 
#ifdef EIGHT_BIT_SAMPLES
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const)))
#endif
#endif
 
#ifndef MULTIPLY /* default definition */
#define MULTIPLY(var,const) ((var) * (const))
#endif
 
#ifndef NO_SPARSE_DCT
#define SPARSE_SCALE_FACTOR 8
#endif
 
/* Precomputed idct value arrays. */
 
static DCTELEM PreIDCT[64][64];
 
/*
*--------------------------------------------------------------
*
* init_pre_idct --
*
* Pre-computes singleton coefficient IDCT values.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
init_pre_idct() {
int i;
 
for (i=0; i<64; i++) {
memset((char *) PreIDCT[i], 0, 64*sizeof(DCTELEM));
PreIDCT[i][i] = 1 << SPARSE_SCALE_FACTOR;
j_rev_dct(PreIDCT[i]);
}
}
 
#ifndef NO_SPARSE_DCT
 
/*
*--------------------------------------------------------------
*
* j_rev_dct_sparse --
*
* Performs the inverse DCT on one block of coefficients.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
j_rev_dct_sparse (data, pos)
DCTBLOCK data;
int pos;
{
short int val;
register int *dp;
register int v;
int quant;
 
#ifdef SPARSE_AC
register DCTELEM *dataptr;
DCTELEM *ndataptr;
int coeff, rr;
DCTBLOCK tmpdata, tmp2data;
DCTELEM *tmpdataptr, *tmp2dataptr;
int printFlag = 1;
#endif
 
 
/* If DC Coefficient. */
if (pos == 0) {
dp = (int *)data;
v = *data;
quant = 8;
 
/* Compute 32 bit value to assign. This speeds things up a bit */
if (v < 0) {
val = -v;
val += (quant >> 1);
val /= quant;
val = -val;
}
else {
val = (v + (quant >> 1)) / quant;
}
 
v = ((val & 0xffff) | (val << 16));
 
dp[0] = v; dp[1] = v; dp[2] = v; dp[3] = v;
dp[4] = v; dp[5] = v; dp[6] = v; dp[7] = v;
dp[8] = v; dp[9] = v; dp[10] = v; dp[11] = v;
dp[12] = v; dp[13] = v; dp[14] = v; dp[15] = v;
dp[16] = v; dp[17] = v; dp[18] = v; dp[19] = v;
dp[20] = v; dp[21] = v; dp[22] = v; dp[23] = v;
dp[24] = v; dp[25] = v; dp[26] = v; dp[27] = v;
dp[28] = v; dp[29] = v; dp[30] = v; dp[31] = v;
 
return;
}
/* Some other coefficient. */
 
#ifdef SPARSE_AC
dataptr = (DCTELEM *)data;
coeff = dataptr[pos];
ndataptr = PreIDCT[pos];
 
printf (" \n");
printf ("COEFFICIENT = %3d, POSITION = %2d\n", coeff, pos);
 
for (v=0; v<64; v++) {
memcpy((char *) tmpdata, data, 64*sizeof(DCTELEM));
}
tmpdataptr = (DCTELEM *)tmpdata;
 
for (v=0; v<64; v++) {
memcpy((char *) tmp2data, data, 64*sizeof(DCTELEM));
}
tmp2dataptr = (DCTELEM *)tmp2data;
 
#ifdef DEBUG
printf ("original DCTBLOCK:\n");
for (rr=0; rr<8; rr++) {
for (v=0; v<8; v++) {
if (dataptr[8*rr+v] != tmpdataptr[8*rr+v])
fprintf(stderr, "Error in copy\n");
printf ("%3d ", dataptr[8*rr+v]);
}
printf("\n");
}
#endif
 
printf("\n");
 
for (rr=0; rr<4; rr++) {
dataptr[0] = (ndataptr[0] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[1] = (ndataptr[1] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[2] = (ndataptr[2] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[3] = (ndataptr[3] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[4] = (ndataptr[4] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[5] = (ndataptr[5] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[6] = (ndataptr[6] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[7] = (ndataptr[7] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[8] = (ndataptr[8] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[9] = (ndataptr[9] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[10] = (ndataptr[10] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[11] = (ndataptr[11] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[12] = (ndataptr[12] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[13] = (ndataptr[13] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[14] = (ndataptr[14] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr[15] = (ndataptr[15] * coeff) >> SPARSE_SCALE_FACTOR;
dataptr += 16;
ndataptr += 16;
}
 
dataptr = (DCTELEM *) data;
 
#ifdef DEBUG
printf ("sparse IDCT:\n");
for (rr=0; rr<8; rr++) {
for (v=0; v<8; v++) {
printf ("%3d ", dataptr[8*rr+v]);
}
printf("\n");
}
printf("\n");
#endif /* DEBUG */
#else /* NO_SPARSE_AC */
#ifdef FLOATDCT
if (qualityFlag)
float_idct(data);
else
#endif /* FLOATDCT */
j_rev_dct(data);
#endif /* SPARSE_AC */
return;
 
}
 
#else
/*
*--------------------------------------------------------------
*
* j_rev_dct_sparse --
*
* Performs the original inverse DCT on one block of
* coefficients.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
j_rev_dct_sparse (data, pos)
DCTBLOCK data;
int pos;
{
j_rev_dct(data);
}
#endif /* SPARSE_DCT */
 
 
#ifndef FIVE_DCT
 
#ifndef ORIG_DCT
 
/*
*--------------------------------------------------------------
*
* j_rev_dct --
*
* The inverse DCT function.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
j_rev_dct (data)
DCTBLOCK data;
{
INT32 tmp0, tmp1, tmp2, tmp3;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 z1, z2, z3, z4, z5;
INT32 d0, d1, d2, d3, d4, d5, d6, d7;
register DCTELEM *dataptr;
int rowctr;
SHIFT_TEMPS
/* Pass 1: process rows. */
/* Note results are scaled up by sqrt(8) compared to a true IDCT; */
/* furthermore, we scale the results by 2**PASS1_BITS. */
 
dataptr = data;
 
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* Due to quantization, we will usually find that many of the input
* coefficients are zero, especially the AC terms. We can exploit this
* by short-circuiting the IDCT calculation for any row in which all
* the AC terms are zero. In that case each output is equal to the
* DC coefficient (with scale factor as needed).
* With typical images and quantization tables, half or more of the
* row DCT calculations can be simplified this way.
*/
 
register int *idataptr = (int*)dataptr;
d0 = dataptr[0];
d1 = dataptr[1];
if ((d1 == 0) && (idataptr[1] | idataptr[2] | idataptr[3]) == 0) {
/* AC terms all zero */
if (d0) {
/* Compute a 32 bit value to assign. */
DCTELEM dcval = (DCTELEM) (d0 << PASS1_BITS);
register int v = (dcval & 0xffff) | (dcval << 16);
idataptr[0] = v;
idataptr[1] = v;
idataptr[2] = v;
idataptr[3] = v;
}
dataptr += DCTSIZE; /* advance pointer to next row */
continue;
}
d2 = dataptr[2];
d3 = dataptr[3];
d4 = dataptr[4];
d5 = dataptr[5];
d6 = dataptr[6];
d7 = dataptr[7];
 
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
if (d6) {
if (d4) {
if (d2) {
if (d0) {
/* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
 
tmp0 = (d0 + d4) << CONST_BITS;
tmp1 = (d0 - d4) << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
} else {
/* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */
z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
 
tmp0 = d4 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp2 - tmp0;
tmp12 = -(tmp0 + tmp2);
}
} else {
if (d0) {
/* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
tmp3 = MULTIPLY(d6, FIX(0.541196100));
 
tmp0 = (d0 + d4) << CONST_BITS;
tmp1 = (d0 - d4) << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
} else {
/* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */
tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
tmp3 = MULTIPLY(d6, FIX(0.541196100));
 
tmp0 = d4 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp2 - tmp0;
tmp12 = -(tmp0 + tmp2);
}
}
} else {
if (d2) {
if (d0) {
/* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */
z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
 
tmp0 = d0 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
} else {
/* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */
z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
 
tmp10 = tmp3;
tmp13 = -tmp3;
tmp11 = tmp2;
tmp12 = -tmp2;
}
} else {
if (d0) {
/* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */
tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
tmp3 = MULTIPLY(d6, FIX(0.541196100));
 
tmp0 = d0 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
} else {
/* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */
tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
tmp3 = MULTIPLY(d6, FIX(0.541196100));
 
tmp10 = tmp3;
tmp13 = -tmp3;
tmp11 = tmp2;
tmp12 = -tmp2;
}
}
}
} else {
if (d4) {
if (d2) {
if (d0) {
/* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
tmp2 = MULTIPLY(d2, FIX(0.541196100));
tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
 
tmp0 = (d0 + d4) << CONST_BITS;
tmp1 = (d0 - d4) << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
} else {
/* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */
tmp2 = MULTIPLY(d2, FIX(0.541196100));
tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
 
tmp0 = d4 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp2 - tmp0;
tmp12 = -(tmp0 + tmp2);
}
} else {
if (d0) {
/* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
} else {
/* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */
tmp10 = tmp13 = d4 << CONST_BITS;
tmp11 = tmp12 = -tmp10;
}
}
} else {
if (d2) {
if (d0) {
/* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */
tmp2 = MULTIPLY(d2, FIX(0.541196100));
tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
 
tmp0 = d0 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
} else {
/* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */
tmp2 = MULTIPLY(d2, FIX(0.541196100));
tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
 
tmp10 = tmp3;
tmp13 = -tmp3;
tmp11 = tmp2;
tmp12 = -tmp2;
}
} else {
if (d0) {
/* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */
tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS;
} else {
/* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */
tmp10 = tmp13 = tmp11 = tmp12 = 0;
}
}
}
}
 
 
/* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
 
if (d7) {
if (d5) {
if (d3) {
if (d1) {
/* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */
z1 = d7 + d1;
z2 = d5 + d3;
z3 = d7 + d3;
z4 = d5 + d1;
z5 = MULTIPLY(z3 + z4, FIX(1.175875602));
tmp0 = MULTIPLY(d7, FIX(0.298631336));
tmp1 = MULTIPLY(d5, FIX(2.053119869));
tmp2 = MULTIPLY(d3, FIX(3.072711026));
tmp3 = MULTIPLY(d1, FIX(1.501321110));
z1 = MULTIPLY(z1, - FIX(0.899976223));
z2 = MULTIPLY(z2, - FIX(2.562915447));
z3 = MULTIPLY(z3, - FIX(1.961570560));
z4 = MULTIPLY(z4, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
} else {
/* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */
z2 = d5 + d3;
z3 = d7 + d3;
z5 = MULTIPLY(z3 + d5, FIX(1.175875602));
tmp0 = MULTIPLY(d7, FIX(0.298631336));
tmp1 = MULTIPLY(d5, FIX(2.053119869));
tmp2 = MULTIPLY(d3, FIX(3.072711026));
z1 = MULTIPLY(d7, - FIX(0.899976223));
z2 = MULTIPLY(z2, - FIX(2.562915447));
z3 = MULTIPLY(z3, - FIX(1.961570560));
z4 = MULTIPLY(d5, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 = z1 + z4;
}
} else {
if (d1) {
/* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */
z1 = d7 + d1;
z4 = d5 + d1;
z5 = MULTIPLY(d7 + z4, FIX(1.175875602));
tmp0 = MULTIPLY(d7, FIX(0.298631336));
tmp1 = MULTIPLY(d5, FIX(2.053119869));
tmp3 = MULTIPLY(d1, FIX(1.501321110));
z1 = MULTIPLY(z1, - FIX(0.899976223));
z2 = MULTIPLY(d5, - FIX(2.562915447));
z3 = MULTIPLY(d7, - FIX(1.961570560));
z4 = MULTIPLY(z4, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 = z2 + z3;
tmp3 += z1 + z4;
} else {
/* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */
z5 = MULTIPLY(d7 + d5, FIX(1.175875602));
 
tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
z1 = MULTIPLY(d7, - FIX(0.899976223));
z3 = MULTIPLY(d7, - FIX(1.961570560));
z2 = MULTIPLY(d5, - FIX(2.562915447));
z4 = MULTIPLY(d5, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z3;
tmp1 += z4;
tmp2 = z2 + z3;
tmp3 = z1 + z4;
}
}
} else {
if (d3) {
if (d1) {
/* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */
z1 = d7 + d1;
z3 = d7 + d3;
z5 = MULTIPLY(z3 + d1, FIX(1.175875602));
tmp0 = MULTIPLY(d7, FIX(0.298631336));
tmp2 = MULTIPLY(d3, FIX(3.072711026));
tmp3 = MULTIPLY(d1, FIX(1.501321110));
z1 = MULTIPLY(z1, - FIX(0.899976223));
z2 = MULTIPLY(d3, - FIX(2.562915447));
z3 = MULTIPLY(z3, - FIX(1.961570560));
z4 = MULTIPLY(d1, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 = z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
} else {
/* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */
z3 = d7 + d3;
z5 = MULTIPLY(z3, FIX(1.175875602));
tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
tmp2 = MULTIPLY(d3, FIX(0.509795579));
z1 = MULTIPLY(d7, - FIX(0.899976223));
z2 = MULTIPLY(d3, - FIX(2.562915447));
z3 = MULTIPLY(z3, - FIX2(0.785694958));
tmp0 += z3;
tmp1 = z2 + z5;
tmp2 += z3;
tmp3 = z1 + z5;
}
} else {
if (d1) {
/* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */
z1 = d7 + d1;
z5 = MULTIPLY(z1, FIX(1.175875602));
 
tmp0 = MULTIPLY(d7, - FIX2(1.662939224));
tmp3 = MULTIPLY(d1, FIX2(1.111140466));
z1 = MULTIPLY(z1, FIX2(0.275899379));
z3 = MULTIPLY(d7, - FIX(1.961570560));
z4 = MULTIPLY(d1, - FIX(0.390180644));
 
tmp0 += z1;
tmp1 = z4 + z5;
tmp2 = z3 + z5;
tmp3 += z1;
} else {
/* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */
tmp0 = MULTIPLY(d7, - FIX2(1.387039845));
tmp1 = MULTIPLY(d7, FIX(1.175875602));
tmp2 = MULTIPLY(d7, - FIX2(0.785694958));
tmp3 = MULTIPLY(d7, FIX2(0.275899379));
}
}
}
} else {
if (d5) {
if (d3) {
if (d1) {
/* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */
z2 = d5 + d3;
z4 = d5 + d1;
z5 = MULTIPLY(d3 + z4, FIX(1.175875602));
tmp1 = MULTIPLY(d5, FIX(2.053119869));
tmp2 = MULTIPLY(d3, FIX(3.072711026));
tmp3 = MULTIPLY(d1, FIX(1.501321110));
z1 = MULTIPLY(d1, - FIX(0.899976223));
z2 = MULTIPLY(z2, - FIX(2.562915447));
z3 = MULTIPLY(d3, - FIX(1.961570560));
z4 = MULTIPLY(z4, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 = z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
} else {
/* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */
z2 = d5 + d3;
z5 = MULTIPLY(z2, FIX(1.175875602));
tmp1 = MULTIPLY(d5, FIX2(1.662939225));
tmp2 = MULTIPLY(d3, FIX2(1.111140466));
z2 = MULTIPLY(z2, - FIX2(1.387039845));
z3 = MULTIPLY(d3, - FIX(1.961570560));
z4 = MULTIPLY(d5, - FIX(0.390180644));
tmp0 = z3 + z5;
tmp1 += z2;
tmp2 += z2;
tmp3 = z4 + z5;
}
} else {
if (d1) {
/* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */
z4 = d5 + d1;
z5 = MULTIPLY(z4, FIX(1.175875602));
tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
tmp3 = MULTIPLY(d1, FIX2(0.601344887));
z1 = MULTIPLY(d1, - FIX(0.899976223));
z2 = MULTIPLY(d5, - FIX(2.562915447));
z4 = MULTIPLY(z4, FIX2(0.785694958));
tmp0 = z1 + z5;
tmp1 += z4;
tmp2 = z2 + z5;
tmp3 += z4;
} else {
/* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */
tmp0 = MULTIPLY(d5, FIX(1.175875602));
tmp1 = MULTIPLY(d5, FIX2(0.275899380));
tmp2 = MULTIPLY(d5, - FIX2(1.387039845));
tmp3 = MULTIPLY(d5, FIX2(0.785694958));
}
}
} else {
if (d3) {
if (d1) {
/* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */
z5 = d3 + d1;
 
tmp2 = MULTIPLY(d3, - FIX(1.451774981));
tmp3 = MULTIPLY(d1, (FIX(0.211164243) - 1));
z1 = MULTIPLY(d1, FIX(1.061594337));
z2 = MULTIPLY(d3, - FIX(2.172734803));
z4 = MULTIPLY(z5, FIX(0.785694958));
z5 = MULTIPLY(z5, FIX(1.175875602));
tmp0 = z1 - z4;
tmp1 = z2 + z4;
tmp2 += z5;
tmp3 += z5;
} else {
/* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */
tmp0 = MULTIPLY(d3, - FIX2(0.785694958));
tmp1 = MULTIPLY(d3, - FIX2(1.387039845));
tmp2 = MULTIPLY(d3, - FIX2(0.275899379));
tmp3 = MULTIPLY(d3, FIX(1.175875602));
}
} else {
if (d1) {
/* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */
tmp0 = MULTIPLY(d1, FIX2(0.275899379));
tmp1 = MULTIPLY(d1, FIX2(0.785694958));
tmp2 = MULTIPLY(d1, FIX(1.175875602));
tmp3 = MULTIPLY(d1, FIX2(1.387039845));
} else {
/* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */
tmp0 = tmp1 = tmp2 = tmp3 = 0;
}
}
}
}
 
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
 
dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
 
dataptr += DCTSIZE; /* advance pointer to next row */
}
 
/* Pass 2: process columns. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
 
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* Columns of zeroes can be exploited in the same way as we did with rows.
* However, the row calculation has created many nonzero AC terms, so the
* simplification applies less often (typically 5% to 10% of the time).
* On machines with very fast multiplication, it's possible that the
* test takes more time than it's worth. In that case this section
* may be commented out.
*/
 
d0 = dataptr[DCTSIZE*0];
d1 = dataptr[DCTSIZE*1];
d2 = dataptr[DCTSIZE*2];
d3 = dataptr[DCTSIZE*3];
d4 = dataptr[DCTSIZE*4];
d5 = dataptr[DCTSIZE*5];
d6 = dataptr[DCTSIZE*6];
d7 = dataptr[DCTSIZE*7];
 
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
if (d6) {
if (d4) {
if (d2) {
if (d0) {
/* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
 
tmp0 = (d0 + d4) << CONST_BITS;
tmp1 = (d0 - d4) << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
} else {
/* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */
z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
 
tmp0 = d4 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp2 - tmp0;
tmp12 = -(tmp0 + tmp2);
}
} else {
if (d0) {
/* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
tmp3 = MULTIPLY(d6, FIX(0.541196100));
 
tmp0 = (d0 + d4) << CONST_BITS;
tmp1 = (d0 - d4) << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
} else {
/* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */
tmp2 = MULTIPLY(d6, -FIX2(1.306562965));
tmp3 = MULTIPLY(d6, FIX(0.541196100));
 
tmp0 = d4 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp2 - tmp0;
tmp12 = -(tmp0 + tmp2);
}
}
} else {
if (d2) {
if (d0) {
/* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */
z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
 
tmp0 = d0 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
} else {
/* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */
z1 = MULTIPLY(d2 + d6, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865));
 
tmp10 = tmp3;
tmp13 = -tmp3;
tmp11 = tmp2;
tmp12 = -tmp2;
}
} else {
if (d0) {
/* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */
tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
tmp3 = MULTIPLY(d6, FIX(0.541196100));
 
tmp0 = d0 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
} else {
/* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */
tmp2 = MULTIPLY(d6, - FIX2(1.306562965));
tmp3 = MULTIPLY(d6, FIX(0.541196100));
 
tmp10 = tmp3;
tmp13 = -tmp3;
tmp11 = tmp2;
tmp12 = -tmp2;
}
}
}
} else {
if (d4) {
if (d2) {
if (d0) {
/* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
tmp2 = MULTIPLY(d2, FIX(0.541196100));
tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
 
tmp0 = (d0 + d4) << CONST_BITS;
tmp1 = (d0 - d4) << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
} else {
/* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */
tmp2 = MULTIPLY(d2, FIX(0.541196100));
tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
 
tmp0 = d4 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp2 - tmp0;
tmp12 = -(tmp0 + tmp2);
}
} else {
if (d0) {
/* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
} else {
/* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */
tmp10 = tmp13 = d4 << CONST_BITS;
tmp11 = tmp12 = -tmp10;
}
}
} else {
if (d2) {
if (d0) {
/* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */
tmp2 = MULTIPLY(d2, FIX(0.541196100));
tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
 
tmp0 = d0 << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
} else {
/* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */
tmp2 = MULTIPLY(d2, FIX(0.541196100));
tmp3 = MULTIPLY(d2, (FIX(1.306562965) + .5));
 
tmp10 = tmp3;
tmp13 = -tmp3;
tmp11 = tmp2;
tmp12 = -tmp2;
}
} else {
if (d0) {
/* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */
tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS;
} else {
/* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */
tmp10 = tmp13 = tmp11 = tmp12 = 0;
}
}
}
}
 
/* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
if (d7) {
if (d5) {
if (d3) {
if (d1) {
/* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */
z1 = d7 + d1;
z2 = d5 + d3;
z3 = d7 + d3;
z4 = d5 + d1;
z5 = MULTIPLY(z3 + z4, FIX(1.175875602));
tmp0 = MULTIPLY(d7, FIX(0.298631336));
tmp1 = MULTIPLY(d5, FIX(2.053119869));
tmp2 = MULTIPLY(d3, FIX(3.072711026));
tmp3 = MULTIPLY(d1, FIX(1.501321110));
z1 = MULTIPLY(z1, - FIX(0.899976223));
z2 = MULTIPLY(z2, - FIX(2.562915447));
z3 = MULTIPLY(z3, - FIX(1.961570560));
z4 = MULTIPLY(z4, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
} else {
/* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */
z2 = d5 + d3;
z3 = d7 + d3;
z5 = MULTIPLY(z3 + d5, FIX(1.175875602));
tmp0 = MULTIPLY(d7, FIX(0.298631336));
tmp1 = MULTIPLY(d5, FIX(2.053119869));
tmp2 = MULTIPLY(d3, FIX(3.072711026));
z1 = MULTIPLY(d7, - FIX(0.899976223));
z2 = MULTIPLY(z2, - FIX(2.562915447));
z3 = MULTIPLY(z3, - FIX(1.961570560));
z4 = MULTIPLY(d5, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 = z1 + z4;
}
} else {
if (d1) {
/* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */
z1 = d7 + d1;
z4 = d5 + d1;
z5 = MULTIPLY(d7 + z4, FIX(1.175875602));
tmp0 = MULTIPLY(d7, FIX(0.298631336));
tmp1 = MULTIPLY(d5, FIX(2.053119869));
tmp3 = MULTIPLY(d1, FIX(1.501321110));
z1 = MULTIPLY(z1, - FIX(0.899976223));
z2 = MULTIPLY(d5, - FIX(2.562915447));
z3 = MULTIPLY(d7, - FIX(1.961570560));
z4 = MULTIPLY(z4, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 = z2 + z3;
tmp3 += z1 + z4;
} else {
/* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */
z5 = MULTIPLY(d5 + d7, FIX(1.175875602));
 
tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
z1 = MULTIPLY(d7, - FIX(0.899976223));
z3 = MULTIPLY(d7, - FIX(1.961570560));
z2 = MULTIPLY(d5, - FIX(2.562915447));
z4 = MULTIPLY(d5, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z3;
tmp1 += z4;
tmp2 = z2 + z3;
tmp3 = z1 + z4;
}
}
} else {
if (d3) {
if (d1) {
/* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */
z1 = d7 + d1;
z3 = d7 + d3;
z5 = MULTIPLY(z3 + d1, FIX(1.175875602));
tmp0 = MULTIPLY(d7, FIX(0.298631336));
tmp2 = MULTIPLY(d3, FIX(3.072711026));
tmp3 = MULTIPLY(d1, FIX(1.501321110));
z1 = MULTIPLY(z1, - FIX(0.899976223));
z2 = MULTIPLY(d3, - FIX(2.562915447));
z3 = MULTIPLY(z3, - FIX(1.961570560));
z4 = MULTIPLY(d1, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 = z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
} else {
/* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */
z3 = d7 + d3;
z5 = MULTIPLY(z3, FIX(1.175875602));
tmp0 = MULTIPLY(d7, - FIX2(0.601344887));
z1 = MULTIPLY(d7, - FIX(0.899976223));
tmp2 = MULTIPLY(d3, FIX(0.509795579));
z2 = MULTIPLY(d3, - FIX(2.562915447));
z3 = MULTIPLY(z3, - FIX2(0.785694958));
tmp0 += z3;
tmp1 = z2 + z5;
tmp2 += z3;
tmp3 = z1 + z5;
}
} else {
if (d1) {
/* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */
z1 = d7 + d1;
z5 = MULTIPLY(z1, FIX(1.175875602));
 
tmp0 = MULTIPLY(d7, - FIX2(1.662939224));
tmp3 = MULTIPLY(d1, FIX2(1.111140466));
z1 = MULTIPLY(z1, FIX2(0.275899379));
z3 = MULTIPLY(d7, - FIX(1.961570560));
z4 = MULTIPLY(d1, - FIX(0.390180644));
 
tmp0 += z1;
tmp1 = z4 + z5;
tmp2 = z3 + z5;
tmp3 += z1;
} else {
/* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */
tmp0 = MULTIPLY(d7, - FIX2(1.387039845));
tmp1 = MULTIPLY(d7, FIX(1.175875602));
tmp2 = MULTIPLY(d7, - FIX2(0.785694958));
tmp3 = MULTIPLY(d7, FIX2(0.275899379));
}
}
}
} else {
if (d5) {
if (d3) {
if (d1) {
/* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */
z2 = d5 + d3;
z4 = d5 + d1;
z5 = MULTIPLY(d3 + z4, FIX(1.175875602));
tmp1 = MULTIPLY(d5, FIX(2.053119869));
tmp2 = MULTIPLY(d3, FIX(3.072711026));
tmp3 = MULTIPLY(d1, FIX(1.501321110));
z1 = MULTIPLY(d1, - FIX(0.899976223));
z2 = MULTIPLY(z2, - FIX(2.562915447));
z3 = MULTIPLY(d3, - FIX(1.961570560));
z4 = MULTIPLY(z4, - FIX(0.390180644));
z3 += z5;
z4 += z5;
tmp0 = z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
} else {
/* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */
z2 = d5 + d3;
z5 = MULTIPLY(z2, FIX(1.175875602));
 
tmp1 = MULTIPLY(d5, FIX2(1.662939225));
tmp2 = MULTIPLY(d3, FIX2(1.111140466));
z2 = MULTIPLY(z2, - FIX2(1.387039845));
z3 = MULTIPLY(d3, - FIX(1.961570560));
z4 = MULTIPLY(d5, - FIX(0.390180644));
tmp0 = z3 + z5;
tmp1 += z2;
tmp2 += z2;
tmp3 = z4 + z5;
}
} else {
if (d1) {
/* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */
z4 = d5 + d1;
z5 = MULTIPLY(z4, FIX(1.175875602));
tmp1 = MULTIPLY(d5, - FIX2(0.509795578));
tmp3 = MULTIPLY(d1, FIX2(0.601344887));
z1 = MULTIPLY(d1, - FIX(0.899976223));
z2 = MULTIPLY(d5, - FIX(2.562915447));
z4 = MULTIPLY(z4, FIX2(0.785694958));
tmp0 = z1 + z5;
tmp1 += z4;
tmp2 = z2 + z5;
tmp3 += z4;
} else {
/* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */
tmp0 = MULTIPLY(d5, FIX(1.175875602));
tmp1 = MULTIPLY(d5, FIX2(0.275899380));
tmp2 = MULTIPLY(d5, - FIX2(1.387039845));
tmp3 = MULTIPLY(d5, FIX2(0.785694958));
}
}
} else {
if (d3) {
if (d1) {
/* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */
z5 = d3 + d1;
 
tmp2 = MULTIPLY(d3, - FIX(1.451774981));
tmp3 = MULTIPLY(d1, (FIX(0.211164243) - 1));
z1 = MULTIPLY(d1, FIX(1.061594337));
z2 = MULTIPLY(d3, - FIX(2.172734803));
z4 = MULTIPLY(z5, FIX(0.785694958));
z5 = MULTIPLY(z5, FIX(1.175875602));
tmp0 = z1 - z4;
tmp1 = z2 + z4;
tmp2 += z5;
tmp3 += z5;
} else {
/* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */
tmp0 = MULTIPLY(d3, - FIX2(0.785694958));
tmp1 = MULTIPLY(d3, - FIX2(1.387039845));
tmp2 = MULTIPLY(d3, - FIX2(0.275899379));
tmp3 = MULTIPLY(d3, FIX(1.175875602));
}
} else {
if (d1) {
/* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */
tmp0 = MULTIPLY(d1, FIX2(0.275899379));
tmp1 = MULTIPLY(d1, FIX2(0.785694958));
tmp2 = MULTIPLY(d1, FIX(1.175875602));
tmp3 = MULTIPLY(d1, FIX2(1.387039845));
} else {
/* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */
tmp0 = tmp1 = tmp2 = tmp3 = 0;
}
}
}
}
 
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
 
dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0,
CONST_BITS+PASS1_BITS+3);
dataptr++; /* advance pointer to next column */
}
}
 
#else
 
 
/*
*--------------------------------------------------------------
*
* j_rev_dct --
*
* The original inverse DCT function.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
j_rev_dct (data)
DCTBLOCK data;
{
INT32 tmp0, tmp1, tmp2, tmp3;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 z1, z2, z3, z4, z5;
register DCTELEM *dataptr;
int rowctr;
SHIFT_TEMPS
 
/* Pass 1: process rows. */
/* Note results are scaled up by sqrt(8) compared to a true IDCT; */
/* furthermore, we scale the results by 2**PASS1_BITS. */
 
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* Due to quantization, we will usually find that many of the input
* coefficients are zero, especially the AC terms. We can exploit this
* by short-circuiting the IDCT calculation for any row in which all
* the AC terms are zero. In that case each output is equal to the
* DC coefficient (with scale factor as needed).
* With typical images and quantization tables, half or more of the
* row DCT calculations can be simplified this way.
*/
 
if ((dataptr[1] | dataptr[2] | dataptr[3] | dataptr[4] |
dataptr[5] | dataptr[6] | dataptr[7]) == 0) {
/* AC terms all zero */
DCTELEM dcval = (DCTELEM) (dataptr[0] << PASS1_BITS);
dataptr[0] = dcval;
dataptr[1] = dcval;
dataptr[2] = dcval;
dataptr[3] = dcval;
dataptr[4] = dcval;
dataptr[5] = dcval;
dataptr[6] = dcval;
dataptr[7] = dcval;
dataptr += DCTSIZE; /* advance pointer to next row */
continue;
}
 
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
 
z2 = (INT32) dataptr[2];
z3 = (INT32) dataptr[6];
 
z1 = MULTIPLY(z2 + z3, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(z3, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(z2, FIX(0.765366865));
 
tmp0 = ((INT32) dataptr[0] + (INT32) dataptr[4]) << CONST_BITS;
tmp1 = ((INT32) dataptr[0] - (INT32) dataptr[4]) << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
/* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
 
tmp0 = (INT32) dataptr[7];
tmp1 = (INT32) dataptr[5];
tmp2 = (INT32) dataptr[3];
tmp3 = (INT32) dataptr[1];
 
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); /* sqrt(2) * c3 */
tmp0 = MULTIPLY(tmp0, FIX(0.298631336)); /* sqrt(2) * (-c1+c3+c5-c7) */
tmp1 = MULTIPLY(tmp1, FIX(2.053119869)); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX(3.072711026)); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX(1.501321110)); /* sqrt(2) * ( c1+c3-c5-c7) */
z1 = MULTIPLY(z1, - FIX(0.899976223)); /* sqrt(2) * (c7-c3) */
z2 = MULTIPLY(z2, - FIX(2.562915447)); /* sqrt(2) * (-c1-c3) */
z3 = MULTIPLY(z3, - FIX(1.961570560)); /* sqrt(2) * (-c3-c5) */
z4 = MULTIPLY(z4, - FIX(0.390180644)); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
 
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
 
dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
 
dataptr += DCTSIZE; /* advance pointer to next row */
}
 
/* Pass 2: process columns. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
 
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* Columns of zeroes can be exploited in the same way as we did with rows.
* However, the row calculation has created many nonzero AC terms, so the
* simplification applies less often (typically 5% to 10% of the time).
* On machines with very fast multiplication, it's possible that the
* test takes more time than it's worth. In that case this section
* may be commented out.
*/
 
#ifndef NO_ZERO_COLUMN_TEST
if ((dataptr[DCTSIZE*1] | dataptr[DCTSIZE*2] | dataptr[DCTSIZE*3] |
dataptr[DCTSIZE*4] | dataptr[DCTSIZE*5] | dataptr[DCTSIZE*6] |
dataptr[DCTSIZE*7]) == 0) {
/* AC terms all zero */
DCTELEM dcval = (DCTELEM) DESCALE((INT32) dataptr[0], PASS1_BITS+3);
dataptr[DCTSIZE*0] = dcval;
dataptr[DCTSIZE*1] = dcval;
dataptr[DCTSIZE*2] = dcval;
dataptr[DCTSIZE*3] = dcval;
dataptr[DCTSIZE*4] = dcval;
dataptr[DCTSIZE*5] = dcval;
dataptr[DCTSIZE*6] = dcval;
dataptr[DCTSIZE*7] = dcval;
dataptr++; /* advance pointer to next column */
continue;
}
#endif
 
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
 
z2 = (INT32) dataptr[DCTSIZE*2];
z3 = (INT32) dataptr[DCTSIZE*6];
 
z1 = MULTIPLY(z2 + z3, FIX(0.541196100));
tmp2 = z1 + MULTIPLY(z3, - FIX(1.847759065));
tmp3 = z1 + MULTIPLY(z2, FIX(0.765366865));
 
tmp0 = ((INT32) dataptr[DCTSIZE*0] + (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
tmp1 = ((INT32) dataptr[DCTSIZE*0] - (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
 
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
/* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
 
tmp0 = (INT32) dataptr[DCTSIZE*7];
tmp1 = (INT32) dataptr[DCTSIZE*5];
tmp2 = (INT32) dataptr[DCTSIZE*3];
tmp3 = (INT32) dataptr[DCTSIZE*1];
 
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); /* sqrt(2) * c3 */
tmp0 = MULTIPLY(tmp0, FIX(0.298631336)); /* sqrt(2) * (-c1+c3+c5-c7) */
tmp1 = MULTIPLY(tmp1, FIX(2.053119869)); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX(3.072711026)); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX(1.501321110)); /* sqrt(2) * ( c1+c3-c5-c7) */
z1 = MULTIPLY(z1, - FIX(0.899976223)); /* sqrt(2) * (c7-c3) */
z2 = MULTIPLY(z2, - FIX(2.562915447)); /* sqrt(2) * (-c1-c3) */
z3 = MULTIPLY(z3, - FIX(1.961570560)); /* sqrt(2) * (-c3-c5) */
z4 = MULTIPLY(z4, - FIX(0.390180644)); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
 
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
 
dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0,
CONST_BITS+PASS1_BITS+3);
dataptr++; /* advance pointer to next column */
}
}
 
 
#endif /* ORIG_DCT */
#endif /* FIVE_DCT */
 
/shark/trunk/ports/mpeg/animmpeg.h
0,0 → 1,114
/*
* Copyright (c) 1994 by Gregory P. Ward.
* All rights reserved.
*
* This file is part of the MNI front end of the Berkeley MPEG decoder.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
* UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER
* IS ON AN "AS IS" BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
*
* Original C version by Greg Ward <greg@pet.mni.mcgill.ca>,
* reentrant C++ version by Loring Holden <lsh@cs.brown.edu>
*
*/
 
#ifndef CPLUSPLUS_MPEG_WRAPPER
#include <stdio.h>
#include <errno.h>
#include <string.h>
extern "C" {
#include "video.h"
}
#include "ANIMbase.H"
 
#ifndef __STDC__
#define __STDC__
#endif
 
extern "C" {
#include "proto.h"
}
#undef const
 
extern "C" {
#include "dither.h"
#include "mpeg.h"
}
#undef const
 
const int BUF_LENGTH=100000;
 
class ANIMmpeg : public ANIMbase {
public:
ANIMmpeg(const char * const inFileName); //Makes a copy of the filename
ANIMmpeg(const ANIMmpeg& rhs); //Copy constructor (same
//movie, but at start)
virtual void newMovie(const char * const infile);
virtual Boolean open();
virtual void rewind();
virtual Boolean GetFrame(char **Frame, Boolean *newFrame);
virtual ~ANIMmpeg();
virtual void InitDither(unsigned long red_mask=0xff,
unsigned long green_mask=0xff00,
unsigned long blue_mask=0xff0000);
 
int BlockHeight; // in Macroblocks
int BlockWidth;
int Depth; // image depth (bits)
int PixelSize; // bits actually stored per pixel
int BitmapPad; // "quantum" of a scanline -- each scanline
// starts on an even interval of this
// many bits
int PictureRate; // required number of frames/sec [?]
int BitRate; // ???
 
private:
VidStream *vid_stream; // Pointer to the vid stream itself
 
void init(); // initialize the object
static void *RunDecode(void *ptr, void *ptr2); //Does the decoding
static int numMovies; // Total number of movies so far
void GetInfo();
void InitStream();
};
 
#define CPLUSPLUS_MPEG_WRAPPER
#endif
/shark/trunk/ports/mpeg/copyrigh
0,0 → 1,20
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/shark/trunk/ports/mpeg/threadmp.c
0,0 → 1,404
/*
* Copyright 1995, Brown University, Providence, RI
*
* Permission to use and modify this software and its documentation for
* any purpose other than its incorporation into a commercial product is
* hereby granted without fee. Permission to copy and distribute this
* software and its documentation only for non-commercial use is also
* granted without fee, provided, however, that the above copyright notice
* appear in all copies, that both that copyright notice and this permission
* notice appear in supporting documentation, that the name of Brown
* University not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission,
* and that the person doing the distribution notify Brown University of
* such distributions outside of his or her organization. Brown University
* makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
* Brown University requests notification of any modifications to this
* software or its documentation.
*
* Send the following redistribution information:
*
* Name:
* Organization:
* Address (postal and/or electronic):
*
* To:
* Software Librarian
* Computer Science Department, Box 1910
* Brown University
* Providence, RI 02912
*
* or
*
* brusd@cs.brown.edu
*
* We will acknowledge all electronic notifications.
*/
 
static char Version[] =
"$Id: threadmp.c,v 1.1.1.1 2002-03-29 14:12:59 pj Exp $";
static char Trick_to_use_Version() {char *unused = Version; return unused[0];}
 
/* -------------------------------------------------------------------------
*
* Original code by Tom Meyer
* Altered by Loring Holden to work with MPEGmovie object
*
* ------------------------------------------------------------------------- */
 
#include "thread_mp.H"
#include <iostream.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
 
#if defined(sol)
#elif defined(sgi)
usptr_t *THREADprocessor_arena;
#endif
 
/* ----------------------- Private Methods ------------------------------- */
//
// ------------ SOL-specific stuff ----------------------
//
#if defined(sol)
#ifdef CPLPLTHREADS
void THREAD_processor::startup()
{
while (1) {
sema->wait(__FILE__, __LINE__);
 
_start_routine(_arg,_arg2);
 
semaDone->post(__FILE__, __LINE__);
}
}
 
int THREAD_processor::wait_for_done()
{
semaDone->wait(__FILE__, __LINE__);
running=0;
return 1;
}
 
int THREAD_processor::still_running()
{
//try_wait returns 0 if semaphore could be decremented
// returns 1 if semaphore could not be decremented
if (semaDone->try_wait()) {
return 1;
} else {
running=0;
return 0;
}
}
#else
 
void *THREADprocessor_startup_func(void *proc)
{
((THREADprocessor *)proc)->startup_func();
return NULL;
}
 
void THREAD_processor::startup_func()
{
while (1) {
sema_wait(&sema);
 
_start_routine(_arg,_arg2);
 
sema_post(&semaDone);
}
}
 
int THREAD_processor::wait_for_done()
{
sema_wait(&semaDone);
running=0;
return 1;
}
 
int THREAD_processor::still_running()
{
//try_wait returns 0 if semaphore could be decremented
// returns 1 if semaphore could not be decremented
if (sema_trywait(&semaDone)) {
return 1;
} else {
running=0;
return 0;
}
}
#endif
 
char new_name[255];
 
THREAD_processor::THREAD_processor(char *name, char *thrname)
#if CPLPLTHREADS
: Thread (thrname)
#endif
{
#if CPLPLTHREADS
char *newname,*newname2;
 
newname = (char *)malloc(sizeof(char)*(strlen(name) + strlen("/sema")));
sprintf(newname, "%s/sema", name);
 
newname2 = (char *)malloc(sizeof(char)*(strlen(name) + strlen("/doneSema")));
sprintf(newname2, "%s/doneSema", name);
sema = new Semaphore(0, newname);
if (sema==NULL) {
cerr << "Could not allocate semaphore (sema)" << endl<<flush;
}
semaDone = new Semaphore(0, newname2);
if (semaDone==NULL) {
cerr << "Could not allocate semaphore (semaDone)" << endl<<flush;
}
make_runnable();
#else
sema_init(&sema, 0, USYNC_THREAD, NULL);
sema_init(&semaDone, 0, USYNC_THREAD, NULL);
thr_create(NULL, NULL, THREADprocessor_startup_func, (void *)this,
THR_BOUND, &thr);
#endif
running=0;
}
 
 
 
void THREAD_processor::start_execute(void *(*start_routine)(void *, void*),
void *arg, void* arg2)
{
if (running) {
fprintf(stderr,"start_execute: already executing\n");
fflush(stderr);
}
// cerr << "Waking up a process" << endl << flush;
_start_routine = start_routine;
_arg = arg;
_arg2 = arg2;
running=1;
#ifdef CPLPLTHREADS
sema->post(__FILE__, __LINE__);
#else
sema_post(&sema);
#endif
}
 
int THREAD_mp_manager::num_procs() const
{
return sysconf(_SC_NPROCESSORS_ONLN);
}
 
THREAD_mp_manager::THREAD_mp_manager(int _procs)
{
}
 
#elif defined(sgi)
//
// ------------ SGI-specific stuff ----------------------
//
 
void THREADprocessor_startup_func(void *proc)
{
((THREADprocessor *)proc)->startup();
}
 
void THREAD_processor::startup()
{
while (1) {
// Wait for us to get restarted
uspsema(_sema);
// Execute the routine that got left for us to do
_start_routine(_arg,_arg2);
// If someone's blocked on us, unblock them
usvsema(semaDone);
}
}
 
 
void THREAD_processor::start_execute(void *(*start_routine)(void *, void *),
void *arg, void *arg2)
{
_start_routine = start_routine;
_arg = arg;
_arg2 = arg2;
 
usvsema(_sema);
running=1;
}
 
int THREAD_processor::wait_for_done()
{
// Block the calling process
uspsema(semaDone);
running=0;
return 1;
}
 
int THREAD_processor::still_running()
{
if (ustestsema(semaDone)){
uspsema(semaDone);
running=0;
return 0;
} else {
return 1;
}
}
 
THREAD_processor::THREAD_processor(char *, char *)
{
_sema = usnewsema(THREADprocessor_arena,0); // Create our semaphore
semaDone = usnewsema(THREADprocessor_arena,0);
if (_sema==NULL) {
cerr << "problem allocating _sema" << endl;
}
if (semaDone==NULL) {
cerr << "problem allocating semaDone" << endl;
}
// Share all vertual space of the parent, Synchronize file open table
if (sproc(THREADprocessor_startup_func, PR_SADDR | PR_SFDS,
(void *)this)==-1) {
cerr << "sproc problem" << endl;
}
}
 
int THREAD_mp_manager::num_procs() const
{
return prctl(PR_MAXPPROCS);
}
 
THREAD_mp_manager::THREAD_mp_manager(int)
{
// Set us up so that everyone dies simultaneously
prctl(PR_SETEXITSIG, SIGQUIT);
 
// Allocate shared memory arena
usconfig(CONF_INITUSERS, num_procs()*2 + 8);
//Should not be a hard coded name in case we are running more than once
//on the same machine
 
char *tmpFile=tempnam("/tmp","THRED");
THREADprocessor_arena = usinit(tmpFile);
unlink(tmpFile);
free(tmpFile);
 
if (!THREADprocessor_arena) {
cerr << "fatal error, shared memory arena could not be created"<<endl;
exit(1);
}
}
 
#else
//
// ------------ Specific stuff for platforms without multi-threading support
//
THREAD_processor::THREAD_processor(char *, char *)
{
running=0;
}
 
void THREAD_processor::start_execute(void *(*start_routine)(void *, void*),
void *arg,void *arg2)
{
start_routine(arg,arg2);
}
 
void THREAD_processor::startup()
{
}
 
 
int THREAD_processor::wait_for_done() {
return 1;
}
 
int THREAD_processor::still_running()
{
return 1;
}
 
THREAD_mp_manager::THREAD_mp_manager(int)
{
cerr << "No multithreading..." << endl;
}
 
THREAD_mp_manager::num_procs() const
{
return 1;
}
 
#endif
 
//
// General stuff for all platforms
//
void
THREADmp_manager::THREADmp_initproc(int i) {
char *name, *thrname;
 
name = (char *)malloc(sizeof(char)*50);
thrname = (char *)malloc(sizeof(char)*50);
sprintf(name, "Proc_%d", i);
sprintf(thrname, "Proc_%d/thread", i);
procs[i] = new THREADprocessor(name, thrname);
enqThread(i);
}
 
void
THREADmp_manager::THREADmp_newproc()
{
procs=(THREADprocessor **) realloc((void *) procs,++_num_procs*
sizeof(THREADprocessor *));
THREADmp_initproc(_num_procs-1);
}
 
THREADmp_manager::THREADmp_manager(int _procs)
: THREAD_mp_manager(_procs)
{
cerr << "Creating mp manager\n";
if (_procs == 0) {
_num_procs = num_procs();
} else {
_num_procs = _procs;
}
 
cerr << "Num procs: " << num_procs() << endl << flush;
procs = (THREADprocessor **)malloc(sizeof(THREADprocessor *) *_num_procs);
for (int i = 0; i < _num_procs; i++) {
THREADmp_initproc(i);
}
cerr << "Done\n";
}
 
void
THREADmp_manager::enqThread(int threadNumber)
{
queue.enQueue(threadNumber);
}
 
int
THREADmp_manager::deqThread()
{
int itemOk;
int retVal=queue.deQueue(itemOk);
 
if (!itemOk) {
// This better allocate a thread, or we're not halting
THREADmp_newproc();
return deqThread();
} else return retVal;
}
 
THREADmp_manager::~THREADmp_manager()
{
for (int i = 0; i < _num_procs; i++)
delete procs[i];
free(procs);
}
/shark/trunk/ports/mpeg/video.c
0,0 → 1,4437
/*
* video.c --
*
* This file contains C code that implements the video decoder model.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
 
#ifndef MIPS
#include <sys/time.h>
#else
#include <sys/types.h>
#include <sys/system.h>
#endif
 
#ifndef NOCONTROLS
#include "ctrlbar.h"
#endif
#include "decoders.h"
#include "video.h"
#include "util.h"
#include "proto.h"
 
/* Declarations of functions. */
static void ReconIMBlock();
static void ReconPMBlock();
static void ReconBMBlock();
static void ReconBiMBlock();
static void ReconSkippedBlock();
static void DoPictureDisplay();
static int ParseSeqHead();
static int ParseGOP();
static int ParsePicture();
static int ParseSlice();
static int ParseMacroBlock();
static void ProcessSkippedPFrameMBlocks();
static void ProcessSkippedBFrameMBlocks();
 
/*
Changes to make the code reentrant:
de-globalized: totNumFrames, realTimeStart, matched_depth, ditherType,
curBits, ReconPMBlock statics, first, [lc]max[xy], ditherFlags,
vid_stream, Parse_done, seekValue, ReadPack static, sys_layer,
bitOffset, bitLength, bitBuffer, curVidStream,
X globals to xinfo (window, et al)
use vid_stream->film_has_ended instead of FilmState
lookup tables only initialized once, global as possible
(default_intra_matrix, zigzag, zigzag_direct, scan)
get rid of setjmp, long jmp
Additional changes:
if DISABLE_DITHER defined then do not compile dithering code
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
 
#define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
 
/* Set up array for fast conversion from zig zag order to row/column
coordinates.
*/
 
const int zigzag[64][2] = {
0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3,
2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4,
3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7,
1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6,
2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6,
7, 5, 7, 6, 6, 7, 7, 7};
/* Array mapping zigzag to array pointer offset. */
 
const int zigzag_direct[64] = {
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
/* Set up array for fast conversion from row/column coordinates to
zig zag order.
*/
 
const int scan[8][8] = {
{0, 1, 5, 6, 14, 15, 27, 28},
{2, 4, 7, 13, 16, 26, 29, 42},
{3, 8, 12, 17, 25, 30, 41, 43},
{9, 11, 18, 24, 31, 40, 44, 53},
{10, 19, 23, 32, 39, 45, 52, 54},
{20, 22, 33, 38, 46, 51, 55, 60},
{21, 34, 37, 47, 50, 56, 59, 61},
{35, 36, 48, 49, 57, 58, 62, 63}};
/* Initialize P and B skip flags. */
 
static int No_P_Flag = FALSE;
static int No_B_Flag = FALSE;
 
/* Max lum, chrom indices for illegal block checking. */
 
 
/*
* We use a lookup table to make sure values stay in the 0..255 range.
* Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
* table the "crop table".
* MAX_NEG_CROP is the maximum neg/pos value we can handle.
*/
 
#define MAX_NEG_CROP 2048
#define NUM_CROP_ENTRIES (2048+2*MAX_NEG_CROP)
static unsigned char cropTbl[NUM_CROP_ENTRIES];
 
/*
The following accounts for time and size spent in various parsing acitivites
if ANALYSIS has been defined.
*/
 
#ifdef ANALYSIS
 
 
unsigned int bitCount = 0;
 
int showmb_flag = 0;
int showEachFlag = 0;
 
typedef struct {
int frametype;
unsigned int totsize;
unsigned int number;
unsigned int i_mbsize;
unsigned int p_mbsize;
unsigned int b_mbsize;
unsigned int bi_mbsize;
unsigned int i_mbnum;
unsigned int p_mbnum;
unsigned int b_mbnum;
unsigned int bi_mbnum;
unsigned int i_mbcbp[64];
unsigned int p_mbcbp[64];
unsigned int b_mbcbp[64];
unsigned int bi_mbcbp[64];
unsigned int i_mbcoeff[64];
unsigned int p_mbcoeff[64];
unsigned int b_mbcoeff[64];
unsigned int bi_mbcoeff[64];
double tottime;
} Statval;
 
Statval stat_a[4];
unsigned int pictureSizeCount;
unsigned int mbSizeCount;
unsigned int *mbCBPPtr, *mbCoeffPtr, *mbSizePtr;
unsigned int cacheHit[8][8];
unsigned int cacheMiss[8][8];
 
static void
init_stat_struct(astat)
Statval *astat;
{
int j;
 
astat->frametype = 0;
astat->totsize = 0;
astat->number = 0;
astat->i_mbsize = 0;
astat->p_mbsize = 0;
astat->b_mbsize = 0;
astat->bi_mbsize = 0;
astat->i_mbnum = 0;
astat->p_mbnum = 0;
astat->b_mbnum = 0;
astat->bi_mbnum = 0;
 
for (j = 0; j < 64; j++) {
 
astat->i_mbcbp[j] = 0;
astat->p_mbcbp[j] = 0;
astat->b_mbcbp[j] = 0;
astat->bi_mbcbp[j] = 0;
astat->i_mbcoeff[j] = 0;
astat->p_mbcoeff[j] = 0;
astat->b_mbcoeff[j] = 0;
astat->bi_mbcoeff[j] = 0;
}
astat->tottime = 0.0;
}
 
void
init_stats()
{
int i, j;
 
for (i = 0; i < 4; i++) {
init_stat_struct(&(stat_a[i]));
stat_a[i].frametype = i;
}
 
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
cacheHit[i][j] = 0;
cacheMiss[i][j] = 0;
}
}
 
bitCount = 0;
}
 
static void
PrintOneStat()
{
int i;
 
printf("\n");
switch (stat_a[0].frametype) {
case I_TYPE:
printf("I FRAME\n");
break;
case P_TYPE:
printf("P FRAME\n");
break;
case B_TYPE:
printf("B FRAME\n");
break;
}
 
printf("Size: %d bytes + %d bits\n", stat_a[0].totsize / 8, stat_a[0].totsize % 8);
if (stat_a[0].i_mbnum > 0) {
printf("\tI Macro Block Stats:\n");
printf("\t%d I Macroblocks\n", stat_a[0].i_mbnum);
printf("\tAvg. Size: %d bytes + %d bits\n",
stat_a[0].i_mbsize / (8 * stat_a[0].i_mbnum),
(stat_a[0].i_mbsize * stat_a[0].i_mbnum) % 8);
printf("\t\tCoded Block Pattern Histogram:\n");
for (i = 0; i < 64; i += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcbp[i],
stat_a[0].i_mbcbp[i + 1], stat_a[0].i_mbcbp[i + 2], stat_a[0].i_mbcbp[i + 3],
stat_a[0].i_mbcbp[i + 4], stat_a[0].i_mbcbp[i + 5], stat_a[0].i_mbcbp[i + 6],
stat_a[0].i_mbcbp[i + 7]);
}
printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
for (i = 0; i < 64; i += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcoeff[i],
stat_a[0].i_mbcoeff[i + 1], stat_a[0].i_mbcoeff[i + 2],
stat_a[0].i_mbcoeff[i + 3], stat_a[0].i_mbcoeff[i + 4],
stat_a[0].i_mbcoeff[i + 5], stat_a[0].i_mbcoeff[i + 6],
stat_a[0].i_mbcoeff[i + 7]);
}
}
if (stat_a[0].p_mbnum > 0) {
printf("\tP Macro Block Stats:\n");
printf("\t%d P Macroblocks\n", stat_a[0].p_mbnum);
printf("\tAvg. Size: %d bytes + %d bits\n",
stat_a[0].p_mbsize / (8 * stat_a[0].p_mbnum),
(stat_a[0].p_mbsize / stat_a[0].p_mbnum) % 8);
printf("\t\tCoded Block Pattern Histogram:\n");
for (i = 0; i < 64; i += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcbp[i],
stat_a[0].p_mbcbp[i + 1], stat_a[0].p_mbcbp[i + 2], stat_a[0].p_mbcbp[i + 3],
stat_a[0].p_mbcbp[i + 4], stat_a[0].p_mbcbp[i + 5], stat_a[0].p_mbcbp[i + 6],
stat_a[0].p_mbcbp[i + 7]);
}
printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
for (i = 0; i < 64; i += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcoeff[i],
stat_a[0].p_mbcoeff[i + 1], stat_a[0].p_mbcoeff[i + 2],
stat_a[0].p_mbcoeff[i + 3], stat_a[0].p_mbcoeff[i + 4],
stat_a[0].p_mbcoeff[i + 5], stat_a[0].p_mbcoeff[i + 6],
stat_a[0].p_mbcoeff[i + 7]);
}
}
if (stat_a[0].b_mbnum > 0) {
printf("\tB Macro Block Stats:\n");
printf("\t%d B Macroblocks\n", stat_a[0].b_mbnum);
printf("\tAvg. Size: %d bytes + %d bits\n",
stat_a[0].b_mbsize / (8 * stat_a[0].b_mbnum),
(stat_a[0].b_mbsize / stat_a[0].b_mbnum) % 8);
printf("\t\tCoded Block Pattern Histogram:\n");
for (i = 0; i < 64; i += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcbp[i],
stat_a[0].b_mbcbp[i + 1], stat_a[0].b_mbcbp[i + 2], stat_a[0].b_mbcbp[i + 3],
stat_a[0].b_mbcbp[i + 4], stat_a[0].b_mbcbp[i + 5], stat_a[0].b_mbcbp[i + 6],
stat_a[0].b_mbcbp[i + 7]);
}
printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
for (i = 0; i < 64; i += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcoeff[i],
stat_a[0].b_mbcoeff[i + 1], stat_a[0].b_mbcoeff[i + 2],
stat_a[0].b_mbcoeff[i + 3], stat_a[0].b_mbcoeff[i + 4],
stat_a[0].b_mbcoeff[i + 5], stat_a[0].b_mbcoeff[i + 6],
stat_a[0].b_mbcoeff[i + 7]);
}
}
if (stat_a[0].bi_mbnum > 0) {
printf("\tBi Macro Block Stats:\n");
printf("\t%d Bi Macroblocks\n", stat_a[0].bi_mbnum);
printf("\tAvg. Size: %d bytes + %d bits\n",
stat_a[0].bi_mbsize / (8 * stat_a[0].bi_mbnum),
(stat_a[0].bi_mbsize * stat_a[0].bi_mbnum) % 8);
printf("\t\tCoded Block Pattern Histogram:\n");
for (i = 0; i < 64; i += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcbp[i],
stat_a[0].bi_mbcbp[i + 1], stat_a[0].bi_mbcbp[i + 2], stat_a[0].bi_mbcbp[i + 3],
stat_a[0].bi_mbcbp[i + 4], stat_a[0].bi_mbcbp[i + 5], stat_a[0].bi_mbcbp[i + 6],
stat_a[0].bi_mbcbp[i + 7]);
}
printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
for (i = 0; i < 64; i += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcoeff[i],
stat_a[0].bi_mbcoeff[i + 1], stat_a[0].bi_mbcoeff[i + 2],
stat_a[0].bi_mbcoeff[i + 3], stat_a[0].bi_mbcoeff[i + 4],
stat_a[0].bi_mbcoeff[i + 5], stat_a[0].bi_mbcoeff[i + 6],
stat_a[0].bi_mbcoeff[i + 7]);
}
}
printf("\nTime to Decode: %g secs.\n", stat_a[0].tottime);
printf("****************\n");
}
 
void
PrintAllStats(vid_stream)
VidStream *vid_stream;
{
int i, j;
unsigned int supertot, supernum;
double supertime;
 
printf("\n");
printf("General Info: \n");
printf("Width: %d\nHeight: %d\n", vid_stream->mb_width * 16, vid_stream->mb_height * 16);
 
for (i = 1; i < 4; i++) {
 
if (stat_a[i].number == 0)
continue;
 
switch (i) {
case 1:
printf("I FRAMES\n");
break;
case 2:
printf("P FRAMES\n");
break;
case 3:
printf("B FRAMES\n");
break;
}
 
printf("Number: %d\n", stat_a[i].number);
printf("Avg. Size: %d bytes + %d bits\n",
stat_a[i].totsize / (8 * stat_a[i].number), (stat_a[i].totsize / stat_a[i].number) % 8);
if (stat_a[i].i_mbnum > 0) {
printf("\tI Macro Block Stats:\n");
printf("\t%d I Macroblocks\n", stat_a[i].i_mbnum);
printf("\tAvg. Size: %d bytes + %d bits\n",
stat_a[i].i_mbsize / (8 * stat_a[i].i_mbnum),
(stat_a[i].i_mbsize / stat_a[i].i_mbnum) % 8);
printf("\t\tCoded Block Pattern Histogram:\n");
for (j = 0; j < 64; j += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcbp[j],
stat_a[i].i_mbcbp[j + 1], stat_a[i].i_mbcbp[j + 2], stat_a[i].i_mbcbp[j + 3],
stat_a[i].i_mbcbp[j + 4], stat_a[i].i_mbcbp[j + 5], stat_a[i].i_mbcbp[j + 6],
stat_a[i].i_mbcbp[j + 7]);
}
printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
for (j = 0; j < 64; j += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcoeff[j],
stat_a[i].i_mbcoeff[j + 1], stat_a[i].i_mbcoeff[j + 2],
stat_a[i].i_mbcoeff[j + 3], stat_a[i].i_mbcoeff[j + 4],
stat_a[i].i_mbcoeff[j + 5], stat_a[i].i_mbcoeff[j + 6],
stat_a[i].i_mbcoeff[j + 7]);
}
}
if (stat_a[i].p_mbnum > 0) {
printf("\tP Macro Block Stats:\n");
printf("\t%d P Macroblocks\n", stat_a[i].p_mbnum);
printf("\tAvg. Size: %d bytes + %d bits\n",
stat_a[i].p_mbsize / (8 * stat_a[i].p_mbnum),
(stat_a[i].p_mbsize / stat_a[i].p_mbnum) % 8);
printf("\t\tCoded Block Pattern Histogram:\n");
for (j = 0; j < 64; j += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcbp[j],
stat_a[i].p_mbcbp[j + 1], stat_a[i].p_mbcbp[j + 2], stat_a[i].p_mbcbp[j + 3],
stat_a[i].p_mbcbp[j + 4], stat_a[i].p_mbcbp[j + 5], stat_a[i].p_mbcbp[j + 6],
stat_a[i].p_mbcbp[j + 7]);
}
printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
for (j = 0; j < 64; j += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcoeff[j],
stat_a[i].p_mbcoeff[j + 1], stat_a[i].p_mbcoeff[j + 2],
stat_a[i].p_mbcoeff[j + 3], stat_a[i].p_mbcoeff[j + 4],
stat_a[i].p_mbcoeff[j + 5], stat_a[i].p_mbcoeff[j + 6],
stat_a[i].p_mbcoeff[j + 7]);
}
}
if (stat_a[i].b_mbnum > 0) {
printf("\tB Macro Block Stats:\n");
printf("\t%d B Macroblocks\n", stat_a[i].b_mbnum);
printf("\tAvg. Size: %d bytes + %d bits\n",
stat_a[i].b_mbsize / (8 * stat_a[i].b_mbnum),
(stat_a[i].b_mbsize * stat_a[i].b_mbnum) % 8);
printf("\t\tCoded Block Pattern Histogram:\n");
for (j = 0; j < 64; j += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcbp[j],
stat_a[i].b_mbcbp[j + 1], stat_a[i].b_mbcbp[j + 2], stat_a[i].b_mbcbp[j + 3],
stat_a[i].b_mbcbp[j + 4], stat_a[i].b_mbcbp[j + 5], stat_a[i].b_mbcbp[j + 6],
stat_a[i].b_mbcbp[j + 7]);
}
printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
for (j = 0; j < 64; j += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcoeff[j],
stat_a[i].b_mbcoeff[j + 1], stat_a[i].b_mbcoeff[j + 2],
stat_a[i].b_mbcoeff[j + 3], stat_a[i].b_mbcoeff[j + 4],
stat_a[i].b_mbcoeff[j + 5], stat_a[i].b_mbcoeff[j + 6],
stat_a[i].b_mbcoeff[j + 7]);
}
}
if (stat_a[i].bi_mbnum > 0) {
printf("\tBi Macro Block Stats:\n");
printf("\t%d Bi Macroblocks\n", stat_a[i].bi_mbnum);
printf("\tAvg. Size: %d bytes + %d bits\n",
stat_a[i].bi_mbsize / (8 * stat_a[i].bi_mbnum),
(stat_a[i].bi_mbsize * stat_a[i].bi_mbnum) % 8);
printf("\t\tCoded Block Pattern Histogram:\n");
for (j = 0; j < 64; j += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcbp[j],
stat_a[i].bi_mbcbp[j + 1], stat_a[i].bi_mbcbp[j + 2], stat_a[i].bi_mbcbp[j + 3],
stat_a[i].bi_mbcbp[j + 4], stat_a[i].bi_mbcbp[j + 5], stat_a[i].bi_mbcbp[j + 6],
stat_a[i].bi_mbcbp[j + 7]);
}
printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
for (j = 0; j < 64; j += 8) {
printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcoeff[j],
stat_a[i].bi_mbcoeff[j + 1], stat_a[i].bi_mbcoeff[j + 2],
stat_a[i].bi_mbcoeff[j + 3], stat_a[i].bi_mbcoeff[j + 4],
stat_a[i].bi_mbcoeff[j + 5], stat_a[i].bi_mbcoeff[j + 6],
stat_a[i].bi_mbcoeff[j + 7]);
}
}
printf("\nAvg. Time to Decode: %f secs.\n",
(stat_a[i].tottime / ((double) stat_a[i].number)));
printf("\n");
printf("*************************\n\n");
}
 
supertot = stat_a[1].totsize + stat_a[2].totsize + stat_a[3].totsize;
supernum = stat_a[1].number + stat_a[2].number + stat_a[3].number;
supertime = stat_a[1].tottime + stat_a[2].tottime + stat_a[3].tottime;
 
printf("Total Number of Frames: %d\n", supernum);
printf("Avg Frame Size: %d bytes %d bits\n",
supertot / (8 * supernum), (supertot / supernum) % 8);
printf("Total Time Decoding: %g secs.\n", supertime);
printf("Avg Decoding Time/Frame: %g secs.\n", supertime / ((double) supernum));
printf("Avg Decoding Frames/Sec: %g secs.\n", ((double) supernum) / supertime);
printf("\n");
 
printf("Cache Hits/Miss\n");
for (i = 0; i < 8; i++) {
printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
cacheHit[i][0], cacheMiss[i][0], cacheHit[i][1], cacheMiss[i][1],
cacheHit[i][2], cacheMiss[i][2], cacheHit[i][3], cacheMiss[i][3]);
printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
cacheHit[i][4], cacheMiss[i][4], cacheHit[i][5], cacheMiss[i][5],
cacheHit[i][6], cacheMiss[i][6], cacheHit[i][7], cacheMiss[i][7]);
}
 
}
 
static void
CollectStats()
{
int i, j;
 
i = stat_a[0].frametype;
 
stat_a[i].totsize += stat_a[0].totsize;
stat_a[i].number += stat_a[0].number;
stat_a[i].i_mbsize += stat_a[0].i_mbsize;
stat_a[i].p_mbsize += stat_a[0].p_mbsize;
stat_a[i].b_mbsize += stat_a[0].b_mbsize;
stat_a[i].bi_mbsize += stat_a[0].bi_mbsize;
stat_a[i].i_mbnum += stat_a[0].i_mbnum;
stat_a[i].p_mbnum += stat_a[0].p_mbnum;
stat_a[i].b_mbnum += stat_a[0].b_mbnum;
stat_a[i].bi_mbnum += stat_a[0].bi_mbnum;
 
for (j = 0; j < 64; j++) {
 
stat_a[i].i_mbcbp[j] += stat_a[0].i_mbcbp[j];
stat_a[i].p_mbcbp[j] += stat_a[0].p_mbcbp[j];
stat_a[i].b_mbcbp[j] += stat_a[0].b_mbcbp[j];
stat_a[i].bi_mbcbp[j] += stat_a[0].bi_mbcbp[j];
stat_a[i].i_mbcoeff[j] += stat_a[0].i_mbcoeff[j];
stat_a[i].p_mbcoeff[j] += stat_a[0].p_mbcoeff[j];
stat_a[i].b_mbcoeff[j] += stat_a[0].b_mbcoeff[j];
stat_a[i].bi_mbcoeff[j] += stat_a[0].bi_mbcoeff[j];
}
 
stat_a[i].tottime += stat_a[0].tottime;
 
init_stat_struct(&(stat_a[0]));
}
 
static unsigned int
bitCountRead()
{
return bitCount;
}
 
static void
StartTime()
{
stat_a[0].tottime = ReadSysClock();
}
 
static void
EndTime()
{
stat_a[0].tottime = ReadSysClock() - stat_a[0].tottime;
}
#endif
 
/*
*--------------------------------------------------------------
*
* ReadSysClock --
*
* Computes the current time according to the system clock.
*
* Results:
* The current time according to the system clock.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
double
ReadSysClock()
{
extern long sys_gettime(void*);
/*struct timeval tv;
(void) gettimeofday(&tv, (struct timezone *)NULL);
return (tv.tv_sec + tv.tv_usec / 1000000.0);*/
//return sys_time();
return sys_gettime(NULL)/1000000.0;
}
 
/*
*--------------------------------------------------------------
*
* PrintTimeInfo --
*
* Displays statistics regarding the video playback time.
*
* Results:
* Outputs time statistics to the screen.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
PrintTimeInfo(vid_stream)
VidStream *vid_stream;
{
double spent;
 
#ifndef NOCONTROLS
if (ControlShow != CTRLBAR_NONE)
spent = StopWatch(STOPWATCH_STOP);
else
spent = ReadSysClock() - vid_stream->realTimeStart;
#else
spent = ReadSysClock() - vid_stream->realTimeStart;
#endif
if (!quietFlag) {
printf("\nReal Time Spent (After Initializations): %f secs.\n", spent);
printf("Avg. Frames/Sec: %f\n",
((double) vid_stream->totNumFrames) / spent);
}
}
 
/*
*--------------------------------------------------------------
*
* InitCrop --
*
* Initializes cropTbl - this was taken from newVidStream so
* that it wasn't done for each new video stream
*
* Results:
* None
*
* Side effects:
* cropTbl will be initialized
*
*--------------------------------------------------------------
*/
void
InitCrop()
{
int i;
 
/* Initialize crop table. */
 
for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) {
if (i <= 0) {
cropTbl[i + MAX_NEG_CROP] = 0;
#ifdef TWELVE_BITS
} else if (i >= 2047) {
cropTbl[i + MAX_NEG_CROP] = 2047;
#endif
} else if (i >= 255) {
cropTbl[i + MAX_NEG_CROP] = 255;
} else {
cropTbl[i + MAX_NEG_CROP] = i;
}
}
 
}
 
 
/*
*--------------------------------------------------------------
*
* NewVidStream --
*
* Allocates and initializes a VidStream structure. Takes
* as parameter requested size for buffer length.
*
* Results:
* A pointer to the new VidStream structure.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
VidStream *
NewVidStream(buffer_len)
unsigned int buffer_len;
{
int i, j;
VidStream *new;
static const unsigned char default_intra_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};
 
/* Check for legal buffer length. */
 
if (buffer_len < 4)
return NULL;
 
/* Make buffer length multiple of 4. */
 
buffer_len = (buffer_len + 3) >> 2;
 
/* Allocate memory for new structure. */
 
new = (VidStream *) malloc(sizeof(VidStream));
 
/* Initialize pointers to extension and user data. */
 
new->group.ext_data = new->group.user_data =
new->picture.extra_info = new->picture.user_data =
new->picture.ext_data = new->slice.extra_info =
new->ext_data = new->user_data = NULL;
 
/* Copy default intra matrix. */
 
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
new->intra_quant_matrix[i][j] = default_intra_matrix[i * 8 + j];
}
}
 
/* Initialize non intra quantization matrix. */
 
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
new->non_intra_quant_matrix[i][j] = 16;
}
}
 
/* Initialize pointers to image spaces. */
 
new->current = new->past = new->future = NULL;
for (i = 0; i < RING_BUF_SIZE; i++) {
new->ring[i] = NULL;
}
 
/* Create buffer. */
new->buf_start = (unsigned int *) malloc(buffer_len * 4);
 
/*
* Set max_buf_length to one less than actual length to deal with messy
* data without proper seq. end codes.
*/
 
new->max_buf_length = buffer_len - 1;
 
/* Initialize bitstream i/o fields. */
 
new->bit_offset = 0;
new->buf_length = 0;
new->buffer = new->buf_start;
 
/* Initialize fields that used to be global */
new->film_has_ended = FALSE;
new->filename = NULL;
new->totNumFrames = 0;
new->ditherFlags = NULL;
new->EOF_flag = FALSE;
 
/* Return structure. */
 
return new;
}
 
 
/*
*--------------------------------------------------------------
*
* ResetVidStream --
*
* Re-initializes a VidStream structure. Takes
* as parameter a pointer to the VidStream to reset.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
ResetVidStream(vid)
VidStream *vid;
{
int i;
 
/* Initialize pointers to image spaces. */
vid->current = vid->past = vid->future = NULL;
 
/* Initialize rings */
for (i = 0; i < RING_BUF_SIZE; i++)
vid->ring[i]->locked = 0; /* Unlock */
 
/* Initialize bitstream i/o fields. */
vid->bit_offset = vid->buf_length = 0;
vid->buffer = vid->buf_start;
vid->curBits = 0;
 
/* We are at the beginning of the film, so film has not ended */
vid->film_has_ended = FALSE;
 
/* Initialize start time */
vid->realTimeStart = ReadSysClock();
 
/* Reset number of frames to zero */
vid->totNumFrames=0;
 
/* Reset EOF_flag to 0 */
vid->EOF_flag = 0;
}
 
/*
*--------------------------------------------------------------
*
* DestroyVidStream --
*
* Deallocates a VidStream structure.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
DestroyVidStream(astream, xinfo)
VidStream *astream;
XInfo *xinfo;
{
int i;
 
if (astream->ext_data != NULL)
free(astream->ext_data);
 
if (astream->user_data != NULL)
free(astream->user_data);
 
if (astream->group.ext_data != NULL)
free(astream->group.ext_data);
 
if (astream->group.user_data != NULL)
free(astream->group.user_data);
 
if (astream->picture.extra_info != NULL)
free(astream->picture.extra_info);
 
if (astream->picture.ext_data != NULL)
free(astream->picture.ext_data);
 
if (astream->picture.user_data != NULL)
free(astream->picture.user_data);
 
if (astream->slice.extra_info != NULL)
free(astream->slice.extra_info);
 
if (astream->buf_start != NULL)
free(astream->buf_start);
 
for (i = 0; i < RING_BUF_SIZE; i++) {
if (astream->ring[i] != NULL) {
DestroyPictImage(astream->ring[i], xinfo);
astream->ring[i] = NULL;
}
}
 
if (astream->ditherFlags !=NULL)
free(astream->ditherFlags);
 
free((char *) astream);
}
 
 
 
/*
*--------------------------------------------------------------
*
* NewPictImage --
*
* Allocates and initializes a PictImage structure.
* The width and height of the image space are passed in
* as parameters.
*
* Results:
* A pointer to the new PictImage structure.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
PictImage *
NewPictImage(vid_stream,xinfo)
VidStream *vid_stream;
XInfo *xinfo;
{
PictImage *new;
int ditherType=vid_stream->ditherType;
unsigned int width=vid_stream->mb_width * 16;
unsigned int height=vid_stream->mb_height * 16;
#ifdef SH_MEM
Display *display=xinfo->display;
#endif
 
/* Allocate memory space for new structure. */
 
new = (PictImage *) malloc(sizeof(PictImage));
 
 
/* Allocate memory for image spaces. */
 
#ifdef SH_MEM
new->ximage = NULL;
if (shmemFlag) {
Visual *fc_visual;
int depth;
/*
* factor is 1 or 2
*/
int factor = 1 + IS_2x2_DITHER(ditherType);
 
Visual *FindFullColorVisual();
#ifndef DISABLE_DITHER
if (ditherType == FULL_COLOR_DITHER || ditherType == FULL_COLOR2_DITHER) {
#endif
fc_visual = FindFullColorVisual(display, &depth);
new->ximage = XShmCreateImage(display, fc_visual, (unsigned int) depth,
ZPixmap,
NULL, &(new->shminfo), width * factor,
height * factor);
#ifndef DISABLE_DITHER
} else if (ditherType == FULL_COLOR2_DITHER) {
fc_visual = FindFullColorVisual(display, &depth);
new->ximage = XShmCreateImage(display, fc_visual, (unsigned int) depth,
ZPixmap,
NULL, &(new->shminfo), width*2, height*2);
} else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
new->ximage = XShmCreateImage(display, None, 1, XYBitmap,
NULL, &(new->shminfo), width * factor,
height * factor);
} else {
new->ximage = XShmCreateImage(display, None, xinfo->depth, ZPixmap, NULL,
&(new->shminfo), width * factor,
height * factor);
}
#endif
 
/* If no go, then revert to normal Xlib calls. */
if (new->ximage == NULL) {
shmemFlag = 0;
if (!quietFlag) {
fprintf(stderr, "Shared memory error, disabling.\n");
fprintf(stderr, "Ximage error.\n");
}
goto shmemerror;
}
 
/* Success here, continue. */
 
#ifdef LITTLE_ENDIAN_ARCHITECTURE
new->ximage->byte_order = LSBFirst;
new->ximage->bitmap_bit_order = LSBFirst;
#else
new->ximage->byte_order = MSBFirst;
new->ximage->bitmap_bit_order = MSBFirst;
#endif
new->shminfo.shmid = shmget(IPC_PRIVATE, (unsigned int) (new->ximage->bytes_per_line *
new->ximage->height),
IPC_CREAT | 0777);
if (new->shminfo.shmid < 0) {
XDestroyImage(new->ximage);
new->ximage = NULL;
shmemFlag = 0;
if (!quietFlag) {
fprintf(stderr, "Shared memory error, disabling.\n");
fprintf(stderr, "Seg. id. error.\n");
}
goto shmemerror;
}
 
new->shminfo.shmaddr = (char *) shmat(new->shminfo.shmid, 0, 0);
 
if (new->shminfo.shmaddr == ((char *) -1)) {
XDestroyImage(new->ximage);
new->ximage = NULL;
shmemFlag = 0;
if (!quietFlag) {
fprintf(stderr, "Shared memory error, disabling.\n");
fprintf(stderr, "Address error.\n");
}
goto shmemerror;
}
 
new->ximage->data = new->shminfo.shmaddr;
new->display = (unsigned char *) new->ximage->data;
new->shminfo.readOnly = False;
 
XShmAttach(display, &(new->shminfo));
XSync(display, False);
 
if (gXErrorFlag) {
/* Ultimate failure here. */
XShmDetach(display,&(new->shminfo));
XSync(display, False);
XDestroyImage(new->ximage);
shmdt (new->shminfo.shmaddr);
shmctl (new->shminfo.shmid, IPC_RMID, 0);
new->ximage = NULL;
shmemFlag = 0;
if (!quietFlag) {
fprintf(stderr, "Shared memory error, disabling.\n");
}
gXErrorFlag = 0;
goto shmemerror;
} else {
shmctl(new->shminfo.shmid, IPC_RMID, 0);
}
if (!quietFlag) {
fprintf(stderr, "Sharing memory.\n");
}
} else
#endif
{
int temp_sz;
int factor;
shmemerror:
#ifndef DISABLE_DITHER
temp_sz = vid_stream->matched_depth >> 3;
#else
temp_sz = 4;
#endif
if(!temp_sz) temp_sz = 1;
if(temp_sz == 3) temp_sz = 4;
factor = 1 + IS_2x2_DITHER(ditherType); /* 1 or 2 */
 
new->display = (unsigned char *) malloc(width * height * temp_sz *
factor * factor);
}
new->luminance = (unsigned char *) malloc(width * height);
new->Cr = (unsigned char *) malloc(width * height / 4);
new->Cb = (unsigned char *) malloc(width * height / 4);
/* Reset locked flag. */
new->locked = 0;
 
/* Return pointer to new structure. */
 
return new;
}
 
 
/*
*--------------------------------------------------------------
*
* DestroyPictImage --
*
* Deallocates a PictImage structure.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
DestroyPictImage(apictimage, xinfo)
PictImage *apictimage;
XInfo *xinfo;
{
if (apictimage->luminance != NULL) {
free(apictimage->luminance);
}
if (apictimage->Cr != NULL) {
free(apictimage->Cr);
}
if (apictimage->Cb != NULL) {
free(apictimage->Cb);
}
#ifdef SH_MEM
if ((apictimage->ximage != NULL)&&!noDisplayFlag&&shmemFlag) {
if (xinfo!=NULL) XShmDetach(xinfo->display, &(apictimage->shminfo));
XDestroyImage(apictimage->ximage);
shmdt(apictimage->shminfo.shmaddr);
apictimage->ximage = NULL;
apictimage->display = NULL;
}
#endif
 
if (apictimage->display != NULL) {
free(apictimage->display);
}
free(apictimage);
}
 
/*
*--------------------------------------------------------------
*
* mpegVidRsrc --
*
* Parses bit stream until MB_QUANTUM number of
* macroblocks have been decoded or current slice or
* picture ends, whichever comes first. If the start
* of a frame is encountered, the frame is time stamped
* with the value passed in time_stamp. If the value
* passed in buffer is not null, the video stream buffer
* is set to buffer and the length of the buffer is
* expected in value passed in through length. The current
* video stream is set to vid_stream. If vid_stream
* is passed as NULL, a new VidStream structure is created
* and initialized and used as the current video stream.
*
* Results:
* A pointer to the video stream structure used.
*
* Side effects:
* Bit stream is irreversibly parsed. If a picture is completed,
* a function is called to display the frame at the correct time.
*
*--------------------------------------------------------------
*/
 
VidStream *
mpegVidRsrc(time_stamp, vid_stream, first, xinfo)
TimeStamp time_stamp;
VidStream *vid_stream;
int first;
XInfo *xinfo;
{
unsigned int data;
int i, status;
 
/* If vid_stream is null, create new VidStream structure. */
 
if (vid_stream == NULL) {
return NULL;
}
 
/*
* If called for the first time, find start code, make sure it is a
* sequence start code.
*/
 
if (first) {
vid_stream->sys_layer=-1;
vid_stream->num_left=0;
vid_stream->leftover_bytes=0;
vid_stream->seekValue=0;
vid_stream->Parse_done=FALSE;
next_start_code(vid_stream); /* sets curBits */
show_bits32(data);
if (data != SEQ_START_CODE) {
fprintf(stderr, "This is not an MPEG video stream. (%x)\n",data);
DestroyVidStream(vid_stream,xinfo);
return NULL;
}
} else {
#ifdef UTIL2
vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;
#else
vid_stream->curBits = *vid_stream->buffer;
#endif
}
 
/* Get next 32 bits (size of start codes). */
 
show_bits32(data);
 
/*
* Process according to start code (or parse macroblock if not a start code
* at all).
*/
 
switch (data) {
 
case SEQ_END_CODE:
case 0x000001b9: /* handle ISO_11172_END_CODE too */
 
/* Display last frame. */
 
if (vid_stream->future != NULL) {
vid_stream->current = vid_stream->future;
#ifndef NOCONTROLS
ExecuteDisplay(vid_stream, 1, xinfo);
#else
ExecuteDisplay(vid_stream, xinfo);
#endif
}
 
/* Sequence done. Do the right thing. For right now, exit. */
if (!quietFlag) {
fprintf(stderr, "\nDone!\n");
}
 
#ifdef ANALYSIS
PrintAllStats(vid_stream);
#endif
PrintTimeInfo(vid_stream);
 
vid_stream->film_has_ended=TRUE;
#ifdef NOCONTROLS
if (loopFlag) {
clear_data_stream(vid_stream);
} else DestroyVidStream(vid_stream, xinfo);
#endif /* !NOCONTROLS */
goto done;
break;
 
case SEQ_START_CODE:
 
/* Sequence start code. Parse sequence header. */
 
if (ParseSeqHead(vid_stream,xinfo) != PARSE_OK)
goto error;
 
/*
* Return after sequence start code so that application above can use
* info in header.
*/
if (vid_stream->seekValue > 0) {
SeekStream(vid_stream);
}
 
 
goto done;
 
case GOP_START_CODE:
 
/* Group of Pictures start code. Parse gop header. */
 
if (ParseGOP(vid_stream) != PARSE_OK)
goto error;
goto done;
 
case PICTURE_START_CODE:
 
/* Picture start code. Parse picture header and first slice header. */
 
status = ParsePicture(vid_stream, time_stamp);
 
if (status == SKIP_PICTURE) {
next_start_code(vid_stream);
while (!next_bits(32, PICTURE_START_CODE, vid_stream)) {
if (next_bits(32, GOP_START_CODE, vid_stream))
break;
else if (next_bits(32, SEQ_END_CODE, vid_stream))
break;
flush_bits(24);
next_start_code(vid_stream);
}
goto done;
} else if (status != PARSE_OK)
goto error;
 
 
if (ParseSlice(vid_stream) != PARSE_OK)
goto error;
break;
 
case SEQUENCE_ERROR_CODE:
flush_bits32;
next_start_code(vid_stream);
goto done;
default:
 
/* Check for slice start code. */
 
if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
 
/* Slice start code. Parse slice header. */
 
if (ParseSlice(vid_stream) != PARSE_OK)
goto error;
}
break;
}
 
/* Parse next MB_QUANTUM macroblocks. */
 
for (i = 0; i < MB_QUANTUM; i++) {
 
/* Check to see if actually a startcode and not a macroblock. */
 
if (!next_bits(23, 0x00000000, vid_stream)) {
 
/* Not start code. Parse Macroblock. */
 
if (ParseMacroBlock(vid_stream) != PARSE_OK)
goto error;
 
#ifdef ANALYSIS
if (showmb_flag) {
DoDitherImage(vid_stream);
#ifndef NOCONTROLS
ExecuteDisplay(vid_stream, 1, xinfo);
#else
ExecuteDisplay(vid_stream, xinfo);
#endif /* !NOCONTROLS */
}
#endif /* ANALYSIS */
 
} else {
 
/* Not macroblock, actually start code. Get start code. */
 
next_start_code(vid_stream);
show_bits32(data);
 
/*
* If start code is outside range of slice start codes, frame is
* complete, display frame.
*/
 
if (((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) &&
(data != SEQUENCE_ERROR_CODE)) {
 
#ifdef ANALYSIS
EndTime();
stat_a[0].totsize += bitCountRead() - pictureSizeCount;
if (showEachFlag) {
PrintOneStat();
};
 
CollectStats();
#endif
 
DoPictureDisplay(vid_stream, xinfo);
}
goto done;
}
}
 
/* Check if we just finished a picture on the MB_QUANTUMth macroblock */
if (next_bits(23, 0x00000000, vid_stream)) {
next_start_code(vid_stream);
show_bits32(data);
if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
 
#ifdef ANALYSIS
EndTime();
stat_a[0].totsize += bitCountRead() - pictureSizeCount;
if (showEachFlag) {
PrintOneStat();
};
 
CollectStats();
#endif
 
DoPictureDisplay(vid_stream, xinfo);
}
}
 
/* Return pointer to video stream structure. */
 
goto done;
 
error:
fprintf(stderr, "Error!!!!\n");
next_start_code(vid_stream);
goto done;
 
done:
 
return vid_stream;
 
}
 
 
 
/*
*--------------------------------------------------------------
*
* ParseSeqHead --
*
* Assumes bit stream is at the begining of the sequence
* header start code. Parses off the sequence header.
*
* Results:
* Fills the vid_stream structure with values derived and
* decoded from the sequence header. Allocates the pict image
* structures based on the dimensions of the image space
* found in the sequence header.
*
* Side effects:
* Bit stream irreversibly parsed off.
*
*--------------------------------------------------------------
*/
static int
ParseSeqHead(vid_stream,xinfo)
VidStream *vid_stream;
XInfo *xinfo;
{
unsigned int data;
int i, ditherType=vid_stream->ditherType;
 
/* Flush off sequence start code. */
 
flush_bits32;
 
/* Get horizontal size of image space. */
 
get_bits12(data);
vid_stream->h_size = data;
 
/* Get vertical size of image space. */
 
get_bits12(data);
vid_stream->v_size = data;
 
/* Calculate macroblock width and height of image space. */
 
vid_stream->mb_width = (vid_stream->h_size + 15) / 16;
vid_stream->mb_height = (vid_stream->v_size + 15) / 16;
 
#ifndef DISABLE_DITHER
/* If dither type is MBORDERED allocate ditherFlags. */
if (ditherType == MBORDERED_DITHER) {
vid_stream->ditherFlags =
(char *) malloc(vid_stream->mb_width*vid_stream->mb_height);
}
#endif
 
/*
* Initialize ring buffer of pict images now that dimensions of image space
* are known.
*/
 
#ifdef SH_MEM
if (xinfo->display != NULL) {
InstallXErrorHandler(xinfo->display);
}
#endif
 
if (vid_stream->ring[0] == NULL) {
for (i = 0; i < RING_BUF_SIZE; i++) {
vid_stream->ring[i] = NewPictImage(vid_stream,xinfo);
}
}
#ifdef SH_MEM
if (xinfo->display != NULL) {
DeInstallXErrorHandler(xinfo->display);
}
#endif
 
/* Parse of aspect ratio code. */
 
get_bits4(data);
vid_stream->aspect_ratio = (unsigned char) data;
 
/* Parse off picture rate code. */
 
get_bits4(data);
vid_stream->picture_rate = (unsigned char) data;
 
/* Parse off bit rate. */
 
get_bits18(data);
vid_stream->bit_rate = data;
 
/* Flush marker bit. */
 
flush_bits(1);
 
/* Parse off vbv buffer size. */
 
get_bits10(data);
vid_stream->vbv_buffer_size = data;
 
#ifdef not_def
/* Lets not bother with this. Only increases memory image */
if (data*1024>vid_stream->max_buf_length) {
unsigned int *newbuf;
int sz=1024*data+1;
/* If they actually want a bigger buffer than we default to,
let them have it! (if we can) */
newbuf = (unsigned int *) realloc(vid_stream->buf_start, (unsigned int) 4*sz);
if (newbuf!=(unsigned int *)NULL) {
vid_stream->max_buf_length=sz;
vid_stream->buffer=
(vid_stream->buffer-vid_stream->buf_start)+newbuf;
vid_stream->buf_start=newbuf;
}}
#endif
 
/* Parse off contrained parameter flag. */
 
get_bits1(data);
if (data) {
vid_stream->const_param_flag = TRUE;
} else
vid_stream->const_param_flag = FALSE;
 
/*
* If intra_quant_matrix_flag set, parse off intra quant matrix values.
*/
 
get_bits1(data);
if (data) {
for (i = 0; i < 64; i++) {
get_bits8(data);
 
vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
(unsigned char) data;
}
}
/*
* If non intra quant matrix flag set, parse off non intra quant matrix
* values.
*/
 
get_bits1(data);
if (data) {
for (i = 0; i < 64; i++) {
get_bits8(data);
 
vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
(unsigned char) data;
}
}
/* Go to next start code. */
 
next_start_code(vid_stream);
 
/*
* If next start code is extension start code, parse off extension data.
*/
 
if (next_bits(32, EXT_START_CODE, vid_stream)) {
flush_bits32;
if (vid_stream->ext_data != NULL) {
free(vid_stream->ext_data);
vid_stream->ext_data = NULL;
}
vid_stream->ext_data = get_ext_data(vid_stream);
}
/* If next start code is user start code, parse off user data. */
 
if (next_bits(32, USER_START_CODE, vid_stream)) {
flush_bits32;
if (vid_stream->user_data != NULL) {
free(vid_stream->user_data);
vid_stream->user_data = NULL;
}
vid_stream->user_data = get_ext_data(vid_stream);
}
return PARSE_OK;
}
 
 
/*
*--------------------------------------------------------------
*
* ParseGOP --
*
* Parses of group of pictures header from bit stream
* associated with vid_stream.
*
* Results:
* Values in gop header placed into video stream structure.
*
* Side effects:
* Bit stream irreversibly parsed.
*
*--------------------------------------------------------------
*/
 
static int
ParseGOP(vid_stream)
VidStream *vid_stream;
{
unsigned int data;
 
/* Flush group of pictures start code. */
 
flush_bits32;
 
/* Parse off drop frame flag. */
 
get_bits1(data);
if (data) {
vid_stream->group.drop_flag = TRUE;
} else
vid_stream->group.drop_flag = FALSE;
 
/* Parse off hour component of time code. */
 
get_bits5(data);
vid_stream->group.tc_hours = data;
 
/* Parse off minute component of time code. */
 
get_bits6(data);
vid_stream->group.tc_minutes = data;
 
/* Flush marker bit. */
 
flush_bits(1);
 
/* Parse off second component of time code. */
 
get_bits6(data);
vid_stream->group.tc_seconds = data;
 
/* Parse off picture count component of time code. */
 
get_bits6(data);
vid_stream->group.tc_pictures = data;
 
/* Parse off closed gop and broken link flags. */
 
get_bits2(data);
if (data > 1) {
vid_stream->group.closed_gop = TRUE;
if (data > 2) {
vid_stream->group.broken_link = TRUE;
} else
vid_stream->group.broken_link = FALSE;
} else {
vid_stream->group.closed_gop = FALSE;
if (data) {
vid_stream->group.broken_link = TRUE;
} else
vid_stream->group.broken_link = FALSE;
}
 
/* Goto next start code. */
 
next_start_code(vid_stream);
 
/* If next start code is extension data, parse off extension data. */
 
if (next_bits(32, EXT_START_CODE, vid_stream)) {
flush_bits32;
if (vid_stream->group.ext_data != NULL) {
free(vid_stream->group.ext_data);
vid_stream->group.ext_data = NULL;
}
vid_stream->group.ext_data = get_ext_data(vid_stream);
}
/* If next start code is user data, parse off user data. */
 
if (next_bits(32, USER_START_CODE,vid_stream)) {
flush_bits32;
if (vid_stream->group.user_data != NULL) {
free(vid_stream->group.user_data);
vid_stream->group.user_data = NULL;
}
vid_stream->group.user_data = get_ext_data(vid_stream);
}
return PARSE_OK;
}
 
 
/*
*--------------------------------------------------------------
*
* ParsePicture --
*
* Parses picture header. Marks picture to be presented
* at particular time given a time stamp.
*
* Results:
* Values from picture header put into video stream structure.
*
* Side effects:
* Bit stream irreversibly parsed.
*
*--------------------------------------------------------------
*/
 
static int
ParsePicture(vid_stream, time_stamp)
VidStream *vid_stream;
TimeStamp time_stamp;
{
unsigned int data;
int i;
 
/* Flush header start code. */
flush_bits32;
 
/* Parse off temporal reference. */
get_bits10(data);
vid_stream->picture.temp_ref = data;
 
/* Parse of picture type. */
get_bits3(data);
vid_stream->picture.code_type = data;
 
if ((vid_stream->picture.code_type == B_TYPE) &&
(/* No_B_Flag || */
(vid_stream->future == NULL) ||
((vid_stream->past == NULL) && !(vid_stream->group.closed_gop))))
/* According to 2-D.5.1 (p D-18) this is ok, if the refereneces are OK */
return SKIP_PICTURE;
 
if ((vid_stream->picture.code_type == P_TYPE) &&
(No_P_Flag || (vid_stream->future == NULL)))
return SKIP_PICTURE;
 
#ifdef ANALYSIS
StartTime();
stat_a[0].frametype = vid_stream->picture.code_type;
stat_a[0].number = 1;
stat_a[0].totsize = 45;
pictureSizeCount = bitCountRead();
#endif
 
/* Parse off vbv buffer delay value. */
get_bits16(data);
vid_stream->picture.vbv_delay = data;
 
/* If P or B type frame... */
 
if ((vid_stream->picture.code_type == P_TYPE) ||
(vid_stream->picture.code_type == B_TYPE)) {
 
/* Parse off forward vector full pixel flag. */
get_bits1(data);
if (data) {
vid_stream->picture.full_pel_forw_vector = TRUE;
} else {
vid_stream->picture.full_pel_forw_vector = FALSE;
}
 
/* Parse of forw_r_code. */
get_bits3(data);
 
/* Decode forw_r_code into forw_r_size and forw_f. */
 
vid_stream->picture.forw_r_size = data - 1;
vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
}
/* If B type frame... */
 
if (vid_stream->picture.code_type == B_TYPE) {
 
/* Parse off back vector full pixel flag. */
get_bits1(data);
if (data)
vid_stream->picture.full_pel_back_vector = TRUE;
else
vid_stream->picture.full_pel_back_vector = FALSE;
 
/* Parse off back_r_code. */
get_bits3(data);
 
/* Decode back_r_code into back_r_size and back_f. */
 
vid_stream->picture.back_r_size = data - 1;
vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
}
/* Get extra bit picture info. */
 
if (vid_stream->picture.extra_info != NULL) {
free(vid_stream->picture.extra_info);
vid_stream->picture.extra_info = NULL;
}
vid_stream->picture.extra_info = get_extra_bit_info(vid_stream);
 
/* Goto next start code. */
next_start_code(vid_stream);
 
/* If start code is extension start code, parse off extension data. */
 
if (next_bits(32, EXT_START_CODE, vid_stream)) {
flush_bits32;
 
if (vid_stream->picture.ext_data != NULL) {
free(vid_stream->picture.ext_data);
vid_stream->picture.ext_data = NULL;
}
vid_stream->picture.ext_data = get_ext_data(vid_stream);
}
/* If start code is user start code, parse off user data. */
 
if (next_bits(32, USER_START_CODE, vid_stream)) {
flush_bits32;
 
if (vid_stream->picture.user_data != NULL) {
free(vid_stream->picture.user_data);
vid_stream->picture.user_data = NULL;
}
vid_stream->picture.user_data = get_ext_data(vid_stream);
}
/* Find a pict image structure in ring buffer not currently locked. */
 
i = 0;
 
while (vid_stream->ring[i]->locked != 0) {
if (++i >= RING_BUF_SIZE) {
perror("Fatal error. Ring buffer full.");
exit(1);
}
}
 
/* Set current pict image structure to the one just found in ring. */
 
vid_stream->current = vid_stream->ring[i];
 
/* Set time stamp. */
 
vid_stream->current->show_time = time_stamp;
 
/* Reset past macroblock address field. */
 
vid_stream->mblock.past_mb_addr = -1;
 
return PARSE_OK;
}
 
 
/*
*--------------------------------------------------------------
*
* ParseSlice --
*
* Parses off slice header.
*
* Results:
* Values found in slice header put into video stream structure.
*
* Side effects:
* Bit stream irreversibly parsed.
*
*--------------------------------------------------------------
*/
 
static int
ParseSlice(vid_stream)
VidStream *vid_stream;
{
unsigned int data;
 
/* Flush slice start code. */
 
flush_bits(24);
 
/* Parse off slice vertical position. */
 
get_bits8(data);
vid_stream->slice.vert_pos = data;
 
/* Parse off quantization scale. */
 
get_bits5(data);
vid_stream->slice.quant_scale = data;
 
/* Parse off extra bit slice info. */
 
if (vid_stream->slice.extra_info != NULL) {
free(vid_stream->slice.extra_info);
vid_stream->slice.extra_info = NULL;
}
vid_stream->slice.extra_info = get_extra_bit_info(vid_stream);
 
/* Reset past intrablock address. */
 
vid_stream->mblock.past_intra_addr = -2;
 
/* Reset previous recon motion vectors. */
 
vid_stream->mblock.recon_right_for_prev = 0;
vid_stream->mblock.recon_down_for_prev = 0;
vid_stream->mblock.recon_right_back_prev = 0;
vid_stream->mblock.recon_down_back_prev = 0;
 
/* Reset macroblock address. */
 
vid_stream->mblock.mb_address = ((vid_stream->slice.vert_pos - 1) *
vid_stream->mb_width) - 1;
 
/* Reset past dct dc y, cr, and cb values. */
 
vid_stream->block.dct_dc_y_past = 1024 << 3;
vid_stream->block.dct_dc_cr_past = 1024 << 3;
vid_stream->block.dct_dc_cb_past = 1024 << 3;
 
return PARSE_OK;
}
 
 
/*
*--------------------------------------------------------------
*
* ParseMacroBlock --
*
* Parseoff macroblock. Reconstructs DCT values. Applies
* inverse DCT, reconstructs motion vectors, calculates and
* set pixel values for macroblock in current pict image
* structure.
*
* Results:
* Here's where everything really happens. Welcome to the
* heart of darkness.
*
* Side effects:
* Bit stream irreversibly parsed off.
*
*--------------------------------------------------------------
*/
 
static int
ParseMacroBlock(vid_stream)
VidStream *vid_stream;
{
int addr_incr;
unsigned int data;
int mask, i, recon_right_for, recon_down_for, recon_right_back,
recon_down_back;
int zero_block_flag;
BOOLEAN mb_quant = 0, mb_motion_forw = 0, mb_motion_back = 0,
mb_pattern = 0;
int no_dith_flag = 0;
int ditherType = vid_stream->ditherType;
 
#ifdef ANALYSIS
mbSizeCount = bitCountRead();
#endif
 
/*
* Parse off macroblock address increment and add to macroblock address.
*/
do {
unsigned int ind;
show_bits11(ind);
DecodeMBAddrInc(addr_incr);
if (mb_addr_inc[ind].num_bits==0) {
addr_incr = 1;
}
if (addr_incr == MB_ESCAPE) {
vid_stream->mblock.mb_address += 33;
addr_incr = MB_STUFFING;
}
} while (addr_incr == MB_STUFFING);
vid_stream->mblock.mb_address += addr_incr;
 
if (vid_stream->mblock.mb_address > (vid_stream->mb_height *
vid_stream->mb_width - 1))
return SKIP_TO_START_CODE;
 
/*
* If macroblocks have been skipped, process skipped macroblocks.
*/
 
if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
if (vid_stream->picture.code_type == P_TYPE)
ProcessSkippedPFrameMBlocks(vid_stream);
else if (vid_stream->picture.code_type == B_TYPE)
ProcessSkippedBFrameMBlocks(vid_stream);
}
/* Set past macroblock address to current macroblock address. */
vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
 
/* Based on picture type decode macroblock type. */
switch (vid_stream->picture.code_type) {
case I_TYPE:
DecodeMBTypeI(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
vid_stream->mblock.mb_intra);
break;
 
case P_TYPE:
DecodeMBTypeP(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
vid_stream->mblock.mb_intra);
break;
 
case B_TYPE:
DecodeMBTypeB(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
vid_stream->mblock.mb_intra);
break;
case D_TYPE:
fprintf(stderr, "ERROR: MPEG-1 Streams with D-frames are not supported\n");
exit(1);
}
 
/* If quantization flag set, parse off new quantization scale. */
 
if (mb_quant == TRUE) {
get_bits5(data);
vid_stream->slice.quant_scale = data;
}
/* If forward motion vectors exist... */
if (mb_motion_forw == TRUE) {
 
/* Parse off and decode horizontal forward motion vector. */
DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
 
/* If horiz. forward r data exists, parse off. */
 
if ((vid_stream->picture.forw_f != 1) &&
(vid_stream->mblock.motion_h_forw_code != 0)) {
get_bitsn(vid_stream->picture.forw_r_size, data);
vid_stream->mblock.motion_h_forw_r = data;
}
/* Parse off and decode vertical forward motion vector. */
DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
 
/* If vert. forw. r data exists, parse off. */
 
if ((vid_stream->picture.forw_f != 1) &&
(vid_stream->mblock.motion_v_forw_code != 0)) {
get_bitsn(vid_stream->picture.forw_r_size, data);
vid_stream->mblock.motion_v_forw_r = data;
}
}
/* If back motion vectors exist... */
if (mb_motion_back == TRUE) {
 
/* Parse off and decode horiz. back motion vector. */
DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
 
/* If horiz. back r data exists, parse off. */
 
if ((vid_stream->picture.back_f != 1) &&
(vid_stream->mblock.motion_h_back_code != 0)) {
get_bitsn(vid_stream->picture.back_r_size, data);
vid_stream->mblock.motion_h_back_r = data;
}
/* Parse off and decode vert. back motion vector. */
DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
 
/* If vert. back r data exists, parse off. */
 
if ((vid_stream->picture.back_f != 1) &&
(vid_stream->mblock.motion_v_back_code != 0)) {
get_bitsn(vid_stream->picture.back_r_size, data);
vid_stream->mblock.motion_v_back_r = data;
}
}
#ifdef ANALYSIS
if (vid_stream->mblock.mb_intra) {
stat_a[0].i_mbnum++;
mbCBPPtr = stat_a[0].i_mbcbp;
mbCoeffPtr = stat_a[0].i_mbcoeff;
mbSizePtr = &(stat_a[0].i_mbsize);
} else if (mb_motion_back && mb_motion_forw) {
stat_a[0].bi_mbnum++;
mbCBPPtr = stat_a[0].bi_mbcbp;
mbCoeffPtr = stat_a[0].bi_mbcoeff;
mbSizePtr = &(stat_a[0].bi_mbsize);
} else if (mb_motion_back) {
stat_a[0].b_mbnum++;
mbCBPPtr = stat_a[0].b_mbcbp;
mbCoeffPtr = stat_a[0].b_mbcoeff;
mbSizePtr = &(stat_a[0].b_mbsize);
} else {
stat_a[0].p_mbnum++;
mbCBPPtr = stat_a[0].p_mbcbp;
mbCoeffPtr = stat_a[0].p_mbcoeff;
mbSizePtr = &(stat_a[0].p_mbsize);
}
#endif
 
/* If mblock pattern flag set, parse and decode CBP (code block pattern). */
if (mb_pattern == TRUE) {
DecodeCBP(vid_stream->mblock.cbp);
}
/* Otherwise, set CBP to zero. */
else
vid_stream->mblock.cbp = 0;
 
 
#ifdef ANALYSIS
mbCBPPtr[vid_stream->mblock.cbp]++;
#endif
 
/* Reconstruct motion vectors depending on picture type. */
if (vid_stream->picture.code_type == P_TYPE) {
 
/*
* If no forw motion vectors, reset previous and current vectors to 0.
*/
 
if (!mb_motion_forw) {
recon_right_for = 0;
recon_down_for = 0;
vid_stream->mblock.recon_right_for_prev = 0;
vid_stream->mblock.recon_down_for_prev = 0;
}
/*
* Otherwise, compute new forw motion vectors. Reset previous vectors to
* current vectors.
*/
 
else {
ComputeForwVector(&recon_right_for, &recon_down_for, vid_stream);
}
}
if (vid_stream->picture.code_type == B_TYPE) {
 
/* Reset prev. and current vectors to zero if mblock is intracoded. */
 
if (vid_stream->mblock.mb_intra) {
vid_stream->mblock.recon_right_for_prev = 0;
vid_stream->mblock.recon_down_for_prev = 0;
vid_stream->mblock.recon_right_back_prev = 0;
vid_stream->mblock.recon_down_back_prev = 0;
} else {
/* If no forw vectors, current vectors equal prev. vectors. */
if (!mb_motion_forw) {
recon_right_for = vid_stream->mblock.recon_right_for_prev;
recon_down_for = vid_stream->mblock.recon_down_for_prev;
}
/*
* Otherwise compute forw. vectors. Reset prev vectors to new values.
*/
else {
ComputeForwVector(&recon_right_for, &recon_down_for, vid_stream);
}
/* If no back vectors, set back vectors to prev back vectors. */
if (!mb_motion_back) {
recon_right_back = vid_stream->mblock.recon_right_back_prev;
recon_down_back = vid_stream->mblock.recon_down_back_prev;
}
/* Otherwise compute new vectors and reset prev. back vectors. */
 
else {
ComputeBackVector(&recon_right_back, &recon_down_back, vid_stream);
}
 
/*
* Store vector existence flags in structure for possible skipped
* macroblocks to follow.
*/
 
vid_stream->mblock.bpict_past_forw = mb_motion_forw;
vid_stream->mblock.bpict_past_back = mb_motion_back;
}
}
 
#ifndef DISABLE_DITHER
/* For each possible block in macroblock. */
if (ditherType == GRAY_DITHER ||
ditherType == GRAY2_DITHER ||
ditherType == GRAY256_DITHER ||
ditherType == GRAY2562_DITHER ||
ditherType == MONO_DITHER ||
ditherType == MONO_THRESHOLD) {
for (mask = 32, i = 0; i < 4; mask >>= 1, i++) {
 
/* If block exists... */
if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
zero_block_flag = 0;
ParseReconBlock(i, vid_stream);
} else {
zero_block_flag = 1;
}
 
/* If macroblock is intra coded... */
if (vid_stream->mblock.mb_intra) {
ReconIMBlock(vid_stream, i);
} else if (mb_motion_forw && mb_motion_back) {
ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
recon_right_back, recon_down_back, zero_block_flag);
} else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
zero_block_flag);
} else if (mb_motion_back) {
ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
zero_block_flag);
}
}
/* Kill the Chrominance blocks... */
if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x2)) {
ParseAwayBlock(4, vid_stream);
}
if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x1)) {
ParseAwayBlock(5, vid_stream);
}
} else {
if ((ditherType == MBORDERED_DITHER) &&
(vid_stream->mblock.cbp == 0) &&
(vid_stream->picture.code_type == 3) &&
(!vid_stream->mblock.mb_intra) &&
(!(mb_motion_forw && mb_motion_back))) {
MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address,
mb_motion_forw, recon_right_for, recon_down_for,
mb_motion_back, recon_right_back, recon_down_back,
vid_stream->past->display, vid_stream->future->display);
vid_stream->ditherFlags[vid_stream->mblock.mb_address] = 0;
no_dith_flag = 1;
}
else {
#endif
for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
/* If block exists... */
if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
zero_block_flag = 0;
ParseReconBlock(i, vid_stream);
} else {
zero_block_flag = 1;
}
/* If macroblock is intra coded... */
if (vid_stream->mblock.mb_intra) {
ReconIMBlock(vid_stream, i);
} else if (mb_motion_forw && mb_motion_back) {
ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
recon_right_back, recon_down_back, zero_block_flag);
} else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
zero_block_flag);
} else if (mb_motion_back) {
ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
zero_block_flag);
}
}
#ifndef DISABLE_DITHER
}
}
#endif
 
#ifndef DISABLE_DITHER
if ((ditherType == MBORDERED_DITHER) && (!no_dith_flag)) {
if ((vid_stream->picture.code_type == 2) &&
(vid_stream->mblock.cbp == 0) &&
(!vid_stream->mblock.mb_intra)) {
MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address,
1, recon_right_for, recon_down_for,
0, 0, 0,
vid_stream->future->display,
(unsigned char *) NULL);
vid_stream->ditherFlags[vid_stream->mblock.mb_address] = 0;
}
else {
vid_stream->ditherFlags[vid_stream->mblock.mb_address] = 1;
}
}
#endif
 
/* If D Type picture, flush marker bit. */
if (vid_stream->picture.code_type == 4)
flush_bits(1);
 
/* If macroblock was intracoded, set macroblock past intra address. */
if (vid_stream->mblock.mb_intra)
vid_stream->mblock.past_intra_addr =
vid_stream->mblock.mb_address;
 
#ifdef ANALYSIS
*mbSizePtr += bitCountRead() - mbSizeCount;
#endif
return PARSE_OK;
}
 
 
/*
*--------------------------------------------------------------
*
* ReconIMBlock --
*
* Reconstructs intra coded macroblock.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
#ifndef NDEBUG
/* If people really want to see such things, check 'em */
#define myassert(x,expression)\
if (!(expression)) {\
fprintf (stderr,"Bad crop value (%d) at line %d\n", x, __LINE__);\
next_start_code(vid_stream); return;}
#define assertCrop(x) myassert(x,((x) >= -MAX_NEG_CROP) && \
((x) <= 2048+MAX_NEG_CROP))
#else
#define assertCrop(x)
#endif
 
static void
ReconIMBlock(vid_stream, bnum)
VidStream *vid_stream;
int bnum;
{
int mb_row, mb_col, row, col, row_size, rr;
unsigned char *dest;
 
/* Calculate macroblock row and column from address. */
 
mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
 
 
/* If block is luminance block... */
 
if (bnum < 4) {
 
/* Calculate row and col values for upper left pixel of block. */
 
row = mb_row * 16;
col = mb_col * 16;
if (bnum > 1)
row += 8;
if (bnum % 2)
col += 8;
 
/* Set dest to luminance plane of current pict image. */
 
dest = vid_stream->current->luminance;
 
/* Establish row size. */
 
row_size = vid_stream->mb_width * 16;
}
/* Otherwise if block is Cr block... */
/* Cr first because of the earlier mixup */
 
else if (bnum == 5) {
 
/* Set dest to Cr plane of current pict image. */
 
dest = vid_stream->current->Cr;
 
/* Establish row size. */
 
row_size = vid_stream->mb_width * 8;
 
/* Calculate row,col for upper left pixel of block. */
 
row = mb_row * 8;
col = mb_col * 8;
}
/* Otherwise block is Cb block, and ... */
 
else {
 
/* Set dest to Cb plane of current pict image. */
 
dest = vid_stream->current->Cb;
 
/* Establish row size. */
 
row_size = vid_stream->mb_width * 8;
 
/* Calculate row,col for upper left pixel value of block. */
 
row = mb_row * 8;
col = mb_col * 8;
}
 
/*
* For each pixel in block, set to cropped reconstructed value from inverse
* dct.
*/
{
short *sp = &vid_stream->block.dct_recon[0][0];
unsigned char *cm = cropTbl + MAX_NEG_CROP;
dest += row * row_size + col;
for (rr = 0; rr < 4; rr++, sp += 16, dest += row_size) {
dest[0] = cm[sp[0]];
assertCrop(sp[0]);
dest[1] = cm[sp[1]];
assertCrop(sp[1]);
dest[2] = cm[sp[2]];
assertCrop(sp[2]);
dest[3] = cm[sp[3]];
assertCrop(sp[3]);
dest[4] = cm[sp[4]];
assertCrop(sp[4]);
dest[5] = cm[sp[5]];
assertCrop(sp[5]);
dest[6] = cm[sp[6]];
assertCrop(sp[6]);
dest[7] = cm[sp[7]];
assertCrop(sp[7]);
 
dest += row_size;
dest[0] = cm[sp[8]];
assertCrop(sp[8]);
dest[1] = cm[sp[9]];
assertCrop(sp[9]);
dest[2] = cm[sp[10]];
assertCrop(sp[10]);
dest[3] = cm[sp[11]];
assertCrop(sp[11]);
dest[4] = cm[sp[12]];
assertCrop(sp[12]);
dest[5] = cm[sp[13]];
assertCrop(sp[13]);
dest[6] = cm[sp[14]];
assertCrop(sp[14]);
dest[7] = cm[sp[15]];
assertCrop(sp[15]);
}
}
}
 
 
/*
*--------------------------------------------------------------
*
* ReconPMBlock --
*
* Reconstructs forward predicted macroblocks.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
static void
ReconPMBlock(vid_stream, bnum, recon_right_for, recon_down_for, zflag)
VidStream *vid_stream;
int bnum, recon_right_for, recon_down_for, zflag;
{
int mb_row, mb_col, row, col, row_size, rr;
unsigned char *dest, *past;
unsigned char *rindex1, *rindex2, *rindex3, *rindex4;
unsigned char *index;
short int *blockvals;
 
#ifdef LOOSE_MPEG
int maxx, maxy, cc;
int illegalBlock = 0;
int row_start, row_end, rfirst, rlast, col_start, col_end, cfirst, clast;
#endif
 
/* Calculate macroblock row and column from address. */
 
mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
 
if (bnum < 4) {
 
/* Calculate right_for, down_for motion vectors. */
 
vid_stream->right_for = recon_right_for >> 1;
vid_stream->down_for = recon_down_for >> 1;
vid_stream->right_half_for = recon_right_for & 0x1;
vid_stream->down_half_for = recon_down_for & 0x1;
 
/* Set dest to luminance plane of current pict image. */
 
dest = vid_stream->current->luminance;
 
if (vid_stream->picture.code_type == B_TYPE) {
if (vid_stream->past != NULL)
past = vid_stream->past->luminance;
} else {
 
/* Set predictive frame to current future frame. */
 
if (vid_stream->future != NULL)
past = vid_stream->future->luminance;
}
 
/* Establish row size. */
 
row_size = vid_stream->mb_width << 4;
 
/* Calculate row,col of upper left pixel in block. */
 
row = mb_row << 4;
col = mb_col << 4;
if (bnum > 1)
row += 8;
if (bnum % 2)
col += 8;
 
#ifdef LOOSE_MPEG
/* Check for block illegality. */
 
maxx = vid_stream->mb_width*16-1;
maxy = vid_stream->mb_height*16-1;
 
if (row + vid_stream->down_for + 7 > maxy) illegalBlock |= 0x4;
else if (row + vid_stream->down_for < 0) illegalBlock |= 0x1;
if (col + vid_stream->right_for + 7 > maxx) illegalBlock |= 0x2;
else if (col + vid_stream->right_for < 0) illegalBlock |= 0x8;
 
#endif
}
/* Otherwise, block is NOT luminance block, ... */
 
else {
 
/* Construct motion vectors. */
 
recon_right_for /= 2;
recon_down_for /= 2;
vid_stream->right_for = recon_right_for >> 1;
vid_stream->down_for = recon_down_for >> 1;
vid_stream->right_half_for = recon_right_for & 0x1;
vid_stream->down_half_for = recon_down_for & 0x1;
 
/* Establish row size. */
 
row_size = vid_stream->mb_width << 3;
 
/* Calculate row,col of upper left pixel in block. */
 
row = mb_row << 3;
col = mb_col << 3;
 
#ifdef LOOSE_MPEG
/* Check for block illegality. */
 
maxx = vid_stream->mb_width*16-1;
maxy = vid_stream->mb_height*16-1;
 
if (row + vid_stream->down_for + 7 > maxy) illegalBlock |= 0x4;
else if (row + vid_stream->down_for < 0) illegalBlock |= 0x1;
 
if (col + vid_stream->right_for + 7 > maxx) illegalBlock |= 0x2;
else if (col + vid_stream->right_for < 0) illegalBlock |= 0x8;
 
#endif
 
/* If block is Cr block... */
/* 5 first because order was mixed up in earlier versions */
 
if (bnum == 5) {
 
/* Set dest to Cr plane of current pict image. */
 
dest = vid_stream->current->Cr;
 
if (vid_stream->picture.code_type == B_TYPE) {
 
if (vid_stream->past != NULL)
past = vid_stream->past->Cr;
} else {
if (vid_stream->future != NULL)
past = vid_stream->future->Cr;
}
}
/* Otherwise, block is Cb block... */
 
else {
 
/* Set dest to Cb plane of current pict image. */
 
dest = vid_stream->current->Cb;
 
if (vid_stream->picture.code_type == B_TYPE) {
if (vid_stream->past != NULL)
past = vid_stream->past->Cb;
} else {
if (vid_stream->future != NULL)
past = vid_stream->future->Cb;
}
}
}
 
/* For each pixel in block... */
 
#ifdef LOOSE_MPEG
 
if (illegalBlock) {
if (illegalBlock & 0x1) {
row_start = 0;
row_end = row+vid_stream->down_for+8;
rfirst = rlast = 8 - row_end;
}
else if (illegalBlock & 0x4) {
row_start = row + vid_stream->down_for;
row_end = maxy+1;
rlast = row_end - row_start - 1;
rfirst = 0;
}
else {
row_start = row+vid_stream->down_for;
row_end = row_start+8;
rfirst = 0;
}
 
if (illegalBlock & 0x8) {
col_start = 0;
col_end = col + vid_stream->right_for + 8;
cfirst = clast = 8 - col_end;
}
else if (illegalBlock & 0x2) {
col_start = col + vid_stream->right_for;
col_end = maxx + 1;
clast = col_end - col_start - 1;
cfirst = 0;
}
else {
col_start = col + vid_stream->right_for;
col_end = col_start + 8;
cfirst = 0;
}
 
for (rr = row_start; rr < row_end; rr++) {
rindex1 = past + (rr * row_size) + col_start;
index = dest + ((row + rfirst) * row_size) + col + cfirst;
for (cc = col_start; cc < col_end; cc++) {
*index++ = *rindex1++;
}
}
 
if (illegalBlock & 0x1) {
for (rr = rlast -1; rr >=0; rr--) {
index = dest + ((row + rr) * row_size) + col;
rindex1 = dest + ((row + rlast) * row_size) + col;
for (cc = 0; cc < 8; cc ++) {
*index++ = *rindex1++;
}
}
}
else if (illegalBlock & 0x4) {
for (rr = rlast+1; rr < 8; rr++) {
index = dest + ((row + rr) * row_size) + col;
rindex1 = dest + ((row + rlast) * row_size) + col;
for (cc = 0; cc < 8; cc ++) {
*index++ = *rindex1++;
}
}
}
 
if (illegalBlock & 0x2) {
for (cc = clast+1; cc < 8; cc++) {
index = dest + (row * row_size) + (col + cc);
rindex1 = dest + (row * row_size) + (col + clast);
for (rr = 0; rr < 8; rr++) {
*index = *rindex1;
index += row_size;
rindex1 += row_size;
}
}
}
else if (illegalBlock & 0x8) {
for (cc = clast-1; cc >= 0; cc--) {
index = dest + (row * row_size) + (col + cc);
rindex1 = dest + (row * row_size) + (col + clast);
for (rr = 0; rr < 8; rr++) {
*index = *rindex1;
index += row_size;
rindex1 += row_size;
}
}
}
 
if (!zflag) {
for (rr = 0; rr < 8; rr++) {
index = dest + (row*row_size) + col;
blockvals = &(vid_stream->block.dct_recon[rr][0]);
index[0] += blockvals[0];
index[1] += blockvals[1];
index[2] += blockvals[2];
index[3] += blockvals[3];
index[4] += blockvals[4];
index[5] += blockvals[5];
index[6] += blockvals[6];
index[7] += blockvals[7];
}
}
}
else {
 
#endif
 
index = dest + (row * row_size) + col;
rindex1 = past + (row + vid_stream->down_for) * row_size
+ col + vid_stream->right_for;
blockvals = &(vid_stream->block.dct_recon[0][0]);
/*
* Calculate predictive pixel value based on motion vectors and copy to
* dest plane.
*/
if ((!vid_stream->down_half_for) && (!vid_stream->right_half_for)) {
unsigned char *cm = cropTbl + MAX_NEG_CROP;
if (!zflag)
for (rr = 0; rr < 4; rr++) {
index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
index += row_size;
rindex1 += row_size;
index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
blockvals += 16;
index += row_size;
rindex1 += row_size;
}
else {
if (vid_stream->right_for & 0x1) {
/* No alignment, use bye copy */
for (rr = 0; rr < 4; rr++) {
index[0] = rindex1[0];
index[1] = rindex1[1];
index[2] = rindex1[2];
index[3] = rindex1[3];
index[4] = rindex1[4];
index[5] = rindex1[5];
index[6] = rindex1[6];
index[7] = rindex1[7];
index += row_size;
rindex1 += row_size;
index[0] = rindex1[0];
index[1] = rindex1[1];
index[2] = rindex1[2];
index[3] = rindex1[3];
index[4] = rindex1[4];
index[5] = rindex1[5];
index[6] = rindex1[6];
index[7] = rindex1[7];
index += row_size;
rindex1 += row_size;
}
} else if (vid_stream->right_for & 0x2) {
/* Half-word bit aligned, use 16 bit copy */
short *src = (short *)rindex1;
short *dest = (short *)index;
row_size >>= 1;
for (rr = 0; rr < 4; rr++) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest += row_size;
src += row_size;
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest += row_size;
src += row_size;
}
} else {
/* Word aligned, use 32 bit copy */
int *src = (int *)rindex1;
int *dest = (int *)index;
row_size >>= 2;
for (rr = 0; rr < 4; rr++) {
dest[0] = src[0];
dest[1] = src[1];
dest += row_size;
src += row_size;
dest[0] = src[0];
dest[1] = src[1];
dest += row_size;
src += row_size;
}
}
}
} else {
unsigned char *cm = cropTbl + MAX_NEG_CROP;
rindex2 = rindex1 + vid_stream->right_half_for
+ (vid_stream->down_half_for * row_size);
 
/* if one of the two is zero, then quality makes no difference */
if ((!vid_stream->right_half_for) ||
(!vid_stream->down_half_for) || (!qualityFlag)) {
if (!zflag) {
for (rr = 0; rr < 4; rr++) {
index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[0]];
index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[1]];
index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[2]];
index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[3]];
index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[4]];
index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[5]];
index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[6]];
index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[7]];
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[8]];
index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[9]];
index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[10]];
index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[11]];
index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[12]];
index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[13]];
index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[14]];
index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[15]];
blockvals += 16;
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
}
} else { /* zflag */
for (rr = 0; rr < 8; rr++) {
index[0] = (int) (rindex1[0] + rindex2[0] + 1) >> 1;
index[1] = (int) (rindex1[1] + rindex2[1] + 1) >> 1;
index[2] = (int) (rindex1[2] + rindex2[2] + 1) >> 1;
index[3] = (int) (rindex1[3] + rindex2[3] + 1) >> 1;
index[4] = (int) (rindex1[4] + rindex2[4] + 1) >> 1;
index[5] = (int) (rindex1[5] + rindex2[5] + 1) >> 1;
index[6] = (int) (rindex1[6] + rindex2[6] + 1) >> 1;
index[7] = (int) (rindex1[7] + rindex2[7] + 1) >> 1;
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
}
}
} else { /* qualityFlag on and both vectors are non-zero */
rindex3 = rindex1 + vid_stream->right_half_for;
rindex4 = rindex1 + (vid_stream->down_half_for * row_size);
if (!zflag) {
for (rr = 0; rr < 4; rr++) {
index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[0]];
index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[1]];
index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[2]];
index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[3]];
index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[4]];
index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[5]];
index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[6]];
index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[7]];
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
rindex3 += row_size;
rindex4 += row_size;
index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[8]];
index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[9]];
index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[10]];
index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[11]];
index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[12]];
index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[13]];
index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[14]];
index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[15]];
blockvals += 16;
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
rindex3 += row_size;
rindex4 += row_size;
}
} else { /* zflag */
for (rr = 0; rr < 8; rr++) {
index[0] = (int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2;
index[1] = (int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2;
index[2] = (int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2;
index[3] = (int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2;
index[4] = (int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2;
index[5] = (int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2;
index[6] = (int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2;
index[7] = (int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2;
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
rindex3 += row_size;
rindex4 += row_size;
}
}
}
 
}
#ifdef LOOSE_MPEG
}
#endif
}
 
/*
*--------------------------------------------------------------
*
* ReconBMBlock --
*
* Reconstructs back predicted macroblocks.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
static void
ReconBMBlock(vid_stream, bnum, recon_right_back, recon_down_back, zflag)
VidStream *vid_stream;
int bnum, recon_right_back, recon_down_back, zflag;
{
int mb_row, mb_col, row, col, row_size, rr;
unsigned char *dest, *future;
int right_back, down_back, right_half_back, down_half_back;
unsigned char *rindex1, *rindex2, *rindex3, *rindex4;
unsigned char *index;
short int *blockvals;
 
#ifdef LOOSE_MPEG
int illegalBlock = 0;
int maxx, maxy, cc;
int row_start, row_end, rlast, rfirst, col_start, col_end, clast, cfirst;
#endif
 
/* Calculate macroblock row and column from address. */
 
mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
 
/* If block is luminance block... */
 
if (bnum < 4) {
 
/* Calculate right_back, down_back motion vectors. */
 
right_back = recon_right_back >> 1;
down_back = recon_down_back >> 1;
right_half_back = recon_right_back & 0x1;
down_half_back = recon_down_back & 0x1;
 
/* Set dest to luminance plane of current pict image. */
 
dest = vid_stream->current->luminance;
 
/*
* If future frame exists, set future to luminance plane of future frame.
*/
 
if (vid_stream->future != NULL)
future = vid_stream->future->luminance;
 
/* Establish row size. */
 
row_size = vid_stream->mb_width << 4;
 
/* Calculate row,col of upper left pixel in block. */
 
row = mb_row << 4;
col = mb_col << 4;
if (bnum > 1)
row += 8;
if (bnum % 2)
col += 8;
 
#ifdef LOOSE_MPEG
 
/* Check for block illegality. */
 
maxx = vid_stream->mb_width*16-1;
maxy = vid_stream->mb_height*16-1;
 
if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
else if (row + down_back < 0) illegalBlock |= 0x1;
if (col + right_back + 7 > maxx) illegalBlock |= 0x2;
else if (col + right_back < 0) illegalBlock |= 0x8;
 
#endif
 
}
/* Otherwise, block is NOT luminance block, ... */
 
else {
 
/* Construct motion vectors. */
 
recon_right_back /= 2;
recon_down_back /= 2;
right_back = recon_right_back >> 1;
down_back = recon_down_back >> 1;
right_half_back = recon_right_back & 0x1;
down_half_back = recon_down_back & 0x1;
 
/* Establish row size. */
 
row_size = vid_stream->mb_width << 3;
 
/* Calculate row,col of upper left pixel in block. */
 
row = mb_row << 3;
col = mb_col << 3;
 
#ifdef LOOSE_MPEG
 
/* Check for block illegality. */
 
maxx = vid_stream->mb_width*8-1;
maxy = vid_stream->mb_height*8-1;
 
if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
else if (row + down_back < 0) illegalBlock |= 0x1;
 
if (col + right_back + 7 > maxx) illegalBlock |= 0x2;
else if (col + right_back < 0) illegalBlock |= 0x8;
 
#endif
 
/* If block is Cr block... */
/* They were switched earlier, so 5 is first - eyhung */
 
if (bnum == 5) {
 
/* Set dest to Cr plane of current pict image. */
 
dest = vid_stream->current->Cr;
 
/*
* If future frame exists, set future to Cr plane of future image.
*/
 
if (vid_stream->future != NULL)
future = vid_stream->future->Cr;
}
/* Otherwise, block is Cb block... */
 
else {
 
/* Set dest to Cb plane of current pict image. */
 
dest = vid_stream->current->Cb;
 
/*
* If future frame exists, set future to Cb plane of future frame.
*/
 
if (vid_stream->future != NULL)
future = vid_stream->future->Cb;
}
}
 
/* For each pixel in block do... */
 
#ifdef LOOSE_MPEG
 
if (illegalBlock) {
if (illegalBlock & 0x1) {
row_start = 0;
row_end = row+down_back+8;
rfirst = rlast = 8 - row_end;
}
else if (illegalBlock & 0x4) {
row_start = row + down_back;
row_end = maxy+1;
rlast = row_end - row_start - 1;
rfirst = 0;
}
else {
row_start = row+down_back;
row_end = row_start+8;
rfirst = 0;
}
 
if (illegalBlock & 0x8) {
col_start = 0;
col_end = col + right_back + 8;
cfirst = clast = 8 - col_end;
}
else if (illegalBlock & 0x2) {
col_start = col + right_back;
col_end = maxx + 1;
clast = col_end - col_start - 1;
cfirst = 0;
}
else {
col_start = col + right_back;
col_end = col_start + 8;
cfirst = 0;
}
 
for (rr = row_start; rr < row_end; rr++) {
rindex1 = future + (rr * row_size) + col_start;
index = dest + ((row + rfirst) * row_size) + col + cfirst;
for (cc = col_start; cc < col_end; cc++) {
*index++ = *rindex1++;
}
}
 
if (illegalBlock & 0x1) {
for (rr = rlast -1; rr >=0; rr--) {
index = dest + ((row + rr) * row_size) + col;
rindex1 = dest + ((row + rlast) * row_size) + col;
for (cc = 0; cc < 8; cc ++) {
*index++ = *rindex1++;
}
}
}
else if (illegalBlock & 0x4) {
for (rr = rlast+1; rr < 8; rr++) {
index = dest + ((row + rr) * row_size) + col;
rindex1 = dest + ((row + rlast) * row_size) + col;
for (cc = 0; cc < 8; cc ++) {
*index++ = *rindex1++;
}
}
}
 
if (illegalBlock & 0x2) {
for (cc = clast+1; cc < 8; cc++) {
index = dest + (row * row_size) + (col + cc);
rindex1 = dest + (row * row_size) + (col + clast);
for (rr = 0; rr < 8; rr++) {
*index = *rindex1;
index += row_size;
rindex1 += row_size;
}
}
}
else if (illegalBlock & 0x8) {
for (cc = clast-1; cc >= 0; cc--) {
index = dest + (row * row_size) + (col + cc);
rindex1 = dest + (row * row_size) + (col + clast);
for (rr = 0; rr < 8; rr++) {
*index = *rindex1;
index += row_size;
rindex1 += row_size;
}
}
}
 
if (!zflag) {
for (rr = 0; rr < 8; rr++) {
index = dest + (row*row_size) + col;
blockvals = &(vid_stream->block.dct_recon[rr][0]);
index[0] += blockvals[0];
index[1] += blockvals[1];
index[2] += blockvals[2];
index[3] += blockvals[3];
index[4] += blockvals[4];
index[5] += blockvals[5];
index[6] += blockvals[6];
index[7] += blockvals[7];
}
}
}
else {
 
#endif
index = dest + (row * row_size) + col;
rindex1 = future + (row + down_back) * row_size + col + right_back;
 
blockvals = &(vid_stream->block.dct_recon[0][0]);
 
if ((!right_half_back) && (!down_half_back)) {
unsigned char *cm = cropTbl + MAX_NEG_CROP;
if (!zflag)
for (rr = 0; rr < 4; rr++) {
index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
index += row_size;
rindex1 += row_size;
index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
blockvals += 16;
index += row_size;
rindex1 += row_size;
}
else {
if (right_back & 0x1) {
/* No alignment, use bye copy */
for (rr = 0; rr < 4; rr++) {
index[0] = rindex1[0];
index[1] = rindex1[1];
index[2] = rindex1[2];
index[3] = rindex1[3];
index[4] = rindex1[4];
index[5] = rindex1[5];
index[6] = rindex1[6];
index[7] = rindex1[7];
index += row_size;
rindex1 += row_size;
index[0] = rindex1[0];
index[1] = rindex1[1];
index[2] = rindex1[2];
index[3] = rindex1[3];
index[4] = rindex1[4];
index[5] = rindex1[5];
index[6] = rindex1[6];
index[7] = rindex1[7];
index += row_size;
rindex1 += row_size;
}
} else if (right_back & 0x2) {
/* Half-word bit aligned, use 16 bit copy */
short *src = (short *)rindex1;
short *dest = (short *)index;
row_size >>= 1;
for (rr = 0; rr < 4; rr++) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest += row_size;
src += row_size;
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest += row_size;
src += row_size;
}
} else {
/* Word aligned, use 32 bit copy */
int *src = (int *)rindex1;
int *dest = (int *)index;
row_size >>= 2;
for (rr = 0; rr < 4; rr++) {
dest[0] = src[0];
dest[1] = src[1];
dest += row_size;
src += row_size;
dest[0] = src[0];
dest[1] = src[1];
dest += row_size;
src += row_size;
}
}
}
} else {
unsigned char *cm = cropTbl + MAX_NEG_CROP;
rindex2 = rindex1 + right_half_back + (down_half_back * row_size);
if (!qualityFlag) {
if (!zflag) {
for (rr = 0; rr < 4; rr++) {
index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[0]];
index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[1]];
index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[2]];
index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[3]];
index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[4]];
index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[5]];
index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[6]];
index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[7]];
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[8]];
index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[9]];
index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[10]];
index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[11]];
index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[12]];
index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[13]];
index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[14]];
index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[15]];
blockvals += 16;
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
}
} else { /* zflag */
for (rr = 0; rr < 8; rr++) {
index[0] = (int) (rindex1[0] + rindex2[0] + 1) >> 1;
index[1] = (int) (rindex1[1] + rindex2[1] + 1) >> 1;
index[2] = (int) (rindex1[2] + rindex2[2] + 1) >> 1;
index[3] = (int) (rindex1[3] + rindex2[3] + 1) >> 1;
index[4] = (int) (rindex1[4] + rindex2[4] + 1) >> 1;
index[5] = (int) (rindex1[5] + rindex2[5] + 1) >> 1;
index[6] = (int) (rindex1[6] + rindex2[6] + 1) >> 1;
index[7] = (int) (rindex1[7] + rindex2[7] + 1) >> 1;
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
}
}
} else { /* qualityFlag on */
rindex3 = rindex1 + right_half_back;
rindex4 = rindex1 + (down_half_back * row_size);
if (!zflag) {
for (rr = 0; rr < 4; rr++) {
index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[0]];
index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[1]];
index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[2]];
index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[3]];
index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[4]];
index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[5]];
index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[6]];
index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[7]];
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
rindex3 += row_size;
rindex4 += row_size;
index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[8]];
index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[9]];
index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[10]];
index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[11]];
index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[12]];
index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[13]];
index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[14]];
index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[15]];
blockvals += 16;
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
rindex3 += row_size;
rindex4 += row_size;
}
} else { /* zflag */
for (rr = 0; rr < 8; rr++) {
index[0] = (int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2;
index[1] = (int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2;
index[2] = (int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2;
index[3] = (int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2;
index[4] = (int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2;
index[5] = (int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2;
index[6] = (int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2;
index[7] = (int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2;
index += row_size;
rindex1 += row_size;
rindex2 += row_size;
rindex3 += row_size;
rindex4 += row_size;
}
}
}
 
}
#ifdef LOOSE_MPEG
}
#endif
}
 
/*
*--------------------------------------------------------------
*
* ReconBiMBlock --
*
* Reconstructs bidirectionally predicted macroblocks.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
static void
ReconBiMBlock(vid_stream, bnum, recon_right_for, recon_down_for,
recon_right_back, recon_down_back, zflag)
VidStream *vid_stream;
int bnum, recon_right_for, recon_down_for, recon_right_back, recon_down_back;
int zflag;
{
int mb_row, mb_col, row, col, row_size, rr;
unsigned char *dest, *past=NULL, *future=NULL;
int right_for, down_for, right_half_for, down_half_for;
int right_back, down_back, right_half_back, down_half_back;
unsigned char *index, *rindex1, *bindex1;
short int *blockvals;
int forw_row_start, back_row_start, forw_col_start, back_col_start;
#ifdef LOOSE_MPEG
int lmaxx = vid_stream->mb_width*16-1;
int lmaxy = vid_stream->mb_height*16-1;
int cmaxx = vid_stream->mb_width*8-1;
int cmaxy = vid_stream->mb_height*8-1;
#endif
 
#ifdef LOOSE_MPEG
int illegal_forw = 0;
int illegal_back = 0;
#endif
 
/* Calculate macroblock row and column from address. */
 
mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
 
/* If block is luminance block... */
 
if (bnum < 4) {
 
/*
* Calculate right_for, down_for, right_half_for, down_half_for,
* right_back, down_bakc, right_half_back, and down_half_back, motion
* vectors.
*/
 
right_for = recon_right_for >> 1;
down_for = recon_down_for >> 1;
right_half_for = recon_right_for & 0x1;
down_half_for = recon_down_for & 0x1;
 
right_back = recon_right_back >> 1;
down_back = recon_down_back >> 1;
right_half_back = recon_right_back & 0x1;
down_half_back = recon_down_back & 0x1;
 
/* Set dest to luminance plane of current pict image. */
 
dest = vid_stream->current->luminance;
 
/* If past frame exists, set past to luminance plane of past frame. */
 
if (vid_stream->past != NULL)
past = vid_stream->past->luminance;
 
/*
* If future frame exists, set future to luminance plane of future frame.
*/
 
if (vid_stream->future != NULL)
future = vid_stream->future->luminance;
 
/* Establish row size. */
 
row_size = (vid_stream->mb_width << 4);
 
/* Calculate row,col of upper left pixel in block. */
 
row = (mb_row << 4);
col = (mb_col << 4);
if (bnum > 1)
row += 8;
if (bnum & 0x01)
col += 8;
 
forw_col_start = col + right_for;
forw_row_start = row + down_for;
 
back_col_start = col + right_back;
back_row_start = row + down_back;
 
#ifdef LOOSE_MPEG
 
/* Check for illegal pred. blocks. */
 
 
if (forw_col_start+7 > lmaxx) illegal_forw = 1;
else if (forw_col_start < 0) illegal_forw = 1;
 
if (forw_row_start+7 > lmaxy) illegal_forw = 1;
else if (forw_row_start < 0) illegal_forw = 1;
 
if (back_col_start+7 > lmaxx) illegal_back = 1;
else if (back_col_start < 0) illegal_back = 1;
 
if (back_row_start+7 > lmaxy) illegal_back = 1;
else if (back_row_start < 0) illegal_back = 1;
 
#endif
 
}
/* Otherwise, block is NOT luminance block, ... */
 
else {
 
/* Construct motion vectors. */
 
recon_right_for /= 2;
recon_down_for /= 2;
right_for = recon_right_for >> 1;
down_for = recon_down_for >> 1;
right_half_for = recon_right_for & 0x1;
down_half_for = recon_down_for & 0x1;
 
recon_right_back /= 2;
recon_down_back /= 2;
right_back = recon_right_back >> 1;
down_back = recon_down_back >> 1;
right_half_back = recon_right_back & 0x1;
down_half_back = recon_down_back & 0x1;
 
/* Establish row size. */
 
row_size = (vid_stream->mb_width << 3);
 
/* Calculate row,col of upper left pixel in block. */
 
row = (mb_row << 3);
col = (mb_col << 3);
 
forw_col_start = col + right_for;
forw_row_start = row + down_for;
 
back_col_start = col + right_back;
back_row_start = row + down_back;
 
#ifdef LOOSE_MPEG
 
/* Check for illegal pred. blocks. */
 
if (forw_col_start+7 > cmaxx) illegal_forw = 1;
else if (forw_col_start < 0) illegal_forw = 1;
 
if (forw_row_start+7 > cmaxy) illegal_forw = 1;
else if (forw_row_start < 0) illegal_forw = 1;
 
if (back_col_start+7 > cmaxx) illegal_back = 1;
else if (back_col_start < 0) illegal_back = 1;
if (back_row_start+7 > cmaxy) illegal_back = 1;
else if (back_row_start < 0) illegal_back = 1;
 
#endif
/* If block is Cr block... */
/* Switched earlier, so we test Cr first - eyhung */
 
if (bnum == 5) {
 
/* Set dest to Cr plane of current pict image. */
 
dest = vid_stream->current->Cr;
 
/* If past frame exists, set past to Cr plane of past image. */
 
if (vid_stream->past != NULL)
past = vid_stream->past->Cr;
 
/*
* If future frame exists, set future to Cr plane of future image.
*/
 
if (vid_stream->future != NULL)
future = vid_stream->future->Cr;
}
/* Otherwise, block is Cb block... */
 
else {
 
/* Set dest to Cb plane of current pict image. */
 
dest = vid_stream->current->Cb;
 
/* If past frame exists, set past to Cb plane of past frame. */
 
if (vid_stream->past != NULL)
past = vid_stream->past->Cb;
 
/*
* If future frame exists, set future to Cb plane of future frame.
*/
 
if (vid_stream->future != NULL)
future = vid_stream->future->Cb;
}
}
 
/* For each pixel in block... */
 
index = dest + (row * row_size) + col;
 
#ifdef LOOSE_MPEG
if (illegal_forw)
rindex1 = future + back_row_start * row_size + back_col_start;
else
#endif
rindex1 = past + forw_row_start * row_size + forw_col_start;
 
#ifdef LOOSE_MPEG
if (illegal_back)
bindex1 = past + forw_row_start * row_size + forw_col_start;
else
#endif
bindex1 = future + back_row_start * row_size + back_col_start;
 
blockvals = (short int *) &(vid_stream->block.dct_recon[0][0]);
 
{
unsigned char *cm = cropTbl + MAX_NEG_CROP;
if (!zflag)
for (rr = 0; rr < 4; rr++) {
index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[0]];
index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[1]];
index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[2]];
index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[3]];
index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[4]];
index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[5]];
index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[6]];
index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[7]];
index += row_size;
rindex1 += row_size;
bindex1 += row_size;
 
index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[8]];
index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[9]];
index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[10]];
index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[11]];
index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[12]];
index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[13]];
index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[14]];
index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[15]];
blockvals += 16;
index += row_size;
rindex1 += row_size;
bindex1 += row_size;
}
 
else
for (rr = 0; rr < 4; rr++) {
index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
index += row_size;
rindex1 += row_size;
bindex1 += row_size;
 
index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
index += row_size;
rindex1 += row_size;
bindex1 += row_size;
}
}
}
 
/*
*--------------------------------------------------------------
*
* ProcessSkippedPFrameMBlocks --
*
* Processes skipped macroblocks in P frames.
*
* Results:
* Calculates pixel values for luminance, Cr, and Cb planes
* in current pict image for skipped macroblocks.
*
* Side effects:
* Pixel values in pict image changed.
*
*--------------------------------------------------------------
*/
 
static void
ProcessSkippedPFrameMBlocks(vid_stream)
VidStream *vid_stream;
{
int row_size, half_row, mb_row, mb_col, row, col, rr;
int addr, row_incr, half_row_incr, crow, ccol;
int *dest, *src, *dest1, *src1;
int ditherType=vid_stream->ditherType;
 
/* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
 
row_size = vid_stream->mb_width << 4;
half_row = (row_size >> 1);
row_incr = row_size >> 2;
half_row_incr = half_row >> 2;
 
/* For each skipped macroblock, do... */
 
for (addr = vid_stream->mblock.past_mb_addr + 1;
addr < vid_stream->mblock.mb_address; addr++) {
 
/* Calculate macroblock row and col. */
 
mb_row = addr / vid_stream->mb_width;
mb_col = addr % vid_stream->mb_width;
 
/* Calculate upper left pixel row,col for luminance plane. */
 
row = mb_row << 4;
col = mb_col << 4;
 
 
/* For each row in macroblock luminance plane... */
 
dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
src = (int *)(vid_stream->future->luminance + (row * row_size) + col);
 
for (rr = 0; rr < 8; rr++) {
 
/* Copy pixel values from last I or P picture. */
 
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest += row_incr;
src += row_incr;
 
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest += row_incr;
src += row_incr;
}
 
/*
* Divide row,col to get upper left pixel of macroblock in Cr and Cb
* planes.
*/
 
crow = row >> 1;
ccol = col >> 1;
 
/* For each row in Cr, and Cb planes... */
 
dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
src = (int *)(vid_stream->future->Cr + (crow * half_row) + ccol);
dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
src1 = (int *)(vid_stream->future->Cb + (crow * half_row) + ccol);
 
for (rr = 0; rr < 4; rr++) {
 
/* Copy pixel values from last I or P picture. */
 
dest[0] = src[0];
dest[1] = src[1];
 
dest1[0] = src1[0];
dest1[1] = src1[1];
 
dest += half_row_incr;
src += half_row_incr;
dest1 += half_row_incr;
src1 += half_row_incr;
 
dest[0] = src[0];
dest[1] = src[1];
 
dest1[0] = src1[0];
dest1[1] = src1[1];
 
dest += half_row_incr;
src += half_row_incr;
dest1 += half_row_incr;
src1 += half_row_incr;
}
 
#ifndef DISABLE_DITHER
if (ditherType == MBORDERED_DITHER) {
MBOrderedDitherDisplayCopy(vid_stream, addr,
1, 0, 0, 0, 0, 0,
vid_stream->future->display,
(unsigned char *) NULL);
vid_stream->ditherFlags[addr] = 0;
}
#endif
}
 
vid_stream->mblock.recon_right_for_prev = 0;
vid_stream->mblock.recon_down_for_prev = 0;
}
 
 
 
 
/*
*--------------------------------------------------------------
*
* ProcessSkippedBFrameMBlocks --
*
* Processes skipped macroblocks in B frames.
*
* Results:
* Calculates pixel values for luminance, Cr, and Cb planes
* in current pict image for skipped macroblocks.
*
* Side effects:
* Pixel values in pict image changed.
*
*--------------------------------------------------------------
*/
 
static void
ProcessSkippedBFrameMBlocks(vid_stream)
VidStream *vid_stream;
{
int row_size, half_row, mb_row, mb_col, row, col, rr;
int right_half_for = 0, down_half_for = 0;
int c_right_half_for = 0, c_down_half_for = 0;
int right_half_back = 0, down_half_back = 0;
int c_right_half_back = 0, c_down_half_back = 0;
int addr, right_for = 0, down_for = 0;
int recon_right_for, recon_down_for;
int recon_right_back, recon_down_back;
int right_back = 0, down_back = 0;
int c_right_for = 0, c_down_for = 0;
int c_right_back = 0, c_down_back = 0;
unsigned char forw_lum[256];
unsigned char forw_cr[64], forw_cb[64];
unsigned char back_lum[256], back_cr[64], back_cb[64];
int row_incr, half_row_incr;
int ccol, crow;
int ditherType=vid_stream->ditherType;
 
/* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
 
row_size = vid_stream->mb_width << 4;
half_row = (row_size >> 1);
row_incr = row_size >> 2;
half_row_incr = half_row >> 2;
 
/* Establish motion vector codes based on full pixel flag. */
 
if (vid_stream->picture.full_pel_forw_vector) {
recon_right_for = vid_stream->mblock.recon_right_for_prev << 1;
recon_down_for = vid_stream->mblock.recon_down_for_prev << 1;
} else {
recon_right_for = vid_stream->mblock.recon_right_for_prev;
recon_down_for = vid_stream->mblock.recon_down_for_prev;
}
 
if (vid_stream->picture.full_pel_back_vector) {
recon_right_back = vid_stream->mblock.recon_right_back_prev << 1;
recon_down_back = vid_stream->mblock.recon_down_back_prev << 1;
} else {
recon_right_back = vid_stream->mblock.recon_right_back_prev;
recon_down_back = vid_stream->mblock.recon_down_back_prev;
}
 
 
/* If only one motion vector, do display copy, else do full
calculation.
*/
 
#ifndef DISABLE_DITHER
if (ditherType == MBORDERED_DITHER) {
if (vid_stream->mblock.bpict_past_forw &&
!vid_stream->mblock.bpict_past_back) {
for (addr = vid_stream->mblock.past_mb_addr+1;
addr < vid_stream->mblock.mb_address; addr++) {
MBOrderedDitherDisplayCopy(vid_stream, addr,
1, recon_right_for, recon_down_for,
0, 0, 0, vid_stream->past->display,
vid_stream->future->display);
vid_stream->ditherFlags[addr] = 0;
}
return;
}
if (vid_stream->mblock.bpict_past_back &&
!vid_stream->mblock.bpict_past_forw) {
for (addr = vid_stream->mblock.past_mb_addr+1;
addr < vid_stream->mblock.mb_address; addr++) {
MBOrderedDitherDisplayCopy(vid_stream, addr,
0, 0, 0,
1, recon_right_back, recon_down_back,
vid_stream->past->display, vid_stream->future->display);
vid_stream->ditherFlags[addr] = 0;
}
return;
}
}
#endif
 
/* Calculate motion vectors. */
if (vid_stream->mblock.bpict_past_forw) {
right_for = recon_right_for >> 1;
down_for = recon_down_for >> 1;
right_half_for = recon_right_for & 0x1;
down_half_for = recon_down_for & 0x1;
recon_right_for /= 2;
recon_down_for /= 2;
c_right_for = recon_right_for >> 1;
c_down_for = recon_down_for >> 1;
c_right_half_for = recon_right_for & 0x1;
c_down_half_for = recon_down_for & 0x1;
}
if (vid_stream->mblock.bpict_past_back) {
right_back = recon_right_back >> 1;
down_back = recon_down_back >> 1;
right_half_back = recon_right_back & 0x1;
down_half_back = recon_down_back & 0x1;
recon_right_back /= 2;
recon_down_back /= 2;
c_right_back = recon_right_back >> 1;
c_down_back = recon_down_back >> 1;
c_right_half_back = recon_right_back & 0x1;
c_down_half_back = recon_down_back & 0x1;
}
/* For each skipped macroblock, do... */
for (addr = vid_stream->mblock.past_mb_addr + 1;
addr < vid_stream->mblock.mb_address; addr++) {
/* Calculate macroblock row and col. */
mb_row = addr / vid_stream->mb_width;
mb_col = addr % vid_stream->mb_width;
/* Calculate upper left pixel row,col for luminance plane. */
row = mb_row << 4;
col = mb_col << 4;
crow = row / 2;
ccol = col / 2;
/* If forward predicted, calculate prediction values. */
if (vid_stream->mblock.bpict_past_forw) {
ReconSkippedBlock(vid_stream->past->luminance, forw_lum,
row, col, row_size, right_for, down_for,
right_half_for, down_half_for, 16);
ReconSkippedBlock(vid_stream->past->Cr, forw_cr, crow,
ccol, half_row,
c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
ReconSkippedBlock(vid_stream->past->Cb, forw_cb, crow,
ccol, half_row,
c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
}
/* If back predicted, calculate prediction values. */
if (vid_stream->mblock.bpict_past_back) {
ReconSkippedBlock(vid_stream->future->luminance, back_lum,
row, col, row_size, right_back, down_back,
right_half_back, down_half_back, 16);
ReconSkippedBlock(vid_stream->future->Cr, back_cr, crow,
ccol, half_row,
c_right_back, c_down_back,
c_right_half_back, c_down_half_back, 8);
ReconSkippedBlock(vid_stream->future->Cb, back_cb, crow,
ccol, half_row,
c_right_back, c_down_back,
c_right_half_back, c_down_half_back, 8);
}
if (vid_stream->mblock.bpict_past_forw &&
!vid_stream->mblock.bpict_past_back) {
int *dest, *dest1;
int *src, *src1;
dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
src = (int *)forw_lum;
for (rr = 0; rr < 16; rr++) {
/* memcpy(dest, forw_lum+(rr<<4), 16); */
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest += row_incr;
src += 4;
}
dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
src = (int *)forw_cr;
src1 = (int *)forw_cb;
for (rr = 0; rr < 8; rr++) {
/*
* memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3),
* 8);
*/
dest[0] = src[0];
dest[1] = src[1];
dest1[0] = src1[0];
dest1[1] = src1[1];
dest += half_row_incr;
dest1 += half_row_incr;
src += 2;
src1 += 2;
}
} else if (vid_stream->mblock.bpict_past_back &&
!vid_stream->mblock.bpict_past_forw) {
int *src, *src1;
int *dest, *dest1;
dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
src = (int *)back_lum;
for (rr = 0; rr < 16; rr++) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest += row_incr;
src += 4;
}
dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
src = (int *)back_cr;
src1 = (int *)back_cb;
for (rr = 0; rr < 8; rr++) {
/*
* memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3),
* 8);
*/
dest[0] = src[0];
dest[1] = src[1];
dest1[0] = src1[0];
dest1[1] = src1[1];
dest += half_row_incr;
dest1 += half_row_incr;
src += 2;
src1 += 2;
}
} else {
unsigned char *src1, *src2, *src1a, *src2a;
unsigned char *dest, *dest1;
dest = vid_stream->current->luminance + (row * row_size) + col;
src1 = forw_lum;
src2 = back_lum;
for (rr = 0; rr < 16; rr++) {
dest[0] = (int) (src1[0] + src2[0]) >> 1;
dest[1] = (int) (src1[1] + src2[1]) >> 1;
dest[2] = (int) (src1[2] + src2[2]) >> 1;
dest[3] = (int) (src1[3] + src2[3]) >> 1;
dest[4] = (int) (src1[4] + src2[4]) >> 1;
dest[5] = (int) (src1[5] + src2[5]) >> 1;
dest[6] = (int) (src1[6] + src2[6]) >> 1;
dest[7] = (int) (src1[7] + src2[7]) >> 1;
dest[8] = (int) (src1[8] + src2[8]) >> 1;
dest[9] = (int) (src1[9] + src2[9]) >> 1;
dest[10] = (int) (src1[10] + src2[10]) >> 1;
dest[11] = (int) (src1[11] + src2[11]) >> 1;
dest[12] = (int) (src1[12] + src2[12]) >> 1;
dest[13] = (int) (src1[13] + src2[13]) >> 1;
dest[14] = (int) (src1[14] + src2[14]) >> 1;
dest[15] = (int) (src1[15] + src2[15]) >> 1;
dest += row_size;
src1 += 16;
src2 += 16;
}
dest = vid_stream->current->Cr + (crow * half_row) + ccol;
dest1 = vid_stream->current->Cb + (crow * half_row) + ccol;
src1 = forw_cr;
src2 = back_cr;
src1a = forw_cb;
src2a = back_cb;
for (rr = 0; rr < 8; rr++) {
dest[0] = (int) (src1[0] + src2[0]) >> 1;
dest[1] = (int) (src1[1] + src2[1]) >> 1;
dest[2] = (int) (src1[2] + src2[2]) >> 1;
dest[3] = (int) (src1[3] + src2[3]) >> 1;
dest[4] = (int) (src1[4] + src2[4]) >> 1;
dest[5] = (int) (src1[5] + src2[5]) >> 1;
dest[6] = (int) (src1[6] + src2[6]) >> 1;
dest[7] = (int) (src1[7] + src2[7]) >> 1;
dest += half_row;
src1 += 8;
src2 += 8;
dest1[0] = (int) (src1a[0] + src2a[0]) >> 1;
dest1[1] = (int) (src1a[1] + src2a[1]) >> 1;
dest1[2] = (int) (src1a[2] + src2a[2]) >> 1;
dest1[3] = (int) (src1a[3] + src2a[3]) >> 1;
dest1[4] = (int) (src1a[4] + src2a[4]) >> 1;
dest1[5] = (int) (src1a[5] + src2a[5]) >> 1;
dest1[6] = (int) (src1a[6] + src2a[6]) >> 1;
dest1[7] = (int) (src1a[7] + src2a[7]) >> 1;
dest1 += half_row;
src1a += 8;
src2a += 8;
}
}
#ifndef DISABLE_DITHER
if (ditherType == MBORDERED_DITHER) {
vid_stream->ditherFlags[addr] = 1;
}
#endif
}
}
 
 
 
 
/*
*--------------------------------------------------------------
*
* ReconSkippedBlock --
*
* Reconstructs predictive block for skipped macroblocks
* in B Frames.
*
* Results:
* No return values.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
static void
ReconSkippedBlock(source, dest, row, col, row_size,
right, down, right_half, down_half, width)
unsigned char *source;
unsigned char *dest;
int row, col, row_size, right, down, right_half, down_half, width;
{
int rr;
unsigned char *source2;
 
source += ((row + down) * row_size) + col + right;
 
if (width == 16) {
if ((!right_half) && (!down_half)) {
if (right & 0x1) {
/* No alignment, use bye copy */
for (rr = 0; rr < 16; rr++) {
dest[0] = source[0];
dest[1] = source[1];
dest[2] = source[2];
dest[3] = source[3];
dest[4] = source[4];
dest[5] = source[5];
dest[6] = source[6];
dest[7] = source[7];
dest[8] = source[8];
dest[9] = source[9];
dest[10] = source[10];
dest[11] = source[11];
dest[12] = source[12];
dest[13] = source[13];
dest[14] = source[14];
dest[15] = source[15];
dest += 16;
source += row_size;
}
} else if (right & 0x2) {
/* Half-word bit aligned, use 16 bit copy */
short *src = (short *)source;
short *d = (short *)dest;
row_size >>= 1;
for (rr = 0; rr < 16; rr++) {
d[0] = src[0];
d[1] = src[1];
d[2] = src[2];
d[3] = src[3];
d[4] = src[4];
d[5] = src[5];
d[6] = src[6];
d[7] = src[7];
d += 8;
src += row_size;
}
} else {
/* Word aligned, use 32 bit copy */
int *src = (int *)source;
int *d = (int *)dest;
row_size >>= 2;
for (rr = 0; rr < 16; rr++) {
d[0] = src[0];
d[1] = src[1];
d[2] = src[2];
d[3] = src[3];
d += 4;
src += row_size;
}
}
} else {
source2 = source + right_half + (row_size * down_half);
for (rr = 0; rr < width; rr++) {
dest[0] = (int) (source[0] + source2[0]) >> 1;
dest[1] = (int) (source[1] + source2[1]) >> 1;
dest[2] = (int) (source[2] + source2[2]) >> 1;
dest[3] = (int) (source[3] + source2[3]) >> 1;
dest[4] = (int) (source[4] + source2[4]) >> 1;
dest[5] = (int) (source[5] + source2[5]) >> 1;
dest[6] = (int) (source[6] + source2[6]) >> 1;
dest[7] = (int) (source[7] + source2[7]) >> 1;
dest[8] = (int) (source[8] + source2[8]) >> 1;
dest[9] = (int) (source[9] + source2[9]) >> 1;
dest[10] = (int) (source[10] + source2[10]) >> 1;
dest[11] = (int) (source[11] + source2[11]) >> 1;
dest[12] = (int) (source[12] + source2[12]) >> 1;
dest[13] = (int) (source[13] + source2[13]) >> 1;
dest[14] = (int) (source[14] + source2[14]) >> 1;
dest[15] = (int) (source[15] + source2[15]) >> 1;
dest += width;
source += row_size;
source2 += row_size;
}
}
} else { /* (width == 8) */
assert(width == 8);
if ((!right_half) && (!down_half)) {
if (right & 0x1) {
for (rr = 0; rr < width; rr++) {
dest[0] = source[0];
dest[1] = source[1];
dest[2] = source[2];
dest[3] = source[3];
dest[4] = source[4];
dest[5] = source[5];
dest[6] = source[6];
dest[7] = source[7];
dest += 8;
source += row_size;
}
} else if (right & 0x02) {
short *d = (short *)dest;
short *src = (short *)source;
row_size >>= 1;
for (rr = 0; rr < width; rr++) {
d[0] = src[0];
d[1] = src[1];
d[2] = src[2];
d[3] = src[3];
d += 4;
src += row_size;
}
} else {
int *d = (int *)dest;
int *src = (int *)source;
row_size >>= 2;
for (rr = 0; rr < width; rr++) {
d[0] = src[0];
d[1] = src[1];
d += 2;
src += row_size;
}
}
} else {
source2 = source + right_half + (row_size * down_half);
for (rr = 0; rr < width; rr++) {
dest[0] = (int) (source[0] + source2[0]) >> 1;
dest[1] = (int) (source[1] + source2[1]) >> 1;
dest[2] = (int) (source[2] + source2[2]) >> 1;
dest[3] = (int) (source[3] + source2[3]) >> 1;
dest[4] = (int) (source[4] + source2[4]) >> 1;
dest[5] = (int) (source[5] + source2[5]) >> 1;
dest[6] = (int) (source[6] + source2[6]) >> 1;
dest[7] = (int) (source[7] + source2[7]) >> 1;
dest += width;
source += row_size;
source2 += row_size;
}
}
}
}
 
 
 
/*
*--------------------------------------------------------------
*
* DoPictureDisplay --
*
* Converts image from Lum, Cr, Cb to colormap space. Puts
* image in lum plane. Updates past and future frame
* pointers. Dithers image. Sends to display mechanism.
*
* Results:
* Pict image structure locked if displaying or if frame
* is needed as past or future reference.
*
* Side effects:
* Lum plane pummelled.
*
*--------------------------------------------------------------
*/
 
static void
DoPictureDisplay(vid_stream, xinfo)
VidStream *vid_stream;
XInfo *xinfo;
{
 
if (No_B_Flag && (vid_stream->picture.code_type == B_TYPE)) return;
 
/* Convert to colormap space and dither. */
DoDitherImage(vid_stream);
 
/* Update past and future references if needed. */
 
if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) {
if (vid_stream->future == NULL) {
vid_stream->future = vid_stream->current;
vid_stream->future->locked |= FUTURE_LOCK;
} else {
if (vid_stream->past != NULL) {
vid_stream->past->locked &= ~PAST_LOCK;
}
vid_stream->past = vid_stream->future;
vid_stream->past->locked &= ~FUTURE_LOCK;
vid_stream->past->locked |= PAST_LOCK;
vid_stream->future = vid_stream->current;
vid_stream->future->locked |= FUTURE_LOCK;
vid_stream->current = vid_stream->past;
#ifndef NOCONTROLS
ExecuteDisplay(vid_stream, 1, xinfo);
#else
ExecuteDisplay(vid_stream, xinfo);
#endif /* !NOCONTROLS */
}
} else {
#ifndef NOCONTROLS
ExecuteDisplay(vid_stream, 1, xinfo);
#else
ExecuteDisplay(vid_stream, xinfo);
#endif /* !NOCONTROLS */
}
}
 
 
 
/*
*--------------------------------------------------------------
*
* SetBFlag --
*
* Called to set no b frame processing flag.
*
* Results:
* No_B_Flag flag is set to its argument.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
SetBFlag(val)
BOOLEAN val;
{
No_B_Flag = val;
}
 
 
 
 
/*
*--------------------------------------------------------------
*
* SetPFlag --
*
* Called to set no p frame processing flag.
*
* Results:
* No_P_Flag flag is set to value of argument
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
SetPFlag(val)
BOOLEAN val;
{
No_P_Flag = val;
}
/shark/trunk/ports/mpeg/mono.c
0,0 → 1,217
/*
* Author: Yoichiro Ueno (ueno@cs.titech.ac.jp)
*
* Copyright (C) 1991, 1992, Yoichiro Ueno.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose is hereby granted by the Author without
* fee, provided that the above copyright notice appear in all copies and
* that both the copyright notice and this permission notice appear in
* supporting documentation, and that the name of the Author not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The Author makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
*/
 
#include <stddef.h>
#include "video.h"
#include "proto.h"
#include "dither.h"
 
 
/*
*--------------------------------------------------------------
*
* MonoDitherImage --
*
* Dithers image into monochrome.
* Dither algorithm is based on dither.c in xli.1.11.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
#define MaxGrey 65280
#define Threshold (MaxGrey/2)
#define MinGrey 0
 
#if LITTLE_ENDIAN_ARCHITECTURE
# define SEED_BIT 0x01
# define OPP_SEED_BIT 0x80
# define SHIFT_SEED_BIT(b) (b <<= 1)
# define OPP_SHIFT_SEED_BIT(b) (b >>= 1)
#else
# define SEED_BIT 0x80
# define OPP_SEED_BIT 0x01
# define SHIFT_SEED_BIT(b) (b >>= 1)
# define OPP_SHIFT_SEED_BIT(b) (b <<= 1)
#endif
 
static int *curr = NULL;
static int *next = NULL;
 
void
MonoDitherImage(lum, cr, cb, out, h, w)
register unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
register unsigned char *out;
int w, h;
{
int bit_r2l;
register unsigned int bit;
register unsigned int data;
int i;
register int j;
int *swap;
register int out_err;
register int next1;
register int next2;
 
if (curr == NULL) {
curr = (int *)malloc((unsigned int) sizeof(int) * (w + 2));
curr += 1;
}
if (next == NULL) {
next = (int *)malloc((unsigned int) sizeof(int) * (w + 2));
next += 1;
}
 
memset ((char *)curr, 0, (size_t)w * sizeof(*curr));
 
bit_r2l = SEED_BIT << ((w - 1) & 7);
for (i = 0; i < h; i ++) {
if (i & 0x01) { /* Right to Left */
bit = bit_r2l;
data = 0;
out_err = curr[w-1];
next1 = 0;
next2 = 0;
for (j=(w-1); j>=0; j--)
{
out_err = (out_err >> 4) + (lum[j] << 8);
if (out_err > Threshold) {
data |= bit;
out_err -= MaxGrey;
}
else
out_err -= MinGrey;
 
next[j+1] = next1 + (out_err * 3);
next1 = next2 + (out_err * 5);
next2 = (out_err * 1);
out_err = curr[j-1] + (out_err * 7);
 
OPP_SHIFT_SEED_BIT(bit);
#if LITTLE_ENDIAN_ARCHITECTURE
if (bit == 0) {
#else
if (bit > 0x80) {
#endif
out[j >> 3] = data;
bit = OPP_SEED_BIT;
data = 0;
}
}
next[0] = next1;
}
else { /* Left to Right */
bit = SEED_BIT;
data = 0;
out_err = curr[0];
next1 = 0;
next2 = 0;
for (j=0; j<w; j++)
{
out_err = (out_err >> 4) + (lum[j] << 8);
if (out_err > Threshold) {
data |= bit;
out_err = out_err - MaxGrey;
}
else
out_err = out_err - MinGrey;
 
next[j-1] = next1 + (out_err * 3);
next1 = next2 + (out_err * 5);
next2 = (out_err * 1);
out_err = curr[j+1] + (out_err * 7);
 
SHIFT_SEED_BIT(bit);
#if LITTLE_ENDIAN_ARCHITECTURE
if (bit > 0x80) {
#else
if (bit == 0) {
#endif
out[j >> 3] = data;
bit = SEED_BIT;
data = 0;
}
}
next[w-1] = next1;
}
lum += w;
out += w >> 3;
swap = curr;
curr = next;
next = swap;
}
}
 
 
/*
*--------------------------------------------------------------
*
* MonoThresholdImage --
*
* convert image into monochrome with threshold.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
MonoThresholdImage(lum, cr, cb, out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int w, h;
{
unsigned char bit;
unsigned char data;
 
bit = SEED_BIT;
data = 0;
for (w*=h; w>0; w--) {
if(*lum++>128)
data |= bit;
 
SHIFT_SEED_BIT(bit);
if(bit == 0) {
*out ++ = data;
bit = SEED_BIT;
data = 0;
}
}
}
/shark/trunk/ports/mpeg/testwrap.c
0,0 → 1,204
/*
* Copyright 1995, Brown University, Providence, RI
*
* Permission to use and modify this software and its documentation for
* any purpose other than its incorporation into a commercial product is
* hereby granted without fee. Permission to copy and distribute this
* software and its documentation only for non-commercial use is also
* granted without fee, provided, however, that the above copyright notice
* appear in all copies, that both that copyright notice and this permission
* notice appear in supporting documentation, that the name of Brown
* University not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission,
* and that the person doing the distribution notify Brown University of
* such distributions outside of his or her organization. Brown University
* makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
* Brown University requests notification of any modifications to this
* software or its documentation.
*
* Send the following redistribution information:
*
* Name:
* Organization:
* Address (postal and/or electronic):
*
* To:
* Software Librarian
* Computer Science Department, Box 1910
* Brown University
* Providence, RI 02912
*
* or
*
* brusd@cs.brown.edu
*
* We will acknowledge all electronic notifications.
*/
#include <stdio.h>
#include <iostream.h>
#include "ANIMdisplay.H"
#include "ANIMmpeg.H"
#ifndef NONV
#include "ANIMnv.H"
#endif
 
extern unsigned long wpixel[256];
extern int quietFlag;
 
const int NUMMOVIES=20;
int numInput=0;
 
/* Global file pointer to incoming data. */
char *inputName[NUMMOVIES];
 
int buffer=TRUE;
int compress=TRUE, cycle=FALSE;
#ifndef NOTHREADS
int mthread=TRUE;
#endif
 
void
displayMovies(ANIMdisplay **theWindows, ANIMbase **theMovies)
{
/* Start multithreading after all the images have been init-ed */
int moviesToDisplay=cycle ? 1 : numInput;
 
for (int i=0;i<moviesToDisplay;i++) {
theMovies[i]->Buffer(buffer, compress);
#ifndef NOTHREADS
theMovies[i]->MultiThread(mthread);
#endif
}
 
quietFlag=0;
Boolean workToDo=TRUE;
 
if (cycle) {
int currentMovie=0, frames=0;
while(1) {
theWindows[0]->display();
frames++;
if (cycle && theWindows[0]->movieDone()) {
ANIMbase *movie= theWindows[0]->_movie;
 
printf("%d %dx%d frames, %s\n",
frames, movie->Width, movie->Height, movie->getName());
fflush(stdout);
frames=0;
currentMovie=++currentMovie % numInput;
theWindows[0]->newMovie(inputName[currentMovie]);
}
}
} else {
while (workToDo) {
for (int whichMovie=0;whichMovie<numInput;whichMovie++) {
theWindows[whichMovie]->display();
}
}
}
}
 
#ifndef __STDC__
void
#else
int
#endif
main(int argc, char **argv)
{
char *filename="/home/lsh/tii/mpeg/eggclock.mpg";
int mark=1;
ANIMbase *theMovie[NUMMOVIES];
ANIMdisplay *theWindow[NUMMOVIES];
char *displayName="";
 
/* Initiialize arrays */
for (int i=0;i<NUMMOVIES; i++) {
inputName[i] = filename;
theWindow[i]=NULL;
theMovie[i]=NULL;
}
 
//
// Get command line arguments
//
argc--;
 
while (argc) {
if (strcmp(argv[mark], "-display") == 0) {
displayName= argv[++mark];
argc -= 2; mark++;
} else if (strcmp(argv[mark], "-no_buffer") == 0) {
buffer=FALSE;
argc--; mark++;
} else if (strcmp(argv[mark], "-no_compress") == 0) {
compress=FALSE;
argc--; mark++;
} else if (strcmp(argv[mark], "-cycle") == 0) {
cycle=TRUE;
buffer=FALSE; //for now, or we don't know to cycle
argc--; mark++;
#ifndef NOTHREADS
} else if (strcmp(argv[mark], "-no_mthread") == 0) {
mthread=FALSE;
argc--; mark++;
#endif
} else {
fflush(stdout);
if (numInput<NUMMOVIES) {
inputName[numInput] = argv[mark];
if ((numInput==0) || !cycle) {
#ifndef NONV
if (strstr(inputName[numInput],"mbone:")!=NULL) {
theMovie[numInput]=
(ANIMbase *) new ANIMnv(inputName[numInput]);
} else
#endif
theMovie[numInput]=
(ANIMbase *) new ANIMmpeg(inputName[numInput]);
if (!theMovie[numInput]->OkFile()) {
fprintf(stderr, "%s: %s not found\n", argv[0],argv[mark]);
/* shouldn't have to delete it each time - reuse!*/
delete theMovie[numInput];
} else {
if (theMovie[numInput]->open()) {
if (numInput==0) {
theWindow[0]=new ANIMdisplay((ANIMbase *) theMovie[0],
displayName,!cycle);
} else {
theWindow[numInput]=new ANIMdisplay(
(ANIMbase *) theMovie[numInput],
theWindow[numInput-1],
!cycle);
}
numInput++;
} else {
fprintf(stderr,"%s: %s not an MPEG file\n",
argv[0],argv[mark]);
delete theMovie[numInput];
}
}
} else if (cycle) {
numInput++;
}
} else {
fprintf(stderr, "Can't load file %s - too many\n", argv[mark]);
}
argc--; mark++;
}
}
 
if (numInput) displayMovies(theWindow, (ANIMbase **) theMovie);
else {
#ifndef NOTHREADS
char *threadStr="-no_mthread";
#else
char *threadStr="";
#endif
fprintf(stderr,"%s: no files entered\n",argv[0]);
fprintf(stderr,
"usage: %s [-display display -no_buffer %s -cycle -no_compress] movie ... \n",
argv[0],threadStr);
exit(1);
}
}
/shark/trunk/ports/mpeg/2x2.c
0,0 → 1,393
/*
* 2x2.c --
*
* Procedures concerned with 2x2 dithering.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "dither.h"
#include "proto.h"
#ifdef __STDC__
#include <stdlib.h>
#endif
 
#define RAND_ERR_RANGE 7
#define RAND_ERR_SUBVAL 3
 
#define NO_LRAND48
#define NO_RANDOM
 
/* Array containing actual pixel values for each possible 2x2 dither pattern. */
 
static unsigned char *dith_a;
 
/* Arrays mapping lum, cr, and cb values to portions of dither pattern code.
The addtion of one value from each array yields a valid dither pattern
code.
*/
 
static int lval_a[256+RAND_ERR_RANGE-1];
static int rval_a[256+RAND_ERR_RANGE-1];
static int bval_a[256+RAND_ERR_RANGE-1];
 
/* Range of possible dither patterns in each channel. */
 
#define L_DITH_RANGE (((LUM_RANGE-1)*4)+1)
#define CR_DITH_RANGE (((CR_RANGE-1)*4)+1)
#define CB_DITH_RANGE (((CB_RANGE-1)*4)+1)
 
/* Arrays of random error terms added to break up contours. */
 
static int *randval_a;
static int **randptr_a;
 
/*
*--------------------------------------------------------------
*
* Init2x2Dither--
*
* Initializes structures used for 2x2 dithering.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
Init2x2Dither()
{
unsigned char *dith_ca;
int numcodes;
int l_range, cr_range, cb_range;
int p1, p2, p3, p4;
int l_dith, cr_dith, cb_dith;
int big_part, small_part;
int i, j;
 
l_range = L_DITH_RANGE;
cr_range = CR_DITH_RANGE;
cb_range = CB_DITH_RANGE;
 
numcodes = l_range * cr_range * cb_range;
 
dith_a = (unsigned char *) malloc(numcodes*4);
 
dith_ca = dith_a;
 
for (i=0; i<numcodes; i++) {
l_dith = i % l_range;
 
big_part = l_dith / 4;
small_part = l_dith % 4;
 
p1 = big_part + ((small_part > 0) ? 1 : 0);
p2 = big_part + ((small_part > 2) ? 1 : 0);
p3 = big_part;
p4 = big_part + ((small_part > 1) ? 1 : 0);
 
p1 *= CR_RANGE * CB_RANGE;
p2 *= CR_RANGE * CB_RANGE;
p3 *= CR_RANGE * CB_RANGE;
p4 *= CR_RANGE * CB_RANGE;
 
cr_dith = (i/l_range) % cr_range;
 
big_part = cr_dith / 4;
small_part = cr_dith % 4;
 
p1 += (big_part + ((small_part > 0) ? 1 : 0))*CB_RANGE;
p2 += (big_part + ((small_part > 2) ? 1 : 0))*CB_RANGE;
p3 += (big_part)*CB_RANGE;
p4 += (big_part + ((small_part > 1) ? 1 : 0))*CB_RANGE;
 
cb_dith = (i/(cr_range*l_range)) % cb_range;
 
big_part = cb_dith / 4;
small_part = cb_dith % 4;
 
p1 += (big_part + ((small_part > 0) ? 1 : 0));
p2 += (big_part + ((small_part > 2) ? 1 : 0));
p3 += (big_part);
p4 += (big_part + ((small_part > 1) ? 1 : 0));
 
*dith_ca++ = p1;
*dith_ca++ = p2;
*dith_ca++ = p3;
*dith_ca++ = p4;
}
 
for (i=RAND_ERR_SUBVAL; i<256+RAND_ERR_SUBVAL; i++) {
j = i-RAND_ERR_SUBVAL;
lval_a[i] = (j * L_DITH_RANGE)/256;
rval_a[i] = (j * CR_DITH_RANGE)/256;
bval_a[i] = (j * CB_DITH_RANGE)/256;
 
bval_a[i] *= CR_DITH_RANGE * L_DITH_RANGE * 4;
rval_a[i] *= L_DITH_RANGE * 4;
lval_a[i] *= 4;
}
 
for (i=0; i<RAND_ERR_SUBVAL; i++) {
lval_a[i] = lval_a[RAND_ERR_SUBVAL];
rval_a[i] = rval_a[RAND_ERR_SUBVAL];
bval_a[i] = bval_a[RAND_ERR_SUBVAL];
}
 
for(i=256+RAND_ERR_SUBVAL; i<256+RAND_ERR_RANGE-1; i++) {
lval_a[i] = lval_a[255+RAND_ERR_SUBVAL];
rval_a[i] = rval_a[255+RAND_ERR_SUBVAL];
bval_a[i] = bval_a[255+RAND_ERR_SUBVAL];
}
}
 
/*
*--------------------------------------------------------------
*
* RandInit --
*
* Initializes the random values used for 2x2 dithering.
*
* Results:
* randval_a filled with random values.
* randptr_a filled with random pointers to random value arrays.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void RandInit(h, w)
int h, w;
{
int i;
 
randval_a = (int *) malloc(w*5*sizeof(int));
randptr_a = (int **) malloc(h*sizeof(int *));
 
#ifdef NO_LRAND48
for (i=0; i<w*5; i++) {
#ifdef NO_RANDOM
#define random() rand()
#else
long int random();
#endif
 
randval_a[i] = random() % RAND_ERR_RANGE;
}
 
for (i=0; i<h; i++) {
#ifndef NO_RANDOM
long int random();
#endif
 
randptr_a[i] = randval_a + (random() % (w*2));
}
#else /* NO_LRAND48 */
 
for (i=0; i<w*5; i++) {
long int lrand48();
randval_a[i] = lrand48() % RAND_ERR_RANGE;
}
for (i=0; i<h; i++) {
long int lrand48();
 
randptr_a[i] = randval_a + (lrand48() % (w*2));
}
#endif
}
 
/*
*--------------------------------------------------------------
*
* PostInit2x2Dither--
*
* Remaps color numbers in dither patterns to actual pixel
* values allocated by the X server.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
PostInit2x2Dither()
{
unsigned char *dith_ca;
int i;
 
dith_ca = dith_a;
 
for (i=0; i < (L_DITH_RANGE * CR_DITH_RANGE * CB_DITH_RANGE); i++) {
*dith_ca = pixel[*dith_ca];
dith_ca++;
*dith_ca = pixel[*dith_ca];
dith_ca++;
*dith_ca = pixel[*dith_ca];
dith_ca++;
*dith_ca = pixel[*dith_ca];
dith_ca++;
}
}
 
/*
*--------------------------------------------------------------
*
* Twox2DitherImage --
*
* Dithers lum, cr, and cb channels togethor using predefined
* and computed 2x2 dither patterns. Each possible combination of
* lum, cr, and cb values combines to point to a particular dither
* pattern (2x2) which is used to represent the pixel. This assumes
* That the display plane is 4 times larger than the lumianance
* plane.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
Twox2DitherImage(lum, cr, cb, out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int w, h;
{
int i, j;
unsigned short *o1, *o2, *o3, *o4;
unsigned char *l1, *l2, *base;
unsigned char B, R;
unsigned short *dith_ca;
int big_adv = 3*w;
int b_val, r_val, l_val;
static int first = 1;
 
if (first) {
RandInit(h, w);
first = 0;
}
 
o1 = (unsigned short *)out;
o2 = (unsigned short *)(out+(2*w));
o3 = (unsigned short *)(out+(4*w));
o4 = (unsigned short *)(out+(6*w));
l1 = lum;
l2 = lum+w;
 
for (i=0; i<h; i+=2) {
for(j=0; j<w; j+= 4) {
B = cb[0];
b_val = bval_a[B];
R = cr[0];
r_val = rval_a[R];
base = dith_a + b_val + r_val;
 
l_val = lval_a[l1[0]];
dith_ca = (unsigned short *)(base + l_val);
o1[0] = dith_ca[0];
o2[0] = dith_ca[1];
 
l_val = lval_a[l1[1]];
dith_ca = (unsigned short *)(base + l_val);
o1[1] = dith_ca[0];
o2[1] = dith_ca[1];
 
l_val = lval_a[l2[0]];
dith_ca = (unsigned short *)(base + l_val);
o3[0] = dith_ca[0];
o4[0] = dith_ca[1];
 
l_val = lval_a[l2[1]];
dith_ca = (unsigned short *)(base + l_val);
o3[1] = dith_ca[0];
o4[1] = dith_ca[1];
 
B = cb[1];
b_val = bval_a[B];
R = cr[1];
r_val = rval_a[R];
base = dith_a + b_val + r_val;
 
l_val = lval_a[l1[2]];
dith_ca = (unsigned short *)(base + l_val);
o1[2] = dith_ca[0];
o2[2] = dith_ca[1];
 
l_val = lval_a[l1[3]];
dith_ca = (unsigned short *)(base + l_val);
o1[3] = dith_ca[0];
o2[3] = dith_ca[1];
 
l_val = lval_a[l2[2]];
dith_ca = (unsigned short *)(base + l_val);
o3[2] = dith_ca[0];
o4[2] = dith_ca[1];
 
l_val = lval_a[l2[3]];
dith_ca = (unsigned short *)(base + l_val);
o3[3] = dith_ca[0];
o4[3] = dith_ca[1];
 
o1 += 4;
o2 += 4;
o3 += 4;
o4 += 4;
l1 += 4;
l2 += 4;
cb += 2;
cr += 2;
}
 
l1 += w;
l2 += w;
o1 += big_adv;
o2 += big_adv;
o3 += big_adv;
o4 += big_adv;
}
}
/shark/trunk/ports/mpeg/video.h
0,0 → 1,456
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#ifndef MPEG_LIB_VIDEO_HEADER
#define MPEG_LIB_VIDEO_HEADER
#include <stdio.h>
 
#ifdef USEX
#include <X11/Xlib.h>
#include <X11/Xutil.h>
 
#ifdef SH_MEM
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#endif
#endif
 
/*
Changes to make the code reentrant:
deglobalized: ditherFlags, totNumFrames, realTimeStart, matched_depth,
filename, ditherType, curBits, ReconPMBlock statics, stream id
variables, Parse_done, swap, seekValue, input, EOF_flag, ReadPacket
statics, sys_layer, curVidStream, curVidStream, jmb_buf env (removed)
X globals now in xinfo: ditherType, visual, depth (also name), hints,
owncmFlag, et al
now const: scan
film_has_ended instead of FilmState
Additional changes:
if DISABLE_DITHER defined, don't compile dithering code
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* X11/xmd.h correctly defines INT32, etc */
#ifndef XMD_H
typedef int INT32;
typedef short INT16;
typedef char INT8;
#endif
typedef unsigned int UINT32;
typedef unsigned short UINT16;
typedef unsigned char UINT8;
/* Define Parsing error codes. */
 
#define SKIP_PICTURE (-10)
#define SKIP_TO_START_CODE (-1)
#define PARSE_OK 1
 
/* Define BOOLEAN, TRUE, and FALSE. */
 
#define BOOLEAN int
#define TRUE 1
#define FALSE 0
 
/* Set ring buffer size. */
 
#define RING_BUF_SIZE 5
 
/* Macros for picture code type. */
 
#define I_TYPE 1
#define P_TYPE 2
#define B_TYPE 3
#define D_TYPE 4
 
/* Start codes. */
 
#define SEQ_END_CODE 0x000001b7
#define SEQ_START_CODE 0x000001b3
#define GOP_START_CODE 0x000001b8
#define PICTURE_START_CODE 0x00000100
#define SLICE_MIN_START_CODE 0x00000101
#define SLICE_MAX_START_CODE 0x000001af
#define EXT_START_CODE 0x000001b5
#define USER_START_CODE 0x000001b2
#define SEQUENCE_ERROR_CODE 0x000001b4
 
/* Number of macroblocks to process in one call to mpegVidRsrc. */
 
#define MB_QUANTUM 100
 
/* Macros used with macroblock address decoding. */
 
#define MB_STUFFING 34
#define MB_ESCAPE 35
 
/* Lock flags for pict images. */
 
#define DISPLAY_LOCK 0x01
#define PAST_LOCK 0x02
#define FUTURE_LOCK 0x04
 
#define HYBRID_DITHER 0
#define HYBRID2_DITHER 1
#define FS4_DITHER 2
#define FS2_DITHER 3
#define FS2FAST_DITHER 4
#define Twox2_DITHER 5
#define GRAY_DITHER 6
#define FULL_COLOR_DITHER 7
#define NO_DITHER 8
#define ORDERED_DITHER 9
#define MONO_DITHER 10
#define MONO_THRESHOLD 11
#define ORDERED2_DITHER 12
#define MBORDERED_DITHER 13
#define GRAY256_DITHER 14
#define PPM_DITHER 15
#define FULL_COLOR2_DITHER 16
#define GRAY2_DITHER 17
#define GRAY2562_DITHER 18
 
// MG
#define HALF_COLOR_DITHER 19
 
#ifdef DISABLE_DITHER
#define IS_2x2_DITHER(a) (0)
#else
#define IS_2x2_DITHER(a) ((a) == Twox2_DITHER || (a) == FULL_COLOR2_DITHER || (a) == GRAY2_DITHER || (a) == (GRAY2562_DITHER))
#endif
 
/* External declaration of row,col to zig zag conversion matrix. */
 
/* Brown - changed to const int because it is a help variable */
extern const int scan[][8];
 
/* Temporary definition of time stamp structure. */
 
typedef int TimeStamp;
 
/* Structure with reconstructed pixel values. */
 
typedef struct pict_image {
unsigned char *luminance; /* Luminance plane. */
unsigned char *Cr; /* Cr plane. */
unsigned char *Cb; /* Cb plane. */
unsigned char *display; /* Display plane. */
int locked; /* Lock flag. */
TimeStamp show_time; /* Presentation time. */
 
#ifdef SH_MEM
XShmSegmentInfo shminfo; /* Segment info. */
XImage *ximage; /* Ximage struct. */
#endif
 
} PictImage;
 
/* Group of pictures structure. */
 
typedef struct GoP {
BOOLEAN drop_flag; /* Flag indicating dropped frame. */
unsigned int tc_hours; /* Hour component of time code. */
unsigned int tc_minutes; /* Minute component of time code. */
unsigned int tc_seconds; /* Second component of time code. */
unsigned int tc_pictures; /* Picture counter of time code. */
BOOLEAN closed_gop; /* Indicates no pred. vectors to
previous group of pictures. */
BOOLEAN broken_link; /* B frame unable to be decoded. */
char *ext_data; /* Extension data. */
char *user_data; /* User data. */
} GoP;
 
/* Picture structure. */
 
typedef struct pict {
unsigned int temp_ref; /* Temporal reference. */
unsigned int code_type; /* Frame type: P, B, I */
unsigned int vbv_delay; /* Buffer delay. */
BOOLEAN full_pel_forw_vector; /* Forw. vectors specified in full
pixel values flag. */
unsigned int forw_r_size; /* Used for vector decoding. */
unsigned int forw_f; /* Used for vector decoding. */
BOOLEAN full_pel_back_vector; /* Back vectors specified in full
pixel values flag. */
unsigned int back_r_size; /* Used in decoding. */
unsigned int back_f; /* Used in decoding. */
char *extra_info; /* Extra bit picture info. */
char *ext_data; /* Extension data. */
char *user_data; /* User data. */
} Pict;
 
/* Slice structure. */
 
typedef struct slice {
unsigned int vert_pos; /* Vertical position of slice. */
unsigned int quant_scale; /* Quantization scale. */
char *extra_info; /* Extra bit slice info. */
} Slice;
 
/* Macroblock structure. */
 
typedef struct macroblock {
int mb_address; /* Macroblock address. */
int past_mb_addr; /* Previous mblock address. */
int motion_h_forw_code; /* Forw. horiz. motion vector code. */
unsigned int motion_h_forw_r; /* Used in decoding vectors. */
int motion_v_forw_code; /* Forw. vert. motion vector code. */
unsigned int motion_v_forw_r; /* Used in decdoinge vectors. */
int motion_h_back_code; /* Back horiz. motion vector code. */
unsigned int motion_h_back_r; /* Used in decoding vectors. */
int motion_v_back_code; /* Back vert. motion vector code. */
unsigned int motion_v_back_r; /* Used in decoding vectors. */
unsigned int cbp; /* Coded block pattern. */
BOOLEAN mb_intra; /* Intracoded mblock flag. */
BOOLEAN bpict_past_forw; /* Past B frame forw. vector flag. */
BOOLEAN bpict_past_back; /* Past B frame back vector flag. */
int past_intra_addr; /* Addr of last intracoded mblock. */
int recon_right_for_prev; /* Past right forw. vector. */
int recon_down_for_prev; /* Past down forw. vector. */
int recon_right_back_prev; /* Past right back vector. */
int recon_down_back_prev; /* Past down back vector. */
} Macroblock;
 
/* Block structure. */
 
typedef struct block {
short int dct_recon[8][8]; /* Reconstructed dct coeff matrix. */
short int dct_dc_y_past; /* Past lum. dc dct coefficient. */
short int dct_dc_cr_past; /* Past cr dc dct coefficient. */
short int dct_dc_cb_past; /* Past cb dc dct coefficient. */
} Block;
 
/* Video stream structure. */
 
typedef struct vid_stream {
unsigned int h_size; /* Horiz. size in pixels. */
unsigned int v_size; /* Vert. size in pixels. */
unsigned int mb_height; /* Vert. size in mblocks. */
unsigned int mb_width; /* Horiz. size in mblocks. */
unsigned char aspect_ratio; /* Code for aspect ratio. */
unsigned char picture_rate; /* Code for picture rate. */
unsigned int bit_rate; /* Bit rate. */
unsigned int vbv_buffer_size; /* Minimum buffer size. */
BOOLEAN const_param_flag; /* Contrained parameter flag. */
unsigned char intra_quant_matrix[8][8]; /* Quantization matrix for
intracoded frames. */
unsigned char non_intra_quant_matrix[8][8]; /* Quanitization matrix for
non intracoded frames. */
char *ext_data; /* Extension data. */
char *user_data; /* User data. */
GoP group; /* Current group of pict. */
Pict picture; /* Current picture. */
Slice slice; /* Current slice. */
Macroblock mblock; /* Current macroblock. */
Block block; /* Current block. */
int state; /* State of decoding. */
int bit_offset; /* Bit offset in stream. */
unsigned int *buffer; /* Pointer to next byte in
buffer. */
int buf_length; /* Length of remaining buffer.*/
unsigned int *buf_start; /* Pointer to buffer start. */
/* Brown - beginning of added variables that used to be static or global */
int max_buf_length; /* Max length of buffer. */
int film_has_ended; /* Boolean - film has ended */
int sys_layer; /* -1 uninitialized,
0 video layer,
1 syslayer */
unsigned int num_left; /* from ReadPacket - leftover */
unsigned int leftover_bytes; /* from ReadPacket - leftover */
int EOF_flag; /* stream is EOF */
FILE *input; /* stream comes from here */
long seekValue; /* 0 no seeking
>0 do a seek,
<0 already has done seek */
BOOLEAN swap; /* from ReadFile */
BOOLEAN Parse_done; /* from read_sys */
int gAudioStreamID;
int gVideoStreamID;
int gReservedStreamID;
int right_for,down_for; /* From ReconPMBlock, video.c */
int right_half_for, down_half_for;
unsigned int curBits; /* current bits */
int matched_depth; /* depth of displayed movie */
char *filename; /* Name of stream filename */
int ditherType; /* What type of dithering */
char *ditherFlags; /* flags for MB Ordered dither*/
int totNumFrames; /* Total Number of Frames */
double realTimeStart; /* When did the movie start? */
/* Brown - end of added variables */
PictImage *past; /* Past predictive frame. */
PictImage *future; /* Future predictive frame. */
PictImage *current; /* Current frame. */
PictImage *ring[RING_BUF_SIZE]; /* Ring buffer of frames. */
/* x,y size of PPM output file */
int ppm_width, ppm_height, ppm_modulus;
} VidStream;
 
typedef struct {
/* XImage *ximage;*/
/* Colormap cmap;*/
/* Window window;*/
/* GC gc;
Display *display;*/
int owncmFlag;
/* XSizeHints hints;*/
/* Visual *visual;*/
int depth;
char *name;
int ditherType;
/* Window ExistingWindow;*/
} XInfo;
 
/* Declaration of global display pointer. */
 
#if SH_MEM
/* Shared memory flag. */
extern int shmemFlag;
#endif
 
/* Quiet mode flag. */
extern int quietFlag;
 
/* Flag controlling the "Press return" prompt */
extern int requireKeypressFlag;
 
/* Flag controlling speed vs. quality */
extern int qualityFlag;
 
/* Gamma correction stuff */
extern int gammaCorrectFlag;
extern double gammaCorrect;
 
/* Chroma correction stuff */
extern int chromaCorrectFlag;
extern double chromaCorrect;
 
/* Definition of Contant integer scale factor. */
 
#define CONST_BITS 13
 
/* Misc DCT definitions */
#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
 
#define GLOBAL /* a function referenced thru EXTERNs */
typedef short DCTELEM;
typedef DCTELEM DCTBLOCK[DCTSIZE2];
 
#ifdef SH_MEM
extern int gXErrorFlag;
#endif
 
extern int loopFlag;
extern int noDisplayFlag;
extern int partialFlag, startFrame, endFrame;
 
#ifdef ANALYSIS
extern unsigned int bitCount;
extern int showEachFlag;
extern unsigned int cacheHit[8][8];
extern unsigned int cacheMiss[8][8];
#endif
 
#if !defined(__MIPSEL__) && (defined(MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || defined(__mipsel) || defined(__mipsel__))
#define __MIPSEL__ 1
#endif
 
#if !defined(__MIPSEB__) && (defined(MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || defined(__mipseb) || defined(__mipseb__))
#define __MIPSEB__ 1
#endif
 
#if !defined(__SPARC__) && (defined(SPARC) || defined(__SPARC) || defined(__SPARC__) || defined(__sparc) || defined(__sparc__))
#define __SPARC__ 1
#endif
 
#if !defined(__alpha__) && (defined(ALPHA) || defined(__ALPHA) || defined(__ALPHA__) || defined(__alpha))
#define __alpha__ 1
#endif
 
#if !defined(__680x0__) && (defined(__680x0) || defined(__680x0__))
#define __680x0__ 1
#endif
 
#if !defined(__AIX__) && (defined(AIX) || defined(_AIX) || defined(__AIX) || defined(__AIX__))
#define __AIX__ 1
#endif
 
#if !defined(__RS6000__) && (defined(__AIX__) || defined(RS6000) || defined(_RS6000) || defined(__RS6000) || defined(__RS6000__))
#define __RS6000__ 1
#endif
 
#if !defined(__HPUX__) && (defined(HPUX) || defined(_HPUX) || defined(__HPUX) || defined(__HPUX__))
#define __HPUX__ 1
#endif
#if !defined(__HPUX__) && (defined(hpux) || defined(_hpux) || defined(__hpux) || defined(__hpux__))
#define __HPUX__ 1
#endif
 
#if !defined(__VAX__) && (defined(VAX) || defined (__VAX))
#define __VAX__ 1
#endif
 
#if !defined(__SCO__) && (defined(SCO) || defined(__SCO) || defined(sco) || defined(__sco__))
#define __SCO__ 1
#endif
 
#if defined(__i386__) || defined(__VAX__) || defined(__MIPSEL__) || defined(__alpha__) || defined(__SCO__)
#undef BIG_ENDIAN_ARCHITECTURE
#define LITTLE_ENDIAN_ARCHITECTURE 1
#endif
 
#if defined(__RS6000__) || defined(__SPARC__) || defined(__680x0__) || defined(__HPUX__) || defined(__MIPSEB__) || defined(convex) || defined(__convex__)
#undef LITTLE_ENDIAN_ARCHITECTURE
#define BIG_ENDIAN_ARCHITECTURE 1
#endif
 
#if !defined(LITTLE_ENDIAN_ARCHITECTURE) && !defined(BIG_ENDIAN_ARCHITECTURE)
Error: Unknown endianism of architecture
#endif
 
#ifdef __alpha__
#define SIXTYFOUR_BIT
#endif
#endif /* video.h already included */
/shark/trunk/ports/mpeg/readfile.c
0,0 → 1,1075
/*
* readfile.c --
*
* Procedures concerned with reading data and parsing
* start codes from MPEG files.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "proto.h"
#include <sys/types.h>
/*#include <signal.h> TO FIX!!! */
#ifndef MIPS
#include <netinet/in.h>
#else
#include <bsd/netinet/in.h>
#endif
 
#include "util.h"
#include "dither.h"
 
#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
#endif
 
/*
*
*
*/
 
extern int x_fseek(FILE *file, long where, int from);
extern size_t x_fread(void *buffer, size_t size, size_t n, FILE *file);
#define fread x_fread
#define fseek x_fseek
 
/*
Changes to make the code reentrant:
deglobalized: totNumFrames, realTimeStart, stream id vars, Prase_done,
swap, seekValue, input, EOF_flag, ReadPacket statics, sys_layer,
bitOffset, bitLength, bitBuffer, curVidStream
removed: [aud,sys,vid]Bytes
Additional changes:
get rid on ANSI C complaints about shifting
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* Silly Constants.... */
#define PACK_START_CODE ((unsigned int)0x000001ba)
#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)
#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00)
#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100)
#define ISO_11172_END_CODE ((unsigned int)0x000001b9)
#define PACK_HEADER_SIZE 8
#define STD_AUDIO_STREAM_ID ((unsigned char) 0xb8)
#define STD_VIDEO_STREAM_ID ((unsigned char) 0xb9)
#define MIN_STREAM_ID_ID ((unsigned char) 0xbc)
#define RESERVED_STREAM_ID ((unsigned char) 0xbc)
#define PRIVATE_STREAM_1_ID ((unsigned char) 0xbd)
#define PADDING_STREAM_ID ((unsigned char) 0xbe)
#define PRIVATE_STREAM_2_ID ((unsigned char) 0xbf)
#define STD_SYSTEM_CLOCK_FREQ (unsigned long)90000
#define MUX_RATE_SCALE_FACTOR 50
#define MAX_STREAMS 8
#define NOT_PACKET_ID ((unsigned char) 0xff)
#define KILL_BUFFER ((unsigned char) 0xfe)
/*
*--------------------------------------------------------------
*
* get_more_data --
*
* Called by get_more_data to read in more data from
* video MPG files (non-system-layer)
*
* Results:
* Input buffer updated, buffer length updated.
* Returns 1 if data read, 0 if EOF, -1 if error.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
int
get_more_data(vid_stream)
VidStream *vid_stream;
{
unsigned int **bs_ptr=&vid_stream->buf_start;
int *max_length=&vid_stream->max_buf_length;
int *length_ptr=&vid_stream->buf_length;
unsigned int **buf_ptr=&vid_stream->buffer;
int ioBytes, data, result;
unsigned char byte;
unsigned int *mark;
int sys_layer= vid_stream->sys_layer;
if (sys_layer == 0) {
return pure_get_more_data(*bs_ptr,
*max_length,
length_ptr,
buf_ptr,
vid_stream);
}
 
if (sys_layer == -1) {
/* Time to init ourselves */
vid_stream->swap = (htonl(1) != 1);
mark = *bs_ptr;
ioBytes = fread(&data, 1, 4, vid_stream->input);
 
if (ioBytes != 4) {
return 0;
}
 
data = ntohl(data);
if ( (data == PACK_START_CODE) || (data == SYSTEM_HEADER_START_CODE) ) {
got_sys:
/* Yow, a System Layer Stream. Much harder to parse. Call in the
specialist.... */
fprintf(stderr,"This is an MPEG System Layer Stream. ");
fprintf(stderr,"Audio is not played.\n");
vid_stream->sys_layer = 1;
result = read_sys(vid_stream,(unsigned int) data);
return result;
} else if (data == SEQ_START_CODE) {
got_seq:
/* No system Layer junk, just pretent we didn't peek,
and hereafter just call pure_get_more_data */
vid_stream->sys_layer = 0;
**bs_ptr = data;
*length_ptr = 1;
result = pure_get_more_data(*bs_ptr, *max_length,
length_ptr, buf_ptr, vid_stream);
*buf_ptr = *bs_ptr;
return result;
} else {
int state;
 
fprintf(stderr, "Junk at start of stream, searching for start code\n");
state = 0;
while (TRUE) {
if ((ioBytes = fread(&byte, 1, 1, vid_stream->input)) != 1) return 0;
if (byte == 0) {
if (state < 2) state++;
} else if ((byte == 1) && (state == 2)) {
state++;
} else {
state = 0;
}
if (state == 3) {
if ((ioBytes = fread(&byte, 1, 1, vid_stream->input)) != 1) return 0;
data = ((unsigned int) byte + 0x100);
switch (data) {
case SEQ_START_CODE:
goto got_seq;
case PACK_START_CODE:
case SYSTEM_HEADER_START_CODE:
goto got_sys;
default:
/* keep looking */
state=0;
}
}
}}
}
 
/* A system layer stream (called after the 1st time), call the specialist */
result = read_sys(vid_stream,0);
return result;
}
 
/*
*-------------------------------------------------------------
*
* clear_data_stream
*
* Empties out internal buffers
*
*-------------------------------------------------------------
*/
void
clear_data_stream(vid_stream)
VidStream *vid_stream;
{
/* Only internal buffer is in ReadPacket */
if (vid_stream->sys_layer) {
ReadPacket(KILL_BUFFER, vid_stream);
}
}
 
/*
*-------------------------------------------------------------
*
* SeekStream
*
* Goto an offset in the steam
*
*-------------------------------------------------------------
*/
void
SeekStream(vid_stream)
VidStream *vid_stream;
{
int errno;
int code;
if (vid_stream->seekValue < 0) return; /* done seeking */
#ifdef SEEK_SET
errno = fseek(vid_stream->input, vid_stream->seekValue, SEEK_SET);
#else
errno = fseek(vid_stream->input, vid_stream->seekValue, 0);
#endif
if (errno != 0) {
fprintf(stderr,"Error in seek (%d)\n",errno);
perror("mpeg_play");
}
vid_stream->seekValue = 0-vid_stream->seekValue;
vid_stream->totNumFrames = 0;
 
/* clear that buffer */
vid_stream->buffer = vid_stream->buf_start;
vid_stream->buf_length = 0;
vid_stream->bit_offset = 0;
 
/* Find a decent start code */
restart:
NO_ZEROS:
switch(fgetc(vid_stream->input)) {
case 0: goto ONE_ZERO;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
ONE_ZERO:
switch(fgetc(vid_stream->input)) {
case 0: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
TWO_ZEROS:
switch(fgetc(vid_stream->input)) {
case 0x01: goto CODE_FOUND;
case 0x00: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
CODE_FOUND:
code = 0x00000100+fgetc(vid_stream->input);
if (vid_stream->sys_layer) {
clear_data_stream(vid_stream);
if (((code & PACKET_START_CODE_MASK) == PACKET_START_CODE_PREFIX) &&
((code & 0xff) >= 0xbc)) {
read_sys(vid_stream, code);
while (TRUE) {
next_start_code(vid_stream);
show_bits32(code);
if ((code == SEQ_START_CODE) ||
(code == GOP_START_CODE)) return;
flush_bits32;
}
}
} else {
if ((code == SEQ_START_CODE) ||
(code == GOP_START_CODE)) {
*vid_stream->buffer = code;
vid_stream->buf_length = 1;
return;
}
}
goto restart;
 
EOF_FOUND: /* received EOF */
fprintf(stderr, "Hit EOF after seeking (offset %ld)\n",
ftell(vid_stream->input));
exit(1);
 
}
 
 
/*
*--------------------------------------------------------------
*
* pure_get_more_data --
* (get_more_data from ver 2.0 with swap added)
*
* Called by get_more_data to read in more data from
* video MPG files (non-system-layer)
*
* Results:
* Input buffer updated, buffer length updated.
* Returns 1 if data read, 0 if EOF, -1 if error.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
int
pure_get_more_data(buf_start, max_length, length_ptr, buf_ptr, vid_stream)
unsigned int *buf_start;
int max_length;
int *length_ptr;
unsigned int **buf_ptr;
VidStream *vid_stream;
{
int length, num_read, i;
unsigned int request;
unsigned char *buffer, *mark;
unsigned int *lmark;
BOOLEAN swap=vid_stream->swap;
if (vid_stream->EOF_flag) return 0;
length = *length_ptr;
buffer = (unsigned char *) *buf_ptr;
if (length > 0) {
memcpy((unsigned char *) buf_start, buffer, (unsigned int) (length*4));
mark = ((unsigned char *) (buf_start + length));
}
else {
mark = (unsigned char *) buf_start;
length = 0;
}
request = (max_length-length)*4;
num_read = fread(mark, 1, request, vid_stream->input);
/* Paulo Villegas - 26/1/1993: Correction for 4-byte alignment */
{
int num_read_rounded;
unsigned char *index;
num_read_rounded = 4*(num_read/4);
/* this can happen only if num_read<request; i.e. end of file reached */
if ( num_read_rounded < num_read ) {
num_read_rounded = 4*( num_read/4+1 );
 
/* fill in with zeros */
for( index=mark+num_read; index<mark+num_read_rounded; *(index++)=0 );
 
/* advance to the next 4-byte boundary */
num_read = num_read_rounded;
}
}
if (num_read < 0) {
return -1;
} else if (num_read == 0) {
*buf_ptr = buf_start;
/* Make 32 bits after end equal to 0 and 32
* bits after that equal to seq end code
* in order to prevent messy data from infinite
* recursion.
*/
*(buf_start + length) = 0x0;
*(buf_start + length+1) = SEQ_END_CODE;
vid_stream->EOF_flag = 1;
return 0;
}
lmark = (unsigned int *) mark;
num_read = num_read/4;
if (swap) {
for (i = 0; i < num_read; i++) {
*lmark = htonl(*lmark);
lmark++;
}
}
*buf_ptr = buf_start;
*length_ptr = length + num_read;
return 1;
}
 
 
 
 
/*
Here is the specialist....
Code is adapted from our program demux....
A bunch of this needs to be #ifdef ANALYSIS'ed
define __SYSREAD_LOGGING_ON__ to get an output file for debugging
*/
 
/* Brown - removed StreamID global variables */
#ifdef ANALYSIS
/* Statistics */
static int gNumAudioPackets;
static int gNumVideoPackets;
static int gNumPaddingPackets;
static int gNumReservedPackets;
static int gNumPrivate_1_Packets;
static int gNumPrivate_2_Packets;
#endif
 
/*
*----------------------------------------------------------
*
* read_sys
*
* Parse out a packet of the system layer MPEG file.
*
* Results: Returns 0 if error or EOF
* Returns 1 if more data read (could be just one int)
*
* Side Effects: ReadPacket can change *bs_ptr to be a new buffer
* buf_ptr will remain pointing at *length_ptr (at input)
* into the buffer
* *length_ptr will be changed to the new size
* *max_length can be changed if a new buffer is alloc'd
*
*----------------------------------------------------------
*/
int read_sys(vid_stream, start)
VidStream *vid_stream;
unsigned int start;
/* start is either a start code or 0 to indicate continued parsing */
{
unsigned int **bs_ptr=&vid_stream->buf_start;
int *max_length = &vid_stream->max_buf_length;
int *length_ptr=&vid_stream->buf_length;
unsigned int **buf_ptr=&vid_stream->buffer;
unsigned int startCode;
int errorCode, PacketReply;
unsigned char packetID;
double systemClockTime;
unsigned long muxRate;
/* Statistics */
#ifdef ANALYSIS
static int numPacks = 0;
static int numPackets = 0;
static int numSystemHeaders = 0;
#endif
BOOLEAN match;
if (!start) {
errorCode = ReadStartCode(&startCode,vid_stream);
if (vid_stream->EOF_flag) return 0;
if (errorCode != 0) {
fprintf(stderr, "Unable to read initial pack start code\n");
return 0;
}}
else {
errorCode = 0;
startCode = start;
}
while (1) {
match=FALSE;
if (startCode == PACK_START_CODE) {
#ifdef ANALYSIS
++numPacks;
#endif
match = TRUE;
errorCode = ReadPackHeader( &systemClockTime, &muxRate, vid_stream);
if (errorCode != 0) {
fprintf(stderr, "Error in reading pack header\n");
return 0;
}
errorCode = ReadStartCode( &startCode, vid_stream );
if (errorCode != 0) {
fprintf(stderr, "Error in reading start code\n");
return 0;
}
}
if (startCode == SYSTEM_HEADER_START_CODE) {
#ifdef ANALYSIS
++numSystemHeaders;
#endif
match = TRUE;
errorCode = ReadSystemHeader(vid_stream);
if (errorCode != 0) {
fprintf(stderr, "Error in reading system header\n");
return 0;
}
errorCode = ReadStartCode( &startCode, vid_stream );
if (errorCode != 0) {
fprintf(stderr,"Error in reading start code after system header\n");
return 0;
}
}
packetID = startCode & 0xff;
while (((startCode & PACKET_START_CODE_MASK) == PACKET_START_CODE_PREFIX) &&
(packetID >= 0xbc)) {
#ifdef ANALYSIS
++numPackets;
#endif
match = TRUE;
packetID = startCode & 0xff;
PacketReply = ReadPacket(packetID, vid_stream);
switch (PacketReply) {
case 2:
return 1;
case 1:
return 0;
default: /* do nothing */
break;
}
errorCode = ReadStartCode( &startCode, vid_stream );
if (errorCode != 0) {
fprintf(stderr,"Error in start code after packet\n");
return 0;
}
if (startCode == PACK_START_CODE || startCode == ISO_11172_END_CODE) {
break;
}
}
if (startCode == ISO_11172_END_CODE) {
match = TRUE;
if (vid_stream->Parse_done) {
return 1;
}
#ifdef ANALYSIS
fprintf(stderr, "Successful parse of MPEG system level\n");
fprintf(stderr, "%d system headers, %d packs, %d packets\n",
numSystemHeaders, numPacks, numPackets);
fprintf(stderr, "%d audio packets, %d video packets, %d padding packets\n",
gNumAudioPackets, gNumVideoPackets, gNumPaddingPackets);
fprintf(stderr, "%d reserved packets, %d/%d private type 1/2 packets\n",
gNumReservedPackets, gNumPrivate_1_Packets, gNumPrivate_2_Packets);
#endif
ReadPacket(NOT_PACKET_ID, vid_stream);
vid_stream->Parse_done = TRUE;
return 1;
}
if (errorCode != 0)
return 1;
if (! match) {
fprintf(stderr,"\nNo match found for start code %08x in system layer, skipping\n",startCode);
startCode = find_start_code(vid_stream->input);
if (startCode == EOF) {
vid_stream->EOF_flag = 1;
return 0;
}
}
}
}
 
/*
*-----------------------------------------------------------
*
* ReadStartCode
*
* Parses a start code out of the stream
*
* Results/Side Effects: Sets *startCode to the code, returns
* 1 on error, 0 on success
*
*-----------------------------------------------------------
*/
int ReadStartCode(startCode, vid_stream)
unsigned int *startCode;
VidStream *vid_stream;
{
int numRead;
numRead = fread((unsigned char *)startCode, 1, 4, vid_stream->input);
*startCode = htonl(*startCode);
if (numRead < 4) {
vid_stream->EOF_flag = 1;
return 1;
}
 
if ((*startCode&0xfffffe00) != 0) {
fprintf(stderr,"Problem with system layer parse, skipping to start code\n");
*startCode = find_start_code(vid_stream->input);
if (*startCode == EOF) {
vid_stream->EOF_flag = TRUE;
return 0;
}
}
 
return 0;
}
 
/*
*-----------------------------------------------------------
*
* find_start_code
*
* Parses a start code out of the stream by tossing bytes until it gets one
*
* Results/Side Effects: Parses bytes of the stream, returns code
* Returns EOF in case of end of file
*
*-----------------------------------------------------------
*/
int find_start_code(input)
FILE *input;
{
NO_ZEROS:
switch(fgetc(input)) {
case 0: goto ONE_ZERO;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
 
ONE_ZERO:
switch(fgetc(input)) {
case 0: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
 
TWO_ZEROS:
switch(fgetc(input)) {
case 0x01: goto CODE_FOUND;
case 0x00: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
 
CODE_FOUND:
return 0x00000100+fgetc(input);
 
EOF_FOUND: /* received EOF */
return EOF;
}
 
 
 
/*
*-----------------------------------------------------------------
*
* ReadPackHeader
*
* Parses out the PACK header
*
* Returns: 1 on error, 0 on success
*
*-------------------------------------------------------------------
*/
int ReadPackHeader(systemClockTime,muxRate, vid_stream)
double *systemClockTime;
unsigned long *muxRate;
VidStream *vid_stream;
{
int numRead;
unsigned char inputBuffer[PACK_HEADER_SIZE];
unsigned long systemClockRef;
unsigned char systemClockRefHiBit;
int errorCode;
numRead = fread(inputBuffer, 1, PACK_HEADER_SIZE, vid_stream->input);
if (numRead < PACK_HEADER_SIZE) {
vid_stream->EOF_flag = 1;
return 1;
}
ReadTimeStamp(inputBuffer, &systemClockRefHiBit, &systemClockRef);
errorCode = MakeFloatClockTime(systemClockRefHiBit, systemClockRef,
systemClockTime);
ReadRate(&inputBuffer[5], muxRate);
*muxRate *= MUX_RATE_SCALE_FACTOR;
return 0;
}
 
/*
*------------------------------------------------------------------
*
* ReadSystemHeader
*
* Parse out the system header, setup out stream IDs for parsing packets
*
* Results: Returns 1 on error, 0 on success.
* Sets gAudioStreamID and gVideoStreamID
*
*------------------------------------------------------------------
*/
int ReadSystemHeader(vid_stream)
VidStream *vid_stream;
{
unsigned char *inputBuffer = NULL;
int numRead;
int pos;
unsigned short headerSize;
unsigned char streamID;
numRead = fread((char *)&headerSize, 1, 2, vid_stream->input);
headerSize = ntohs(headerSize);
if (numRead != 2) {
vid_stream->EOF_flag = 1;
return 1;
}
inputBuffer = (unsigned char *) malloc((unsigned int) headerSize+1);
if (inputBuffer == NULL) {
return 1;
}
inputBuffer[headerSize]=0;
numRead = fread(inputBuffer, 1, headerSize, vid_stream->input);
/* Brown - get rid of Ansi C complaints */
if (numRead < (int) headerSize) {
vid_stream->EOF_flag = 1;
return 1;
}
pos = 6;
while ((inputBuffer[pos] & 0x80) == 0x80) {
streamID = inputBuffer[pos];
switch (streamID) {
case STD_VIDEO_STREAM_ID:
break;
case STD_AUDIO_STREAM_ID:
break;
case RESERVED_STREAM_ID:
break;
case PADDING_STREAM_ID:
break;
case PRIVATE_STREAM_1_ID:
break;
case PRIVATE_STREAM_2_ID:
break;
default:
if (streamID < MIN_STREAM_ID_ID) {
return 1;
}
switch (streamID >> 4) {
case 0xc:
case 0xd:
vid_stream->gAudioStreamID = streamID;
break;
case 0xe:
if ((vid_stream->gVideoStreamID != 0) &&
(vid_stream->gVideoStreamID!=streamID)) {
break;
}
vid_stream->gVideoStreamID = streamID;
break;
case 0xf:
/*Brown - deglobalized gReservedStreamID */
vid_stream->gReservedStreamID = streamID;
break;
}
break;
}
pos += 3;
}
if (inputBuffer != NULL)
free(inputBuffer);
return 0;
}
 
/*
*-----------------------------------------------------------------
*
* ReadPacket
*
* Reads a single packet out of the stream, and puts it in the
* buffer if it is video.
*
* Results:
* Changes the value of *length_ptr to be the new length (plus old)
* If the buffer is too small, can change *bs_ptr, *max_length, and
* buf_ptr to be correct for a newly allocated buffer.
*
* State:
* The buffer is in ints, but the packets can be an arbitrary number
* of bytes, so leftover bytes are kept in the VidStream variable and
* are added on the next call.
*
*-----------------------------------------------------------------
*/
#ifdef __STDC__
int ReadPacket(unsigned char packetID, VidStream *vid_stream)
#else
int ReadPacket(packetID, vid_stream)
unsigned char packetID;
VidStream *vid_stream;
#endif
 
/* Returns:
0 - no error, but not video packet we want
1 - error
2 - got video packet into buffer
*/
{
unsigned int **bs_ptr=&vid_stream->buf_start;
int *max_length = &vid_stream->max_buf_length;
int *length_ptr=&vid_stream->buf_length;
unsigned int **buf_ptr=&vid_stream->buffer;
int ioBytes;
unsigned char nextByte;
unsigned short packetLength;
unsigned char *packetBuffer = NULL;
int pos;
int numStuffBytes = 0;
unsigned int packetDataLength;
int byte_length;
unsigned char scratch[10];
/* Leftovers from previous video packets */
if (packetID == NOT_PACKET_ID) {
/* Gross hack to handle unread bytes before end of stream */
if (vid_stream->num_left != 0) {
/* Sigh, deal with previous leftovers */
*(*buf_ptr+*length_ptr) = vid_stream->leftover_bytes;
*(*buf_ptr+*length_ptr+1) = ISO_11172_END_CODE;
*length_ptr += 2;
} else {
*(*buf_ptr+*length_ptr) = ISO_11172_END_CODE;
*length_ptr += 1;
}
return 1;
} else if (packetID==KILL_BUFFER) {
vid_stream->num_left=0;
vid_stream->leftover_bytes=0;
return 0;
}
ioBytes = fread(&packetLength, 1, 2, vid_stream->input);
packetLength = htons(packetLength);
if (ioBytes < 2) {
return 1;
}
if (packetID == vid_stream->gAudioStreamID) {
#ifdef ANALYSIS
++gNumAudioPackets;
#endif
}
else if (packetID == vid_stream->gVideoStreamID) {
#ifdef ANALYSIS
++gNumVideoPackets;
#endif
}
else {
switch (packetID) {
case PADDING_STREAM_ID:
#ifdef ANALYSIS
++gNumPaddingPackets;
#endif
break;
case RESERVED_STREAM_ID:
#ifdef ANALYSIS
++gNumReservedPackets;
#endif
break;
case PRIVATE_STREAM_1_ID:
#ifdef ANALYSIS
++gNumPrivate_1_Packets;
#endif
break;
case PRIVATE_STREAM_2_ID:
#ifdef ANALYSIS
++gNumPrivate_2_Packets;
#endif
break;
default:
fprintf(stderr, "\nUnknown packet type encountered. P'bly audio? (%x) at %d\n",
packetID,(int) ftell(vid_stream->input));
}
if (packetID != vid_stream->gVideoStreamID) {/* changed by jim */
fseek(vid_stream->input, packetLength, 1);
return 0;
}
}
 
fread(&nextByte,1,1,vid_stream->input);
pos = 0;
while (nextByte & 0x80) {
++numStuffBytes;
++pos;
fread(&nextByte,1,1,vid_stream->input);
}
if ((nextByte >> 6) == 0x01) {
pos += 2;
fread(&nextByte,1,1,vid_stream->input);
fread(&nextByte,1,1,vid_stream->input);
}
if ((nextByte >> 4) == 0x02) {
scratch[0] = nextByte; /* jim */
fread(&scratch[1],1,4,vid_stream->input); /* jim */
fread(&nextByte,1,1,vid_stream->input);
pos += 5;
}
else if ((nextByte >> 4) == 0x03) {
scratch[0] = nextByte; /* jim */
fread(&scratch[1],1,9,vid_stream->input); /* jim */
fread(&nextByte,1,1,vid_stream->input);
pos += 10;
}
else {
fread(&nextByte,1,1,vid_stream->input);
pos += 1;
}
/* Read all the headers, now make room for packet */
if (*bs_ptr + *max_length < *buf_ptr+ packetLength/4 + *length_ptr) {
/* Brown - get rid of Ansi C complaints */
if (*max_length - *length_ptr < (int) packetLength/4) {
/* Buffer too small for a packet (plus whats there),
* time to enlarge it!
*/
unsigned int *old = *bs_ptr;
*max_length = *length_ptr + packetLength/2;
*bs_ptr=(unsigned int *)malloc(*max_length*4);
if (*bs_ptr == NULL) {
return 1;
}
memcpy((unsigned char *)*bs_ptr, *buf_ptr, (unsigned int) *length_ptr*4);
free(old);
*buf_ptr = *bs_ptr;
} else {
memcpy((unsigned char *)*bs_ptr, *buf_ptr, (unsigned int) *length_ptr*4);
*buf_ptr = *bs_ptr;
}}
byte_length = *length_ptr*4;
if (vid_stream->num_left != 0) {
/* Sigh, deal with previous leftovers */
byte_length += vid_stream->num_left;
*(*buf_ptr+*length_ptr) = vid_stream->leftover_bytes;
}
packetBuffer=((unsigned char *)*buf_ptr)+byte_length;
packetDataLength = packetLength - pos;
*packetBuffer++ = nextByte;
/* Brown - deglobalize gVideoStreamID */
if (packetID == vid_stream->gVideoStreamID) {
ioBytes = fread(packetBuffer, 1, packetDataLength-1, vid_stream->input);
if (ioBytes != packetDataLength-1) {
vid_stream->EOF_flag = 1;
return 1;
}
if (1 != ntohl(1)) {
unsigned int *mark = *buf_ptr+*length_ptr;
int i;
for (i=0; i < ((packetDataLength+
vid_stream->num_left)&0xfffffffc); i+=4) {
*mark=ntohl(*mark);
mark++;
}
}
byte_length = byte_length + packetDataLength;
vid_stream->num_left = byte_length % 4;
*length_ptr = byte_length / 4;
vid_stream->leftover_bytes = *(*buf_ptr + *length_ptr);
return 2;
}
else if (packetID == vid_stream->gAudioStreamID) {
packetBuffer = (unsigned char *)(*buf_ptr + *length_ptr + 1);
fread(packetBuffer, 1, packetDataLength - 1, vid_stream->input);
}
else /* Donno what it is, just nuke it */ {
/* This code should be unreachable */
packetBuffer = (unsigned char *)(*buf_ptr + *length_ptr + 1);
fread(packetBuffer, 1, packetDataLength - 1, vid_stream->input);
}
return 0;
}
 
 
/*
* The remaining procedures are formatting utility procedures.
*/
void ReadTimeStamp(inputBuffer,hiBit,low4Bytes)
unsigned char *inputBuffer, *hiBit;
unsigned long *low4Bytes;
{
*hiBit = ((unsigned long)inputBuffer[0] >> 3) & 0x01;
*low4Bytes = (((unsigned long)inputBuffer[0] >> 1) & 0x03) << 30;
*low4Bytes |= (unsigned long)inputBuffer[1] << 22;
*low4Bytes |= ((unsigned long)inputBuffer[2] >> 1) << 15;
*low4Bytes |= (unsigned long)inputBuffer[3] << 7;
*low4Bytes |= ((unsigned long)inputBuffer[4]) >> 1;
}
 
void ReadSTD(inputBuffer,stdBufferScale,stdBufferSize)
unsigned char *inputBuffer;
unsigned char *stdBufferScale;
unsigned long *stdBufferSize;
{
/* Brown - get rid of ANSI C complaints */
*stdBufferScale = ((int)(inputBuffer[0] & 0x20) >> 5);
*stdBufferSize = ((unsigned long)inputBuffer[0] & 0x1f) << 8;
*stdBufferSize |= (unsigned long)inputBuffer[1];
}
 
 
void ReadRate(inputBuffer,rate)
unsigned char *inputBuffer;
unsigned long *rate;
{
*rate = (inputBuffer[0] & 0x7f) << 15;
*rate |= inputBuffer[1] << 7;
/* Brown - get rid of ANSI C complaints */
*rate |= (int) (inputBuffer[2] & 0xfe) >> 1;
}
 
#define FLOAT_0x10000 (double)((unsigned long)1 << 16)
 
#ifdef __STDC__
int MakeFloatClockTime(unsigned char hiBit, unsigned long low4Bytes,
double * floatClockTime)
#else
int MakeFloatClockTime(hiBit,low4Bytes,floatClockTime)
unsigned char hiBit;
unsigned long low4Bytes;
double *floatClockTime;
#endif
{
if (hiBit != 0 && hiBit != 1) {
*floatClockTime = 0.0;
return 1;
}
*floatClockTime
= (double)hiBit*FLOAT_0x10000*FLOAT_0x10000 + (double)low4Bytes;
*floatClockTime /= (double)STD_SYSTEM_CLOCK_FREQ;
return 0;
}
/shark/trunk/ports/mpeg/readme
0,0 → 1,77
MPEG Video Software Decoder
(Version 2.3; March 1996)
 
Lawrence A. Rowe, Ketan Patel, Brian Smith, Steve Smoot, and Eugene Hung
Computer Science Division-EECS, Univ. of Calif. at Berkeley
 
This directory contains a public domain MPEG video software
decoder. The decoder is implemented as a library that will
take a video stream and display it in an X window on an 8, 24
or 32 bit deep display. The main routine is supplied to
demonstrate the use of the decoder library. Several dithering
algorithms are supplied based on the Floyd-Steinberg, ordered
dither, and half-toning algorithms that tradeoff quality and
performance. Neither the library nor the main routine handle
real-time synchronization or audio streams.
 
The decoder implements the standard described in the Committee
Draft ISO/IEC CD 11172 dated December 6, 1991 which is
sometimes refered to as "Paris Format." The code has been
compiled and tested on the following platforms:
 
HP PA-RISC (HP/UX 9.X, X11R5) (i.e., HP 9000/7XX and 9000/3XX)
Sun Sparc (SunOS 4.X, Solaris)
DECstation 5000 and Alpha
Silicon Graphics Indigo
MIPS RISC/os 4.51
Linux
 
If you decide to port the code to a new architecture, please let
us know if there are any significant changes, so that we can incorporate
them into our sources.
 
This directory contains everything required to build and
display video. We have included source code, a makefile, an Imakefile,
installation instructions, and a man page. Data files can
be obtained from the same ftp site this was located in.
See the INSTALL file for instructions on how to
compile and run the decoder.
 
Our future plans include porting the decoder to run on other
platforms, integrating it into a video playback system that
supports real-time synchronization and audio streams, and
further experiments to improve the performance of the
decoder. Vendors or other organizations interested in supporting
this research or discussing other aspects of this project should
contact Larry Rowe at Rowe@CS.Berkeley.EDU.
 
The decoder can not be compiled as a library, see README.lib
 
Reporting bugs:
If you find any bugs in this software, please send them to
mpeg-bugs@plateau.cs.berkeley.edu. Since this software
is unsupported, we make no guarantees about how long it will
take to fix the bug, or if it will be fixed at all. Bug fixes
will be cheerfully accepted. Please include as much detailed
information as possible, including:
 
1) the version number of the program you are using (cf. VERSION)
2) the data file that caused the bug (if possible)
3) the OS version and machine type you ran the program on
4) the compiler used to compile the program
 
ACKNOWLEDGEMENTS:
We gratefully thank Hewlett-Packard, Fujitsu, the Semiconductor
Research Corporation for financial support.
 
We also want to thank the following people for their help:
 
Tom Lane of the Independent JPEG Group provided us with
the basic inverse DCT code used by our player.
(tom_lane@g.gp.cs.cmu.edu)
 
Reid Judd of Sun Microsystems provided advice and assistance.
 
Todd Brunhoff of NVR provided advice and assistance.
 
Toshihiko Kawai of Sony provided advice and assistance.
/shark/trunk/ports/mpeg/wrapper.c
0,0 → 1,553
/*
* Copyright (c) 1994 by Gregory P. Ward.
* All rights reserved.
*
* This file is part of the MNI front end of the Berkeley MPEG decoder.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
* UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER
* IS ON AN "AS IS" BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : wrapper.c
@INPUT :
@OUTPUT :
@RETURNS :
@DESCRIPTION: Functions and variables used in the interface between
user applications and the Berkely MPEG decoder. This
file essentially comprises the MNI front end to the
Berkeley decoder; applications should NOT have access to any of
these. The functions in this file are the only ones to
which users of the MPEG library have access; all other
functions in the library are private.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED :
@MODIFIED :
---------------------------------------------------------------------------- */
 
#include <stdio.h>
#include <errno.h>
#include "video.h"
#include "proto.h"
#include "util.h"
#include "dither.h"
#include "mpeg.h"
 
#define BUF_LENGTH 100000
 
 
/*
* Global variables shared between this file and the core MPEG decoder
* (but nowhere else!) - these are the only globals!
*/
int quietFlag=1, loopFlag=1,qualityFlag=0, requireKeypressFlag=0;
int framerate=0,gammaCorrectFlag=0, chromaCorrectFlag=0, noDisplayFlag=0;
int partialFlag=0,startFrame=-1, endFrame=-1;
double gammaCorrect = 1.0, chromaCorrect=1.0;
 
static int numMovies=0;
 
/* Prototypes for functions local to this file: */
 
void GetMPEGInfo (ImageDesc *Info);
 
int dprintf (char *format, ...) {}
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : OpenMPEG
@INPUT : MPEGfile - pointer to a stream opened for reading, positioned
at the beginning of an MPEG stream
ImgInfo - pointer to an ImageDesc structure which will have
information such as frame height, width, depth
and size (total bytes per frame) put in it.
@OUTPUT :
@RETURNS :
@DESCRIPTION: Creates and initializes the variables needed to start
reading/decoding an MPEG stream.
 
This function is part of the MNI front end to the Berkeley
MPEG decoder, adapted from the original Berkeley code.
@METHOD :
@GLOBALS : LUM_RANGE, CR_RANGE, CB_RANGE
lum_values, cr_values, cb_values
@CALLS : GetMPEGInfo()
init_tables()
InitDither()
@CREATED : 94/6/16, Greg Ward (adapted from main() in the original
Berkeley source)
@MODIFIED :
---------------------------------------------------------------------------- */
Boolean OpenMPEG (FILE *MPEGfile, ImageDesc *ImgInfo)
{
VidStream *vid_stream;
/*
* First reinitialize these globals in case we're opening a second
* (or more) file - thanks to Loren Holding (art054@cs.brown.edu)
* for the patch
*/
 
/* unneeded - done in NewVidStream or ResetVidStream */
 
/*
* Create the video stream and read the first chunk to get movie
* stats -- width and height in particular.
*/
 
if (ImgInfo->vid_stream==NULL) {
ImgInfo->vid_stream = vid_stream =NewVidStream((unsigned int) BUF_LENGTH);
} else {
vid_stream=ImgInfo->vid_stream;
clear_data_stream(vid_stream);
ResetVidStream(vid_stream);
}
vid_stream->input = MPEGfile;
vid_stream->filename = "mniwrapper";
vid_stream->matched_depth=24;
vid_stream->ditherType=FULL_COLOR_DITHER; /* default */
 
numMovies++;
 
if (numMovies==1) {
/* Allocate/initialize tables used for dithering (?) */
lum_values = (int *) malloc(LUM_RANGE*sizeof(int));
cr_values = (int *) malloc(CR_RANGE*sizeof(int));
cb_values = (int *) malloc(CB_RANGE*sizeof(int));
 
init_tables(); /* initialize decoding stuff */
InitCrop();
 
#if 0
InitDither(ImgInfo); /* initializes dithering structures and */
/* colormap (i.e. this is where we do */
/* all dither-specific stuff) */
#endif
}
 
if (mpegVidRsrc(0, ImgInfo->vid_stream, 1, NULL )==NULL) {
return FALSE;
} else {
GetMPEGInfo(ImgInfo);
return TRUE;
}
} /* OpenMPEG () */
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : CloseMPEG
@INPUT : (none)
@OUTPUT : (none)
@RETURNS : (void)
@DESCRIPTION: Frees up some of the memory allocated by OpenMPEG() (some
is not freed because the Berkeley code doesn't take into
account the fact that somebody might want to, say, free
up the memory it allocates... someday, I'll probably have
to hack into it to fix that, but not today thanks.)
@METHOD :
@GLOBALS : lum_values
cr_values
cb_values
@CALLS : DestroyVidStream
@CREATED : 94/6/27, Greg Ward
@MODIFIED :
---------------------------------------------------------------------------- */
void CloseMPEG (ImageDesc *ImgInfo)
{
DestroyVidStream(ImgInfo->vid_stream, NULL);
free (lum_values);
free (cr_values);
free (cb_values);
}
 
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : RewindMPEG
@INPUT : MPEGfile - the input stream where the MPEG's coming from
Image - image descriptor (just passed to OpenMPEG ())
@OUTPUT : (none)
@RETURNS : (void)
@DESCRIPTION: Resets things so that the caller can start reading the MPEG
stream from the start again. Note that the caller does NOT
need to call OpenMPEG() again -- after a call to RewindMPEG(),
the next call to GetMPEGFrame() will return the first frame
of the MPEG.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 94/7/20, Greg Ward
@MODIFIED :
@COMMENTS :
---------------------------------------------------------------------------- */
void RewindMPEG (FILE *MPEGfile, ImageDesc *Image)
{
rewind (MPEGfile);
 
OpenMPEG (MPEGfile, Image);
}
 
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : GetMPEGInfo
@INPUT : vid_stream - a video stream that is open and has had at
least one call to mpegVidRsrc() performed on it
Info - a pointer to an ImageDesc struct in the caller's
space (i.e., the argument to OpenMPEG()) where
the image information will be copied
@OUTPUT :
@RETURNS : (void)
@DESCRIPTION: From the video stream, determines the width, height, pixel
size and depth (in bits) and total image size (in bytes)
for an MPEG stream. Sets the fields in the structure
pointed to by the Info pointer.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 94/6/17, Greg Ward: based on code from ExecuteDisplay() in the
original Berkeley source
@MODIFIED :
---------------------------------------------------------------------------- */
void GetMPEGInfo (ImageDesc *Info)
{
#ifndef DISABLE_DITHER
switch (Info->vid_stream->ditherType)
{
case Twox2_DITHER:
{
Info->Height = Info->vid_stream->mb_height * 32;
Info->Width = Info->vid_stream->mb_width * 32;
Info->Depth = 8;
Info->PixelSize = 8;
Info->BitmapPad = 8;
break;
}
case FULL_COLOR_DITHER:
{
#endif
Info->Height = Info->vid_stream->mb_height * 16;
Info->Width = Info->vid_stream->mb_width * 16;
Info->Depth = 24;
Info->PixelSize = 32;
Info->BitmapPad = 32;
#ifndef DISABLE_DITHER
break;
}
// MG
case HALF_COLOR_DITHER:
Info->Height = Info->vid_stream->mb_height * 16;
Info->Width = Info->vid_stream->mb_width * 16;
Info->Depth = 16;
Info->PixelSize = 16;
Info->BitmapPad = 16;
break;
case MONO_DITHER:
case MONO_THRESHOLD:
{
Info->Height = Info->vid_stream->mb_height * 16;
Info->Width = Info->vid_stream->mb_width * 16;
Info->Depth = 1;
Info->PixelSize = 1;
Info->BitmapPad = 8;
break;
}
default: /* including GRAY_DITHER and ORDERED_DITHER */
{
Info->Height = Info->vid_stream->mb_height * 16;
Info->Width = Info->vid_stream->mb_width * 16;
Info->Depth = 8;
Info->PixelSize = 8;
Info->BitmapPad = 8;
break;
}
} /* switch on ditherType */
#endif
 
Info->Size = (Info->Height*Info->Width*Info->PixelSize) / 8;
Info->PictureRate = Info->vid_stream->picture_rate;
Info->BitRate = Info->vid_stream->bit_rate;
 
} /* GetMPEGInfo () */
 
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : SetMPEGOption
@INPUT : Option - which option to set
Value - what to set it to
@OUTPUT :
@RETURNS :
@DESCRIPTION: Set an MPEG option. The options are all assigned intelligent
defaults when they are created (as global variables), so
calling SetMPEGOption is optional (as you might expect
from the name). Whether SetMPEGOption() is called before
or after OpenMPEG() is important, but it depends on which
option you're setting. In particular, the dithering type
and luminance/chromaticity ranges must be set before
OpenMPEG(); but (unless your code is more clever than it
needs to be), the colourmap indeces probably won't be set
until after OpenMPEG(). RTFM for explanations of what the
individual options do.
 
The currently available options are:
MPEG_DITHER
MPEG_LUM_RANGE
MPEG_CR_RANGE
MPEG_CB_RANGE
MPEG_CMAP_INDEX
 
@METHOD :
@GLOBALS : Depending on the value of Option, sets one of the MPEG
decoders global variables:
LUM_RANGE
CR_RANGE
CB_RANGE
@CALLS :
@CREATED : 94/6/17, Greg Ward.
@MODIFIED : 95/3/18, GW: added MPEG_CMAP_INDEX option.
---------------------------------------------------------------------------- */
void SetMPEGOption (ImageDesc *Info, MPEGOptionEnum Option, int Value)
{
 
switch (Option)
{
case MPEG_DITHER:
#ifndef DISABLE_DITHER
Info->vid_stream->ditherType = (DitherEnum) Value;
InitDither(Info); /* initializes dithering structures and */
/* colormap (i.e. this is where we do */
/* all dither-specific stuff) */
#endif
break;
case MPEG_LUM_RANGE: LUM_RANGE = Value; break;
case MPEG_CR_RANGE: CR_RANGE = Value; break;
case MPEG_CB_RANGE: CB_RANGE = Value; break;
#ifndef DISABLE_DITHER
case MPEG_CMAP_INDEX:
{
int i;
unsigned char *cmap_index;
 
cmap_index = (unsigned char *) Value;
for (i = 0; i < Info->ColormapSize; i++)
{
pixel[i] = cmap_index[i];
}
break;
}
#endif
}
} /* SetMPEGOption () */
 
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : GetMPEGFrame
@INPUT :
@OUTPUT : Frame - the image data, converted to RGB space, is
copied to the area pointed to by Frame. There must be
enough room for the entire image; the ImageDesc
structure returned by OpenMPEG() will tell you just how
much memory this is. The format of the data depends on
the dithering type; for full colour dithering, there are
four bytes per pixel: red, green, blue, and unused.
(Perfect for passing to lrectwrite() or XPutImage().)
@RETURNS : TRUE if there are still frames left to decode
FALSE if we have just decoded the last frame
@DESCRIPTION: Part of the MNI front end to the Berkeley MPEG decoder.
Essentially reads, decodes, and converts to RGB space the
next frame in the MPEG stream opened with OpenMPEG().
@METHOD :
@GLOBALS :
@CALLS : mpegVidRsrc ()
@CREATED : 94/6/16, Greg Ward
@MODIFIED :
---------------------------------------------------------------------------- */
Boolean GetMPEGFrame (ImageDesc *image, char *Frame)
{
Boolean MovieDone = FALSE;
int frames;
char *CurrentImage;
 
dprintf ("GetMPEGFrame: starting or continuing movie\n");
 
frames=image->vid_stream->totNumFrames;
while (!MovieDone && (frames==image->vid_stream->totNumFrames))
{
mpegVidRsrc(0,image->vid_stream,0, NULL);
MovieDone = image->vid_stream->film_has_ended;
}
 
CurrentImage=(char *) image->vid_stream->current->display;
 
dprintf ("\nGetMPEGFrame: just received a finished frame: "
"copying from %08X to %08X\n", CurrentImage, Frame);
 
memcpy (Frame, CurrentImage, image->Size);
return (!MovieDone);
 
} /* GetMPEGFrame () */
 
#ifndef DISABLE_DITHER
/* ----------------------------- MNI Header -----------------------------------
@NAME : DoDitherImage
@INPUT : l, Cr, Cb - pointers to the luminance, Cr, and Cb planes
disp - ?
h, w - height and width of image (?)
@OUTPUT :
@RETURNS :
@DESCRIPTION: Called when image needs to be dithered. Selects correct
dither routine based on info in ditherType.
@METHOD :
@GLOBALS : ditherType
@CALLS : One of the following, depending on the value of ditherType:
HybridDitherImage (hybrid.c)
HybridErrorDitherImage (hybriderr.c)
FS2FastDitherImage (fs2fast.c)
FS2DitherImage (fs2.c)
FS4DitherImage (fs4.c)
Twox2DitherImage (2x2.c)
ColorDitherImage (16bit.c)
GrayDitherImage (gray.c)
OrderedDitherImage (ordered.c)
MonoDitherImage (mono.c)
MonoThresholdImage (mono.c)
Ordered2DitherImage (ordered2.c)
MBOrderedDitherImage (mb_ordered.c)
@CREATED : (taken from the original Berkeley code)
@MODIFIED :
---------------------------------------------------------------------------- */
void
DoDitherImage(vid_stream)
VidStream *vid_stream;
{
unsigned char *l=vid_stream->current->luminance,
*Cr=vid_stream->current->Cr,
*Cb=vid_stream->current->Cb,
*disp=vid_stream->current->display;
int h=(int) vid_stream->mb_height * 16;
int w=(int) vid_stream->mb_width * 16;
int ditherType=vid_stream->ditherType;
int matched_depth=vid_stream->matched_depth;
 
switch(ditherType) {
case HYBRID_DITHER:
HybridDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case HYBRID2_DITHER:
HybridErrorDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FS2FAST_DITHER:
FS2FastDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FS2_DITHER:
FS2DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FS4_DITHER:
FS4DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case Twox2_DITHER:
Twox2DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FULL_COLOR_DITHER:
Color32DitherImage(l, Cr, Cb, disp, h, w);
break;
 
// MG
case HALF_COLOR_DITHER:
Color16DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case GRAY_DITHER:
GrayDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case NO_DITHER:
break;
 
case PPM_DITHER:
Color32DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case ORDERED_DITHER:
OrderedDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case MONO_DITHER:
MonoDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case MONO_THRESHOLD:
MonoThresholdImage(l, Cr, Cb, disp, h, w);
break;
 
case ORDERED2_DITHER:
Ordered2DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case MBORDERED_DITHER:
MBOrderedDitherImage(l, Cr, Cb, disp, h, w, vid_stream->ditherFlags);
break;
}
} /* DoDitherImage () */
#else
void
DoDitherImage(vid_stream)
VidStream *vid_stream;
{
unsigned char *l=vid_stream->current->luminance,
*Cr=vid_stream->current->Cr,
*Cb=vid_stream->current->Cb,
*disp=vid_stream->current->display;
int h=(int) vid_stream->mb_height * 16;
int w=(int) vid_stream->mb_width * 16;
 
Color32DitherImage(l,Cr,Cb,disp,h,w);
}
#endif
/shark/trunk/ports/mpeg/rules.mak
0,0 → 1,63
#
# Rules and common variables
#
 
HOSTNAME=$(shell uname)
 
ifeq ($(HOSTNAME),Linux)
else
ifeq ($(HOSTNAME),MS-DOS)
else
all::
@echo System "$(HOSTNAME)" unknow
@error
endif
endif
 
#
#
#
 
LIBNAME = mpeg
 
 
#
INCLUDE_PATH = $(HARTIK)/h
LIB_PATH = $(HARTIK)/lib
 
CC = gcc
 
C_DEF_TOREMOVE = -D__GNU__
 
C_DEF = -D_PARANOIA -D_GNU_SOURCE $(C_DEF_TOREMOVE)
C_WARN = -Wimplicit-function-declaration -Wall
C_FLAGS = -O -finline-functions -fno-builtin -nostdinc
 
 
C_INC = -I. -I$(HARTIK)/include -I$(HARTIK)
 
 
#C_MAC = -imacros $(HARTIK)/include/hartik/bdevconf.h
C_MAC =
C_OPT = $(C_DEF) $(C_WARN) $(C_INC) $(C_MAC) $(C_FLAGS)
C_OUTPUT = -o $(notdir $*.o)
 
# for mpeg lib
C_DEF += -DHAVE_CONFIG_H -D__LINUX__ -DNOCONTROLS
C_INC += -I$(HARTIK)/../oskit/src/include -I$(HARTIK)/drivers/linuxcom/include
C_INC += -I$(HARTIK)/h -I$(HARTIK)/h/sys -I$(HARTIK)/h/x86
 
ASM_DEF =
ASM_WARN =
ASM_FLAGS =
ASM_INC = -I. -I$(HARTIK)/include
ASM_MAC =
ASM_OPT = $(ASM_DEF) $(ASM_WARN) $(ASM_INC) $(ASM_MAC) $(ASM_FLAGS)
ASM_OUTPUT = -o $*.o
 
 
%.o : %.c
$(REDIR) $(CC) $(C_OPT) $(C_OUTPUT) -c $<
 
%.o : %.S
$(REDIR) $(CC) $(ASM_OPT) $(ASM_OUTPUT) -c $<
/shark/trunk/ports/mpeg/mpeg_pla.txt
0,0 → 1,204
MPEG_PLAY(1) MPEG_PLAY(1)
28 May 1995
 
NAME
mpeg_play - plays mpeg-1 encoded bitstreams using X11
 
SYNOPSIS
mpeg_play [ -nob ] [ -nop ] [ -display display_name ] [ -quality
{on|off} ] [ -dither dither_option ] [ -loop ] [ -eachstat ] [ -seek
offset ] [ -start num ] [ -end num ] [ -gamma gamma_correction_value ]
[ -framerate num ] [ -no_display ] [ -controls {on|off|none} ] [ -
shmem_off ] [ -l_range num ] [ -cr_range num ] [ -cb_range num ] [ -
quiet ] file_name
 
DESCRIPTION
mpeg_play decodes and displays mpeg-1 encoded bitstreams on systems
running X11. The player will create a new window, display the
bitstream, and exit. Any error messages or notices are sent to
stderr.
 
OPTIONS
-nob : causes the player to ignore and not display any B frames.
 
-nop : causes the player to ignore and not display any P and B frames.
 
-display display_name : causes the player to open the window on the
display display_name.
 
-quality {on|off} : forces player to choose output quality over speed
when on, and vice versa when off. When quality is on, the player
uses a computationally expensive IDCT and also improves playback
through improved handling of half pixel motion vectors. The
default can be set to on if you compile mpeg_play with the flag
-DQUALITY.
 
-dither dither_option : selects from a variety of dither options. The
possible values are:
 
ordered - ordered dither.
 
ordered2 - a faster ordered dither. This is the default.
 
mbordered - ordered dithering at the macroblock level. Although
there is a noticeable decrease in dither quality, this is
the fastest dither available.
 
fs4 - Floyd-Steinberg dithering with 4 error values propagated.
 
fs2 - Floyd-Steinberg dithering with 2 error values propagated.
 
fs2fast - Fast Floyd-Steinberg dithering with 2 error values
propagated.
 
hybrid - Hybrid dithering, a combination of ordered dithering for
the luminance channel and Floyd-Steinberg 2 error dithering
for the chrominance channels. Errors are NOT propagated
properly and are dropped all together every two pixels in
either direction.
 
hybrid2 - Hybrid dithering as above, but with error propagation
among pixels.
 
2x2 - A dithering technique using a 2x2 pixel area for each
pixel. The image displayed is 4 times larger than the
original image encoded. Random error terms are added to each
pixel to break up contours and gradients.
 
gray - Grayscale dithering. The image is dithered into 128
grayscales. Chrominance information is thrown away.
 
gray256 - Grayscale dithering. The image is dithered into 256
grayscales (requires private colormap). Chrominance
information is thrown away.
 
color - Full color display (only available on 16/24 bit color
displays).
 
color2 - Full color display with increased size (only available
on 16/24 bit color displays).
 
none - no dithering is done, no image is displayed. Used to time
decoding process.
 
mono - Floyd-Steinberg dithering for monochrome displays.
 
threshold - Floyd-simple dithering for monochrome displays.
 
ppm - Write a PPM file for each frame.
 
-loop : makes the player loop back to the beginning after reaching the
end.
 
-owncm : makes the player use a private colormap for the window.
 
-step : requires the user to press return for each new frame.
 
-seek offset : before playing the movie, seek to the given offset in
the file (useful for large movies). In this case -end is
redefined to give the number of frames to play, and -start has no
meaning. The offset should point to a Sequence or (closed) GOP
header, but data will be discarded until one is found. The
initial sequence header will be parsed before the seek. The
skipped sections must not change the quantization matrices or the
results are undefined.
 
-start num : Waits to start display until this frame number (previous
frames are parsed).
 
-end num : ends display at this frame number (except when -seek is
used).
 
-gamma gamma_correction_param : specifies the amount of gamma
correction. Default is 1.0. Use higher values if movie looks
dark and hard to see.
 
-framerate num : sets the framerate of the playback to num frames per
second. A value of 0 indicates that the stream should be played
as fast as possible. The default is to play at the rate
specified in the stream (if possible). Note this is merely a
framerate limiter, it will not discard frames to meet the rate.
 
-controls {on|off|none} : determines the initial interactive X user
interface control bar state (if available). The value on
(default) opens the control bar at initialization and enters
pause mode after displaying the first frame. The value off
leaves the control bar initially hidden and begins playback
without pausing (similar to the old behavior). The control bar
can be toggled on and off at any time by clicking in the video
display window, unless the -controls none option is specified, in
which case the control bar is unavailable and playback functions
as though the player were built without interactive controls
(exactly the old behavior).
 
-quiet : suppresses printing of frame numbers, timing information, and
most error messages.
 
-eachstat : causes statistics to be displayed after each frame. Only
valid when compiled with -DANALYSIS.
 
-shmem_off : turns shared memory off.
 
-l_range num_colors : sets the number of colors assigned to the
luminance component when dithering the image. The product of
l_range, cr_range and cb_range should be less than the number of
colors on the display.
 
-cr_range num_colors : sets the number of colors assigned to the red
component of the chrominance range when dithering the image. The
product of l_range, cr_range and cb_range should be less than the
number of colors on the display.
 
-cb_range num_colors : sets the number of colors assigned to the blue
component of the chrominance range when dithering the image. The
product of l_range, cr_range and cb_range should be less than the
number of colors on the display.
 
-no_display : dithers, but does not display, usually used for testing
and timing purposes.
 
NOTES
The player expects video streams only. It can handle multiplexed MPEG
streams (video+audio streams) by discarding the audio. Some streams do
not end with the proper sequence end code and will probably generate
an "Improper sequence end code." error when done playing. This player
can play XING data files. Be aware that XING makes no use of temporal
redundancy or motion vector information. In other words, they do not
use any P or B frames in their streams. Instead, XING data is simply a
sequence of I frames. Since I frames take significantly longer to
decode, performance of the player using XING data is not
representative of the player's ability. The player does not play
MPEG-1 D-frame streams, but they are a rarity. If the player is
compiled without the controlbar, then it can play multiple streams in
different windows.
 
VERSION
This is version 2.1a, containing some new features since 2.0, and
several bug fixes. It is a major change since version 1.0.
 
BUGS
The only known bug is that multiple mpeg_plays cannot seem to be run
simultaneously on a multiprocessor SPARC 20 or a SparcCenter 2000E
using shared memory (in particular: "On a bi-processor Sparc 20/20
sparc-processor 2000E running Solaris 2.3 or 2.4, it is not possible
to run two concurrent 'mpeg_play -loop' on the same bitstream. One of
the mpeg_play dies when it loops." This may be a problem with the X
shared memory library and not our code.)
 
AUTHORS
Ketan Patel - University of California, Berkeley,
kpatel@cs.berkeley.edu
 
Brian Smith - University of California, Berkeley,
bsmith@cs.berkeley.edu
 
Henry Chi-To Ma - University of California, Berkeley,
cma@cs.berkeley.edu
 
Kim Man Liu - University of California, Berkeley, kliu@cs.berkeley.edu
 
Steve Smoot - University of California, Berkeley,
smoot@cs.berkeley.edu
 
Eugene Hung - University of California, Berkeley,
eyhung@cs.berkeley.edu
/shark/trunk/ports/mpeg/hybrid.c
0,0 → 1,240
/*
* hybrid.c --
*
* Procedures dealing with hybrid dithers.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/* This file contains C code to implement an ordered dither. */
 
#include "video.h"
#include "proto.h"
#include "dither.h"
 
#define DITH_SIZE 16
 
 
/* Structures used to implement hybrid ordered dither/floyd-steinberg
dither algorithm.
*/
 
static unsigned char *l_darrays[DITH_SIZE];
static unsigned char cr_fsarray[256][4];
static unsigned char cb_fsarray[256][4];
 
/*
*--------------------------------------------------------------
*
* InitHybridDither--
*
* Structures intialized for hybrid dithering. Ordered dither
* patterns set for luminance channel, f-s errors precomputed
* for chrominance channels.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
InitHybridDither()
{
int i, j, k, err_range, threshval;
unsigned char *lmark;
 
for (i=0; i<DITH_SIZE; i++) {
lmark = l_darrays[i] = (unsigned char *) malloc(256);
 
for (j=0; j<lum_values[0]; j++) {
*lmark++ = 0;
}
 
for (j=0; j<(LUM_RANGE-1); j++) {
err_range = lum_values[j+1] - lum_values[j];
threshval = ((i * err_range) / DITH_SIZE)+lum_values[j];
 
for (k=lum_values[j]; k<lum_values[j+1]; k++) {
if (k > threshval) *lmark++ = ((j+1) * (CR_RANGE * CB_RANGE));
else *lmark++ = (j * (CR_RANGE * CB_RANGE));
}
}
 
for (j=lum_values[LUM_RANGE-1]; j<256; j++) {
*lmark++ = (LUM_RANGE-1)*(CR_RANGE * CB_RANGE);
}
 
}
{
int cr1, cr2, cr3, cr4, err1, err2;
int cb1, cb2, cb3, cb4, val, nval;
 
for (i=0; i<256; i++) {
 
val = i;
 
cr1 = (val * CR_RANGE) / 256;
err1 = (val - cr_values[cr1])/2;
err2 = (val - cr_values[cr1]) - err1;
 
nval = val+err1;
if (nval > 255) nval = 255;
else if (nval < 0) nval = 0;
cr2 = (nval * CR_RANGE) / 256;
err1 = (nval - cr_values[cr2])/2;
 
nval = val+err2;
if (nval > 255) nval = 255;
else if (nval < 0) nval = 0;
cr3 = (nval * CR_RANGE) / 256;
err2 = (nval - cr_values[cr3])/2;
 
nval = val+err1+err2;
if (nval > 255) nval = 255;
else if (nval < 0) nval = 0;
cr4 = (nval * CR_RANGE) / 256;
 
cr_fsarray[i][0] = cr1*CB_RANGE;
cr_fsarray[i][1] = cr2*CB_RANGE;
cr_fsarray[i][2] = cr3*CB_RANGE;
cr_fsarray[i][3] = cr4*CB_RANGE;
}
for (i=0; i<256; i++) {
 
val = i;
 
cb1 = (val * CB_RANGE) / 256;
err1 = (val - cb_values[cb1])/2;
err2 = (val - cb_values[cb1]) - err1;
 
nval = val+err1;
if (nval > 255) nval = 255;
else if (nval < 0) nval = 0;
cb2 = (nval * CB_RANGE) / 256;
err1 = (nval - cb_values[cb2])/2;
 
nval = val+err2;
if (nval > 255) nval = 255;
else if (nval < 0) nval = 0;
cb3 = (nval * CB_RANGE) / 256;
err2 = (nval - cb_values[cb3])/2;
 
nval = val+err1+err2;
if (nval > 255) nval = 255;
else if (nval < 0) nval = 0;
cb4 = (nval * CB_RANGE) / 256;
 
cb_fsarray[i][0] = cb1;
cb_fsarray[i][1] = cb2;
cb_fsarray[i][2] = cb3;
cb_fsarray[i][3] = cb4;
}
}
}
 
/*
*--------------------------------------------------------------
*
* HybridDitherImage --
*
* Dithers an image using an ordered dither.
* Assumptions made:
* 1) The color space is allocated y:cr:cb = 8:4:4
* 2) The spatial resolution of y:cr:cb is 4:1:1
* The luminance channel is dithered based on the standard
* ordered dither pattern for a 4x4 area. The Chrominance
* channels are dithered based on precomputed f-s errors.
* Two errors are propogated per pixel. Errors are NOT propogated
* beyond a 2x2 pixel area.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
HybridDitherImage (lum, cr, cb, out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int w, h;
{
unsigned char *l, *r, *b, *o1, *o2;
unsigned char *l2;
int i, j;
 
l = lum;
l2 = lum+w;
r = cr;
b = cb;
o1 = out;
o2 = out+w;
 
for (i=0; i<h; i+=4) {
 
for (j=0; j<w; j+=4) {
 
*o1++ = pixel[(l_darrays[0][*l++] | cr_fsarray[*r][0] | cb_fsarray[*b][0])];
*o1++ = pixel[(l_darrays[8][*l++] | cr_fsarray[*r][1] | cb_fsarray[*b][1])];
*o2++ = pixel[(l_darrays[12][*l2++] | cr_fsarray[*r][2] | cb_fsarray[*b][2])];
*o2++ = pixel[(l_darrays[4][*l2++] | cr_fsarray[*r++][3] | cb_fsarray[*b++][3])];
 
*o1++ = pixel[(l_darrays[2][*l++] | cr_fsarray[*r][0] | cb_fsarray[*b][0])];
*o1++ = pixel[(l_darrays[10][*l++] | cr_fsarray[*r][1] | cb_fsarray[*b][1])];
*o2++ = pixel[(l_darrays[14][*l2++] | cr_fsarray[*r][2] | cb_fsarray[*b][2])];
*o2++ = pixel[(l_darrays[6][*l2++] | cr_fsarray[*r++][3] | cb_fsarray[*b++][3])];
}
 
l += w; l2 += w;
o1 += w; o2 += w;
 
for (j=0; j<w; j+=4) {
 
*o1++ = pixel[(l_darrays[3][*l++] | cr_fsarray[*r][1] | cb_fsarray[*b][1])];
*o1++ = pixel[(l_darrays[11][*l++] | cr_fsarray[*r][0] | cb_fsarray[*b][0])];
*o2++ = pixel[(l_darrays[15][*l2++] | cr_fsarray[*r][3] | cb_fsarray[*b][3])];
*o2++ = pixel[(l_darrays[7][*l2++] | cr_fsarray[*r++][2] | cb_fsarray[*b++][2])];
 
*o1++ = pixel[(l_darrays[1][*l++] | cr_fsarray[*r][1] | cb_fsarray[*b][1])];
*o1++ = pixel[(l_darrays[9][*l++] | cr_fsarray[*r][0] | cb_fsarray[*b][0])];
*o2++ = pixel[(l_darrays[13][*l2++] | cr_fsarray[*r][3] | cb_fsarray[*b][3])];
*o2++ = pixel[(l_darrays[5][*l2++] | cr_fsarray[*r++][2] | cb_fsarray[*b++][2])];
}
 
l += w; l2 += w;
o1 += w; o2 += w;
}
}
 
 
/shark/trunk/ports/mpeg/install
0,0 → 1,110
These are the instructions for compiling mpeg_play, the software MPEG
decoder and player.
 
1) Untar the file mpeg_play.tar.gz. This is best done by creating a new
directory for the files involved, moving the tar file into this directory
and invoking the command:
 
zcat mpeg_play-2.1.tar.gz | tar xvf -
(or gtar -zxvf mpeg_play-2.1.tar.gz )
 
2) Create and customize the Makefile. Do this by copying the file
Makefile.proto to Makefile. Then edit Makefile for your particular needs.
 
In the Makefile the CFLAGS definition is multiply defined for a couple of
different machines, uncomment the one you want to use, or define your own
if necessary.
 
The INCLUDEDIR variable should be set to include the paths leading to the
standard header files such as stdio.h as well as to X11/Xlib.h (on most
systems, this is /usr/include). To do this set the INCLUDEDIR variable to
-I followed by the pathname. For example, if the path is /usr/local/include,
edit the Makefile to look like this:
 
INCLUDEDIR = -I/usr/local/include
 
If more than one pathname is necessary, simply prepend -I to each path.
For example if you needed to include /usr/local/include and /usr/X11/include,
the variable definition would look like:
 
INCLUDEDIR = -I/usr/local/include -I/usr/X11/include
 
Finally, make sure the LIBS variable is set to the path and name of your
Xext and X11 librarys. For example:
 
LIBS = /usr/lib/X11/libXext.a /usr/lib/X11/libX11.a
 
or
LIBS = -lXext -lX11
 
3) Type make all.
 
4) To remove .o files, type make clean
 
5) Install mpeg_play and mpeg_play.1 into the appropriate places.
 
6) Try it out! You can ftp some sample data files from the same site
you got this player from. Data files usually end in .mpg or .mpeg
The command line for the player is described in the man page, but
is basically:
 
mpeg_play [options] [file_name]
 
7) If you want the player to collect statistics on size of frames,
macroblocks, time to decode, etc., add the following to the
definition of CFLAGS in the Makefile:
-DANALYSIS
Remove all .o files with "make clean" and remake with "make all"
The player will now print summarized statistics at the end of the
video clip and can be made to print frame by frame statistics with
the use of the -eachstat flag. Read man page for more info.
 
You may prefer to use mpeg_stat if you're really into statistics.
 
------------------------------------------------------------------------
 
Using Imake
 
We have included an Imakefile for use with Imake. Since we do not use
Imake ourselves and the file was provided by someone else, we can not
give any specific instructions on how to use it. Please, consult
someone more experienced with Imake.
Thanks.
 
------------------------------------------------------------------------
 
Some platforms are "special", if you have problems read the PLATFORMS file
for hints.
 
------------------------------------------------------------------------
 
NOTES
 
It seems that much of the time is spent converting the 24 bit MPEG image
to an 8 bit color space. This process is called "dithering". We've included
several dithering algorithms. Read the man pages for more instructions.
 
The data files available are produced by XING. These images are
usually small (~160X120). XING data does not take advantage
of P or B frames (ie, frames with motion compensation). The data is simply
a series of I frames. Performance of the player on XING data is
significantly lower (half or less) of the performance when motion compensated
MPEG data is decoded.
 
Reporting bugs:
If you find any bugs in this software, please send them to
mpeg-bugs@plateau.cs.berkeley.edu. Since this software
is unsupported, we make no guarantees about how long it will
take to fix the bug, or if it will be fixed at all. Bug fixes
will be cheerfully accepted. Please include as much detailed
information as possible, including:
 
1) the version number of the program you are using (cf. VERSION)
2) the data file that caused the bug (if possible)
3) the OS version and machine type you ran the program on
4) the compiler used to compile the program
 
 
 
 
 
/shark/trunk/ports/mpeg/parseblock.c
0,0 → 1,534
/*
* parseblock.c --
*
* Procedures to read in the values of a block and store them
* in a place where the player can use them.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#define NO_SANITY_CHECKS
#include <assert.h>
#include "video.h"
#include "proto.h"
#include "decoders.h"
 
 
/*
Changes to make the code reentrant:
deglobalized: curBits, bitOffset, bitLength, bitBuffer, curVidStream,
zigzag_direct now a const int variable initialized once
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* External declarations. */
extern const int zigzag_direct[];
#ifdef DCPREC
extern int dcprec;
#endif
 
/* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
 
#define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
 
/*
*--------------------------------------------------------------
*
* ParseReconBlock --
*
* Parse values for block structure from bitstream.
* n is an indication of the position of the block within
* the macroblock (i.e. 0-5) and indicates the type of
* block (i.e. luminance or chrominance). Reconstructs
* coefficients from values parsed and puts in
* block.dct_recon array in vid stream structure.
* sparseFlag is set when the block contains only one
* coeffictient and is used by the IDCT.
*
* Results:
*
*
* Side effects:
* Bit stream irreversibly parsed.
*
*--------------------------------------------------------------
*/
 
#define DCT_recon blockPtr->dct_recon
#define DCT_dc_y_past blockPtr->dct_dc_y_past
#define DCT_dc_cr_past blockPtr->dct_dc_cr_past
#define DCT_dc_cb_past blockPtr->dct_dc_cb_past
 
#define DECODE_DCT_COEFF_FIRST DecodeDCTCoeffFirst
#define DECODE_DCT_COEFF_NEXT DecodeDCTCoeffNext
 
void
ParseReconBlock(n, vid_stream)
int n;
VidStream *vid_stream;
{
#ifdef RISC
unsigned int temp_curBits;
int temp_bitOffset;
int temp_bufLength;
unsigned int *temp_bitBuffer;
#endif
 
Block *blockPtr = &vid_stream->block;
int coeffCount=0;
if (vid_stream->buf_length < 100)
correct_underflow(vid_stream);
 
#ifdef RISC
temp_curBits = vid_stream->curBits;
temp_bitOffset = vid_stream->buf_offset;
temp_bufLength = vid_stream->buf_length;
temp_bitBuffer = bitBuffer;
#endif
 
{
/*
* Copy the VidStream fields curBits, bitOffset, and bitBuffer
* into local variables with the same names, so the macros use the
* local variables instead. This allows register allocation and
* can provide 1-2 fps speedup. On machines with not so many registers,
* don't do this.
*/
#ifdef RISC
register unsigned int curBits = temp_curBits;
register int bitOffset = temp_bitOffset;
register int bufLength = temp_bufLength;
register unsigned int *bitBuffer = temp_bitBuffer;
#endif
 
int diff;
int size, level=0, i, run, pos, coeff;
short int *reconptr;
unsigned char *iqmatrixptr, *niqmatrixptr;
int qscale;
 
reconptr = DCT_recon[0];
 
/*
* Hand coded version of memset that's a little faster...
* Old call:
* memset((char *) DCT_recon, 0, 64*sizeof(short int));
*/
{
INT32 *p;
p = (INT32 *) reconptr;
 
p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = p[8] = p[9] =
p[10] = p[11] = p[12] = p[13] = p[14] = p[15] = p[16] = p[17] = p[18] =
p[19] = p[20] = p[21] = p[22] = p[23] = p[24] = p[25] = p[26] = p[27] =
p[28] = p[29] = p[30] = p[31] = 0;
 
}
 
if (vid_stream->mblock.mb_intra) {
 
if (n < 4) {
 
/*
* Get the luminance bits. This code has been hand optimized to
* get by the normal bit parsing routines. We get some speedup
* by grabbing the next 16 bits and parsing things locally.
* Thus, calls are translated as:
*
* show_bitsX <--> next16bits >> (16-X)
* get_bitsX <--> val = next16bits >> (16-flushed-X);
* flushed += X;
* next16bits &= bitMask[flushed];
* flush_bitsX <--> flushed += X;
* next16bits &= bitMask[flushed];
*
* I've streamlined the code a lot, so that we don't have to mask
* out the low order bits and a few of the extra adds are removed.
* bsmith
*/
unsigned int next16bits, index, flushed;
 
show_bits16(next16bits);
index = next16bits >> (16-5);
if (index < 31) {
size = dct_dc_size_luminance[index].value;
flushed = dct_dc_size_luminance[index].num_bits;
} else {
index = next16bits >> (16-9);
index -= 0x1f0;
size = dct_dc_size_luminance1[index].value;
flushed = dct_dc_size_luminance1[index].num_bits;
}
next16bits &= bitMask[16+flushed];
 
if (size != 0) {
flushed += size;
diff = next16bits >> (16-flushed);
if (!(diff & bitTest[32-size])) {
diff = rBitMask[size] | (diff + 1);
}
} else {
diff = 0;
}
flush_bits(flushed);
 
if (n == 0) {
coeff = diff << 3;
if (vid_stream->mblock.mb_address -
vid_stream->mblock.past_intra_addr > 1) {
coeff += 1024;
} else {
coeff += DCT_dc_y_past;
}
DCT_dc_y_past = coeff;
} else {
coeff = DCT_dc_y_past + (diff << 3);
DCT_dc_y_past = coeff;
}
 
} else { /* n = 4 or 5 */
/*
* Get the chrominance bits. This code has been hand optimized to
* as described above
*/
 
unsigned int next16bits, index, flushed;
 
show_bits16(next16bits);
index = next16bits >> (16-5);
if (index < 31) {
size = dct_dc_size_chrominance[index].value;
flushed = dct_dc_size_chrominance[index].num_bits;
} else {
index = next16bits >> (16-10);
index -= 0x3e0;
size = dct_dc_size_chrominance1[index].value;
flushed = dct_dc_size_chrominance1[index].num_bits;
}
next16bits &= bitMask[16+flushed];
if (size != 0) {
flushed += size;
diff = next16bits >> (16-flushed);
if (!(diff & bitTest[32-size])) {
diff = rBitMask[size] | (diff + 1);
}
} else {
diff = 0;
}
flush_bits(flushed);
/* We test 5 first; a result of the mixup of Cr and Cb */
if (n == 5) {
coeff = diff << 3;
 
if (vid_stream->mblock.mb_address -
vid_stream->mblock.past_intra_addr > 1) {
coeff += 1024;
} else {
coeff += DCT_dc_cr_past;
}
DCT_dc_cr_past = coeff;
} else {
coeff = diff << 3;
if (vid_stream->mblock.mb_address -
vid_stream->mblock.past_intra_addr > 1) {
coeff += 1024;
} else {
coeff += DCT_dc_cb_past;
}
DCT_dc_cb_past = coeff;
}
}
*reconptr = coeff;
i = 0;
pos = 0;
coeffCount = (coeff != 0);
if (vid_stream->picture.code_type != 4) {
qscale = vid_stream->slice.quant_scale;
iqmatrixptr = vid_stream->intra_quant_matrix[0];
while(1) {
DECODE_DCT_COEFF_NEXT(run, level);
 
if (run >= END_OF_BLOCK) break;
 
i = i + run + 1;
pos = zigzag_direct[i];
 
/* quantizes and oddifies each coefficient */
if (level < 0) {
coeff = ((level<<1) * qscale *
((int) (iqmatrixptr[pos]))) / 16;
coeff += (1 - (coeff & 1));
} else {
coeff = ((level<<1) * qscale *
((int) (*(iqmatrixptr+pos)))) >> 4;
coeff -= (1 - (coeff & 1));
}
#ifdef QUANT_CHECK
printf ("coeff: %d\n", coeff);
#endif
 
reconptr[pos] = coeff;
coeffCount++;
 
}
 
#ifdef QUANT_CHECK
printf ("\n");
#endif
 
#ifdef ANALYSIS
{
extern unsigned int *mbCoeffPtr;
mbCoeffPtr[pos]++;
}
#endif
 
flush_bits(2);
goto end;
}
} else { /* non-intra-coded macroblock */
niqmatrixptr = vid_stream->non_intra_quant_matrix[0];
qscale = vid_stream->slice.quant_scale;
DECODE_DCT_COEFF_FIRST(run, level);
i = run;
 
pos = zigzag_direct[i];
 
/* quantizes and oddifies each coefficient */
if (level < 0) {
coeff = (((level<<1) - 1) * qscale *
((int) (niqmatrixptr[pos]))) / 16;
if ((coeff & 1) == 0) {coeff = coeff + 1;}
} else {
coeff = (((level<<1) + 1) * qscale *
((int) (*(niqmatrixptr+pos)))) >> 4;
coeff = (coeff-1) | 1; /* equivalent to: if ((coeff&1)==0) coeff = coeff - 1; */
}
 
reconptr[pos] = coeff;
if (coeff) {
coeffCount = 1;
}
 
if (vid_stream->picture.code_type != 4) {
while(1) {
DECODE_DCT_COEFF_NEXT(run, level);
 
if (run >= END_OF_BLOCK) {
break;
}
 
i = i+run+1;
pos = zigzag_direct[i];
if (level < 0) {
coeff = (((level<<1) - 1) * qscale *
((int) (niqmatrixptr[pos]))) / 16;
if ((coeff & 1) == 0) {coeff = coeff + 1;}
} else {
coeff = (((level<<1) + 1) * qscale *
((int) (*(niqmatrixptr+pos)))) >> 4;
coeff = (coeff-1) | 1; /* equivalent to: if ((coeff&1)==0) coeff = coeff - 1; */
}
reconptr[pos] = coeff;
coeffCount++;
} /* end while */
 
#ifdef ANALYSIS
{
extern unsigned int *mbCoeffPtr;
mbCoeffPtr[pos]++;
}
#endif
 
flush_bits(2);
 
goto end;
} /* end if (vid_stream->picture.code_type != 4) */
}
end:
 
if (coeffCount == 1) {
j_rev_dct_sparse (reconptr, pos);
}
else {
#ifdef FLOATDCT
if (qualityFlag) {
float_idct(reconptr);
} else {
#endif
j_rev_dct(reconptr);
#ifdef FLOATDCT
}
#endif
}
 
#ifdef RISC
temp_curBits = vid_stream->curBits;
temp_bitOffset = vid_stream->bit_offset;
temp_bufLength = vid_stream->buf_length;
temp_bitBuffer = bitBuffer;
#endif
 
}
 
#ifdef RISC
vid_stream->curBits = temp_curBits;
vid_stream->bitOffset = temp_bitOffset;
vid_stream->buf_length = temp_bufLength;
bitBuffer = temp_bitBuffer;
#endif
}
#undef DCT_recon
#undef DCT_dc_y_past
#undef DCT_dc_cr_past
#undef DCT_dc_cb_past
 
/*
*--------------------------------------------------------------
*
* ParseAwayBlock --
*
* Parses off block values, throwing them away.
* Used with grayscale dithering.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
ParseAwayBlock(n, vid_stream)
int n;
VidStream *vid_stream;
{
unsigned int diff;
unsigned int size, run;
int level;
 
if (vid_stream->buf_length < 100)
correct_underflow(vid_stream);
 
if (vid_stream->mblock.mb_intra) {
 
/* If the block is a luminance block... */
 
if (n < 4) {
 
/* Parse and decode size of first coefficient. */
 
DecodeDCTDCSizeLum(size);
 
/* Parse first coefficient. */
 
if (size != 0) {
get_bitsn(size, diff);
}
}
 
/* Otherwise, block is chrominance block... */
 
else {
 
/* Parse and decode size of first coefficient. */
 
DecodeDCTDCSizeChrom(size);
 
/* Parse first coefficient. */
 
if (size != 0) {
get_bitsn(size, diff);
}
}
}
 
/* Otherwise, block is not intracoded... */
 
else {
 
/* Decode and set first coefficient. */
 
DECODE_DCT_COEFF_FIRST(run, level);
}
 
/* If picture is not D type (i.e. I, P, or B)... */
 
if (vid_stream->picture.code_type != 4) {
 
/* While end of macroblock has not been reached... */
 
while (1) {
 
/* Get the dct_coeff_next */
 
DECODE_DCT_COEFF_NEXT(run, level);
 
if (run >= END_OF_BLOCK) break;
}
 
/* End_of_block */
 
flush_bits(2);
}
}
/shark/trunk/ports/mpeg/announce
0,0 → 1,190
BERKELEY MPEG TOOLS (Version 1.0, Release 2; August 1995)
 
Lawrence A. Rowe, Steve Smoot, Ketan Patel, Brian Smith, Kevin Gong,
Eugene Hung, Doug Banks, Sam Tze-San Fung, Darryl Brown, and Dan Wallach
 
--------------------
Changes since release one:
mpeg_encode - important bug fixes
mpeg_play - simple user interface added
others - small bugfixes
--------------------
 
Computer Science Division-EECS University of California at Berkeley
Berkeley, CA 94720-1776
 
This distribution is a combined release of tools developed at
Berkeley and elsewhere for manipulating MPEG-1 video.
 
This release includes the following tools:
 
mpeg_play - software-only MPEG-1 video decoder
mpeg_encode - software-only MPEG-1 video encoder
mpeg_stat - a bitstream analysis tool
mpeg_blocks - an interactive tool to examine macroblock coding
mpeg_bits - an interactive tool to examine bit allocation to blocks
 
The package is available at the URL
 
ftp://mm-ftp.cs.berkeley.edu/pub/multimedia/mpeg/bmt1r1.tar.gz
 
For more information on MPEG standards and other MPEG software and
hardware, see http://www-plateau.cs.berkeley.edu/mpeg/index.html.
Other sites where you can find interesting MPEG related software
and movies are:
 
ftp://sunsite.unc.edu/pub/multimedia/utilities
ftp://netcom.com:/pub/cf/cfogg/
http://www.acm.uiuc.edu/rml/Mpeg
 
The remainder of this file describes each tool including changes,
if any, from previous releases and other information about the
release. In the descriptions below reference is made to papers
describing various aspects of these programs. These papers are
also available at the Plateau WWW site (http://www-plateau.cs.berkeley.edu/)
or in our FTP site in the directory pub/multimedia/papers.
 
 
MPEG_PLAY (V2.3)
 
This program decodes and displays an MPEG-1 video stream. The
program has been written to be portable, which means it has not
been optimized for specific platforms. The decoder is implemented
as a library that will take a video stream and display it in an X
window on an 8, 24 or 32 bit deep display. The main routine is
supplied to demonstrate the use of the decoder library. Several
dithering algorithms are supplied based on the Floyd-Steinberg,
ordered dither, and half-toning algorithms that tradeoff quality
and performance. Neither the library nor the main routine handle
real-time synchronization or audio streams.
 
A paper published at ACM Multimedia 93 describes the decoder and
compares the performance of the program on several platforms (see
pub/multimedia/papers/MM93.ps.Z). An updated version of this
comparison is included in the file doc/mpegperf.ps in this
distribution. This code has also been included in our Continuous
Media Player (cmplayer) that plays synchronized audio and video
across a network. This system adapts to the decoding performance
of the destination machine. A paper describing these algorithms
and the performance of the system was published at IS&T SPIE 94
(see /pub/multimedia/papers/CMMPEG-SPIE94.ps.Z).
 
This release fixes numerous bugs in the player including the motion
vector problem that caused problems when playing MPEGs generated
from computer-generated animations, the error in the color space
equations, some IDCT problems, and a number of minor problems with
installation on platforms with new OS releases.
 
New features have also been implemented, chief of which are the ability
to play system layer MPEG streams (discarding audio), gamma correction, and
frame rate control.
 
 
MPEG_ENCODE (V1.5R2)
 
This program generates an MPEG-1 video bitstream given a sequence
of images in an acceptable format (e.g., yuv, ppm, jpeg, etc.).
It can be run on one computer (i.e., sequential) or on several
computers (i.e., parallel). Our goal was to produce a portable,
easy-to-use encoder that can be used to encode video material for
a variety of desktop applications (e.g., video-on-demand). The
parallelism is done on a sequence of pictures. In other words,
you can spawn one or more children to encode continuous runs of
pictures. The goal is to allow you to encode using multiple
processors, think spare cycles on workstations, to speed up the
encoding time. Although performance depends on the speed of
individual processors, the file system and network, and the P/B
frame search methods, we have encoded 3.75 frames/second on 8 HP
Snakes running in parallel as compared with 0.6 frames/second on
1 Snake when coding CIF size images. The encoder has also been
ported to an Intel supercomputer (Paragon) on which it has encoded CCIR
601 images at 40 frames/second.
 
A paper describing the parallel encoder and our experiments on a
network of workstations was published at the 1994 Picture Coding
Symposium (see /pub/multimedia/papers/mpeg-encode.ps.Z). A paper
describing the port to the Intel supercomputer and the performance
experiments on that system was presented at IS&T SPIE95 (see
/pub/multimedia/papers/intelsc-mpeg-encode.ps.Z). This work was
done jointly with Ed Delp and his student Ke Shen from Purdue.
You can get a copy of the Intel code from /pub/dist/delp/spie95-coding
at skynet.ecn.purdue.edu.
 
This release fixed several bugs and added some new features.
Specifically, the encoder has been modified to: 1) accept input
images generated on the fly by another program, 2) generate constant
bitrate bitstreams, 3) be much more flexible about input formats,
and 4) allow a priori specification of motion vectors or Qscales on a
macroblock level, to avoid repetitive motion searches when reencoding.
 
MPEG_STAT (V2.2R2)
 
MPEG_STAT has been modified to gather more statistics (e.g., bit
rate, real Q-scale information, detailed motion vector/cbp information,
constrained parameter checking, etc.) and fix some bugs. The major
change (from 2.1) was to add some additional verification checks to help
determine the validty of a bitstream including illegal motion
vectors and CPB settings, and speed it up even more.
 
 
MPEG_BLOCKS (V1.0R2)
 
This program is a new tool that allows a user to examine how a
movie has been encoded on a picture-by-picture basis. It shows
size statistics on the different frame types and how each macroblock
was coded. The program also shows the decoded image so you can
see the effect of these coding parameters.
 
The current version of this program only works on systems that
support the X Windowing System and Tcl/Tk because it provides a
user-friendly GUI.
 
 
MPEG_BITS (V1.0R2)
 
This program is also new in this release. It is based on the
MPEG_BLOCKS program, but instead of showing block encoding, it
shows how many bits were allocated to each block. It uses the same
GUI interface.
 
MPEG_BITS also allows you to specify a range of blocks that should
receive more bits when recoding the sequence. The mpeg_encoder
has not yet been modified to take this specification, but it will
in a future release.
 
 
ACKNOWLEDGEMENTS
 
We gratefully thank Hewlett-Packard, Fujitsu, Hitachi, and Philips who
provided financial support for this work. We also want to thank the
following people and organizations for their help:
 
Jef Poskanzer who developed the pbmplus package.
 
Eiichi Kowashi of Intel and Avideh Zakhor of U.C. Berkeley who
provided valuable suggestions on motion vector searching.
 
Chad Fogg of Chromatic Research, Inc. who has helped us understand
many issues in MPEG coding and decoding.
 
Rainer Menes of the Technical University of Munich who
ported previous versions of the Berkeley MPEG encoder and
decoder to the Macintosh. He has provided us with many suggestions
to improve the code.
 
Robert Safranek of ATT for comments, suggestions, and most of
the code for custom quantization tables.
 
Jim Boucher of Boston University for jmovie2jpeg.
 
The San Diego SuperComputing Center for providing facilities
to develop some of the code contained within.
 
Tom Lane of the Independent JPEG Group who provided us with the basic
inverse DCT code used by our player. (tom_lane@g.gp.cs.cmu.edu)
 
Reid Judd of Sun Microsystems who provided advice and assistance.
 
Todd Brunhoff of NVR who provided advice and assistance.
 
Toshihiko Kawai of Sony who provided advice and assistance.
/shark/trunk/ports/mpeg/changes
0,0 → 1,85
Changes since last version:
 
1.1
o Fixed -dither color option to find best 24 bit or greater visual
for most machines.
o Fixed recursive loop in Makefile.
o Added entries for R6000 and SGI's in Makefile
o Fixed declaration of j_rev_dct.
o Does initial sequence start code check to confirm validity of mpeg stream.
o Changed or's in ordered dither to add's to allow more flexible
allocation of color ranges.
o Uses shared memory.
o Lots of little bugs fixed.
 
1.2
o Fixed shared memory problem (freeing memory twice on exit).
o Added entries for Sony NEWS machines
o Added monochrome support.
o Unrolled loops for optimization.
o Variety of small bugs.
 
2.0
o Added ability to use private colormap.
o Display name can now be given as part of command line.
o Fixed green artifacts problem
o Fixed sequence end code cutoff problem.
o Lots of performance tweaks.
o Other bugs.
 
2.1
o Fixed frame dropping problem.
o Supports MPEG system layer (tosses audio)
o 16, 32 bit color modes (thanks to: Erik Corry erik@kroete2.freinet.de)
o Added -owncm to guarantee a private colormap
o Added gray256 to get 256 shades of grey (and added gray/grey no diff)
o Fixed leaving of shared memory buffers when shared memory crashes
(in the common case of running from the wrong display)
o Instructions for IRIX4 Cflags in PLATFORMS.
o Added -step, -start, and -end
o Fixed insanely subtle readfile bug
o Added color2 true color doubling dither, provided by garyo@avs.com (thanks!)
o Added ppm dither, provided by Jef Poskanzer <jef@acme.com> (thanks!)
o Added bzero.c for silly SOLARIS
o -no_display doesnt put up a window now.
o -gamma float, raises the luminance of each pixel to float (a
floating point number), thus -gamma 0.8 darkens, -gamma 1.2 lightens
o Fixed ycc to rgb conversion block assignment mixup.
(thanks to John Toebes <toebes@unx.sas.com> for pointing this out)
o Added frame rate limiting (-framerate)
o Doesn't skip initial B frames (after an I) if the GOP is closed.
o Auto-determines RGB order of server (well, RGB vs BGR anyway).
o Fixed a few grainy blocks appearing due to bugs in sparse IDCT function.
o -nop now implies -nob (doesnt make sense to have B's w/o P's)
o -seek indexes into files
o Added chroma averaging in color and color2 dithers (thanks to
tristan@tcela.la.tce.com (Tristan 'RAMBO' Savatier))
o Added -quality option, which, when turned on,
o correctly implements halfpel motion vector averaging
o uses a very time-consuming but accurate IDCT
o Sped up player a little by using lookup tables for y/cr/cb values
o Minor, unreported bugs.
 
2.2
o added controlbar (thanks: "Michael J. Donahue" <donahue@ulexite.nist.gov>)
o made -step work AFTER the picture display
o made default state be to play the video (in control panel)
o fixed bug in -start w/o -end
o fixed color equn's more (thanks tristan@cauliflower.la.tce.com (Tristan 'RAMBO' Savatier))
o made INTERPOLATE the default in color2
o made gamma_correction abstracted and in greyscale too, (thanks Tristan)
o made includes happier for VMS
 
2.3
o added -position (thanks to jingo@VNET.IBM.COM)
o fixed bug in parseblick.c, lower bit of level handled wrong
o extensive changes in moving variables around to make as a
reentrant library (thanks to Loring Holden <lsh@cs.brown.edu>)
o added (then removed) -xid to have it play in an established window.
Doesn't seem to work with the reentrant changes. Ideas anyone?
o -ppm{width,height,skip} for scaling/subsampling in
-dither ppm (thanks legalize@xmission.com)
o -nob bug fixed
o now skips until it finds a start code... Slower on bad files (like
mpeg_play /kernel but works with sliced up MPEGs
o -no_display / -dithe rppm fixed (Jason Patterson <jason@reflections.com.au>)
/shark/trunk/ports/mpeg/motionvector.c
0,0 → 1,237
/*
* motionvector.c --
*
* Procedures to compute motion vectors.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "proto.h"
#include "util.h"
 
/*
Changes to make the code reentrant:
deglobalize curVidStream
Additional changes:
none
-lsh@cs.brown.edu (Loring Holden)
*/
 
/*
*--------------------------------------------------------------
*
* ComputeVector --
*
* Computes motion vector given parameters previously parsed
* and reconstructed.
*
* Results:
* Reconstructed motion vector info is put into recon_* parameters
* passed to this function. Also updated previous motion vector
* information.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
#define ComputeVector(recon_right_ptr, recon_down_ptr, recon_right_prev, recon_down_prev, f, full_pel_vector, motion_h_code, motion_v_code, motion_h_r, motion_v_r) \
\
{ \
int comp_h_r, comp_v_r; \
int right_little, right_big, down_little, down_big; \
int max, min, new_vector; \
\
/* The following procedure for the reconstruction of motion vectors \
is a direct and simple implementation of the instructions given \
in the mpeg December 1991 standard draft. \
*/ \
\
if (f == 1 || motion_h_code == 0) \
comp_h_r = 0; \
else \
comp_h_r = f - 1 - motion_h_r; \
\
if (f == 1 || motion_v_code == 0) \
comp_v_r = 0; \
else \
comp_v_r = f - 1 - motion_v_r; \
\
right_little = motion_h_code * f; \
if (right_little == 0) \
right_big = 0; \
else { \
if (right_little > 0) { \
right_little = right_little - comp_h_r; \
right_big = right_little - 32 * f; \
} \
else { \
right_little = right_little + comp_h_r; \
right_big = right_little + 32 * f; \
} \
} \
\
down_little = motion_v_code * f; \
if (down_little == 0) \
down_big = 0; \
else { \
if (down_little > 0) { \
down_little = down_little - comp_v_r; \
down_big = down_little - 32 * f; \
} \
else { \
down_little = down_little + comp_v_r; \
down_big = down_little + 32 * f; \
} \
} \
\
max = 16 * f - 1; \
min = -16 * f; \
\
new_vector = recon_right_prev + right_little; \
\
if (new_vector <= max && new_vector >= min) \
*recon_right_ptr = recon_right_prev + right_little; \
/* just new_vector */ \
else \
*recon_right_ptr = recon_right_prev + right_big; \
recon_right_prev = *recon_right_ptr; \
if (full_pel_vector) \
*recon_right_ptr = *recon_right_ptr << 1; \
\
new_vector = recon_down_prev + down_little; \
if (new_vector <= max && new_vector >= min) \
*recon_down_ptr = recon_down_prev + down_little; \
/* just new_vector */ \
else \
*recon_down_ptr = recon_down_prev + down_big; \
recon_down_prev = *recon_down_ptr; \
if (full_pel_vector) \
*recon_down_ptr = *recon_down_ptr << 1; \
}
 
/*
*--------------------------------------------------------------
*
* ComputeForwVector --
*
* Computes forward motion vector by calling ComputeVector
* with appropriate parameters.
*
* Results:
* Reconstructed motion vector placed in recon_right_for_ptr and
* recon_down_for_ptr.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
ComputeForwVector(recon_right_for_ptr, recon_down_for_ptr, the_stream)
int *recon_right_for_ptr;
int *recon_down_for_ptr;
VidStream *the_stream;
{
 
Pict *picture;
Macroblock *mblock;
 
picture = &(the_stream->picture);
mblock = &(the_stream->mblock);
 
ComputeVector(recon_right_for_ptr, recon_down_for_ptr,
mblock->recon_right_for_prev,
mblock->recon_down_for_prev,
(int) picture->forw_f,
picture->full_pel_forw_vector,
mblock->motion_h_forw_code, mblock->motion_v_forw_code,
mblock->motion_h_forw_r, mblock->motion_v_forw_r);
}
 
/*
*--------------------------------------------------------------
*
* ComputeBackVector --
*
* Computes backward motion vector by calling ComputeVector
* with appropriate parameters.
*
* Results:
* Reconstructed motion vector placed in recon_right_back_ptr and
* recon_down_back_ptr.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
ComputeBackVector(recon_right_back_ptr, recon_down_back_ptr, the_stream)
int *recon_right_back_ptr;
int *recon_down_back_ptr;
VidStream *the_stream;
{
Pict *picture;
Macroblock *mblock;
 
picture = &(the_stream->picture);
mblock = &(the_stream->mblock);
 
ComputeVector(recon_right_back_ptr, recon_down_back_ptr,
mblock->recon_right_back_prev,
mblock->recon_down_back_prev,
(int) picture->back_f,
picture->full_pel_back_vector,
mblock->motion_h_back_code, mblock->motion_v_back_code,
mblock->motion_h_back_r, mblock->motion_v_back_r);
 
}
/shark/trunk/ports/mpeg/makefile.pro
0,0 → 1,204
# Step 1:
# Set CC to the C compiler you want to use. On Sun, gcc
# produces faster code. Your mileage may vary.
CC = gcc
#CC = cc
 
# Step 2:
# Set INCLUDEDIR equal to -I followed by include directory
# path for X11 include files.
 
INCLUDEDIR = -I/usr/include -I/usr/include/X11
 
# For Solaris/openwindows
#INCLUDEDIR = -I/usr/include -I/usr/openwin/share/include -I/usr/openwin/include -I/usr/dt/include
 
#
# Step 3:
# Set CFLAGS. Below are def's for some machines. Uncomment the
# appropriate one or make one of your own. If you want the player
# to gather statistics about the video stream, add -DANALYSIS to
# CFLAGS. If you do NOT want to use shared memory, remove
# -DSH_MEM from CFLAGS.
# Use -DSIG_ONE_PARAM if the function passed to signal takes
# one parameter (linux, Solaris)
# Do not use it if it takes none (SunOS, HPUX, Ultrix, OSF1, )
# It works either way, (i think), just gets rid of a warning.
#
# Use -NDEBUG for speed, -DDEBUG for resiliance. On invalid MPEG
# streams a DEBUG compiled mpeg_play will exit gracefully, while
# a NDEBUG one will dump core. But NDEBUG is faster.
 
# Use -DQUIET to have mpeg_play print little by default (useful for
# when it is called by another program like netscape).
 
# Use -DQUALITY if you want the default to play streams that conform
# strictly to the MPEG standard but take longer to display by defualt.
# It is also available as -quality on at runtime
 
# Use -DFLOATDCT to enable using the computationally expensive but
# accurate floating point DCT through the -quality parameter.
 
# Use -DDEFAULT_ORDERED_DITHER to use ORDERED_DITHER instead of
# ORDERED2_DITHER. On some machines (e.g., Intel Pentiums),
# ORDERED_DITHER is much faster than ORDERED2_DITHER.
# Use -DNOCONTROLS to totally disable the X user interface. See
# also HDRS, OBJS, and SRCS below.
# To compile as a library (especially reentrant library, see README.lib)
 
# gcc
CFLAGS = -O3 -DNDEBUG -DNONANSI_INCLUDES -DSH_MEM $(INCLUDEDIR)
 
#Sun Solaris/Openwindows
#CFLAGS = -O3 -DNDEBUG -DBSD -DNONANSI_INCLUDES -DSH_MEM -DSIG_ONE_PARAM $(INCLUDEDIR)
 
#Linux C Flags
#CFLAGS = -O3 -fomit-frame-pointer -ffast-math -finline-functions -m486 -DNDEBUG -DNONANSI_INCLUDES -DSH_MEM -DSIG_ONE_PARAM $(INCLUDEDIR) -DDEFAULT_ORDERED_DITHER
 
#HP C Flags
#CFLAGS = -Ac +O3 -DSH_MEM -DNDEBUG $(INCLUDEDIR)
 
#DEC C Flags (On some Alpha's you need -lbsd also)
#CFLAGS = -O -DSH_MEM -DNDEBUG $(INCLUDEDIR)
 
#RS6000 C Flags -- Most RS6000's do not support shared memory,
# but we include it 'cuz it helps so much if you have it.
# by the way, if you want to give us a version of libXext with them, feel free
#CFLAGS = -O -DSH_MEM $(INCLUDEDIR)
 
#SGI C Flags
#CFLAGS = -O -cckr -DSH_MEM $(INCLUDEDIR)
 
#MIPGS RISC/os 4.5{1,2} C Flags
#CFLAGS = -O -systype sysv -DSH_MEM -DNONANSI_INCLUDES -DMIPS
 
#PTX Flags (Dynix)
#CFLAGS = -O -DNDEBUG $(INCLUDEDIR)
 
#NEWS C Flags
#CFLAGS = -O2 -DSh_MEM -DNO_LRAND48 -DNDEBUG -DNONANSI_INCUDES $(INCLUDEDIR)
 
#
#NeXT C Flags
#CFLAGS = -O -DNO_LRAND48 -DNDEBUG $(INCLUDEDIR)
 
#CETIA Unigraph/X C Flags
#CFLAGS = -O -DNDEBUGS -DBSDCOMPAT -DBSD_LARGE -DCETIA -DX_NOT_STDC_ENV $(INCLUDEDIR)
 
# Convex 3820 (ConvexOS)
#CFLAGS = -O3 -DNDEBUG -DNONANSI_INCLUDES $(INCLUDEDIR) -DNO_LRAND48
 
#
# Step 4:
# Set LIBS equal to path of libXext.a and libX11.a or the loader
# flag equivalents (i.e. -lXext -lX11).
# If you are NOT using shared memory, libXext.a is unecessary.
# NOTE: below the default definition are
# a few definitions for specific architectures.
 
LIBS = -L/usr/lib/X11 -lXext -lX11
 
# LIBS for MIPS RISC/os 4.5{1,2}
#LIBS = -systype sysv -lXext -lX11 -lbsd
 
# LIBS for PTX/Dynix
#LIBS = -lXext -lX11 -lsocket -linet -lnsl -lseq
 
# LIBS for CETIA Unigraph/X
#LIBS = -lX11 -lbsd
 
# LIBS for Solaris/Openwindows (some also need -lucb)
#LIBS = -lXext -lX11 -lsocket -lnsl -lw -ldl -lelf
 
# LIBS for SunOS 4.1.3/Openwindows
#LIBS = -lXext -lX11 -lnsl -ldl
 
 
# Some versions of Linux need this
#LIBS = -L/usr/X11/lib -L/usr/lib/X11 -lXext -lX11
 
#
# Step 5:
# Set DEST to pathname of final destination of player...
#
DEST = ~/bin
 
 
#
# Step 6 (System Dependant Stuff):
# On SOLARIS a user reports:
# Some systems are missing regcmp, to fix
# add -lgen to CFLAGS
# Also, uncomment the special SOLARIS INSTALL and LDFLAGS parameters.
 
#
# That's it! The rest of this shouldn't need any modifications...
#
 
EXTHDRS =
 
HDRS = util.h video.h decoders.h fs2.h dither.h fs4.h ctrlbar.h
 
INSTALL = /etc/install
 
#Solaris INSTALL
#INSTALL = /usr/sbin/install
 
LD = $(CC)
 
LDFLAGS =
 
#Solaris LDFLAGS
#LDFLAGS = -R/usr/openwin/lib:/usr/dt/lib -L/usr/openwin/lib -L/usr/dt/lib
 
 
MAKEFILE = Makefile
 
OBJS = util.o video.o parseblock.o motionvector.o decoders.o \
fs2.o fs2fast.o fs4.o hybrid.o hybriderr.o 2x2.o floatdct.o\
gdith.o gray.o mono.o main.o jrevdct.o 16bit.o util32.o\
ordered.o ordered2.o mb_ordered.o readfile.o ctrlbar.o
 
PRINT = pr
 
PROGRAM = mpeg_play
 
SHELL = /bin/sh
 
SRCS = util.c video.c parseblock.c motionvector.c decoders.c \
main.c gdith.c fs2.c fs2fast.c fs4.c hybrid.c hybriderr.c \
2x2.c gray.c mono.c jrevdct.c 16bit.c util32.c ordered.c \
ordered2.c mb_ordered.c readfile.c floatdct.c ctrlbar.c
 
SYSHDRS =
 
all: $(PROGRAM)
 
$(PROGRAM): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) $(LIBS) -lm -o $(PROGRAM)
strip $(PROGRAM)
 
clean:; rm -f $(OBJS) core
@make depend
 
clobber:; rm -f $(OBJS) $(PROGRAM) core tags
 
depend:; makedepend -- $(CFLAGS) -- $(SRCS)
 
echo:; @echo $(HDRS) $(SRCS)
 
index:; @ctags -wx $(HDRS) $(SRCS)
 
install: $(PROGRAM)
@echo Installing $(PROGRAM) in $(DEST)
@-strip $(PROGRAM)
@if [ $(DEST) != . ]; then \
(rm -f $(DEST)/$(PROGRAM); $(INSTALL) -f $(DEST) $(PROGRAM)); fi
 
print:; @$(PRINT) $(HDRS) $(SRCS)
 
tags: $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
 
update: $(DEST)/$(PROGRAM)
 
# DO NOT DELETE THIS LINE -- make depend depends on it.
/shark/trunk/ports/mpeg/mpeg.h
0,0 → 1,137
/*
* Copyright (c) 1994 by Gregory P. Ward.
* All rights reserved.
*
* This file is part of the MNI front end of the Berkeley MPEG decoder.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
* UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER
* IS ON AN "AS IS" BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : mpeg.h
@INPUT :
@OUTPUT :
@RETURNS :
@DESCRIPTION: Types and function prototypes needed for applications to
use the Berkely MPEG decoding engine via the MNI front
end.
@METHOD :
@GLOBALS : Types defined:
ImageDesc - structure giving height, width, etc.
DitherEnum - the different dither types supported by
the decoding engine
@CALLS :
@CREATED : Greg Ward, 94/6/16.
@MODIFIED : Greg Ward, 94/9/12 (based on John Cristy's fixes): made
more amenable to use with other libraries that also
happen to define TRUE, FALSE, [Bb]oolean, and added
PROTO macro
---------------------------------------------------------------------------- */
 
#ifndef __MPEG_H
#define __MPEG_H
 
#include <stdio.h>
 
/* An attempt at a portable and integrable boolean type... */
 
#if (!defined(TRUE) || !defined(FALSE))
# define TRUE (char) 1
# define FALSE (char) 0
#endif
 
#ifndef BOOLEAN_TYPE_EXISTS
typedef char Boolean;
#define BOOLEAN_TYPE_EXISTS
#endif
 
typedef struct
{
short red, green, blue;
} ColormapEntry;
 
typedef struct
{
int Height; /* in pixels */
int Width;
int Depth; /* image depth (bits) */
int PixelSize; /* bits actually stored per pixel */
int Size; /* bytes for whole image */
int BitmapPad; /* "quantum" of a scanline -- each scanline */
/* starts on an even interval of this */
/* many bits */
int PictureRate; /* required number of frames/sec [?] */
int BitRate; /* ??? */
 
VidStream *vid_stream; /* Pointer to the vid stream itself */
int ColormapSize;
ColormapEntry *Colormap; /* an array of ColormapSize entries */
} ImageDesc;
 
#define DitherEnum int
 
typedef enum
{
MPEG_DITHER,
MPEG_QUIET,
MPEG_LUM_RANGE,
MPEG_CR_RANGE,
MPEG_CB_RANGE,
MPEG_CMAP_INDEX
} MPEGOptionEnum;
 
/* Kludge so we can compile under ANSI or K&R */
 
#undef PROTO
#if defined(__STDC__) || defined(__cplusplus)
#define PROTO(formal_parameters) formal_parameters
#else
#define const
#define PROTO(formal_parameters) ()
#endif
 
/* Function prototypes (all are defined in wrapper.c) */
 
Boolean OpenMPEG PROTO((FILE *MPEGfile, ImageDesc *ImgInfo));
void CloseMPEG PROTO((ImageDesc *ImgInfo));
void RewindMPEG PROTO((FILE *MPEGfile, ImageDesc *Image));
void SetMPEGOption PROTO((ImageDesc *Info, MPEGOptionEnum Option, int value));
Boolean GetMPEGFrame PROTO((ImageDesc *image, char *Frame));
 
#endif /* __MPEG_H */
/shark/trunk/ports/mpeg/mpeg_pla.1
0,0 → 1,240
.\" @(#)mpeg_play.1 2.1a 93/01/27 SMI;
.TH MPEG_PLAY 1 "28 May 1995"
.SH NAME
mpeg_play \- plays mpeg-1 encoded bitstreams using X11
.SH SYNOPSIS
.B mpeg_play
[
.B -nob
] [
.B -nop
] [
.B -display display_name
] [
.B -quality {on|off}
] [
.B -dither dither_option
] [
.B -loop
] [
.B -eachstat
] [
.B -seek offset
] [
.B -start num
] [
.B -end num
] [
.B -gamma gamma_correction_value
] [
.B -framerate num
] [
.B -no_display
] [
.B -controls {on|off|none}
] [
.B -shmem_off
] [
.B -l_range num
] [
.B -cr_range num
] [
.B -cb_range num
] [
.B -quiet
]
.B file_name
.SH DESCRIPTION
.B mpeg_play
decodes and displays mpeg-1 encoded bitstreams on systems running X11.
The player will create a new window, display the bitstream, and exit.
Any error messages or notices are sent to stderr.
.SH OPTIONS
.HP
.B -nob
: causes the player to ignore and not display any B frames.
.HP
.B -nop
: causes the player to ignore and not display any P and B frames.
.HP
.B -display display_name
: causes the player to open the window on the display \fIdisplay_name\fP.
.HP
.B -quality {on|off}
: forces player to choose output quality over speed when on, and vice versa
when off. When quality is on, the player uses a computationally expensive
IDCT and also improves playback through improved handling of half pixel
motion vectors. The default can be set to on if you compile mpeg_play
with the flag -DQUALITY.
.HP
.B -dither dither_option
: selects from a variety of dither options. The possible values are:
.RS
.HP
ordered - ordered dither.
.HP
ordered2 - a faster ordered dither. This is the default.
.HP
mbordered - ordered dithering at the macroblock level. Although there
is a noticeable decrease in dither quality, this is the fastest dither
available.
.HP
fs4 - Floyd-Steinberg dithering with 4 error values propagated.
.HP
fs2 - Floyd-Steinberg dithering with 2 error values propagated.
.HP
fs2fast - Fast Floyd-Steinberg dithering with 2 error values propagated.
.HP
hybrid - Hybrid dithering, a combination of ordered dithering for the luminance
channel and Floyd-Steinberg 2 error dithering for the chrominance channels. Errors
are NOT propagated properly and are dropped all together every two pixels in either
direction.
.HP
hybrid2 - Hybrid dithering as above, but with error propagation among pixels.
.HP
2x2 - A dithering technique using a 2x2 pixel area for each pixel. The image displayed
is 4 times larger than the original image encoded. Random error terms are added to
each pixel to break up contours and gradients.
.HP
gray - Grayscale dithering. The image is dithered into 128 grayscales. Chrominance
information is thrown away.
.HP
gray256 - Grayscale dithering. The image is dithered into 256 grayscales
(requires private colormap). Chrominance information is thrown away.
.HP
color - Full color display (only available on 16/24 bit color displays).
.HP
color2 - Full color display with increased size (only available on 16/24
bit color displays).
.HP
none - no dithering is done, no image is displayed. Used to time decoding process.
.HP
mono - Floyd-Steinberg dithering for monochrome displays.
.HP
threshold - Floyd-simple dithering for monochrome displays.
.HP
ppm - Write a PPM file for each frame.
.RE
.HP
.B -loop
: makes the player loop back to the beginning after reaching the end.
.HP
.B -owncm
: makes the player use a private colormap for the window.
.HP
.B -step
: requires the user to press return for each new frame.
.HP
.B -seek offset
: before playing the movie, seek to the given offset in the file (useful
for large movies). In this case -end is redefined to give the number of
frames to play, and -start has no meaning. The offset should point to a
Sequence or (closed) GOP header, but data will be discarded until one is
found.
The initial sequence header will be parsed before the seek. The skipped
sections must not change the quantization matrices or the results are
undefined.
.HP
.B -start num
: Waits to start display until this frame number (previous frames are
parsed).
.HP
.B -end num
: ends display at this frame number (except when -seek is used).
.HP
.B -gamma gamma_correction_param
: specifies the amount of gamma correction. Default is 1.0. Use higher
values if movie looks dark and hard to see.
.HP
.B -framerate num
: sets the framerate of the playback to num frames per second. A value of
0 indicates that the stream should be played as fast as possible. The
default is to play at the rate specified in the stream (if possible). Note
this is merely a framerate limiter, it will not discard frames to meet the
rate.
.HP
.B -controls {on|off|none}
: determines the initial interactive X user interface control bar
state (if available). The value on (default) opens the control bar at
initialization and enters pause mode after displaying the first frame.
The value off leaves the control bar initially hidden and begins
playback without pausing (similar to the old behavior). The control bar
can be toggled on and off
at any time by clicking in the video display window, unless the
-controls none option is specified, in which case the control bar is
unavailable and playback functions as though the player were built
without interactive controls (exactly the old behavior).
.HP
.B -quiet
: suppresses printing of frame numbers, timing information, and most error
messages.
.HP
.B -eachstat
: causes statistics to be displayed after each frame. Only valid when
compiled with -DANALYSIS.
.HP
.B -shmem_off
: turns shared memory off.
.HP
.B -l_range num_colors
: sets the number of colors assigned to the luminance component when
dithering the image. The product of l_range, cr_range and cb_range
should be less than the number of colors on the display.
.HP
.B -cr_range num_colors
: sets the number of colors assigned to the red component of the
chrominance range when dithering the image. The product of l_range,
cr_range and cb_range should be less than the number of colors on the
display.
.HP
.B -cb_range num_colors
: sets the number of colors assigned to the blue component of the
chrominance range when dithering the image. The product of l_range,
cr_range and cb_range should be less than the number of colors on the
display.
.HP
.B -no_display
: dithers, but does not display, usually used for testing and timing
purposes.
.SH NOTES
The player expects video streams only. It can handle multiplexed MPEG streams
(video+audio streams) by discarding the audio.
.LP
Some streams do not end with the proper sequence end code and will probably generate
an "Improper sequence end code." error when done playing.
.LP
This player can play XING data files. Be aware that XING makes no use of temporal
redundancy or motion vector information. In other words, they do not use any P or
B frames in their streams. Instead, XING data is simply a sequence of I frames. Since
I frames take significantly longer to decode, performance of the player using XING
data is not representative of the player's ability.
.LP
The player does not play MPEG-1 D-frame streams, but they are a rarity.
.LP
If the player is compiled without the controlbar, then it can play
multiple streams in different windows.
.SH VERSION
This is version 2.1a, containing some new features since 2.0, and several bug
fixes. It is a major change since version 1.0.
.SH BUGS
The only known bug is that multiple mpeg_plays cannot seem to be run
simultaneously on a multiprocessor SPARC 20 or a SparcCenter 2000E using
shared memory
(in particular: "On a bi-processor Sparc 20/20 sparc-processor 2000E running
Solaris 2.3 or 2.4, it is not possible to run two concurrent 'mpeg_play -loop'
on the same bitstream. One of the mpeg_play dies when it loops." This
may be a problem with the X shared memory library and not our code.)
.SH AUTHORS
.HP
Ketan Patel - University of California, Berkeley, kpatel@cs.berkeley.edu
.HP
Brian Smith - University of California, Berkeley, bsmith@cs.berkeley.edu
.HP
Henry Chi-To Ma - University of California, Berkeley, cma@cs.berkeley.edu
.HP
Kim Man Liu - University of California, Berkeley, kliu@cs.berkeley.edu
.HP
Steve Smoot - University of California, Berkeley, smoot@cs.berkeley.edu
.HP
Eugene Hung - University of California, Berkeley, eyhung@cs.berkeley.edu
 
/shark/trunk/ports/mpeg/platform
0,0 → 1,15
This file contains notes on compiling the code for different platforms.
 
The Makefile contains comments to support many platforms. You should
modify it to set the parameters for your platform. Some common problems
people run into are discussed below.
 
On RS6000s libXext does not seem to support shared memory, remove -DSH_MEM
 
On an SGI IRIX 4, make sure to set the environment variable SGI_IRIX4
to 1, and remove none of the commented out CFLAGS.
 
On VMS: the standard way for building images is to use mms. if you compile
without mms, the following variables must be defined(at least for dec c
4.0, i did not try any other compiler):
NO_LRAND48 NO_RANDOM SIG_ONE_PARAM NO_GETTIMEOFDAY
/shark/trunk/ports/mpeg/ordered2.c
0,0 → 1,337
/*
* ordered2.c --
*
* This file contains C code to implement a faster ordered dither
* than the one found in ordered.c. This dither is the default
* if no dither is specified.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "proto.h"
#include "dither.h"
 
#define DITH_SIZE 16
 
 
/* Structures used to implement hybrid ordered dither/floyd-steinberg
dither algorithm.
*/
 
static unsigned char ***ditherPtr[DITH_SIZE];
 
/*
*--------------------------------------------------------------
*
* InitOrderedDither--
*
* Structures intialized for ordered dithering.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
InitOrdered2Dither()
{
unsigned char ****pos_2_cb;
unsigned char ***cb_2_cr;
unsigned char **cr_2_l;
int cb_val, cb_rval, cr_val, cr_rval, l_val, l_rval;
int i, j, pos;
int err_range, threshval;
 
pos_2_cb = (unsigned char ****) malloc (DITH_SIZE*sizeof(unsigned char ***));
cb_2_cr = (unsigned char ***) malloc(CB_RANGE*sizeof(unsigned char **));
cr_2_l = (unsigned char **) malloc(CR_RANGE*sizeof(unsigned char *));
 
for (pos=0; pos<DITH_SIZE; pos++) {
pos_2_cb[pos] = (unsigned char ***) malloc(256*(sizeof(unsigned char **)));
 
for (j=0; j<CB_RANGE; j++) {
cb_2_cr[j] = (unsigned char **) malloc(256*(sizeof(unsigned char *)));
}
 
for (cb_val=0; cb_val<cb_values[0]; cb_val++) {
(pos_2_cb[pos])[cb_val] = cb_2_cr[0];
}
 
for (cb_rval=0; cb_rval<(CB_RANGE-1); cb_rval++) {
err_range = cb_values[cb_rval+1] - cb_values[cb_rval];
threshval = ((pos*err_range)/DITH_SIZE)+cb_values[cb_rval];
 
for (cb_val=cb_values[cb_rval]; cb_val<cb_values[cb_rval+1]; cb_val++) {
if (cb_val>threshval) (pos_2_cb[pos])[cb_val] = cb_2_cr[cb_rval+1];
else (pos_2_cb[pos])[cb_val] = cb_2_cr[cb_rval];
}
}
 
for (cb_val=cb_values[CB_RANGE-1]; cb_val<256; cb_val++) {
(pos_2_cb[pos])[cb_val] = cb_2_cr[CB_RANGE-1];
}
 
for (cb_rval=0; cb_rval<CB_RANGE; cb_rval++) {
for (j=0; j<CR_RANGE; j++) {
cr_2_l[j] = (unsigned char *) malloc(256*(sizeof(unsigned char)));
}
 
for (cr_val=0; cr_val < cr_values[0]; cr_val++) {
(cb_2_cr[cb_rval])[cr_val] = cr_2_l[0];
}
 
for (cr_rval=0; cr_rval<(CR_RANGE-1); cr_rval++) {
err_range = cr_values[cr_rval+1] - cr_values[cr_rval];
threshval = ((pos*err_range)/DITH_SIZE)+cr_values[cr_rval];
for (cr_val=cr_values[cr_rval]; cr_val<cr_values[cr_rval+1]; cr_val++) {
if (cr_val>threshval) (cb_2_cr[cb_rval])[cr_val] = cr_2_l[cr_rval+1];
else (cb_2_cr[cb_rval])[cr_val] = cr_2_l[cr_rval];
}
}
for (cr_val=cr_values[CR_RANGE-1]; cr_val<256; cr_val++) {
(cb_2_cr[cb_rval])[cr_val] = cr_2_l[CR_RANGE-1];
}
for (cr_rval=0; cr_rval<CR_RANGE; cr_rval++) {
for (l_val = 0; l_val < lum_values[0]; l_val++) {
(cr_2_l[cr_rval])[l_val] = pixel[cb_rval+(cr_rval*CB_RANGE)+
(0*CR_RANGE*CB_RANGE)];
}
 
for (l_rval=0; l_rval<(LUM_RANGE-1); l_rval++) {
err_range = lum_values[l_rval+1] - lum_values[l_rval];
threshval = ((pos*err_range) /DITH_SIZE) + lum_values[l_rval];
 
for (l_val = lum_values[l_rval]; l_val < lum_values[l_rval+1]; l_val++) {
if (l_val>threshval) (cr_2_l[cr_rval])[l_val] =
pixel[cb_rval+(cr_rval*CB_RANGE)+((l_rval+1)*CR_RANGE*CB_RANGE)];
else (cr_2_l[cr_rval])[l_val] =
pixel[cb_rval+(cr_rval*CB_RANGE)+(l_rval*CR_RANGE*CB_RANGE)];
}
}
 
for (l_val = lum_values[LUM_RANGE-1]; l_val < 256; l_val++) {
(cr_2_l[cr_rval])[l_val] =
pixel[cb_rval+(cr_rval*CB_RANGE)+((LUM_RANGE-1)*CR_RANGE*CB_RANGE)];
}
}
}
}
 
for (i=0; i<DITH_SIZE; i++) {
ditherPtr[i] = pos_2_cb[i];
}
}
 
/*
*--------------------------------------------------------------
*
* Ordered2DitherImage --
*
* Dithers an image using an ordered dither.
* Assumptions made:
* 1) The color space is allocated y:cr:cb = 8:4:4
* 2) The spatial resolution of y:cr:cb is 4:1:1
* The channels are dithered based on the standard
* ordered dither pattern for a 4x4 area.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
Ordered2DitherImage (lum, cr, cb, out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int w, h;
{
unsigned char *l, *r, *b, *o1, *o2;
unsigned char *l2;
unsigned char L, R, B;
int i, j;
unsigned char ***dp0 = ditherPtr[0];
unsigned char ***dp2 = ditherPtr[2];
unsigned char ***dp4 = ditherPtr[4];
unsigned char ***dp6 = ditherPtr[6];
unsigned char ***dp8 = ditherPtr[8];
unsigned char ***dp10 = ditherPtr[10];
unsigned char ***dp12 = ditherPtr[12];
unsigned char ***dp14 = ditherPtr[14];
unsigned char ***dp1 = ditherPtr[1];
unsigned char ***dp3 = ditherPtr[3];
unsigned char ***dp5 = ditherPtr[5];
unsigned char ***dp7 = ditherPtr[7];
unsigned char ***dp9 = ditherPtr[9];
unsigned char ***dp11 = ditherPtr[11];
unsigned char ***dp13 = ditherPtr[13];
unsigned char ***dp15 = ditherPtr[15];
 
l = lum;
l2 = lum+w;
r = cr;
b = cb;
o1 = out;
o2 = out+w;
 
for (i=0; i<h; i+=4) {
 
for (j=0; j<w; j+=8) {
 
R = r[0]; B = b[0];
 
L = l[0];
o1[0] = ((dp0[B])[R])[L];
L = l[1];
o1[1] = ((dp8[B])[R])[L];
L = l2[0];
o2[0] = ((dp12[B])[R])[L];
L = l2[1];
o2[1] = ((dp4[B])[R])[L];
 
R = r[1]; B = b[1];
 
L = l[2];
o1[2] = ((dp2[B])[R])[L];
L = l[3];
o1[3] = ((dp10[B])[R])[L];
L = l2[2];
o2[2] = ((dp14[B])[R])[L];
L = l2[3];
o2[3] = ((dp6[B])[R])[L];
 
R = r[2]; B = b[2];
 
L = l[4];
o1[4] = ((dp0[B])[R])[L];
L = l[5];
o1[5] = ((dp8[B])[R])[L];
L = l2[4];
o2[4] = ((dp12[B])[R])[L];
L = l2[5];
o2[5] = ((dp4[B])[R])[L];
 
R = r[3]; B = b[3];
 
L = l[6];
o1[6] = ((dp2[B])[R])[L];
L = l[7];
o1[7] = ((dp10[B])[R])[L];
L = l2[6];
o2[6] = ((dp14[B])[R])[L];
L = l2[7];
o2[7] = ((dp6[B])[R])[L];
 
l += 8;
l2 += 8;
r += 4;
b += 4;
o1 += 8;
o2 += 8;
}
 
l += w;
l2 += w;
o1 += w;
o2 += w;
 
for (j=0; j<w; j+=8) {
 
R = r[0]; B = b[0];
 
L = l[0];
o1[0] = ((dp3[B])[R])[L];
L = l[1];
o1[1] = ((dp11[B])[R])[L];
L = l2[0];
o2[0] = ((dp15[B])[R])[L];
L = l2[1];
o2[1] = ((dp7[B])[R])[L];
 
R = r[1]; B = b[1];
 
L = l[2];
o1[2] = ((dp1[B])[R])[L];
L = l[3];
o1[3] = ((dp9[B])[R])[L];
L = l2[2];
o2[2] = ((dp13[B])[R])[L];
L = l2[3];
o2[3] = ((dp5[B])[R])[L];
 
R = r[2]; B = b[2];
 
L = l[4];
o1[4] = ((dp3[B])[R])[L];
L = l[5];
o1[5] = ((dp11[B])[R])[L];
L = l2[4];
o2[4] = ((dp15[B])[R])[L];
L = l2[5];
o2[5] = ((dp7[B])[R])[L];
 
R = r[3]; B = b[3];
 
L = l[6];
o1[6] = ((dp1[B])[R])[L];
L = l[7];
o1[7] = ((dp9[B])[R])[L];
L = l2[6];
o2[6] = ((dp13[B])[R])[L];
L = l2[7];
o2[7] = ((dp5[B])[R])[L];
 
l += 8;
l2 += 8;
r += 4;
b += 4;
o1 += 8;
o2 += 8;
}
 
l += w;
l2 += w;
o1 += w;
o2 += w;
}
}
 
 
/shark/trunk/ports/mpeg/check-sh.c
0,0 → 1,40
/*
code "borrowed" from JPEG-5 config code
*/
 
#include <stdio.h>
 
int is_shifting_signed (arg)
long arg;
/* See whether right-shift on a long is signed or not. */
{
long res = arg >> 4;
 
if (res == -0x7F7E80CL) { /* expected result for signed shift */
return 1; /* right shift is signed */
}
 
/* see if unsigned-shift hack will fix it. */
/* we can't just test exact value since it depends on width of long... */
res |= (~0L) << (32-4);
 
if (res == -0x7F7E80CL) { /* expected result now? */
return 0; /* right shift is unsigned */
}
 
fprintf(stderr, "Right shift isn't acting as I expect it to.\n");
fprintf(stderr, "I fear the DCT software will not work at all.\n\n");
exit(1);
}
 
main()
{
 
if (is_shifting_signed(-0x7F7E80B1L)) {
printf("do not define RIGHT_SHIFT_IS_UNSIGNED\n");
}
else {
printf("define RIGHT_SHIFT_IS_UNSIGNED\n");
}
 
}
/shark/trunk/ports/mpeg/16bit.c
0,0 → 1,885
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Copyright (c) 1995 Erik Corry
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
* SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
* THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "dither.h"
#include "proto.h"
#include <math.h>
 
/*
Changes to make the code reentrant:
None
Additional changes:
do not define INTERPOLATE, add #ifdef INTERPOLATE
-lsh@cs.brown.edu (Loring Holden)
*/
/* #define INTERPOLATE */
 
/*
* Erik Corry's multi-byte dither routines.
*
* The basic idea is that the Init generates all the necessary tables.
* The tables incorporate the information about the layout of pixels
* in the XImage, so that it should be able to cope with 15-bit, 16-bit
* 24-bit (non-packed) and 32-bit (10-11 bits per color!) screens.
* At present it cannot cope with 24-bit packed mode, since this involves
* getting down to byte level again. It is assumed that the bits for each
* color are contiguous in the longword.
*
* Writing to memory is done in shorts or ints. (Unfortunately, short is not
* very fast on Alpha, so there is room for improvement here). There is no
* dither time check for overflow - instead the tables have slack at
* each end. This is likely to be faster than an 'if' test as many modern
* architectures are really bad at ifs. Potentially, each '&&' causes a
* pipeline flush!
*
* There is no shifting and fixed point arithmetic, as I really doubt you
* can see the difference, and it costs. This may be just my bias, since I
* heard that Intel is really bad at shifting.
*/
 
/*
* How many 1 bits are there in the longword.
* Low performance, do not call often.
*/
static int
number_of_bits_set(a)
unsigned long a;
{
if(!a) return 0;
if(a & 1) return 1 + number_of_bits_set(a >> 1);
return(number_of_bits_set(a >> 1));
}
 
/*
* Shift the 0s in the least significant end out of the longword.
* Low performance, do not call often.
*/
static unsigned long
shifted_down(a)
unsigned long a;
{
if(!a) return 0;
if(a & 1) return a;
return a >> 1;
}
 
/*
* How many 0 bits are there at most significant end of longword.
* Low performance, do not call often.
*/
static int
free_bits_at_top(a)
unsigned long a;
{
/* assume char is 8 bits */
if(!a) return sizeof(unsigned long) * 8;
/* assume twos complement */
if(((long)a) < 0l) return 0;
return 1 + free_bits_at_top ( a << 1);
}
 
/*
* How many 0 bits are there at least significant end of longword.
* Low performance, do not call often.
*/
static int
free_bits_at_bottom(a)
unsigned long a;
{
/* assume char is 8 bits */
if(!a) return sizeof(unsigned long) * 8;
if(((long)a) & 1l) return 0;
return 1 + free_bits_at_bottom ( a >> 1);
}
 
static int *L_tab=NULL, *Cr_r_tab=NULL, *Cr_g_tab=NULL, *Cb_g_tab=NULL,
*Cb_b_tab=NULL;
 
/*
* We define tables that convert a color value between -256 and 512
* into the R, G and B parts of the pixel. The normal range is 0-255.
*/
 
static long *r_2_pix=NULL;
static long *g_2_pix=NULL;
static long *b_2_pix=NULL;
static long *r_2_pix_alloc=NULL;
static long *g_2_pix_alloc=NULL;
static long *b_2_pix_alloc=NULL;
 
/*
*--------------------------------------------------------------
*
* InitColor16Dither --
*
* To get rid of the multiply and other conversions in color
* dither, we use a lookup table.
*
* Results:
* None.
*
* Side effects:
* The lookup tables are initialized.
*
*--------------------------------------------------------------
*/
 
void
InitColorDither(thirty2)
int thirty2;
{
/*
* misuse of the wpixel array for the pixel masks. Note that this
* implies that the window is created before this routine is called
*/
unsigned long red_mask = wpixel[0];
unsigned long green_mask = wpixel[1];
unsigned long blue_mask = wpixel[2];
 
int L, CR, CB, i;
 
if (L_tab==NULL)
L_tab = (int *)malloc(256*sizeof(int));
if (Cr_r_tab==NULL)
Cr_r_tab = (int *)malloc(256*sizeof(int));
if (Cr_g_tab==NULL)
Cr_g_tab = (int *)malloc(256*sizeof(int));
if (Cb_g_tab==NULL)
Cb_g_tab = (int *)malloc(256*sizeof(int));
if (Cb_b_tab==NULL)
Cb_b_tab = (int *)malloc(256*sizeof(int));
 
if (r_2_pix_alloc==NULL)
r_2_pix_alloc = (long *)malloc(768*sizeof(long));
if (g_2_pix_alloc==NULL)
g_2_pix_alloc = (long *)malloc(768*sizeof(long));
if (b_2_pix_alloc==NULL)
b_2_pix_alloc = (long *)malloc(768*sizeof(long));
 
if (L_tab == NULL ||
Cr_r_tab == NULL ||
Cr_g_tab == NULL ||
Cb_g_tab == NULL ||
Cb_b_tab == NULL ||
r_2_pix_alloc == NULL ||
g_2_pix_alloc == NULL ||
b_2_pix_alloc == NULL) {
fprintf(stderr, "Could not get enough memory in InitColorDither\n");
exit(1);
}
 
for (i=0; i<256; i++) {
L_tab[i] = i;
if (gammaCorrectFlag) {
L_tab[i] = GAMMA_CORRECTION(i);
}
CB = CR = i;
 
if (chromaCorrectFlag) {
CB -= 128;
CB = CHROMA_CORRECTION128(CB);
CR -= 128;
CR = CHROMA_CORRECTION128(CR);
} else {
CB -= 128; CR -= 128;
}
/* was
Cr_r_tab[i] = 1.596 * CR;
Cr_g_tab[i] = -0.813 * CR;
Cb_g_tab[i] = -0.391 * CB;
Cb_b_tab[i] = 2.018 * CB;
but they were just messed up.
Then was (_Video Deymstified_):
Cr_r_tab[i] = 1.366 * CR;
Cr_g_tab[i] = -0.700 * CR;
Cb_g_tab[i] = -0.334 * CB;
Cb_b_tab[i] = 1.732 * CB;
but really should be:
(from ITU-R BT.470-2 System B, G and SMPTE 170M )
*/
Cr_r_tab[i] = (0.419/0.299) * CR;
Cr_g_tab[i] = -(0.299/0.419) * CR;
Cb_g_tab[i] = -(0.114/0.331) * CB;
Cb_b_tab[i] = (0.587/0.331) * CB;
 
/*
though you could argue for:
SMPTE 240M
Cr_r_tab[i] = (0.445/0.212) * CR;
Cr_g_tab[i] = -(0.212/0.445) * CR;
Cb_g_tab[i] = -(0.087/0.384) * CB;
Cb_b_tab[i] = (0.701/0.384) * CB;
FCC
Cr_r_tab[i] = (0.421/0.30) * CR;
Cr_g_tab[i] = -(0.30/0.421) * CR;
Cb_g_tab[i] = -(0.11/0.331) * CB;
Cb_b_tab[i] = (0.59/0.331) * CB;
ITU-R BT.709
Cr_r_tab[i] = (0.454/0.2125) * CR;
Cr_g_tab[i] = -(0.2125/0.454) * CR;
Cb_g_tab[i] = -(0.0721/0.386) * CB;
Cb_b_tab[i] = (0.7154/0.386) * CB;
*/
}
 
/*
* Set up entries 0-255 in rgb-to-pixel value tables.
*/
for (i = 0; i < 256; i++) {
r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(red_mask));
r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(red_mask);
g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(green_mask));
g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(green_mask);
b_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(blue_mask));
b_2_pix_alloc[i + 256] <<= free_bits_at_bottom(blue_mask);
/*
* If we have 16-bit output depth, then we double the value
* in the top word. This means that we can write out both
* pixels in the pixel doubling mode with one op. It is
* harmless in the normal case as storing a 32-bit value
* through a short pointer will lose the top bits anyway.
* A similar optimisation for Alpha for 64 bit has been
* prepared for, but is not yet implemented.
*/
if(!thirty2) {
 
r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16;
 
}
#ifdef SIXTYFOUR_BIT
if(thirty2) {
 
r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 32;
g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 32;
b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 32;
 
}
#endif
}
 
/*
* Spread out the values we have to the rest of the array so that
* we do not need to check for overflow.
*/
for (i = 0; i < 256; i++) {
r_2_pix_alloc[i] = r_2_pix_alloc[256];
r_2_pix_alloc[i+ 512] = r_2_pix_alloc[511];
g_2_pix_alloc[i] = g_2_pix_alloc[256];
g_2_pix_alloc[i+ 512] = g_2_pix_alloc[511];
b_2_pix_alloc[i] = b_2_pix_alloc[256];
b_2_pix_alloc[i+ 512] = b_2_pix_alloc[511];
}
 
r_2_pix = r_2_pix_alloc + 256;
g_2_pix = g_2_pix_alloc + 256;
b_2_pix = b_2_pix_alloc + 256;
 
}
 
/*
*--------------------------------------------------------------
*
* Color16DitherImage --
*
* Converts image into 16 bit color.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
Color16DitherImage(lum, cr, cb, out, rows, cols)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int cols, rows;
 
{
int L, CR, CB;
unsigned short *row1, *row2;
unsigned char *lum2;
int x, y;
unsigned int r, b, g;
int cr_r;
int cr_g;
int cb_g;
int cb_b;
int cols_2 = cols/2;
 
row1 = (unsigned short *)out;
row2 = row1 + cols_2 + cols_2;
lum2 = lum + cols_2 + cols_2;
 
for (y=0; y<rows; y+=2) {
for (x=0; x<cols_2; x++) {
int R, G, B;
 
CR = *cr++;
CB = *cb++;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
 
L = L_tab[(int) *lum++];
 
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
*row1++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
 
#ifdef INTERPOLATE
if(x != cols_2 - 1) {
CR = (CR + *cr) >> 1;
CB = (CB + *cb) >> 1;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
}
#endif
 
L = L_tab[(int) *lum++];
 
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
*row1++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
 
/*
* Now, do second row.
*/
#ifdef INTERPOLATE
if(y != rows - 2) {
CR = (CR + *(cr + cols_2 - 1)) >> 1;
CB = (CB + *(cb + cols_2 - 1)) >> 1;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
}
#endif
 
L = L_tab[(int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
*row2++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
 
L = L_tab[(int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
*row2++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
}
/*
* These values are at the start of the next line, (due
* to the ++'s above),but they need to be at the start
* of the line after that.
*/
lum += cols_2 + cols_2;
lum2 += cols_2 + cols_2;
row1 += cols_2 + cols_2;
row2 += cols_2 + cols_2;
}
}
 
 
 
/*
*--------------------------------------------------------------
*
* Color32DitherImage --
*
* Converts image into 32 bit color (or 24-bit non-packed).
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
/*
* This is a copysoft version of the function above with ints instead
* of shorts to cause a 4-byte pixel size
*/
 
void
Color32DitherImage(lum, cr, cb, out, rows, cols)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int cols, rows;
 
{
int L, CR, CB;
unsigned int *row1, *row2;
unsigned char *lum2;
int x, y;
unsigned int r, b, g;
int cr_r;
int cr_g;
int cb_g;
int cb_b;
int cols_2 = cols / 2;
 
row1 = (unsigned int *)out;
row2 = row1 + cols_2 + cols_2;
lum2 = lum + cols_2 + cols_2;
for (y=0; y<rows; y+=2) {
for (x=0; x<cols_2; x++) {
int R, G, B;
 
CR = *cr++;
CB = *cb++;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
 
L = L_tab[(int) *lum++];
 
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
*row1++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
 
#ifdef INTERPOLATE
if(x != cols_2 - 1) {
CR = (CR + *cr) >> 1;
CB = (CB + *cb) >> 1;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
}
#endif
 
L = L_tab[(int) *lum++];
 
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
*row1++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
 
/*
* Now, do second row.
*/
 
#ifdef INTERPOLATE
if(y != rows - 2) {
CR = (CR + *(cr + cols_2 - 1)) >> 1;
CB = (CB + *(cb + cols_2 - 1)) >> 1;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
}
#endif
 
L = L_tab [(int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
*row2++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
 
L = L_tab [(int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
*row2++ = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
}
lum += cols_2 + cols_2;
lum2 += cols_2 + cols_2;
row1 += cols_2 + cols_2;
row2 += cols_2 + cols_2;
}
}
 
/*
* Erik Corry's pixel doubling routines for 15/16/24/32 bit screens.
*/
 
 
/*
*--------------------------------------------------------------
*
* Twox2Color16DitherImage --
*
* Converts image into 16 bit color at double size.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
/*
* In this function I make use of a nasty trick. The tables have the lower
* 16 bits replicated in the upper 16. This means I can write ints and get
* the horisontal doubling for free (almost).
*/
 
void
Twox2Color16DitherImage(lum, cr, cb, out, rows, cols)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int cols, rows;
 
{
int L, CR, CB;
unsigned int *row1 = (unsigned int *)out;
unsigned int *row2 = row1 + cols;
unsigned int *row3 = row2 + cols;
unsigned int *row4 = row3 + cols;
unsigned char *lum2;
int x, y;
unsigned int r, b, g;
int cr_r;
int cr_g;
int cb_g;
int cb_b;
int cols_2 = cols/2;
 
lum2 = lum + cols_2 + cols_2;
for (y=0; y<rows; y+=2) {
for (x=0; x<cols_2; x++) {
int R, G, B;
int t;
 
CR = *cr++;
CB = *cb++;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
 
L = L_tab[(int) *lum++];
 
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
row1[0] = t;
row1++;
row2[0] = t;
row2++;
 
#ifdef INTERPOLATE
if(x != cols_2 - 1) {
CR = (CR + *cr) >> 1;
CB = (CB + *cb) >> 1;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
}
#endif
L = L_tab[(int) *lum++];
 
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
row1[0] = t;
row1++;
row2[0] = t;
row2++;
 
/*
* Now, do second row.
*/
#ifdef INTERPOLATE
if(y != rows - 2) {
CR = (CR + *(cr + cols_2 - 1)) >> 1;
CB = (CB + *(cb + cols_2 - 1)) >> 1;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
}
#endif
L = L_tab[(int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
row3[0] = t;
row3++;
row4[0] = t;
row4++;
 
L = L_tab[(int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
row3[0] = t;
row3++;
row4[0] = t;
row4++;
}
lum += cols_2 + cols_2;
lum2 += cols_2 + cols_2;
row1 += 6 * cols_2;
row3 += 6 * cols_2;
row2 += 6 * cols_2;
row4 += 6 * cols_2;
}
}
 
 
 
/*
*--------------------------------------------------------------
*
* Twox2Color32 --
*
* Converts image into 24/32 bit color.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
#ifdef SIXTYFOUR_BIT
#define ONE_TWO 1
#else
#define ONE_TWO 2
#endif
 
void
Twox2Color32DitherImage(lum, cr, cb, out, rows, cols)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int cols, rows;
 
{
int L, CR, CB;
unsigned long *row1 = (unsigned long *)out;
unsigned long *row2 = row1 + cols * ONE_TWO;
unsigned long *row3 = row2 + cols * ONE_TWO;
unsigned long *row4 = row3 + cols * ONE_TWO;
unsigned char *lum2;
int x, y;
unsigned int r, b, g;
int cr_r;
int cr_g;
int cb_g;
int cb_b;
int cols_2 = cols/2;
 
lum2 = lum + cols_2 + cols_2;
for (y=0; y<rows; y+=2) {
for (x=0; x<cols_2; x++) {
int R, G, B;
long t;
 
CR = *cr++;
CB = *cb++;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
 
L = L_tab[ (int) *lum++];
 
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
row1[0] = t;
row2[0] = t;
#ifndef SIXTYFOUR_BIT
row1[1] = t;
row2[1] = t;
#endif
row1 += ONE_TWO;
row2 += ONE_TWO;
 
/* INTERPOLATE is now standard */
#ifdef INTERPOLATE
if(x != cols_2 - 1) {
CR = (CR + *cr) >> 1;
CB = (CB + *cb) >> 1;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
}
#endif
/* end INTERPOLATE */
L = L_tab[ (int) *lum++];
 
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
row1[0] = t;
row2[0] = t;
#ifndef SIXTYFOUR_BIT
row1[1] = t;
row2[1] = t;
#endif
row1 += ONE_TWO;
row2 += ONE_TWO;
 
/*
* Now, do second row.
*/
/* INTERPOLATE is now standard */
#ifdef INTERPOLATE
if(y != rows - 2) {
CR = (unsigned int) (CR + *(cr + cols_2 - 1)) >> 1;
CB = (unsigned int) (CB + *(cb + cols_2 - 1)) >> 1;
cr_r = Cr_r_tab[CR];
cr_g = Cr_g_tab[CR];
cb_g = Cb_g_tab[CB];
cb_b = Cb_b_tab[CB];
}
#endif
/* endif */
L = L_tab[ (int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
row3[0] = t;
row4[0] = t;
#ifndef SIXTYFOUR_BIT
row3[1] = t;
row4[1] = t;
#endif
row3 += ONE_TWO;
row4 += ONE_TWO;
 
L = L_tab[(int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
 
t = (r_2_pix[R] | g_2_pix[G] | b_2_pix[B]);
row3[0] = t;
row4[0] = t;
#ifndef SIXTYFOUR_BIT
row3[1] = t;
row4[1] = t;
#endif
row3 += ONE_TWO;
row4 += ONE_TWO;
}
lum += cols_2 + cols_2;
lum2 += cols_2 + cols_2;
 
row1 += ONE_TWO * 6 *cols_2;
row3 += ONE_TWO * 6 *cols_2;
row2 += ONE_TWO * 6 *cols_2;
row4 += ONE_TWO * 6 *cols_2;
}
}
 
/shark/trunk/ports/mpeg/readme.jpe
0,0 → 1,389
jrevdct.c comes from the IJG libjpeg release,
The "official" archive site for this software is ftp.uu.net (Internet
address 192.48.96.9). The most recent released version can always be
found there in directory graphics/jpeg.
This is the README from that software.
 
The Independent JPEG Group's JPEG software
==========================================
 
README for release 6a of 7-Feb-96
=================================
 
This distribution contains the sixth public release of the Independent JPEG
Group's free JPEG software. You are welcome to redistribute this software and
to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
 
Serious users of this software (particularly those incorporating it into
larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
our electronic mailing list. Mailing list members are notified of updates
and have a chance to participate in technical discussions, etc.
 
This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, Jim
Boucher, Lee Crocker, Julian Minguillon, George Phillips, Davide Rossi,
Ge' Weijers, and other members of the Independent JPEG Group.
 
IJG is not affiliated with the official ISO JPEG standards committee.
 
 
DOCUMENTATION ROADMAP
=====================
 
This file contains the following sections:
 
OVERVIEW General description of JPEG and the IJG software.
LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
REFERENCES Where to learn more about JPEG.
ARCHIVE LOCATIONS Where to find newer versions of this software.
RELATED SOFTWARE Other stuff you should get.
FILE FORMAT WARS Software *not* to get.
TO DO Plans for future IJG releases.
 
Other documentation files in the distribution are:
 
User documentation:
install.doc How to configure and install the IJG software.
usage.doc Usage instructions for cjpeg, djpeg, jpegtran,
rdjpgcom, and wrjpgcom.
*.1 Unix-style man pages for programs (same info as usage.doc).
wizard.doc Advanced usage instructions for JPEG wizards only.
change.log Version-to-version change highlights.
Programmer and internal documentation:
libjpeg.doc How to use the JPEG library in your own programs.
example.c Sample code for calling the JPEG library.
structure.doc Overview of the JPEG library's internal structure.
filelist.doc Road map of IJG files.
coderules.doc Coding style rules --- please read if you contribute code.
 
Please read at least the files install.doc and usage.doc. Useful information
can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
 
If you want to understand how the JPEG code works, we suggest reading one or
more of the REFERENCES, then looking at the documentation files (in roughly
the order listed) before diving into the code.
 
 
OVERVIEW
========
 
This package contains C software to implement JPEG image compression and
decompression. JPEG (pronounced "jay-peg") is a standardized compression
method for full-color and gray-scale images. JPEG is intended for compressing
"real-world" scenes; line drawings, cartoons and other non-realistic images
are not its strong suit. JPEG is lossy, meaning that the output image is not
exactly identical to the input image. Hence you must not use JPEG if you
have to have identical output bits. However, on typical photographic images,
very good compression levels can be obtained with no visible change, and
remarkably high compression levels are possible if you can tolerate a
low-quality image. For more details, see the references, or just experiment
with various compression settings.
 
This software implements JPEG baseline, extended-sequential, and progressive
compression processes. Provision is made for supporting all variants of these
processes, although some uncommon parameter settings aren't implemented yet.
For legal reasons, we are not distributing code for the arithmetic-coding
variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting
the hierarchical or lossless processes defined in the standard.
 
We provide a set of library routines for reading and writing JPEG image files,
plus two sample applications "cjpeg" and "djpeg", which use the library to
perform conversion between JPEG and some other popular image file formats.
The library is intended to be reused in other applications.
 
In order to support file conversion and viewing software, we have included
considerable functionality beyond the bare JPEG coding/decoding capability;
for example, the color quantization modules are not strictly part of JPEG
decoding, but they are essential for output to colormapped file formats or
colormapped displays. These extra functions can be compiled out of the
library if not required for a particular application. We have also included
"jpegtran", a utility for lossless transcoding between different JPEG
processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
inserting and extracting textual comments in JFIF files.
 
The emphasis in designing this software has been on achieving portability and
flexibility, while also making it fast enough to be useful. In particular,
the software is not intended to be read as a tutorial on JPEG. (See the
REFERENCES section for introductory material.) Rather, it is intended to
be reliable, portable, industrial-strength code. We do not claim to have
achieved that goal in every aspect of the software, but we strive for it.
 
We welcome the use of this software as a component of commercial products.
No royalty is required, but we do ask for an acknowledgement in product
documentation, as described under LEGAL ISSUES.
 
 
LEGAL ISSUES
============
 
In plain English:
 
1. We don't promise that this software works. (But if you find any bugs,
please let us know!)
2. You can use this software for whatever you want. You don't have to pay us.
3. You may not pretend that you wrote this software. If you use it in a
program, you must acknowledge somewhere in your documentation that
you've used the IJG code.
 
In legalese:
 
The authors make NO WARRANTY or representation, either express or implied,
with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
 
This software is copyright (C) 1991-1996, Thomas G. Lane.
All Rights Reserved except as specified below.
 
Permission is hereby granted to use, copy, modify, and distribute this
software (or portions thereof) for any purpose, without fee, subject to these
conditions:
(1) If any part of the source code for this software is distributed, then this
README file must be included, with this copyright and no-warranty notice
unaltered; and any additions, deletions, or changes to the original files
must be clearly indicated in accompanying documentation.
(2) If only executable code is distributed, then the accompanying
documentation must state that "this software is based in part on the work of
the Independent JPEG Group".
(3) Permission for use of this software is granted only if the user accepts
full responsibility for any undesirable consequences; the authors accept
NO LIABILITY for damages of any kind.
 
These conditions apply to any software derived from or based on the IJG code,
not just to the unmodified library. If you use our work, you ought to
acknowledge us.
 
Permission is NOT granted for the use of any IJG author's name or company name
in advertising or publicity relating to this software or products derived from
it. This software may be referred to only as "the Independent JPEG Group's
software".
 
We specifically permit and encourage the use of this software as the basis of
commercial products, provided that all warranty or liability claims are
assumed by the product vendor.
 
 
ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
ansi2knr.c is NOT covered by the above copyright and conditions, but instead
by the usual distribution terms of the Free Software Foundation; principally,
that you must include source code if you redistribute it. (See the file
ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
of any program generated from the IJG code, this does not limit you more than
the foregoing paragraphs do.
 
The configuration script "configure" was produced with GNU Autoconf. It
is copyright by the Free Software Foundation but is freely distributable.
 
It appears that the arithmetic coding option of the JPEG spec is covered by
patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
legally be used without obtaining one or more licenses. For this reason,
support for arithmetic coding has been removed from the free JPEG software.
(Since arithmetic coding provides only a marginal gain over the unpatented
Huffman mode, it is unlikely that very many implementations will support it.)
So far as we are aware, there are no patent restrictions on the remaining
code.
 
WARNING: Unisys has begun to enforce their patent on LZW compression against
GIF encoders and decoders. You will need a license from Unisys to use the
included rdgif.c or wrgif.c files in a commercial or shareware application.
At this time, Unisys is not enforcing their patent against freeware, so
distribution of this package remains legal. However, we intend to remove
GIF support from the IJG package as soon as a suitable replacement format
becomes reasonably popular.
 
We are required to state that
"The Graphics Interchange Format(c) is the Copyright property of
CompuServe Incorporated. GIF(sm) is a Service Mark property of
CompuServe Incorporated."
 
 
REFERENCES
==========
 
We highly recommend reading one or more of these references before trying to
understand the innards of the JPEG software.
 
The best short technical introduction to the JPEG compression algorithm is
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
(Adjacent articles in that issue discuss MPEG motion picture compression,
applications of JPEG, and related topics.) If you don't have the CACM issue
handy, a PostScript file containing a revised version of Wallace's article
is available at ftp.uu.net, graphics/jpeg/wallace.ps.gz. The file (actually
a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
omits the sample images that appeared in CACM, but it includes corrections
and some added material. Note: the Wallace article is copyright ACM and
IEEE, and it may not be used for commercial purposes.
 
A somewhat less technical, more leisurely introduction to JPEG can be found in
"The Data Compression Book" by Mark Nelson, published by M&T Books (Redwood
City, CA), 1991, ISBN 1-55851-216-0. This book provides good explanations and
example C code for a multitude of compression methods including JPEG. It is
an excellent source if you are comfortable reading C code but don't know much
about data compression in general. The book's JPEG sample code is far from
industrial-strength, but when you are ready to look at a full implementation,
you've got one here...
 
The best full description of JPEG is the textbook "JPEG Still Image Data
Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp.
The book includes the complete text of the ISO JPEG standards (DIS 10918-1
and draft DIS 10918-2). This is by far the most complete exposition of JPEG
in existence, and we highly recommend it.
 
The JPEG standard itself is not available electronically; you must order a
paper copy through ISO or ITU. (Unless you feel a need to own a certified
official copy, we recommend buying the Pennebaker and Mitchell book instead;
it's much cheaper and includes a great deal of useful explanatory material.)
In the USA, copies of the standard may be ordered from ANSI Sales at (212)
642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI
doesn't take credit card orders, but Global does.) It's not cheap: as of
1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
shipping/handling. The standard is divided into two parts, Part 1 being the
actual specification, while Part 2 covers compliance testing methods. Part 1
is titled "Digital Compression and Coding of Continuous-tone Still Images,
Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
Continuous-tone Still Images, Part 2: Compliance testing" and has document
numbers ISO/IEC IS 10918-2, ITU-T T.83.
 
Extensions to the original JPEG standard are defined in JPEG Part 3, a new ISO
document. Part 3 is undergoing ISO balloting and is expected to be approved
by the end of 1995; it will have document numbers ISO/IEC IS 10918-3, ITU-T
T.84. IJG currently does not support any Part 3 extensions.
 
The JPEG standard does not specify all details of an interchangeable file
format. For the omitted details we follow the "JFIF" conventions, revision
1.02. A copy of the JFIF spec is available from:
Literature Department
C-Cube Microsystems, Inc.
1778 McCarthy Blvd.
Milpitas, CA 95035
phone (408) 944-6300, fax (408) 944-6314
A PostScript version of this document is available at ftp.uu.net, file
graphics/jpeg/jfif.ps.gz. It can also be obtained by e-mail from the C-Cube
mail server, netlib@c3.pla.ca.us. Send the message "send jfif_ps from jpeg"
to the server to obtain the JFIF document; send the message "help" if you have
trouble.
 
The TIFF 6.0 file format specification can be obtained by FTP from sgi.com
(192.48.153.1), file graphics/tiff/TIFF6.ps.Z; or you can order a printed
copy from Aldus Corp. at (206) 628-6593. The JPEG incorporation scheme
found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
(Compression tag 7). Copies of this Note can be obtained from sgi.com or
from ftp.uu.net:/graphics/jpeg/. It is expected that the next revision of
the TIFF spec will replace the 6.0 JPEG design with the Note's design.
Although IJG's own code does not support TIFF/JPEG, the free libtiff library
uses our library to implement TIFF/JPEG per the Note. libtiff is available
from sgi.com:/graphics/tiff/.
 
 
ARCHIVE LOCATIONS
=================
 
The "official" archive site for this software is ftp.uu.net (Internet
address 192.48.96.9). The most recent released version can always be found
there in directory graphics/jpeg. This particular version will be archived
as graphics/jpeg/jpegsrc.v6a.tar.gz. If you are on the Internet, you
can retrieve files from ftp.uu.net by standard anonymous FTP. If you don't
have FTP access, UUNET's archives are also available via UUCP; contact
help@uunet.uu.net for information on retrieving files that way.
 
Numerous Internet sites maintain copies of the UUNET files. However, only
ftp.uu.net is guaranteed to have the latest official version.
 
You can also obtain this software in DOS-compatible "zip" archive format from
the SimTel archives (ftp.coast.net:/SimTel/msdos/graphics/), or on CompuServe
in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 "JPEG Tools".
Again, these versions may sometimes lag behind the ftp.uu.net release.
 
The JPEG FAQ (Frequently Asked Questions) article is a useful source of
general information about JPEG. It is updated constantly and therefore is
not included in this distribution. The FAQ is posted every two weeks to
Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
You can always obtain the latest version from the news.answers archive at
rtfm.mit.edu. By FTP, fetch /pub/usenet/news.answers/jpeg-faq/part1 and
.../part2. If you don't have FTP, send e-mail to mail-server@rtfm.mit.edu
with body
send usenet/news.answers/jpeg-faq/part1
send usenet/news.answers/jpeg-faq/part2
 
 
RELATED SOFTWARE
================
 
Numerous viewing and image manipulation programs now support JPEG. (Quite a
few of them use this library to do so.) The JPEG FAQ described above lists
some of the more popular free and shareware viewers, and tells where to
obtain them on Internet.
 
If you are on a Unix machine, we highly recommend Jef Poskanzer's free
PBMPLUS image software, which provides many useful operations on PPM-format
image files. In particular, it can convert PPM images to and from a wide
range of other formats. You can obtain this package by FTP from ftp.x.org
(contrib/pbmplus*.tar.Z) or ftp.ee.lbl.gov (pbmplus*.tar.Z). There is also
a newer update of this package called NETPBM, available from
wuarchive.wustl.edu under directory /graphics/graphics/packages/NetPBM/.
Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software
is; you are likely to have difficulty making it work on any non-Unix machine.
 
A different free JPEG implementation, written by the PVRG group at Stanford,
is available from havefun.stanford.edu in directory pub/jpeg. This program
is designed for research and experimentation rather than production use;
it is slower, harder to use, and less portable than the IJG code, but it
is easier to read and modify. Also, the PVRG code supports lossless JPEG,
which we do not.
 
 
FILE FORMAT WARS
================
 
Some JPEG programs produce files that are not compatible with our library.
The root of the problem is that the ISO JPEG committee failed to specify a
concrete file format. Some vendors "filled in the blanks" on their own,
creating proprietary formats that no one else could read. (For example, none
of the early commercial JPEG implementations for the Macintosh were able to
exchange compressed files.)
 
The file format we have adopted is called JFIF (see REFERENCES). This format
has been agreed to by a number of major commercial JPEG vendors, and it has
become the de facto standard. JFIF is a minimal or "low end" representation.
We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
Technical Note #2) for "high end" applications that need to record a lot of
additional data about an image. TIFF/JPEG is fairly new and not yet widely
supported, unfortunately.
 
The upcoming JPEG Part 3 standard defines a file format called SPIFF.
SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
be able to read the most common variant of SPIFF. SPIFF has some technical
advantages over JFIF, but its major claim to fame is simply that it is an
official standard rather than an informal one. At this point it is unclear
whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
standard. IJG intends to support SPIFF once the standard is frozen, but we
have not decided whether it should become our default output format or not.
(In any case, our decoder will remain capable of reading JFIF indefinitely.)
 
Various proprietary file formats incorporating JPEG compression also exist.
We have little or no sympathy for the existence of these formats. Indeed,
one of the original reasons for developing this free software was to help
force convergence on common, open format standards for JPEG files. Don't
use a proprietary file format!
 
 
TO DO
=====
 
In future versions, we are considering supporting some of the upcoming JPEG
Part 3 extensions --- principally, variable quantization and the SPIFF file
format.
 
Tuning the software for better behavior at low quality/high compression
settings is also of interest. The current method for scaling the
quantization tables is known not to be very good at low Q values.
 
As always, speeding things up is high on our priority list.
 
Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
/shark/trunk/ports/mpeg/queueint.c
0,0 → 1,99
/*
* Copyright 1995, Brown University, Providence, RI
*
* Permission to use and modify this software and its documentation for
* any purpose other than its incorporation into a commercial product is
* hereby granted without fee. Permission to copy and distribute this
* software and its documentation only for non-commercial use is also
* granted without fee, provided, however, that the above copyright notice
* appear in all copies, that both that copyright notice and this permission
* notice appear in supporting documentation, that the name of Brown
* University not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission,
* and that the person doing the distribution notify Brown University of
* such distributions outside of his or her organization. Brown University
* makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
* Brown University requests notification of any modifications to this
* software or its documentation.
*
* Send the following redistribution information:
*
* Name:
* Organization:
* Address (postal and/or electronic):
*
* To:
* Software Librarian
* Computer Science Department, Box 1910
* Brown University
* Providence, RI 02912
*
* or
*
* brusd@cs.brown.edu
*
* We will acknowledge all electronic notifications.
*/
#include "queue_int.H"
 
QUEUEint::QUEUEint()
: headOfList(NULL),
tailOfList(NULL)
{
}
 
 
//Deconstructor
QUEUEint::~QUEUEint()
{
//Dequeue all the nodes
for (int result=1,tmp;result;tmp=deQueue(result)) {
}
 
}
 
int QUEUEint::deQueue(int &result)
{
if (!tailOfList) {
result=0;
return 0;
} else result=1;
 
int retVal = headOfList->data;
 
//save node to delete
Item *deleteNode=headOfList;
 
// only one node on list?
if (tailOfList==headOfList) {
tailOfList=headOfList=NULL;
} else headOfList=headOfList->next;
 
delete [] deleteNode;
return retVal;
}
 
void
QUEUEint::enQueue(const int& inVal)
{
//Allocate new node
Item *newNode=(Item *) new char[sizeof(Item)];
 
//Set value
newNode->data=inVal;
 
//Set links in newNode
newNode->prev=tailOfList;
newNode->next=NULL;
 
//Set links to this node
if (tailOfList) {
//Already a tail node whose next pointer we have to fix
tailOfList->next=newNode;
} else {
//first node
headOfList=newNode;
}
tailOfList=newNode;
}
/shark/trunk/ports/mpeg/floatdct.c
0,0 → 1,119
/* idctref.c, Inverse Discrete Fourier Transform, double precision */
 
/* Copyright (C) 1994, MPEG Software Simulation Group. All Rights Reserved. */
 
/*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license fee or
* royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
* any and all warranties, whether express, implied, or statuary, including any
* implied warranties or merchantability or of fitness for a particular
* purpose. In no event shall the copyright-holder be liable for any
* incidental, punitive, or consequential damages of any kind whatsoever
* arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and user's
* customers, employees, agents, transferees, successors, and assigns.
*
* The MPEG Software Simulation Group does not represent or warrant that the
* programs furnished hereunder are free of infringement of any third-party
* patents.
*
* Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
* are subject to royalty fees to patent holders. Many of these patents are
* general enough such that they are unavoidable regardless of implementation
* design.
*
*/
 
/* Perform IEEE 1180 reference (64-bit floating point, separable 8x1
* direct matrix multiply) Inverse Discrete Cosine Transform
*/
 
 
/* Here we use math.h to generate constants. Compiler results may
vary a little */
 
#include <math.h>
 
#ifndef __STDC__
#define _ANSI_ARGS_(x) ()
#else
#define _ANSI_ARGS_(x) x
#endif
 
#define RB "rb"
#define WB "wb"
 
#ifndef O_BINARY
#define O_BINARY 0
#endif
 
#ifndef PI
# ifdef M_PI
# define PI M_PI
# else
# define PI 3.14159265358979323846
# endif
#endif
 
/* global declarations */
void init_float_idct _ANSI_ARGS_((void));
void float_idct _ANSI_ARGS_((short *block));
 
/* private data */
 
/* cosine transform matrix for 8x1 IDCT */
static double c[8][8];
 
/* initialize DCT coefficient matrix */
 
void init_float_idct()
{
int freq, time;
double scale;
 
for (freq=0; freq < 8; freq++)
{
scale = (freq == 0) ? sqrt(0.125) : 0.5;
for (time=0; time<8; time++)
c[freq][time] = scale*cos((PI/8.0)*freq*(time + 0.5));
}
}
 
/* perform IDCT matrix multiply for 8x8 coefficient block */
 
void float_idct(block)
short *block;
{
int i, j, k, v;
double partial_product;
double tmp[64];
 
for (i=0; i<8; i++)
for (j=0; j<8; j++)
{
partial_product = 0.0;
 
for (k=0; k<8; k++)
partial_product+= c[k][j]*block[8*i+k];
 
tmp[8*i+j] = partial_product;
}
 
/* Transpose operation is integrated into address mapping by switching
loop order of i and j */
 
for (j=0; j<8; j++)
for (i=0; i<8; i++)
{
partial_product = 0.0;
 
for (k=0; k<8; k++)
partial_product+= c[k][i]*tmp[8*k+j];
 
v = floor(partial_product+0.5);
block[8*i+j] = (v<-256) ? -256 : ((v>255) ? 255 : v);
}
}
/shark/trunk/ports/mpeg/mb_ordered.c
0,0 → 1,567
/*
* mb_ordered.c
*
* This file contains C code to implement an macroblock ordered dither.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "proto.h"
#include "dither.h"
 
/*
Changes to make the code reentrant:
ditherFlags now not global, passed to MBOrderedDitherImage
-lsh@cs.brown.edu (Loring Holden)
*/
 
#define DITH_SIZE 16
 
 
/* Structures used to implement macroblock ordered
dither algorithm.
*/
 
static unsigned char ***ditherPtr[DITH_SIZE];
 
/*
*--------------------------------------------------------------
*
* InitMBOrderedDither--
*
* Structures intialized for ordered dithering.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
InitMBOrderedDither()
{
unsigned char ****pos_2_cb;
unsigned char ***cb_2_cr;
unsigned char **cr_2_l;
int cb_val, cb_rval, cr_val, cr_rval, l_val, l_rval;
int i, j, pos;
int err_range, threshval;
 
pos_2_cb = (unsigned char ****) malloc (DITH_SIZE*sizeof(unsigned char ***));
cb_2_cr = (unsigned char ***) malloc(CB_RANGE*sizeof(unsigned char **));
cr_2_l = (unsigned char **) malloc(CR_RANGE*sizeof(unsigned char *));
 
for (pos=0; pos<DITH_SIZE; pos++) {
pos_2_cb[pos] = (unsigned char ***) malloc(256*(sizeof(unsigned char **)));
 
for (j=0; j<CB_RANGE; j++) {
cb_2_cr[j] = (unsigned char **) malloc(256*(sizeof(unsigned char *)));
}
 
for (cb_val=0; cb_val<cb_values[0]; cb_val++) {
(pos_2_cb[pos])[cb_val] = cb_2_cr[0];
}
 
for (cb_rval=0; cb_rval<(CB_RANGE-1); cb_rval++) {
err_range = cb_values[cb_rval+1] - cb_values[cb_rval];
threshval = ((pos*err_range)/DITH_SIZE)+cb_values[cb_rval];
 
for (cb_val=cb_values[cb_rval]; cb_val<cb_values[cb_rval+1]; cb_val++) {
if (cb_val>threshval) (pos_2_cb[pos])[cb_val] = cb_2_cr[cb_rval+1];
else (pos_2_cb[pos])[cb_val] = cb_2_cr[cb_rval];
}
}
 
for (cb_val=cb_values[CB_RANGE-1]; cb_val<256; cb_val++) {
(pos_2_cb[pos])[cb_val] = cb_2_cr[CB_RANGE-1];
}
 
for (cb_rval=0; cb_rval<CB_RANGE; cb_rval++) {
for (j=0; j<CR_RANGE; j++) {
cr_2_l[j] = (unsigned char *) malloc(256*(sizeof(unsigned char)));
}
 
for (cr_val=0; cr_val < cr_values[0]; cr_val++) {
(cb_2_cr[cb_rval])[cr_val] = cr_2_l[0];
}
 
for (cr_rval=0; cr_rval<(CR_RANGE-1); cr_rval++) {
err_range = cr_values[cr_rval+1] - cr_values[cr_rval];
threshval = ((pos*err_range)/DITH_SIZE)+cr_values[cr_rval];
for (cr_val=cr_values[cr_rval]; cr_val<cr_values[cr_rval+1]; cr_val++) {
if (cr_val>threshval) (cb_2_cr[cb_rval])[cr_val] = cr_2_l[cr_rval+1];
else (cb_2_cr[cb_rval])[cr_val] = cr_2_l[cr_rval];
}
}
for (cr_val=cr_values[CR_RANGE-1]; cr_val<256; cr_val++) {
(cb_2_cr[cb_rval])[cr_val] = cr_2_l[CR_RANGE-1];
}
for (cr_rval=0; cr_rval<CR_RANGE; cr_rval++) {
for (l_val = 0; l_val < lum_values[0]; l_val++) {
(cr_2_l[cr_rval])[l_val] = pixel[cb_rval+(cr_rval*CB_RANGE)+
(0*CR_RANGE*CB_RANGE)];
}
 
for (l_rval=0; l_rval<(LUM_RANGE-1); l_rval++) {
err_range = lum_values[l_rval+1] - lum_values[l_rval];
threshval = ((pos*err_range) /DITH_SIZE) + lum_values[l_rval];
 
for (l_val = lum_values[l_rval]; l_val < lum_values[l_rval+1]; l_val++) {
if (l_val>threshval) (cr_2_l[cr_rval])[l_val] =
pixel[cb_rval+(cr_rval*CB_RANGE)+((l_rval+1)*CR_RANGE*CB_RANGE)];
else (cr_2_l[cr_rval])[l_val] =
pixel[cb_rval+(cr_rval*CB_RANGE)+(l_rval*CR_RANGE*CB_RANGE)];
}
}
 
for (l_val = lum_values[LUM_RANGE-1]; l_val < 256; l_val++) {
(cr_2_l[cr_rval])[l_val] =
pixel[cb_rval+(cr_rval*CB_RANGE)+((LUM_RANGE-1)*CR_RANGE*CB_RANGE)];
}
}
}
}
 
for (i=0; i<DITH_SIZE; i++) {
ditherPtr[i] = pos_2_cb[i];
}
}
 
 
/*
*--------------------------------------------------------------
*
* MBOrderedDitherImage --
*
* Dithers an image using an ordered dither at macroblock level.
* Assumptions made:
* 1) The color space is allocated y:cr:cb = 8:4:4
* 2) The spatial resolution of y:cr:cb is 4:1:1
* The channels are dithered based on the standard
* ordered dither pattern for a 4x4 area.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
MBOrderedDitherImage (lum, cr, cb, out, h, w, ditherFlags)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int h, w;
char *ditherFlags;
{
unsigned char *l, *r, *b, *o1, *o2;
unsigned char *l2;
unsigned char L, R, B;
int i, j, mbaddr, mbwidth;
unsigned char ***dp0 = ditherPtr[0];
unsigned char ***dp2 = ditherPtr[2];
unsigned char ***dp4 = ditherPtr[4];
unsigned char ***dp6 = ditherPtr[6];
unsigned char ***dp8 = ditherPtr[8];
unsigned char ***dp10 = ditherPtr[10];
unsigned char ***dp12 = ditherPtr[12];
unsigned char ***dp14 = ditherPtr[14];
unsigned char ***dp1 = ditherPtr[1];
unsigned char ***dp3 = ditherPtr[3];
unsigned char ***dp5 = ditherPtr[5];
unsigned char ***dp7 = ditherPtr[7];
unsigned char ***dp9 = ditherPtr[9];
unsigned char ***dp11 = ditherPtr[11];
unsigned char ***dp13 = ditherPtr[13];
unsigned char ***dp15 = ditherPtr[15];
 
l = lum;
l2 = lum + w;
r = cr;
b = cb;
o1 = out;
o2 = out+w;
mbwidth = w / 16;
 
for (i=0; i<h; i+=4) {
 
mbaddr = (i / 16) * mbwidth ;
 
for (j=0; j<w; j+=8) {
 
if (ditherFlags[mbaddr+(j/16)]) {
R = r[0]; B = b[0];
L = l[0];
o1[0] = ((dp0[B])[R])[L];
L = l[1];
o1[1] = ((dp8[B])[R])[L];
L = l2[0];
o2[0] = ((dp12[B])[R])[L];
L = l2[1];
o2[1] = ((dp4[B])[R])[L];
R = r[1]; B = b[1];
L = l[2];
o1[2] = ((dp2[B])[R])[L];
L = l[3];
o1[3] = ((dp10[B])[R])[L];
L = l2[2];
o2[2] = ((dp14[B])[R])[L];
L = l2[3];
o2[3] = ((dp6[B])[R])[L];
R = r[2]; B = b[2];
L = l[4];
o1[4] = ((dp0[B])[R])[L];
L = l[5];
o1[5] = ((dp8[B])[R])[L];
L = l2[4];
o2[4] = ((dp12[B])[R])[L];
L = l2[5];
o2[5] = ((dp4[B])[R])[L];
R = r[3]; B = b[3];
L = l[6];
o1[6] = ((dp2[B])[R])[L];
L = l[7];
o1[7] = ((dp10[B])[R])[L];
L = l2[6];
o2[6] = ((dp14[B])[R])[L];
L = l2[7];
o2[7] = ((dp6[B])[R])[L];
}
l += 8;
l2 += 8;
r += 4;
b += 4;
o1 += 8;
o2 += 8;
}
l += w; l2 += w;
o1 += w; o2 += w;
 
for (j=0; j<w; j+=8) {
 
if (ditherFlags[mbaddr+(j/16)]) {
 
R = r[0]; B = b[0];
L = l[0];
o1[0] = ((dp3[B])[R])[L];
L = l[1];
o1[1] = ((dp11[B])[R])[L];
L = l2[0];
o2[0] = ((dp15[B])[R])[L];
L = l2[1];
o2[1] = ((dp7[B])[R])[L];
R = r[1]; B = b[1];
L = l[2];
o1[2] = ((dp1[B])[R])[L];
L = l[3];
o1[3] = ((dp9[B])[R])[L];
L = l2[2];
o2[2] = ((dp13[B])[R])[L];
L = l2[3];
o2[3] = ((dp5[B])[R])[L];
R = r[2]; B = b[2];
L = l[4];
o1[4] = ((dp3[B])[R])[L];
L = l[5];
o1[5] = ((dp11[B])[R])[L];
L = l2[4];
o2[4] = ((dp15[B])[R])[L];
L = l2[5];
o2[5] = ((dp7[B])[R])[L];
R = r[3]; B = b[3];
L = l[6];
o1[6] = ((dp1[B])[R])[L];
L = l[7];
o1[7] = ((dp9[B])[R])[L];
L = l2[6];
o2[6] = ((dp13[B])[R])[L];
L = l2[7];
o2[7] = ((dp5[B])[R])[L];
}
 
l += 8;
l2 += 8;
r += 4;
b += 4;
o1 += 8;
o2 += 8;
}
l += w; l2 += w;
o1 += w; o2 += w;
}
}
 
 
/*
*--------------------------------------------------------------
*
* MBOrderedDitherDisplayCopy --
*
* Copies an image to the display (?)
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
MBOrderedDitherDisplayCopy(vid_stream, mb_addr, motion_forw, r_right_forw,
r_down_forw, motion_back, r_right_back, r_down_back, past, future)
VidStream *vid_stream;
int mb_addr;
int motion_forw, r_right_forw, r_down_forw;
int motion_back, r_right_back, r_down_back;
unsigned char *past, *future;
{
int right_back = 0, right_forw = 0, down_back, down_forw;
unsigned char *dest;
unsigned char *src1 = 0, *src2 = 0;
int row, col, row_size, rr;
int mc, mr;
 
row = (mb_addr / vid_stream->mb_width) << 4;
col = (mb_addr % vid_stream->mb_width) << 4;
row_size = vid_stream->mb_width << 4;
 
dest = vid_stream->current->display + (row * row_size) + col;
 
if (motion_forw) {
right_forw = r_right_forw >> 1;
down_forw = r_down_forw >> 1;
src1 = past + ((row + down_forw) * row_size) + (col + right_forw);
}
 
if (motion_back) {
right_back = r_right_back >> 1;
down_back = r_down_back >> 1;
src2 = future + ((row + down_back) * row_size) + (col + right_back);
}
if (motion_forw) {
if (motion_back) {
for (rr = 0; rr<16; rr++) {
dest[0] = src1[0]; dest[1] = src2[1];
dest[2] = src1[2]; dest[3] = src2[3];
dest[4] = src1[4]; dest[5] = src2[5];
dest[6] = src1[6]; dest[7] = src2[7];
dest[8] = src1[8]; dest[9] = src2[9];
dest[10] = src1[10]; dest[11] = src2[11];
dest[12] = src1[12]; dest[13] = src2[13];
dest[14] = src1[14]; dest[15] = src2[15];
 
dest += row_size;
src1 += row_size;
src2 += row_size;
}
}
else {
mc = col & 0x3;
mr = right_forw & 0x3;
if (!mc && !mr) {
/* Use 32 bit copy */
int *d, *s;
 
d = (int *) dest;
s = (int *) src1;
row_size /= 4;
for (rr = 0; rr < 16; rr++) {
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
d[3] = s[3];
d += row_size;
s += row_size;
}
} else if ((!mc || (mc == 2)) &&
(!mr || (mr == 2))) {
/* Use 16 bit copy */
short int *d, * s;
d = (short int *) dest;
s = (short int *) src1;
row_size /= 2;
for (rr = 0; rr < 16; rr++) {
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
d[3] = s[3];
d[4] = s[4];
d[5] = s[5];
d[6] = s[6];
d[7] = s[7];
d += row_size;
s += row_size;
}
}
else {
for (rr = 0; rr < 16; rr++) {
dest[0] = src1[0];
dest[1] = src1[1];
dest[2] = src1[2];
dest[3] = src1[3];
dest[4] = src1[4];
dest[5] = src1[5];
dest[6] = src1[6];
dest[7] = src1[7];
dest[8] = src1[8];
dest[9] = src1[9];
dest[10] = src1[10];
dest[11] = src1[11];
dest[12] = src1[12];
dest[13] = src1[13];
dest[14] = src1[14];
dest[15] = src1[15];
dest += row_size;
src1 += row_size;
}
}
}
} else if (motion_back) {
mc = col & 0x3;
mr = right_back & 0x3;
if (!mc && !mr) {
/* Use 32 bit copy */
int *d, *s;
d = (int *) dest;
s = (int *) src2;
row_size /= 4;
for (rr = 0; rr < 16; rr++) {
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
d[3] = s[3];
d += row_size;
s += row_size;
}
}
else if ((!mc || mc == 2) &&
(!mr || mr == 2)) {
/* Use 8 bit copy */
short int *d, *s;
d = (short int *) dest;
s = (short int *) src2;
row_size /= 2;
for (rr = 0; rr < 16; rr++) {
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
d[3] = s[3];
d[4] = s[4];
d[5] = s[5];
d[6] = s[6];
d[7] = s[7];
d += row_size;
s += row_size;
}
}
else {
for (rr = 0; rr < 16; rr++) {
/* Use 8 bit copy */
dest[0] = src2[0];
dest[1] = src2[1];
dest[2] = src2[2];
dest[3] = src2[3];
dest[4] = src2[4];
dest[5] = src2[5];
dest[6] = src2[6];
dest[7] = src2[7];
dest[8] = src2[8];
dest[9] = src2[9];
dest[10] = src2[10];
dest[11] = src2[11];
dest[12] = src2[12];
dest[13] = src2[13];
dest[14] = src2[14];
dest[15] = src2[15];
 
dest += row_size;
src2 += row_size;
}
}
}
}
/shark/trunk/ports/mpeg/gdithmni.c
0,0 → 1,308
/*
* Copyright (c) 1992 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
 
#include "video.h"
#include "dither.h"
#include "mpeg.h" /* for ImageDesc */
 
#define NUM_COLORS 256 /* number of entries in colormap */
/* for gray-scale dithering */
 
/* Range values for lum, cr, cb. */
extern int LUM_RANGE;
extern int CR_RANGE;
extern int CB_RANGE;
 
/* Array that remaps color numbers to actual pixel values used by X server. */
 
extern unsigned char pixel[256];
 
/* Arrays holding quantized value ranged for lum, cr, and cb. */
 
extern int *lum_values;
extern int *cr_values;
extern int *cb_values;
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : InitColormap
@INPUT : (none)
@OUTPUT : *NumColors - number of entries in the newly-created colormap
*Map - an array of colourmap entries; each one contains a
red, green, and blue byte-values (0 .. 255).
*Map[i] gives the colour to display a pixel value i.
@RETURNS : (none)
@DESCRIPTION: Creates a colour map used for most dithering methods
(everything except full-colour, gray, and monochrome).
The colour map itself is pretty self-explanatory -- a
pixel with value i is to be displayed using the red, green
and blue values in *Map[i] after InitColormap() is done.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 95/3/4, Greg Ward: based on InitColorDisplay(), from gdith.c
in the original Berkeley player
@MODIFIED :
---------------------------------------------------------------------------- */
#ifndef DISABLE_DITHER
static void
InitColormap (int *NumColors, ColormapEntry **Map)
{
int i, lum_num, cr_num, cb_num;
 
*NumColors = LUM_RANGE*CB_RANGE*CR_RANGE;
*Map = (ColormapEntry *) malloc (*NumColors * sizeof (ColormapEntry));
 
for (i = 0; i < *NumColors; i++)
{
lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE;
cr_num = (i / CB_RANGE)%CR_RANGE;
cb_num = i % CB_RANGE;
/* ConvertColor(lum_values[lum_num], cr_values[cr_num], cb_values[cb_num],
&(*Map)[i].red, &(*Map)[i].green, &(*Map)[i].blue);
*/
pixel[i] = i;
}
}
#endif
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : InitGrayColormap
@INPUT : (none)
@OUTPUT : *NumColors - number of entries in the newly-created colormap
*Map - an array of colourmap entries
@RETURNS : (none)
@DESCRIPTION: Creates a colour map used for gray-scale dithering, i.e.
the red/green/blue values are the same for any given
pixel value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 95/3/4, Greg Ward: based on InitGrayDisplay(), from gdith.c
in the original Berkeley player
@MODIFIED :
---------------------------------------------------------------------------- */
#ifndef DISABLE_DITHER
static void
InitGrayColormap (int *NumColors, ColormapEntry **Map)
{
int i;
//cprintf("InitGColor...\n");
*NumColors = NUM_COLORS;
*Map = (ColormapEntry *) malloc (*NumColors * sizeof (ColormapEntry));
 
for (i = 0; i < *NumColors; i++)
{
(*Map)[i].red = (*Map)[i].green = (*Map)[i].blue = i;
pixel[i] = i;
}
}
#endif
 
 
/* ----------------------------- MNI Header -----------------------------------
@NAME : InitDither
@INPUT : Image - pointer to the image descriptor for the current MPEG
@OUTPUT : Image->ColormapSize, Image->Colormap - the colour map for
this movie, as initialized by either InitColormap or
InitGrayColormap (unless the current dithering scheme
is full colour, in which case there is no colour map)
@RETURNS : (none)
@DESCRIPTION: Does all initialization particular to the type of dithering
being used. Basically, sets up the internal data structures
needed by the dithering code, and then sets up a colour map
needed to display the pixels output by the ditherers.
@METHOD :
@GLOBALS :
@CALLS : InitColor (for most dithering methods)
InitColormap (for most dithering methods)
InitGrayColormap (for gray-scale dithering)
Init(..)Dither (.. = the current dithering method)
@CREATED : 95/3/3, Greg Ward: taken mostly from main() in the original
Berkeley player
@MODIFIED :
---------------------------------------------------------------------------- */
void
InitDither (ImageDesc *Image)
{
LUM_RANGE = 8;
CR_RANGE = 4;
CB_RANGE = 4;
 
//cprintf("InitDitherin'...\n");
switch (Image->vid_stream->ditherType)
{
#ifndef DISABLE_DITHER
case HYBRID_DITHER:
InitColor ();
InitHybridDither ();
InitColormap (&Image->ColormapSize, &Image->Colormap);
break;
 
case HYBRID2_DITHER:
InitColor ();
InitHybridErrorDither ();
InitColormap (&Image->ColormapSize, &Image->Colormap);
break;
 
case FS4_DITHER:
InitColor ();
InitFS4Dither ();
InitColormap (&Image->ColormapSize, &Image->Colormap);
break;
 
case FS2_DITHER:
InitColor ();
InitFS2Dither ();
InitColormap (&Image->ColormapSize, &Image->Colormap);
break;
 
case FS2FAST_DITHER:
InitColor ();
InitFS2FastDither ();
InitColormap (&Image->ColormapSize, &Image->Colormap);
break;
 
case Twox2_DITHER:
InitColor ();
Init2x2Dither ();
InitColormap (&Image->ColormapSize, &Image->Colormap);
PostInit2x2Dither ();
break;
 
case GRAY_DITHER:
//cprintf("InitGray\n");
InitGrayColormap (&Image->ColormapSize, &Image->Colormap);
break;
#endif
case FULL_COLOR_DITHER:
wpixel[0] = 0xff;
wpixel[1] = 0xff00;
wpixel[2] = 0xff0000;
Image->vid_stream->matched_depth=24;
InitColorDither(1);
Image->ColormapSize = -1;
Image->Colormap = NULL;
break;
 
#ifndef DISABLE_DITHER
 
// MG
case HALF_COLOR_DITHER:
wpixel[2] = 0x001f;
wpixel[1] = 0x07e0;
wpixel[0] = 0xf800;
Image->vid_stream->matched_depth=16;
InitColorDither(1);
Image->ColormapSize = -1;
Image->Colormap = NULL;
break;
 
case NO_DITHER:
break;
 
case ORDERED_DITHER:
InitColor ();
InitOrderedDither ();
InitColormap (&Image->ColormapSize, &Image->Colormap);
break;
 
case MONO_DITHER:
case MONO_THRESHOLD:
break;
 
case ORDERED2_DITHER:
InitColor ();
InitColormap (&Image->ColormapSize, &Image->Colormap);
InitOrdered2Dither ();
break;
 
case MBORDERED_DITHER:
InitColor ();
InitColormap (&Image->ColormapSize, &Image->Colormap);
InitMBOrderedDither ();
break;
 
case PPM_DITHER:
Image->ColormapSize = -1;
Image->Colormap = NULL;
wpixel[0] = 0xff;
wpixel[1] = 0xff00;
wpixel[2] = 0xff0000;
Image->vid_stream->matched_depth=24;
InitColorDither(TRUE);
break;
#endif
}
}
 
 
void ExecuteDisplay(VidStream *vid_stream, XInfo *xinfo)
{
char dummy;
int depth, result;
static int rate_deal = -1;
static int one_frame_time;
register int usec, sec;
 
vid_stream->totNumFrames++;
 
if (partialFlag) {
if ((endFrame != -1) && (vid_stream->totNumFrames > endFrame)) {
 
vid_stream->film_has_ended=TRUE;
if (loopFlag) {
clear_data_stream(vid_stream);
} else DestroyVidStream(vid_stream, xinfo);
return;
}
if (vid_stream->totNumFrames < startFrame) {
return;
}
}
}
 
/shark/trunk/ports/mpeg/descrip.mms
0,0 → 1,0
VMSFLAGS=(no_lrand48,no_random,sig_one_param,no_gettimeofday).SUFFIXES .c .obj.c.obj : CC/define=$(VMSFLAGS)/object=$@ $?/prefix=all ! /prefix for deccOBJS= 16BIT,24BIT,2X2,DECODERS,FS2,FS2FAST,FS4,GDITH,GRAY,HYBRID,\ HYBRIDERR,JREVDCT,MAIN,MB_ORDERED,MONO,MOTIONVECTOR,ORDERED,\ ORDERED2,PARSEBLOCK,READFILE,UTIL,UTIL32,VIDEOmpeg_play.exe : mpeg.olb($(OBJS)) link$(LFLAGS)/exe=$@ mpeg.olb/lib/include=main,vms.opt/option
/shark/trunk/ports/mpeg/version
0,0 → 1,0
VERSION 2.3
/shark/trunk/ports/mpeg/buffer.c
0,0 → 1,191
/*
* Copyright 1995, Brown University, Providence, RI
*
* Permission to use and modify this software and its documentation for
* any purpose other than its incorporation into a commercial product is
* hereby granted without fee. Permission to copy and distribute this
* software and its documentation only for non-commercial use is also
* granted without fee, provided, however, that the above copyright notice
* appear in all copies, that both that copyright notice and this permission
* notice appear in supporting documentation, that the name of Brown
* University not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission,
* and that the person doing the distribution notify Brown University of
* such distributions outside of his or her organization. Brown University
* makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
* Brown University requests notification of any modifications to this
* software or its documentation.
*
* Send the following redistribution information:
*
* Name:
* Organization:
* Address (postal and/or electronic):
*
* To:
* Software Librarian
* Computer Science Department, Box 1910
* Brown University
* Providence, RI 02912
*
* or
*
* brusd@cs.brown.edu
*
* We will acknowledge all electronic notifications.
*/
 
#include "buffer.H"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
 
long BUFFER::totalAllocated=0;
 
// Constructor
// Default: bytesGet=4, bytesSave=3, stepSize=25
//
BUFFER::BUFFER(int itemSize, int bytesGet, int bytesSave,int stepSize)
:
_size(0),
bufferSize(stepSize),
location(0),
firstRetrieve(1),
_bytesGet(bytesGet),
_bytesSave(bytesSave),
_stepSize(stepSize),
sizeGet(itemSize),
sizeSave(itemSize),
tmpBlock(NULL)
{
buffer=new char*[stepSize];
if (!buffer) {
// Should not die, but return a result code...
bufferSize=0;
return;
}
 
// Should add checking for bytesSave, bytesGet
// only supported value for bytesGet [4]
// only supported value for bytesSave [3,4]
 
//Initialize pointers to buffer blocks
for (int i=0;i<stepSize;i++) {
buffer[i]=NULL;
}
 
//If we are trying to compress
if (bytesGet!=bytesSave) {
sizeSave=sizeGet/bytesGet*bytesSave;
tmpBlock=(char *) malloc(sizeGet);
}
}
 
// Destructor
//
//
BUFFER::~BUFFER()
{
if (tmpBlock) free(tmpBlock);
for (int i=0;i<_size;i++) {
free(buffer[i]);
}
delete [] buffer;
}
 
// addToBuffer
// buffer an item, compressing if need be
//
int
BUFFER::addToBuffer(void *item)
{
// Enlarge the buffer if need be
if (_size>=bufferSize) {
int oldSize=bufferSize;
bufferSize+=_stepSize;
char **tmpBuffer=buffer;
buffer=(char **) realloc(buffer,sizeof(char *)*bufferSize);
if (!buffer) {
//can't get more memory
//set buffer to point to old buffer;
buffer=tmpBuffer;
bufferSize=oldSize;
return 0;
}
for (int i=oldSize;i<bufferSize;i++) {
buffer[i]=NULL;
}
}
if ( !(buffer[_size]=(char *)malloc(sizeGet)) ) {
//can't get more memory
return 0;
}
if (sizeGet==sizeSave) {
// No compressing, straight copy
memcpy(buffer[_size],item,sizeGet);
} else {
// Compressing, copy 3 out of 4 bytes
char *ptrTo, *ptrFrom;
int x;
for (ptrTo=buffer[_size],ptrFrom=(char *) item,x=0;
x<sizeGet;
ptrFrom+=_bytesGet,ptrTo+=_bytesSave,x+=_bytesGet) {
*(ptrTo+0)=*(ptrFrom+3);
*(ptrTo+1)=*(ptrFrom+2);
*(ptrTo+2)=*(ptrFrom+1);
}
}
_size++;
return 1;
}
 
const char * const BUFFER::nextBufferItem(int *looped)
{
int tmpLoc=location;
 
// If first time we are retrieving
if (firstRetrieve) {
// shrink buffer array down to size
char **oldLoc=buffer;
buffer=(char **) realloc(buffer,sizeof(char*)*_size);
if (!buffer) {
//since we are shortening the size of a memory block
// we shouldn't get here...
buffer=oldLoc;
}
firstRetrieve=0;
long allocated=sizeSave * _size;
 
printf("Data allocated for buffer: %d (%dk)\n",
allocated, (int) allocated/1024);
totalAllocated+=allocated;
printf("Running total: %d (%dk)\n",
totalAllocated, (int) totalAllocated/1024);
}
 
location++;
 
//Tell the caller if we have looped around
if (looped) {
*looped =(location==_size);
}
 
location %= _size;
if (_bytesGet==_bytesSave) {
// No compressing, straight return
return buffer[tmpLoc];
} else {
// Compressing, copy 3 out of 4 bytes
char *ptrTo, *ptrFrom;
int x;
for (ptrTo=tmpBlock,ptrFrom=buffer[tmpLoc],x=0;
x<sizeGet;ptrFrom+=_bytesSave,ptrTo+=_bytesGet,x+=_bytesGet) {
*(ptrTo+3)=*(ptrFrom+0);
*(ptrTo+2)=*(ptrFrom+1);
*(ptrTo+1)=*(ptrFrom+2);
}
return tmpBlock;
}
}
/shark/trunk/ports/mpeg/buffer.h
0,0 → 1,55
/*
* Copyright 1995, Brown University, Providence, RI
*
* Permission to use and modify this software and its documentation for
* any purpose other than its incorporation into a commercial product is
* hereby granted without fee. Permission to copy and distribute this
* software and its documentation only for non-commercial use is also
* granted without fee, provided, however, that the above copyright notice
* appear in all copies, that both that copyright notice and this permission
* notice appear in supporting documentation, that the name of Brown
* University not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission,
* and that the person doing the distribution notify Brown University of
* such distributions outside of his or her organization. Brown University
* makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
* Brown University requests notification of any modifications to this
* software or its documentation.
*
* Send the following redistribution information:
*
* Name:
* Organization:
* Address (postal and/or electronic):
*
* To:
* Software Librarian
* Computer Science Department, Box 1910
* Brown University
* Providence, RI 02912
*
* or
*
* brusd@cs.brown.edu
*
* We will acknowledge all electronic notifications.
*/
 
#ifndef BUFFER_CLASS_DEF
class BUFFER {
public:
BUFFER(int itemSize, int bytesGet=4, int bytesSave=3, int stepSize=25);
~BUFFER();
int addToBuffer(void *item);
const char * const nextBufferItem(int *looped);
private:
int _size, bufferSize, location, firstRetrieve;
const int _bytesGet, _bytesSave, _stepSize, sizeGet;
int sizeSave;
char *tmpBlock;
char **buffer;
static long totalAllocated;
};
#define BUFFER_CLASS_DEF
#endif
/shark/trunk/ports/mpeg/animbase.c
0,0 → 1,183
/*
* Copyright (c) 1994 by Gregory P. Ward.
* All rights reserved.
*
* This file is part of the MNI front end of the Berkeley MPEG decoder.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
* UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER
* IS ON AN "AS IS" BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
*
* Original C version by Greg Ward <greg@pet.mni.mcgill.ca>,
* reentrant C++ version by Loring Holden <lsh@cs.brown.edu>
*
* All functions that have an "MNI Header" are rewritten from the original
* MNI C function
*
*/
 
#include "ANIMbase.H"
 
#ifndef NOTHREADS
THREADmp_manager *ANIMbase::mp_man=NULL;
#endif
 
//
//Constructor
//
//
ANIMbase::ANIMbase()
: threadNumber(-1),
moreFrames(FALSE),
#ifndef NOTHREADS
MultiThreaded(FALSE),
#endif
fileName(NULL),
buffering(FALSE),
allBuffered(FALSE),
frameBuffer(NULL),
filePtr(NULL),
frames(0)
{
}
 
//
//Copy constructor
//Copies settings from MultiThreading and buffering, and starts
//the same movie from the beginning
//
ANIMbase::ANIMbase(const ANIMbase& rhs)
: threadNumber(-1),
moreFrames(FALSE),
#ifndef NOTHREADS
MultiThreaded(rhs.MultiThreaded),
#endif
fileName(NULL),
buffering(rhs.buffering),
allBuffered(FALSE),
frameBuffer(NULL),
filePtr(NULL),
frames(0)
{
}
 
 
// Destructor
/* ----------------------------- MNI Header -----------------------------------
@NAME : CloseMPEG
@INPUT : (none)
@OUTPUT : (none)
@RETURNS : (void)
@DESCRIPTION: Frees up some of the memory allocated by OpenMPEG() (some
is not freed because the Berkeley code doesn't take into
account the fact that somebody might want to, say, free
up the memory it allocates... someday, I'll probably have
to hack into it to fix that, but not today thanks.)
@METHOD :
@GLOBALS : lum_values
cr_values
cb_values
@CALLS : DestroyVidStream
@CREATED : 94/6/27, Greg Ward
@MODIFIED : 95/10, Loring Holden (made reentrant and ported to C++)
---------------------------------------------------------------------------- */
ANIMbase::~ANIMbase()
{
// newMovie(NULL); //Like we are playing a new movie, but no new
// //allocation
#ifndef NOTHREADS
MultiThread(FALSE);
#endif
 
}
 
//
// Access to private member MultiThreaded for the masses
// (Deals with starting or stopping MultiThreading)
//
#ifndef NOTHREADS
void
ANIMbase::MultiThread(Boolean whether) {
if (whether==MultiThreaded) return;
 
if (whether) {
//We should only do multi-threading if we have a routine to run
//or we haven't buffered the movie yet
if ((thread_routine!=NULL) && !allBuffered) {
if (mp_man==NULL) mp_man=new THREADmp_manager(1);
threadNumber=mp_man->deqThread();
// If we haven't called open() then don't start process
if (moreFrames)
mp_man->processor(threadNumber)->
start_execute(thread_routine,this,NULL);
} else return;
} else {
whether=FALSE;
if (mp_man->processor(threadNumber)->running) {
mp_man->processor(threadNumber)->wait_for_done();
}
mp_man->enqThread(threadNumber);
threadNumber=-1;
}
MultiThreaded=whether;
}
#endif
 
//
// Access to private member buffering for the masses
// (allocates or deallocates buffer)
//
void
ANIMbase::Buffer(Boolean whether, Boolean compress) {
if (whether==(buffering || allBuffered)) return;
if (whether && !allBuffered && moreFrames) {
int bytesSave=4;
buffering=TRUE;
allBuffered=FALSE;
// create buffer to hold the frames
if (compress) bytesSave=3;
frameBuffer=new BUFFER(Size,4,bytesSave);
}
if (!whether) {
buffering=allBuffered=FALSE;
// delete buffer
delete frameBuffer;
frameBuffer=NULL;
}
}
/shark/trunk/ports/mpeg/queue_in.h
0,0 → 1,55
/*
* Copyright 1995, Brown University, Providence, RI
*
* Permission to use and modify this software and its documentation for
* any purpose other than its incorporation into a commercial product is
* hereby granted without fee. Permission to copy and distribute this
* software and its documentation only for non-commercial use is also
* granted without fee, provided, however, that the above copyright notice
* appear in all copies, that both that copyright notice and this permission
* notice appear in supporting documentation, that the name of Brown
* University not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission,
* and that the person doing the distribution notify Brown University of
* such distributions outside of his or her organization. Brown University
* makes no representations about the suitability of this software for
* any purpose. It is provided "as is" without express or implied warranty.
* Brown University requests notification of any modifications to this
* software or its documentation.
*
* Send the following redistribution information:
*
* Name:
* Organization:
* Address (postal and/or electronic):
*
* To:
* Software Librarian
* Computer Science Department, Box 1910
* Brown University
* Providence, RI 02912
*
* or
*
* brusd@cs.brown.edu
*
* We will acknowledge all electronic notifications.
*/
#include <stdlib.h>
 
//Should use templates, but that isn't portable (yet)
 
class QUEUEint {
public:
QUEUEint();
~QUEUEint();
int deQueue(int& result);
void enQueue(const int& inVal);
private:
struct Item {
int data;
Item *next;
Item *prev;
};
Item *headOfList, *tailOfList;
};
/shark/trunk/ports/mpeg/readme.lib
0,0 → 1,70
It is probably best to get the updated library patches from
http://www.cs.brown.edu/software/ooMPEG/
Here are the implementor's notes.....
--------------------
MPEG Changes for Reentrancy (plus)
 
Sun compiler commands to use code as a library:
-DBSD -DNONANSI_INCLUDES -DSIG_ONE_PARAM -DDEFAULT_FULL_COLOR -DNOFRAMECOUNT
-DNOCONTROLS -DDISABLE_DITHER
 
SGI compiler commands to use code as a library:
+w -cckr -DDEFAULT_FULL_COLOR -DNOFRAMECOUNT -DNOCONTROLS -DDISABLE_DITHER
 
HP compile commands for use code as a library:
-Aa -D_HPUX_SOURCE -DDEFAULT_FULL_COLOR -DNOFRAMECOUNT -DDISABLE_DITHER
 
Most changes just involved making sure that previous global information
(or static function variables) are passed down the call path to those
functions that need the information.
 
Changes not involving reentrancy (also mentioned in source files):
do not define INTERPOLATE, add #ifdef INTERPOLATE (16bit.c)
Do prototyping for static function (ctrlbar.c)
Now can name and position each movie window individually (gdith.c, main.c)
DISABLE_DITHER cpp define - do not include dither code if defined
(gdith,main.c, util32.c video.c video.h)
NOFRAMECOUNT cpp define - do not count frames when running without
controls (gdith.c)
Short circuit InitColorDisplay if not displaying anything (gdith.c)
Ability to play >1 movie (w/out CONTROLS) (main.c, et al)
Make sure we do a full frame for each movie (main.c)
Changes to deal with non-MPEG streams (main.c)
Now deals with NO_DITHER, PPM_DITHER and noDisplayFlag==1 (main.c)
get rid on ANSI C complaints about shifting (readfile.c)
only call DestroyVidStream up in mpegVidRsrc, not in correct_underflow
(util.c)
fix parameter types for XCreateWindow call (util32.c)
 
 
 
Further changes that might (should?) be made:
 
statics that should be "de-globalized":
gdith.c: ExecuteDisplay rate_deal, one_frame_time, tftarget, tfnow
(when framerate=0, these aren't used)
video.c: No_[PB]_Flag
(effects how the movies are decoded)
 
globals that should be de-globalized
main.c, gdith.c: framerate
(set framerate=0 for multiple movies - no waiting)
video.h: quietFlag, qualityFlag, gammaCorrectFlag,
chromaCorrectFlag, chromaCorrect
(quietFlag=0 - don't print stuff out)
(qualityFlag=0 - don't do high quality)
(correctFlag's - same for all movies)
gdith.c,video.h: startFrame,endFrame
(startFrame=endFrame=-1 - don't do any frame weirdness)
 
Note - my development Makefile is included in the tar file, but it uses
gnu-make and depends on:
UGA_ARCH environment variable set to: sgi, hp, or sol (architecture
type)
File system location is hardcoded in, including binary directories for
each architecture and compile type (controls, dithering, shared
memory)
 
Loring Holden
lsh@cs.brown.edu
Why did I do this? see http://www.cs.brown.edu/people/lsh/projects.html
/shark/trunk/ports/mpeg/todo
0,0 → 1,27
TODO list for next release of mpeg_play
---------------------------------------
 
change mpegvga.patch to work with new files [ ]
new dither [ ]
sparc10 mp problem [ ]
vms patches [ ]
Change frame-rate limiter to do time-average
(and thus better match) [ ]
save button [ ]
-nob/p buttons [ ]
 
 
WISH LIST
---------
Add AC-prediction decoding [ ]
Get dithers to work in VGA mode [ ]
IDCT compliance [ ]
Implement frame-dropping to meet rates [ ]
audio support [ ]
MPEG2 [ ]
-realtime (frame dropping) [ ]
 
x = done
y = done but not yet incorporated, working
? = status unknown
 
/shark/trunk/ports/mpeg/makefile.ori
0,0 → 1,89
# Generated automatically from Makefile.in by configure.
#
# Makefile.in for the MPEG Library -- this has to be processed by
# `configure' to be meaningful!
#
 
 
# Various programs and their options
 
CC = gcc
#OPT = -nostdinc -O6 -finline-functions -fno-builtin
OPT = -Wall -nostdinc -O -finline-functions -fno-builtin
OPT = -Wall -O -finline-functions -fno-builtin
HARTIK = ../../hartik
LIB_PATH = $(HARTIK)/lib
DEFS = -DHAVE_CONFIG_H -D__LINUX__ -DNOCONTROLS
INCLUDES = -I.
INCLUDES = -I. -I$(HARTIK)/drivers/linuxcom/include -I$(HARTIK)/h/x86 -I$(HARTIK)/h -I$(HARTIK)/h/sys
CFLAGS = $(OPT) $(DEFS) $(INCLUDES)
AR = ar
#ARFLAGS = ru
ARFLAGS = rs
#RANLIB = ranlib
#SHELL = /bin/sh
 
 
LIBNAME = mpg
 
# Source for the library itself -- note that we define LIBSRC and
# LIBOBJ this way (instead of just LIBOBJ=$(LIBSRC:.c=.o) because
# HP-UX make is stupid.
 
DECODER_SRC = util.c video.c parseblock.c motionvector.c decoders.c \
jrevdct.c wrapper.c gdith.c gdithMNI.c readfile.c 16bit.c
DITHER_SRC = fs2.c fs2fast.c fs4.c hybrid.c hybriderr.c 2x2.c gray.c \
mono.c ordered.c ordered2.c mb_ordered.c
LIBSRC = $(DECODER_SRC) $(DITHER_SRC)
LIBOBJ = $(DECODER_SRC:.c=.o) $(DITHER_SRC:.c=.o)
 
 
# Other files of interest
 
LIBRARY = libmpeg.a
MPEGTEST = mpegtest
 
# Targets for all platforms
 
#all: $(LIBRARY) mpegtest
all: $(LIBRARY)
 
$(LIBRARY): $(LIBOBJ)
$(AR) $(ARFLAGS) $(LIBRARY) $(LIBOBJ)
# $(RANLIB) $(LIBRARY)
 
#$(LIBOBJ): Makefile
 
 
# Makefile fragment to compile stuff in extras/ (regardless of
# whether it can be built or not -- that's decided in the main
# Makefile)
 
mpegtest: extras/mpegtest libmpeg.a
rm -f mpegtest
ln -s extras/mpegtest .
 
extras/mpegtest:extras
(cd extras ; $(MAKE) mpegtest)
 
easympeg: extras/easympeg libmpeg.a
rm -f easympeg
ln -s extras/easympeg .
 
extras/easympeg:extras
(cd extras ; $(MAKE) easympeg)
 
check: mpegtest
./mpegtest -checksum test.mpg
 
clean:
rm -f $(LIBRARY) mpegtest core $(LIBOBJ)
(cd extras ; $(MAKE) clean)
 
distclean: clean
rm -f config.cache config.log config.status Makefile config.h
cd extras && $(MAKE) distclean
 
# Include a system-specific Makefile fragment, if any
 
 
/shark/trunk/ports/mpeg/main.c
0,0 → 1,1204
/*
* main.c --
*
* Main procedure
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "proto.h"
#ifndef NOCONTROLS
#include "ctrlbar.h"
#endif
#include <math.h>
#include <sys/types.h>
#include <signal.h>
#include <netinet/in.h>
#include <string.h> /* strtok */
#include "util.h"
#include "dither.h"
 
/*
Changes to make the code reentrant:
Got rid of setjmp, longjmp
deglobalized: EOF_flag, FilmState, curVidStream, bitOffset, bitLength,
bitBuffer, sys_layer, input, seekValue, window, X Windows globals (to
xinfo), curBits, ditherType, matched_depth, totNumFrames, realTimeStart
 
Additional changes:
Ability to play >1 movie (w/out CONTROLS)
Make sure we do a full frame for each movie
DISABLE_DITHER #ifdef to avoid compiling dithering code
Changes to deal with non-MPEG streams
Now deals with NO_DITHER, PPM_DITHER and noDisplayFlag==1
CONTROLS version now can deal with >1 movie
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* Make Ordered be the default dither */
#define DEFAULT_ORDERED_DITHER
 
/* Define buffer length. */
#define BUF_LENGTH 80000
 
/* Function return type declarations */
void usage();
 
/* Forward declaration of functions in this file. */
#ifndef P
# ifdef __STDC__
# define P(s) s
# else
# define P(s) ()
# endif
#endif
 
#ifndef SIG_ONE_PARAM
void int_handler P((void ));
void bad_handler P((void ));
#else
void int_handler P((int signum));
void bad_handler P((int signum));
#endif
void usage P((char *s ));
 
#ifdef DCPREC
/* Declaration of global variable to hold DC precision */
int dcprec = 0;
#endif
 
/* Global file pointer to incoming data. */
FILE **input;
char **inputName;
 
/* Loop flag. */
int loopFlag = 0;
 
/* Shared memory flag. */
int shmemFlag = 0;
 
/* Quiet flag. */
#ifdef QUIET
int quietFlag = 1;
#else
int quietFlag = 0;
#endif
 
/* "Press return" flag, requires return for each new frame */
int requireKeypressFlag = 0;
 
/* Display image on screen? */
int noDisplayFlag = 0;
 
/* Seek Value.
0 means do not seek.
N (N>0) means seek to N after the header is parsed
N (N<0) means the seek has beeen done to offset N
*/
 
/* Framerate, -1: specified in stream (default)
0: as fast as possible
N (N>0): N frames/sec
*/
int framerate = -1;
 
/* Flags/values to control Arbitrary start/stop frames. */
int partialFlag = 0, startFrame = -1, endFrame = -1;
 
/* Flag for gamma correction */
int gammaCorrectFlag = 0;
double gammaCorrect = 1.0;
 
/* Flag for chroma correction */
int chromaCorrectFlag = 0;
double chromaCorrect = 1.0;
 
/* Flag for high quality at the expense of speed */
#ifdef QUALITY
int qualityFlag = 1;
#else
int qualityFlag = 0;
#endif
 
/* no further error messages */
static BOOLEAN exiting=FALSE;
 
/* global variable for interrupt handlers */
VidStream **curVidStream;
 
/* Brown - put X specific variables in xinfo struct */
#define NUMMOVIES 15
XInfo xinfo[NUMMOVIES];
int numInput=0;
 
/*
#define Color16DitherImage ColorDitherImage
#define Color32DitherImage ColorDitherImage
*/
 
/*
*--------------------------------------------------------------
*
* int_handler --
*
* Handles Cntl-C interupts..
* (two different ones for different OSes)
* Results: None.
* Side effects: None.
*--------------------------------------------------------------
*/
#ifndef SIG_ONE_PARAM
void
int_handler()
#else
void
int_handler(signum)
int signum;
#endif
{
int i,displayClosed=0;
 
if (!quietFlag && !exiting) {
fprintf(stderr, "Interrupted!\n");
}
exiting = TRUE;
for (i = 0; i < numInput; i++) {
if (curVidStream[i] != NULL)
DestroyVidStream(curVidStream[i], &xinfo[i]);
if ((xinfo[i].display != NULL) && !displayClosed) {
XCloseDisplay(xinfo[i].display);
displayClosed=1;
}
}
exit(1);
}
 
 
/*
*--------------------------------------------------------------
*
* bad_handler --
*
* Handles Seg faults/bus errors...
* (two different ones for different OSes)
* Results: None.
* Side effects: None.
*
*--------------------------------------------------------------
*/
 
#ifndef SIG_ONE_PARAM
void
bad_handler()
#else
void
bad_handler(signum)
int signum;
#endif
{
if (!exiting) {
fprintf(stderr, "Bad MPEG? Giving up.\ntry 'mpeg_stat -verify' to see if the stream is valid.\n");
}
exit(0);
}
 
 
/*
*--------------------------------------------------------------
*
* getposition --
*
*--------------------------------------------------------------
*/
void getposition(arg, xpos, ypos)
char *arg;
int *xpos, *ypos;
{
char *pos;
 
if ((pos = strtok(arg, "+-")) != NULL) {
*xpos = atoi(pos);
if ((pos = strtok(NULL, "+-")) != NULL) {
*ypos = atoi(pos);
return;
}
}
if (!quietFlag) {
fprintf(stderr, "Illegal position... Warning: argument ignored! (-position +x+y)\n");
}
return;
}
 
 
/*
*--------------------------------------------------------------
*
* main --
*
* Parses command line, starts decoding and displaying.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
#ifndef __STDC__
void
#endif
main(argc, argv)
int argc;
char **argv;
{
 
char *name;
static VidStream **theStream;
int mark;
int i, mult, largy, y, lastStream, firstStream=-1, workToDo=TRUE;
int doDisplay=0; /* Current movie is displaying on screen */
long seekValue=0;/* holds value before it is put in vid_stream */
int owncmFlag=0; /* holds value before it is put in xinfo */
BOOLEAN firstRead=FALSE;
int ppm_width = -1, ppm_height = -1, ppm_modulus = -1;
 
mark = 1;
argc--;
 
input = (FILE **) malloc(NUMMOVIES*sizeof(FILE *));
inputName = (char **) malloc(NUMMOVIES *sizeof(char *));
theStream = (VidStream **) malloc(NUMMOVIES *sizeof(VidStream *));
curVidStream = (VidStream **) malloc(NUMMOVIES *sizeof(VidStream *));
for (i = 0; i < NUMMOVIES; i++) {
input[i] = NULL;
inputName[i] = "stdin";
theStream[i] = NULL;
curVidStream[i] = NULL;
xinfo[i].hints.x = -1;
xinfo[i].hints.y = -1;
xinfo[i].ExistingWindow = 0;
}
name = (char *) "";
 
#ifndef DISABLE_DITHER
#ifndef DEFAULT_ORDERED_DITHER
xinfo[0].ditherType = FULL_COLOR_DITHER;
#else
xinfo[0].ditherType = ORDERED_DITHER;
#endif
#endif
 
LUM_RANGE = 8;
CR_RANGE = CB_RANGE = 4;
noDisplayFlag = 0;
 
#ifdef SH_MEM
shmemFlag = 1;
#endif
 
while (argc) {
if (strcmp(argv[mark], "-nop") == 0) {
SetPFlag(TRUE);
SetBFlag(TRUE);
argc--; mark++;
} else if (strcmp(argv[mark], "-nob") == 0) {
SetBFlag(TRUE);
argc--; mark++;
} else if (strcmp(argv[mark], "-display") == 0) {
name = argv[++mark];
argc -= 2; mark++;
} else if (strcmp(argv[mark], "-position") == 0) {
argc--; mark++;
getposition(argv[mark], &xinfo[numInput].hints.x, &xinfo[numInput].hints.y);
argc--; mark++;
} else if (strcmp(argv[mark], "-xid") == 0) {
xinfo[numInput].ExistingWindow = atoi(argv[++mark]);
argc -= 2; mark++;
} else if (strcmp(argv[mark], "-start") == 0) {
if (argc < 2) usage(argv[0]);
partialFlag = TRUE;
if (seekValue != 0) {
fprintf(stderr, "Cannot use -start with -seek (ignored)\n");
} else {
startFrame = atoi(argv[++mark]);
}
argc -= 2; mark++;
} else if (strcmp(argv[mark], "-seek") == 0) {
if (argc < 2) usage(argv[0]);
seekValue = atoi(argv[++mark]);
if (startFrame != -1) startFrame = 0;
argc -= 2; mark++;
} else if (strcmp(argv[mark], "-end") == 0) {
if (argc < 2) usage(argv[0]);
endFrame = atoi(argv[++mark]);
partialFlag = TRUE;
argc -= 2; mark++;
} else if (strcmp(argv[mark], "-gamma") == 0) {
if (argc < 2) usage(argv[0]);
gammaCorrectFlag = 1;
sscanf(argv[++mark], "%lf", &gammaCorrect);
if (gammaCorrect <= 0.0) {
fprintf(stderr, "ERROR: Gamma correction must be greater than 0.\n");
gammaCorrect = 1.0;
}
if (!quietFlag) {
printf("Gamma Correction set to %4.2f.\n", gammaCorrect);
}
argc -= 2; mark++;
} else if (strcmp(argv[mark], "-chroma") == 0) {
if (argc < 2) usage(argv[0]);
chromaCorrectFlag = 1;
sscanf(argv[++mark], "%lf", &chromaCorrect);
if (chromaCorrect <= 0.0) {
fprintf(stderr, "ERROR: Chroma correction must be greater than 0.\n");
chromaCorrect = 1.0;
}
if (!quietFlag) {
printf("Chroma Correction set to %4.2f.\n",chromaCorrect);
}
argc -= 2; mark++;
#ifdef DCPREC
} else if (strcmp(argv[mark], "-dc") == 0) {
argc--; mark++;
if (argc < 1) {
perror("Must specify dc precision after -dc flag");
usage(argv[0]);
}
dcprec = atoi(argv[mark]) - 8;
if ((dcprec > 3) || (dcprec < 0)) {
perror("DC precision must be at least 8 and at most 11");
usage(argv[0]);
}
argc--; mark++;
#endif
} else if (strcmp(argv[mark], "-quality") == 0) {
argc--; mark++;
if (argc < 1) {
perror("Must specify on or off after -quality flag");
usage(argv[0]);
}
if (strcmp(argv[mark], "on") == 0) {
argc--; mark++;
qualityFlag = 1;
}
else if (strcmp(argv[mark], "off") == 0) {
argc--; mark++;
qualityFlag = 0;
}
else {
perror("Must specify on or off after -quality flag");
usage(argv[0]);
}
} else if (strcmp(argv[mark], "-framerate") == 0) {
argc--; mark++;
if (argc < 1) {
perror("Must specify framerate after -framerate flag");
usage(argv[0]);
}
framerate = atoi(argv[mark]);
argc--; mark++;
} else if (strcmp(argv[mark], "-ppmwidth") == 0) {
argc--; mark++;
if (argc < 1) {
perror("Must specify PPM file width after -ppmwidth flag");
usage(argv[0]);
}
ppm_width = atoi(argv[mark]);
argc--; mark++;
} else if (strcmp(argv[mark], "-ppmheight") == 0) {
argc--; mark++;
if (argc < 1) {
perror("Must specify PPM file height after -ppmheight flag");
usage(argv[0]);
}
ppm_height = atoi(argv[mark]);
argc--; mark++;
} else if (strcmp(argv[mark], "-ppmskip") == 0) {
argc--; mark++;
if (argc < 1) {
perror("Must specify PPM file height after -ppmheight flag");
usage(argv[0]);
}
ppm_modulus = atoi(argv[mark]);
argc--; mark++;
#ifndef DISABLE_DITHER
} else if (strcmp(argv[mark], "-dither") == 0) {
argc--; mark++;
if (argc < 1) {
perror("Must specify dither option after -dither flag");
usage(argv[0]);
}
if (strcmp(argv[mark], "hybrid") == 0) {
argc--; mark++;
xinfo[0].ditherType = HYBRID_DITHER;
} else if (strcmp(argv[mark], "hybrid2") == 0) {
argc--; mark++;
xinfo[0].ditherType = HYBRID2_DITHER;
} else if (strcmp(argv[mark], "fs4") == 0) {
argc--; mark++;
xinfo[0].ditherType = FS4_DITHER;
} else if (strcmp(argv[mark], "fs2") == 0) {
argc--; mark++;
xinfo[0].ditherType = FS2_DITHER;
} else if (strcmp(argv[mark], "fs2fast") == 0) {
argc--; mark++;
xinfo[0].ditherType = FS2FAST_DITHER;
} else if (strcmp(argv[mark], "hybrid2") == 0) {
argc--; mark++;
xinfo[0].ditherType = HYBRID2_DITHER;
} else if (strcmp(argv[mark], "2x2") == 0) {
argc--; mark++;
xinfo[0].ditherType = Twox2_DITHER;
} else if ((strcmp(argv[mark], "gray256") == 0) ||
(strcmp(argv[mark], "grey256") == 0)) {
argc--; mark++;
xinfo[0].ditherType = GRAY256_DITHER;
} else if ((strcmp(argv[mark], "gray") == 0) ||
(strcmp(argv[mark], "grey") == 0)) {
argc--; mark++;
xinfo[0].ditherType = GRAY_DITHER;
} else if ((strcmp(argv[mark], "gray256x2") == 0) ||
(strcmp(argv[mark], "grey256x2") == 0)) {
argc--; mark++;
xinfo[0].ditherType = GRAY2562_DITHER;
} else if ((strcmp(argv[mark], "gray") == 0) ||
(strcmp(argv[mark], "grey") == 0)) {
argc--; mark++;
xinfo[0].ditherType = GRAY_DITHER;
} else if ((strcmp(argv[mark], "gray2") == 0) ||
(strcmp(argv[mark], "grey2") == 0)) {
argc--; mark++;
xinfo[0].ditherType = GRAY2_DITHER;
} else if (strcmp(argv[mark], "color") == 0 ||
strcmp(argv[mark], "colour") == 0) {
argc--; mark++;
xinfo[0].ditherType = FULL_COLOR_DITHER;
} else if (strcmp(argv[mark], "color2") == 0 ||
strcmp(argv[mark], "colour2") == 0) {
argc--; mark++;
xinfo[0].ditherType = FULL_COLOR2_DITHER;
} else if (strcmp(argv[mark], "none") == 0) {
argc--; mark++;
xinfo[0].ditherType = NO_DITHER;
} else if (strcmp(argv[mark], "ppm") == 0) {
argc--; mark++;
xinfo[0].ditherType = PPM_DITHER;
} else if (strcmp(argv[mark], "ordered") == 0) {
argc--; mark++;
xinfo[0].ditherType = ORDERED_DITHER;
} else if (strcmp(argv[mark], "ordered2") == 0) {
argc--; mark++;
xinfo[0].ditherType = ORDERED2_DITHER;
} else if (strcmp(argv[mark], "mbordered") == 0) {
argc--; mark++;
xinfo[0].ditherType = MBORDERED_DITHER;
} else if (strcmp(argv[mark], "mono") == 0) {
argc--; mark++;
xinfo[0].ditherType = MONO_DITHER;
} else if (strcmp(argv[mark], "threshold") == 0) {
argc--; mark++;
xinfo[0].ditherType = MONO_THRESHOLD;
} else {
perror("Illegal dither option.");
usage(argv[0]);
}
#endif
}
else if (strcmp(argv[mark], "-eachstat") == 0) {
argc--; mark++;
#ifdef ANALYSIS
showEachFlag = 1;
#else
fprintf(stderr, "To use -eachstat, recompile with -DANALYSIS in CFLAGS\n");
exit(1);
#endif
}
else if (strcmp(argv[mark], "-shmem_off") == 0) {
argc--; mark++;
shmemFlag = 0;
}
#ifdef QUIET
else if (strcmp(argv[mark], "-quiet") == 0) {
argc--; mark++;
}
else if (strcmp(argv[mark], "-noisy") == 0) {
#else
else if (strcmp(argv[mark], "-noisy") == 0) {
argc--; mark++;
}
else if (strcmp(argv[mark], "-quiet") == 0) {
#endif
argc--; mark++;
quietFlag = !quietFlag;
}
else if (strcmp(argv[mark], "-owncm") == 0) {
argc--; mark++;
owncmFlag = 1;
}
else if (strcmp(argv[mark], "-step") == 0) {
argc--; mark++;
requireKeypressFlag = 1;
}
else if (strcmp(argv[mark], "-loop") == 0) {
argc--; mark++;
loopFlag = 1;
}
else if (strcmp(argv[mark], "-no_display") == 0) {
argc--; mark++;
noDisplayFlag = 1;
shmemFlag = 0;
}
else if (strcmp(argv[mark], "-l_range") == 0) {
argc--; mark++;
LUM_RANGE = atoi(argv[mark]);
if (LUM_RANGE < 1) {
fprintf(stderr, "Illegal luminance range value: %d\n", LUM_RANGE);
exit(1);
}
argc--; mark++;
}
else if (strcmp(argv[mark], "-cr_range") == 0) {
argc--; mark++;
CR_RANGE = atoi(argv[mark]);
if (CR_RANGE < 1) {
fprintf(stderr, "Illegal cr range value: %d\n", CR_RANGE);
exit(1);
}
argc--; mark++;
}
else if (strcmp(argv[mark], "-cb_range") == 0) {
argc--; mark++;
CB_RANGE = atoi(argv[mark]);
if (CB_RANGE < 1) {
fprintf(stderr, "Illegal cb range value: %d\n", CB_RANGE);
exit(1);
}
argc--; mark++;
}
#ifndef NOCONTROLS
else if (strcmp(argv[mark], "-controls") == 0 ||
strcmp(argv[mark], "-controlbar") == 0 ||
strcmp(argv[mark], "-control_bar") == 0) {
argc--; mark++;
if (argc < 1) {
perror("Must specify on, off, or none after -controls flag");
usage(argv[0]);
}
if (strcmp(argv[mark], "on") == 0) {
argc--; mark++;
ControlShow = CTRLBAR_ON;
}
else if (strcmp(argv[mark], "off") == 0) {
argc--; mark++;
ControlShow = CTRLBAR_OFF;
}
else if (strcmp(argv[mark], "none") == 0) {
argc--; mark++;
ControlShow = CTRLBAR_NONE;
}
else {
perror("Must specify on, off, or none after -controls flag");
usage(argv[0]);
}
}
#endif /* !NOCONTROLS */
else if ((strcmp(argv[mark], "-?") == 0) ||
(strcmp(argv[mark], "-Help") == 0) ||
(strcmp(argv[mark], "-help") == 0)) {
usage(argv[0]);
}
else if (argv[mark][0] == '-' && argv[mark][1]==0) {
fflush(stdout);
if (numInput<NUMMOVIES) {
input[numInput]=stdin;
inputName[numInput++] = "stdin";
} else {
fprintf(stderr, "Can't load file %s - too many\n", "stdin");
}
argc--; mark++;
}
else if (argv[mark][0] == '-') {
fprintf(stderr, "Un-recognized flag %s\n",argv[mark]);
usage(argv[0]);
}
else {
fflush(stdout);
if (numInput<NUMMOVIES) {
input[numInput]=fopen(argv[mark], "r");
if (input[numInput] == NULL) {
fprintf(stderr, "Could not open file %s\n", argv[mark]);
usage(argv[0]);
}
inputName[numInput++] = argv[mark];
} else {
fprintf(stderr, "Can't load file %s - too many\n", argv[mark]);
}
argc--; mark++;
}
}
 
lum_values = (int *) malloc(LUM_RANGE*sizeof(int));
cr_values = (int *) malloc(CR_RANGE*sizeof(int));
cb_values = (int *) malloc(CB_RANGE*sizeof(int));
 
signal(SIGINT, int_handler);
#ifndef DEBUG
signal(SIGSEGV, bad_handler);
signal(SIGBUS, bad_handler);
#endif
if ((startFrame != -1) && (endFrame != -1) &&
(endFrame < startFrame)) {
usage(argv[0]);
}
 
init_tables();
for (i = 0; i < numInput; i++) {
xinfo[i].owncmFlag = owncmFlag;
xinfo[i].display = NULL; /* xinfo.ximage is set to null later */
if (xinfo[i].hints.x == -1) {
xinfo[i].hints.x = 200;
xinfo[i].hints.y = 300;
}
xinfo[i].hints.width = 150;
xinfo[i].hints.height = 150;
xinfo[i].visual = NULL;
xinfo[i].name = inputName[i];
xinfo[i].cmap = 0;
xinfo[i].gc = 0;
}
 
#ifndef DISABLE_DITHER
if (xinfo[0].ditherType == MONO_DITHER ||
xinfo[0].ditherType == MONO_THRESHOLD)
xinfo[0].depth= 1;
 
switch (xinfo[0].ditherType) {
case HYBRID_DITHER:
InitColor();
InitHybridDither();
InitDisplay(name, &xinfo[0]);
break;
case HYBRID2_DITHER:
InitColor();
InitHybridErrorDither();
InitDisplay(name, &xinfo[0]);
break;
case FS4_DITHER:
InitColor();
InitFS4Dither();
InitDisplay(name, &xinfo[0]);
break;
case FS2_DITHER:
InitColor();
InitFS2Dither();
InitDisplay(name, &xinfo[0]);
break;
case FS2FAST_DITHER:
InitColor();
InitFS2FastDither();
InitDisplay(name, &xinfo[0]);
break;
case Twox2_DITHER:
InitColor();
Init2x2Dither();
InitDisplay(name, &xinfo[0]);
PostInit2x2Dither();
break;
 
case GRAY_DITHER:
case GRAY2_DITHER:
InitGrayDisplay(name, &xinfo[0]);
break;
 
case GRAY256_DITHER:
case GRAY2562_DITHER:
InitGray256Display(name, &xinfo[0]);
break;
 
case FULL_COLOR_DITHER:
case FULL_COLOR2_DITHER:
InitColorDisplay(name, &xinfo[0]);
InitColorDither(xinfo[0].depth>=24);
#else
InitColorDisplay(name, &xinfo[0]);
InitColorDither(xinfo[0].depth>=24);
#endif
#ifndef DISABLE_DITHER
break;
 
case NO_DITHER:
shmemFlag = 0;
break;
 
case PPM_DITHER:
shmemFlag = 0;
wpixel[0] = 0xff;
wpixel[1] = 0xff00;
wpixel[2] = 0xff0000;
xinfo[0].depth = 24;
InitColorDither(1);
break;
 
case ORDERED_DITHER:
InitColor();
InitOrderedDither();
InitDisplay(name, &xinfo[0]);
break;
 
case MONO_DITHER:
case MONO_THRESHOLD:
InitMonoDisplay(name, &xinfo[0]);
break;
 
case ORDERED2_DITHER:
InitColor();
InitDisplay(name, &xinfo[0]);
InitOrdered2Dither();
break;
 
case MBORDERED_DITHER:
InitColor();
InitDisplay(name, &xinfo[0]);
InitMBOrderedDither();
break;
}
#endif
 
#ifdef SH_MEM
if (shmemFlag && (xinfo[0].display != NULL)) {
if (!XShmQueryExtension(xinfo[0].display)) {
shmemFlag = 0;
if (!quietFlag) {
fprintf(stderr, "Shared memory not supported\n");
fprintf(stderr, "Reverting to normal Xlib.\n");
}
}
}
#endif
 
InitCrop();
 
y=300;
largy=0;
for (i=0;i<numInput;i++) {
doDisplay=!noDisplayFlag;
#ifndef DISABLE_DITHER
if ((xinfo[i].ditherType == NO_DITHER) ||
(xinfo[i].ditherType == PPM_DITHER))
doDisplay = FALSE;
#endif
lastStream = i-1;
while ((lastStream>=0) && (theStream[lastStream]==NULL)) {
lastStream--;
}
if ((i != 0) && doDisplay) {
if (lastStream > -1) {
xinfo[i].hints.x =
xinfo[lastStream].hints.x+10 + theStream[lastStream]->h_size;
if (theStream[lastStream]->v_size>largy)
largy = theStream[lastStream]->v_size;
if (xinfo[i].hints.x > DisplayWidth(xinfo[firstStream].display,
XDefaultScreen(xinfo[firstStream].display)) -80) {
 
y += largy + 30;
largy = 0;
xinfo[i].hints.x = 0;
}
xinfo[i].hints.y = y;
xinfo[i].visual = xinfo[firstStream].visual;
xinfo[i].cmap = xinfo[firstStream].cmap;
xinfo[i].gc = xinfo[firstStream].gc;
}
xinfo[i].display = xinfo[0].display;
xinfo[i].depth = xinfo[0].depth;
xinfo[i].ditherType = xinfo[0].ditherType;
InitColorDisplay(name, &xinfo[i]);
}
curVidStream[i] = theStream[i] = NewVidStream((unsigned int) BUF_LENGTH);
theStream[i]->ppm_width = ppm_width;
theStream[i]->ppm_height = ppm_height;
theStream[i]->ppm_modulus = ppm_modulus;
theStream[i]->input = input[i];
theStream[i]->seekValue = seekValue;
theStream[i]->filename = inputName[i];
theStream[i]->ditherType = xinfo[i].ditherType;
theStream[i]->matched_depth = xinfo[i].depth;
mark = quietFlag;
quietFlag=1;
if (mpegVidRsrc(0, theStream[i], 1, &xinfo[i])==NULL) {
if (doDisplay) {
XDestroyWindow(xinfo[i].display, xinfo[i].window);
}
/* stream has already been destroyed */
curVidStream[i] = theStream[i]=NULL;
fprintf(stderr, "Skipping movie %d, \"%s\" - not an MPEG stream\n",
i, inputName[i]);
fclose(input[i]);
if (i+1 == numInput) numInput--;
} else if (firstStream == -1) firstStream=i;
quietFlag = mark;
 
#ifndef DISABLE_DITHER
if (IS_2x2_DITHER(xinfo[i].ditherType)) {
mult = 2;
}
else {
mult = 1;
}
#else
mult = 1;
#endif
 
if (doDisplay && (theStream[i]!=NULL)) {
ResizeDisplay((unsigned int) theStream[i]->h_size* mult,
(unsigned int) theStream[i]->v_size* mult,
&xinfo[i]);
}
}
 
if (numInput > 1) {
loopFlag = TRUE;
framerate = 0;
}
 
#ifndef NOCONTROLS
if (xinfo[0].display == NULL) {
ControlShow = CTRLBAR_NONE; /* no display => no controls */
}
 
if (ControlShow != CTRLBAR_NONE) {
MakeControlBar(&xinfo[0]);
ControlBar(theStream, xinfo, numInput);
}
for (i = 0; i < numInput; i++) {
if (theStream[i] != NULL) theStream[i]->realTimeStart = ReadSysClock();
}
#else
/* Start time for each movie - do after windows are mapped */
for (i = 0; i < numInput; i++) {
if (theStream[i] != NULL) theStream[i]->realTimeStart = ReadSysClock();
}
#endif
 
 
#ifndef NOCONTROLS
if (ControlShow == CTRLBAR_NONE) {
while (TRUE) {
for (i=0;i < numInput; i++) {
while (theStream[i]->film_has_ended != TRUE) {
mpegVidRsrc(0, theStream[i], 0, &xinfo[i]);
}
if (loopFlag) {
rewind(theStream[i]->input);
ResetVidStream(theStream[i]); /* Reinitialize vid_stream pointers */
if (theStream[i]->seekValue < 0) {
theStream[i]->seekValue = 0 - theStream[i]->seekValue;
}
mpegVidRsrc(0, theStream[i], 1, &xinfo[i]); /* Process start codes */
} else if (doDisplay) break;
else goto done;
}
}
}
else {
ControlLoop(theStream, xinfo, numInput);
}
 
done:
mark=0;
for (i=0;i < numInput; i++) {
DestroyVidStream(theStream[i], &xinfo[i]);
if ((xinfo[i].display != NULL) && !mark) {
XCloseDisplay(xinfo[i].display);
mark=1;
}
}
exit(0);
#else /* !NOCONTROLS */
if (!numInput) {
fprintf(stderr, "Must enter MPEG file to play\n");
usage(argv[0]);
}
while (workToDo) {
workToDo = FALSE;
for (i = 0; i < numInput; i++) {
if (theStream[i] != NULL) {
mark = theStream[i]->totNumFrames;
/* make sure we do a whole frame */
while (mark == theStream[i]->totNumFrames) {
mpegVidRsrc(0, theStream[i], 0, &xinfo[i]);
}
if (theStream[i]->film_has_ended) {
if (loopFlag) {
clear_data_stream(theStream[i]);
/* Reinitialize vid_stream pointers */
ResetVidStream(theStream[i]);
rewind(theStream[i]->input);
if (theStream[i]->seekValue < 0) {
theStream[i]->seekValue = 0 - theStream[i]->seekValue;
}
#ifdef ANALYSIS
init_stats();
#endif
/* Process start codes */
if (mpegVidRsrc(0, theStream[i], 1, &xinfo[i])==NULL) {
/* print something sensible here,
but we only get here if the file is changed while we
are decoding, right?
*/
}
} /* loopFlag */
} /* film_has_ended */
workToDo = workToDo || (!theStream[i]->film_has_ended);
} /* theStream[i]!=NULL */
} /* for (i.. */
} /* while workToDo */
sleep(1000);
/* freeze on the last frame */
#endif /* NOCONTROLS */
}
/*
*--------------------------------------------------------------
*
* usage --
*
* Print mpeg_play usage
*
* Results:
* None.
*
* Side effects:
* exits with a return value -1
*
*--------------------------------------------------------------
*/
 
void
usage(s)
char *s; /* program name */
{
fprintf(stderr, "Usage:\n");
#ifndef NOCONTROLS
fprintf(stderr, "mpeg_play [options] [filename]\n");
#else
fprintf(stderr, "mpeg_play [[options] [filename]] [[options] [filename]] [..]\n");
#endif
fprintf(stderr, "Options :\n");
fprintf(stderr, " [-display X_display]\t[-no_display]\n");
#ifndef DISABLE_DITHER
fprintf(stderr, " [-dither {ordered|ordered2|mbordered|fs4|fs2|fs2fast|hybrid|\n");
fprintf(stderr, " hybrid2|2x2|gray|gray256|color|color2|none|mono|threshold|ppm|\n");
fprintf(stderr, " gray2|gray256x2}]\n");
#endif
fprintf(stderr, " [-loop]\n");
fprintf(stderr, " [-start frame_num]\t[-end frame_num]\t[-seek file_offset]\n");
fprintf(stderr, " [-gamma gamma_correction_value]\t[-chroma chroma_correction_value]\n");
fprintf(stderr, " [-framerate num_frames_per_sec] (0 means as fast as possible)\n");
fprintf(stderr, " [-position +x+y]\t[-quality {on|off}] (compiled default is ");
#ifdef QUALITY
fprintf(stderr, "ON)\n");
#else
fprintf(stderr, "OFF)\n");
#endif
#ifdef QUIET
fprintf(stderr, " [-noisy] (turns on all program output)\n");
#else
fprintf(stderr, " [-quiet] (turns off all program output)\n");
#endif
#ifndef NOCONTROLS
fprintf(stderr, " [-controls {on|off|none}] (default is on)\n");
#endif
fprintf(stderr, " [-?]\t[-help] for help (this message)\n");
fprintf(stderr, "Rare options:\n");
fprintf(stderr, " [-nob]\t[-nop]\n");
#ifdef ANALYSIS
fprintf(stderr, " [-eachstat]\t[-owncm]\t[-shmem_off]\n");
#else
fprintf(stderr, " [-owncm]\t[-shmem_off]\n");
#endif
fprintf(stderr, " [-l_range num]\t[-cr_range num]\t[-cb_range num]\n");
/* fprintf(stderr, " [-xid xid]\n"); */
#ifdef DCPREC
fprintf(stderr, " [-dc {8|9|10|11}] (defaults to 8)\n");
#endif
fprintf(stderr, " with -dither ppm:\n");
fprintf(stderr, " [-ppmwidth num]\t[-ppmheight num]\t[-ppmskip num]\n");
exit (-1);
}
 
 
/*
*--------------------------------------------------------------
*
* DoDitherImage --
*
* Called when image needs to be dithered. Selects correct
* dither routine based on info in xinfo[0].ditherType.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
DoDitherImage(vid_stream)
VidStream *vid_stream;
{
unsigned char *l=vid_stream->current->luminance,
*Cr=vid_stream->current->Cr,
*Cb=vid_stream->current->Cb,
*disp=vid_stream->current->display;
int h=(int) vid_stream->mb_height * 16;
int w=(int) vid_stream->mb_width * 16;
int ditherType=vid_stream->ditherType;
int matched_depth=vid_stream->matched_depth;
 
#ifndef DISABLE_DITHER
switch(ditherType) {
case HYBRID_DITHER:
HybridDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case HYBRID2_DITHER:
HybridErrorDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FS2FAST_DITHER:
FS2FastDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FS2_DITHER:
FS2DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FS4_DITHER:
FS4DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case Twox2_DITHER:
Twox2DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case FULL_COLOR2_DITHER:
if (matched_depth >= 24)
Twox2Color32DitherImage(l, Cr, Cb, disp, h, w);
else
Twox2Color16DitherImage(l, Cr, Cb, disp, h, w);
break;
case FULL_COLOR_DITHER:
if (matched_depth >= 24)
#endif
 
Color32DitherImage(l, Cr, Cb, disp, h, w);
 
#ifndef DISABLE_DITHER
else
Color16DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case GRAY_DITHER:
case GRAY256_DITHER:
if (matched_depth == 8)
GrayDitherImage(l, Cr, Cb, disp, h, w);
else if (matched_depth == 16)
Gray16DitherImage(l, Cr, Cb, disp, h, w);
else if (matched_depth == 32 || matched_depth == 24)
Gray32DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case GRAY2_DITHER:
case GRAY2562_DITHER:
if (matched_depth == 8)
Gray2DitherImage(l, Cr, Cb, disp, h, w);
else if (matched_depth == 16)
Gray216DitherImage(l, Cr, Cb, disp, h, w);
else if (matched_depth == 32 || matched_depth == 24)
Gray232DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case NO_DITHER:
break;
 
case PPM_DITHER:
Color32DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case ORDERED_DITHER:
OrderedDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case MONO_DITHER:
MonoDitherImage(l, Cr, Cb, disp, h, w);
break;
 
case MONO_THRESHOLD:
MonoThresholdImage(l, Cr, Cb, disp, h, w);
break;
 
case ORDERED2_DITHER:
Ordered2DitherImage(l, Cr, Cb, disp, h, w);
break;
 
case MBORDERED_DITHER:
MBOrderedDitherImage(l, Cr, Cb, disp, h, w, vid_stream->ditherFlags);
break;
}
#endif
}
/shark/trunk/ports/mpeg/dither.h
0,0 → 1,53
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
extern int LUM_RANGE;
extern int CR_RANGE;
extern int CB_RANGE;
 
 
#define CB_BASE 1
#define CR_BASE (CB_BASE*CB_RANGE)
#define LUM_BASE (CR_BASE*CR_RANGE)
 
extern unsigned char pixel[256];
extern unsigned long wpixel[256];
extern int *lum_values;
extern int *cr_values;
extern int *cb_values;
 
#define Min(x,y) (((x) < (y)) ? (x) : (y))
#define Max(x,y) (((x) > (y)) ? (x) : (y))
 
#define GAMMA_CORRECTION(x) ((int)(pow((x) / 255.0, 1.0 / gammaCorrect) * 255.0))
#define CHROMA_CORRECTION256(x) ((x) >= 128 \
? 128 + Min(127, (int)(((x) - 128.0) * chromaCorrect)) \
: 128 - Min(128, (int)((128.0 - (x)) * chromaCorrect)))
#define CHROMA_CORRECTION128(x) ((x) >= 0 \
? Min(127, (int)(((x) * chromaCorrect))) \
: Max(-128, (int)(((x) * chromaCorrect))))
#define CHROMA_CORRECTION256D(x) ((x) >= 128 \
? 128.0 + Min(127.0, (((x) - 128.0) * chromaCorrect)) \
: 128.0 - Min(128.0, (((128.0 - (x)) * chromaCorrect))))
#define CHROMA_CORRECTION128D(x) ((x) >= 0 \
? Min(127.0, ((x) * chromaCorrect)) \
: Max(-128.0, ((x) * chromaCorrect)))
 
/shark/trunk/ports/mpeg/animbase.h
0,0 → 1,120
/*
* Copyright (c) 1994 by Gregory P. Ward.
* All rights reserved.
*
* This file is part of the MNI front end of the Berkeley MPEG decoder.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
* UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER
* IS ON AN "AS IS" BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* This is the abstract base class on which to easily build animation objects
* for animation objects (MPEG, Quicktime, etc.)
*
* Original C version of the MPEG wrapper by Greg Ward <greg@pet.mni.mcgill.ca>,
* reentrant C++ version by Loring Holden <lsh@cs.brown.edu>
*
*/
 
#ifndef CPLUSPLUS_ANIM_WRAPPER
#include <stdio.h>
#include <errno.h>
#include <string.h>
//Originally from the MPEG Wrapper by Greg Ward
#ifndef BOOLEAN_TYPE_EXISTS
typedef char Boolean;
#define BOOLEAN_TYPE_EXISTS
#endif
 
#if (!defined(TRUE) || !defined(FALSE))
# define TRUE (char) 1
# define FALSE (char) 0
#endif
 
#ifndef NOTHREADS
#include "thread_mp.H"
#endif
#include "buffer.H"
 
class ANIMbase {
public:
ANIMbase();
ANIMbase(const ANIMbase& rhs); //Copy constructor (same
//animation, but at start)
virtual void newMovie(const char * const infile) = 0;
const char * const getName() const {return fileName;};
virtual Boolean open() = 0;
virtual void rewind() = 0;
virtual Boolean GetFrame(char **Frame, Boolean *newFrame) = 0;
virtual Boolean OkFile() {return filePtr!=NULL;};
virtual void InitDither(unsigned long /*red_mask*/,
unsigned long /*green_mask*/,
unsigned long /*blue_mask*/) {};
#ifndef NOTHREADS
virtual void MultiThread(Boolean mt);
#endif
virtual void Buffer(Boolean buff, Boolean compress=TRUE);
virtual ~ANIMbase();
 
int Height; // in pixels
int Width;
int Size; // bytes for whole image
int frames; // Frames so far
 
Boolean moreFrames; // Are there more frames in the movie?
 
protected:
int threadNumber; // the number of the thread we're using
char *fileName; // Name of the animation file
 
FILE *filePtr;
Boolean buffering, // Are we buffering frames?
allBuffered; // We can stop if we have buffered all frames
BUFFER *frameBuffer; // Buffer object to hold frames
#ifndef NOTHREADS
Boolean MultiThreaded;
static THREADmp_manager *mp_man;
#endif
void *(*thread_routine)(void *,void *);//Routine to run when multi-threaded
private:
ANIMbase& operator=(const ANIMbase& rhs);
};
 
#define CPLUSPLUS_ANIM_WRAPPER
#endif
/shark/trunk/ports/mpeg/ordered.c
0,0 → 1,309
/*
* ordered.c --
*
* This file contains C code to implement an ordered dither.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "proto.h"
#include "dither.h"
 
#define DITH_SIZE 16
 
 
/* Structures used to implement hybrid ordered dither/floyd-steinberg
dither algorithm.
*/
 
static unsigned char *l_darrays[DITH_SIZE];
static unsigned char *cr_darrays[DITH_SIZE];
static unsigned char *cb_darrays[DITH_SIZE];
/*
*--------------------------------------------------------------
*
* InitOrderedDither--
*
* Structures intialized for ordered dithering.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
InitOrderedDither()
{
int i, j, k, err_range, threshval;
unsigned char *lmark, *cmark;
 
for (i=0; i<DITH_SIZE; i++) {
lmark = l_darrays[i] = (unsigned char *) malloc(256);
 
for (j=0; j<lum_values[0]; j++) {
*lmark++ = 0;
}
 
for (j=0; j<(LUM_RANGE-1); j++) {
err_range = lum_values[j+1] - lum_values[j];
threshval = ((i * err_range) / DITH_SIZE)+lum_values[j];
 
for (k=lum_values[j]; k<lum_values[j+1]; k++) {
if (k > threshval) {
*lmark++ = ((j+1) * (CR_RANGE * CB_RANGE));
}
else {
*lmark++ = (j * (CR_RANGE * CB_RANGE));
}
}
}
 
for (j=lum_values[LUM_RANGE-1]; j<256; j++) {
*lmark++ = (LUM_RANGE-1)*(CR_RANGE * CB_RANGE);
}
}
 
for (i=0; i<DITH_SIZE; i++) {
cmark = cr_darrays[i] = (unsigned char *) malloc(256);
 
for (j=0; j<cr_values[0]; j++) {
*cmark++ = 0;
}
 
for (j=0; j<(CR_RANGE-1); j++) {
err_range = cr_values[j+1] - cr_values[j];
threshval = ((i * err_range) / DITH_SIZE)+cr_values[j];
 
for (k=cr_values[j]; k<cr_values[j+1]; k++) {
if (k > threshval) {
*cmark++ = ((j+1) * CB_RANGE);
}
else {
*cmark++ = (j * CB_RANGE);
}
}
}
 
for (j=cr_values[CR_RANGE-1]; j<256; j++) {
*cmark++ = (CR_RANGE-1)*(CB_RANGE);
}
}
 
for (i=0; i<DITH_SIZE; i++) {
cmark = cb_darrays[i] = (unsigned char *) malloc(256);
 
for (j=0; j<cb_values[0]; j++) {
*cmark++ = 0;
}
 
for (j=0; j<(CB_RANGE-1); j++) {
err_range = cb_values[j+1] - cb_values[j];
threshval = ((i * err_range) / DITH_SIZE)+cb_values[j];
 
for (k=cb_values[j]; k<cb_values[j+1]; k++) {
if (k > threshval) {
*cmark++ = j+1;
}
else {
*cmark++ = j;
}
}
}
 
for (j=cb_values[CB_RANGE-1]; j<256; j++) {
*cmark++ = CB_RANGE-1;
}
}
}
 
/*
*--------------------------------------------------------------
*
* OrderedDitherImage --
*
* Dithers an image using an ordered dither.
* Assumptions made:
* 1) The color space is allocated y:cr:cb = 8:4:4
* 2) The spatial resolution of y:cr:cb is 4:1:1
* The channels are dithered based on the standard
* ordered dither pattern for a 4x4 area.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
OrderedDitherImage (lum, cr, cb, out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int w, h;
{
unsigned char *l, *r, *b, *o1, *o2;
unsigned char *l2;
unsigned char L, R, B;
int i, j;
 
l = lum;
l2 = lum+w;
r = cr;
b = cb;
o1 = out;
o2 = out+w;
 
for (i=0; i<h; i+=4) {
 
for (j=0; j<w; j+=8) {
 
R = r[0]; B = b[0];
 
L = l[0];
o1[0] = pixel[(l_darrays[0][L] + cr_darrays[0][R] + cb_darrays[0][B])];
L = l[1];
o1[1] = pixel[(l_darrays[8][L] + cr_darrays[8][R] + cb_darrays[8][B])];
L = l2[0];
o2[0] = pixel[(l_darrays[12][L] + cr_darrays[12][R] + cb_darrays[12][B])];
L = l2[1];
o2[1] = pixel[(l_darrays[4][L] + cr_darrays[4][R] + cb_darrays[4][B])];
 
R = r[1]; B = b[1];
 
L = l[2];
o1[2] = pixel[(l_darrays[2][L] + cr_darrays[2][R] + cb_darrays[2][B])];
L = l[3];
o1[3] = pixel[(l_darrays[10][L] + cr_darrays[10][R] + cb_darrays[10][B])];
L = l2[2];
o2[2] = pixel[(l_darrays[14][L] + cr_darrays[14][R] + cb_darrays[14][B])];
L = l2[3];
o2[3] = pixel[(l_darrays[6][L] + cr_darrays[6][R] + cb_darrays[6][B])];
 
R = r[2]; B = b[2];
 
L = l[4];
o1[4] = pixel[(l_darrays[0][L] + cr_darrays[0][R] + cb_darrays[0][B])];
L = l[5];
o1[5] = pixel[(l_darrays[8][L] + cr_darrays[8][R] + cb_darrays[8][B])];
L = l2[4];
o2[4] = pixel[(l_darrays[12][L] + cr_darrays[12][R] + cb_darrays[12][B])];
L = l2[5];
o2[5] = pixel[(l_darrays[4][L] + cr_darrays[4][R] + cb_darrays[4][B])];
 
R = r[3]; B = b[3];
 
L = l[6];
o1[6] = pixel[(l_darrays[2][L] + cr_darrays[2][R] + cb_darrays[2][B])];
L = l[7];
o1[7] = pixel[(l_darrays[10][L] + cr_darrays[10][R] + cb_darrays[10][B])];
L = l2[6];
o2[6] = pixel[(l_darrays[14][L] + cr_darrays[14][R] + cb_darrays[14][B])];
L = l2[7];
o2[7] = pixel[(l_darrays[6][L] + cr_darrays[6][R] + cb_darrays[6][B])];
 
l += 8;
l2 += 8;
r += 4;
b += 4;
o1 += 8;
o2 += 8;
}
 
l += w;
l2 += w;
o1 += w;
o2 += w;
 
for (j=0; j<w; j+=8) {
 
R = r[0]; B = b[0];
 
L = l[0];
o1[0] = pixel[(l_darrays[3][L] + cr_darrays[3][R] + cb_darrays[3][B])];
L = l[1];
o1[1] = pixel[(l_darrays[11][L] + cr_darrays[11][R] + cb_darrays[11][B])];
L = l2[0];
o2[0] = pixel[(l_darrays[15][L] + cr_darrays[15][R] + cb_darrays[15][B])];
L = l2[1];
o2[1] = pixel[(l_darrays[7][L] + cr_darrays[7][R] + cb_darrays[7][B])];
 
R = r[1]; B = b[1];
 
L = l[2];
o1[2] = pixel[(l_darrays[1][L] + cr_darrays[1][R] + cb_darrays[1][B])];
L = l[3];
o1[3] = pixel[(l_darrays[9][L] + cr_darrays[9][R] + cb_darrays[9][B])];
L = l2[2];
o2[2] = pixel[(l_darrays[13][L] + cr_darrays[13][R] + cb_darrays[13][B])];
L = l2[3];
o2[3] = pixel[(l_darrays[5][L] + cr_darrays[5][R] + cb_darrays[5][B])];
 
R = r[2]; B = b[2];
 
L = l[4];
o1[4] = pixel[(l_darrays[3][L] + cr_darrays[3][R] + cb_darrays[3][B])];
L = l[5];
o1[5] = pixel[(l_darrays[11][L] + cr_darrays[11][R] + cb_darrays[11][B])];
L = l2[4];
o2[4] = pixel[(l_darrays[15][L] + cr_darrays[15][R] + cb_darrays[15][B])];
L = l2[5];
o2[5] = pixel[(l_darrays[7][L] + cr_darrays[7][R] + cb_darrays[7][B])];
 
R = r[3]; B = b[3];
 
L = l[6];
o1[6] = pixel[(l_darrays[1][L] + cr_darrays[1][R] + cb_darrays[1][B])];
L = l[7];
o1[7] = pixel[(l_darrays[9][L] + cr_darrays[9][R] + cb_darrays[9][B])];
L = l2[6];
o2[6] = pixel[(l_darrays[13][L] + cr_darrays[13][R] + cb_darrays[13][B])];
L = l2[7];
o2[7] = pixel[(l_darrays[5][L] + cr_darrays[5][R] + cb_darrays[5][B])];
 
l += 8;
l2 += 8;
r += 4;
b += 4;
o1 += 8;
o2 += 8;
}
 
l += w;
l2 += w;
o1 += w;
o2 += w;
}
}
 
 
/shark/trunk/ports/mpeg/decoders.c
0,0 → 1,968
/*
* decoders.c
*
* This file contains all the routines for Huffman decoding required in
* MPEG
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include <stdio.h>
#include <assert.h>
#include "decoders.h"
#include "util.h"
#include "video.h"
#include "proto.h"
 
/*
Changes to make the code reentrant:
curVidStream now not global - DecodeDCT* functioned #ifdef'd out
(are they needed?)
Additional changes:
none
-lsh@cs.brown.edu (Loring Holden)
*/
 
/* Decoding table for macroblock_address_increment */
mb_addr_inc_entry mb_addr_inc[2048];
 
/* Decoding table for macroblock_type in predictive-coded pictures */
mb_type_entry mb_type_P[64];
 
/* Decoding table for macroblock_type in bidirectionally-coded pictures */
mb_type_entry mb_type_B[64];
 
/* Decoding table for motion vectors */
motion_vectors_entry motion_vectors[2048];
 
/* Decoding table for coded_block_pattern */
 
coded_block_pattern_entry coded_block_pattern[512] =
{ {(unsigned int)ERROR, 0}, {(unsigned int)ERROR, 0}, {39, 9}, {27, 9}, {59, 9}, {55, 9}, {47, 9}, {31, 9},
{58, 8}, {58, 8}, {54, 8}, {54, 8}, {46, 8}, {46, 8}, {30, 8}, {30, 8},
{57, 8}, {57, 8}, {53, 8}, {53, 8}, {45, 8}, {45, 8}, {29, 8}, {29, 8},
{38, 8}, {38, 8}, {26, 8}, {26, 8}, {37, 8}, {37, 8}, {25, 8}, {25, 8},
{43, 8}, {43, 8}, {23, 8}, {23, 8}, {51, 8}, {51, 8}, {15, 8}, {15, 8},
{42, 8}, {42, 8}, {22, 8}, {22, 8}, {50, 8}, {50, 8}, {14, 8}, {14, 8},
{41, 8}, {41, 8}, {21, 8}, {21, 8}, {49, 8}, {49, 8}, {13, 8}, {13, 8},
{35, 8}, {35, 8}, {19, 8}, {19, 8}, {11, 8}, {11, 8}, {7, 8}, {7, 8},
{34, 7}, {34, 7}, {34, 7}, {34, 7}, {18, 7}, {18, 7}, {18, 7}, {18, 7},
{10, 7}, {10, 7}, {10, 7}, {10, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7},
{33, 7}, {33, 7}, {33, 7}, {33, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
{9, 7}, {9, 7}, {9, 7}, {9, 7}, {5, 7}, {5, 7}, {5, 7}, {5, 7},
{63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6}, {63, 6},
{3, 6}, {3, 6}, {3, 6}, {3, 6}, {3, 6}, {3, 6}, {3, 6}, {3, 6},
{36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6}, {36, 6},
{24, 6}, {24, 6}, {24, 6}, {24, 6}, {24, 6}, {24, 6}, {24, 6}, {24, 6},
{62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5},
{62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5}, {62, 5},
{2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5},
{2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5}, {2, 5},
{61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5},
{61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5}, {61, 5},
{1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5},
{1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5}, {1, 5},
{56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5},
{56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5}, {56, 5},
{52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5},
{52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5}, {52, 5},
{44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5},
{44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5}, {44, 5},
{28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5},
{28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5}, {28, 5},
{40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5},
{40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5}, {40, 5},
{20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5},
{20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5}, {20, 5},
{48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5},
{48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5}, {48, 5},
{12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
{12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
{32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
{32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
{32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
{32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
{16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
{16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
{16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
{16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
{8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4},
{8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4},
{8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4},
{8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4}, {8, 4},
{4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
{4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
{4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
{4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
{60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
{60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
{60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
{60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
{60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
{60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
{60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3},
{60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}, {60, 3}
};
 
/* Decoding tables for dct_dc_size_luminance */
dct_dc_size_entry dct_dc_size_luminance[32] =
{ {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
{0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3},
{4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}, {(unsigned int)ERROR, 0}
};
 
dct_dc_size_entry dct_dc_size_luminance1[16] =
{ {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6},
{8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9}
};
 
/* Decoding table for dct_dc_size_chrominance */
dct_dc_size_entry dct_dc_size_chrominance[32] =
{ {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2},
{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
{3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}, {(unsigned int)ERROR, 0}
};
 
dct_dc_size_entry dct_dc_size_chrominance1[32] =
{ {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6},
{6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6},
{7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7},
{8, 8}, {8, 8}, {8, 8}, {8, 8}, {9, 9}, {9, 9}, {10, 10}, {11, 10}
};
 
/* DCT coeff tables. */
 
unsigned short int dct_coeff_tbl_0[256] =
{
0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff,
0x052f, 0x051f, 0x050f, 0x04ff,
0x183f, 0x402f, 0x3c2f, 0x382f,
0x342f, 0x302f, 0x2c2f, 0x7c1f,
0x781f, 0x741f, 0x701f, 0x6c1f,
0x028e, 0x028e, 0x027e, 0x027e,
0x026e, 0x026e, 0x025e, 0x025e,
0x024e, 0x024e, 0x023e, 0x023e,
0x022e, 0x022e, 0x021e, 0x021e,
0x020e, 0x020e, 0x04ee, 0x04ee,
0x04de, 0x04de, 0x04ce, 0x04ce,
0x04be, 0x04be, 0x04ae, 0x04ae,
0x049e, 0x049e, 0x048e, 0x048e,
0x01fd, 0x01fd, 0x01fd, 0x01fd,
0x01ed, 0x01ed, 0x01ed, 0x01ed,
0x01dd, 0x01dd, 0x01dd, 0x01dd,
0x01cd, 0x01cd, 0x01cd, 0x01cd,
0x01bd, 0x01bd, 0x01bd, 0x01bd,
0x01ad, 0x01ad, 0x01ad, 0x01ad,
0x019d, 0x019d, 0x019d, 0x019d,
0x018d, 0x018d, 0x018d, 0x018d,
0x017d, 0x017d, 0x017d, 0x017d,
0x016d, 0x016d, 0x016d, 0x016d,
0x015d, 0x015d, 0x015d, 0x015d,
0x014d, 0x014d, 0x014d, 0x014d,
0x013d, 0x013d, 0x013d, 0x013d,
0x012d, 0x012d, 0x012d, 0x012d,
0x011d, 0x011d, 0x011d, 0x011d,
0x010d, 0x010d, 0x010d, 0x010d,
0x282c, 0x282c, 0x282c, 0x282c,
0x282c, 0x282c, 0x282c, 0x282c,
0x242c, 0x242c, 0x242c, 0x242c,
0x242c, 0x242c, 0x242c, 0x242c,
0x143c, 0x143c, 0x143c, 0x143c,
0x143c, 0x143c, 0x143c, 0x143c,
0x0c4c, 0x0c4c, 0x0c4c, 0x0c4c,
0x0c4c, 0x0c4c, 0x0c4c, 0x0c4c,
0x085c, 0x085c, 0x085c, 0x085c,
0x085c, 0x085c, 0x085c, 0x085c,
0x047c, 0x047c, 0x047c, 0x047c,
0x047c, 0x047c, 0x047c, 0x047c,
0x046c, 0x046c, 0x046c, 0x046c,
0x046c, 0x046c, 0x046c, 0x046c,
0x00fc, 0x00fc, 0x00fc, 0x00fc,
0x00fc, 0x00fc, 0x00fc, 0x00fc,
0x00ec, 0x00ec, 0x00ec, 0x00ec,
0x00ec, 0x00ec, 0x00ec, 0x00ec,
0x00dc, 0x00dc, 0x00dc, 0x00dc,
0x00dc, 0x00dc, 0x00dc, 0x00dc,
0x00cc, 0x00cc, 0x00cc, 0x00cc,
0x00cc, 0x00cc, 0x00cc, 0x00cc,
0x681c, 0x681c, 0x681c, 0x681c,
0x681c, 0x681c, 0x681c, 0x681c,
0x641c, 0x641c, 0x641c, 0x641c,
0x641c, 0x641c, 0x641c, 0x641c,
0x601c, 0x601c, 0x601c, 0x601c,
0x601c, 0x601c, 0x601c, 0x601c,
0x5c1c, 0x5c1c, 0x5c1c, 0x5c1c,
0x5c1c, 0x5c1c, 0x5c1c, 0x5c1c,
0x581c, 0x581c, 0x581c, 0x581c,
0x581c, 0x581c, 0x581c, 0x581c,
};
 
unsigned short int dct_coeff_tbl_1[16] =
{
0x00bb, 0x202b, 0x103b, 0x00ab,
0x084b, 0x1c2b, 0x541b, 0x501b,
0x009b, 0x4c1b, 0x481b, 0x045b,
0x0c3b, 0x008b, 0x182b, 0x441b,
};
 
unsigned short int dct_coeff_tbl_2[4] =
{
0x4019, 0x1429, 0x0079, 0x0839,
};
 
unsigned short int dct_coeff_tbl_3[4] =
{
0x0449, 0x3c19, 0x3819, 0x1029,
};
 
unsigned short int dct_coeff_next[256] =
{
0xffff, 0xffff, 0xffff, 0xffff,
0xf7d5, 0xf7d5, 0xf7d5, 0xf7d5,
0x0826, 0x0826, 0x2416, 0x2416,
0x0046, 0x0046, 0x2016, 0x2016,
0x1c15, 0x1c15, 0x1c15, 0x1c15,
0x1815, 0x1815, 0x1815, 0x1815,
0x0425, 0x0425, 0x0425, 0x0425,
0x1415, 0x1415, 0x1415, 0x1415,
0x3417, 0x0067, 0x3017, 0x2c17,
0x0c27, 0x0437, 0x0057, 0x2817,
0x0034, 0x0034, 0x0034, 0x0034,
0x0034, 0x0034, 0x0034, 0x0034,
0x1014, 0x1014, 0x1014, 0x1014,
0x1014, 0x1014, 0x1014, 0x1014,
0x0c14, 0x0c14, 0x0c14, 0x0c14,
0x0c14, 0x0c14, 0x0c14, 0x0c14,
0x0023, 0x0023, 0x0023, 0x0023,
0x0023, 0x0023, 0x0023, 0x0023,
0x0023, 0x0023, 0x0023, 0x0023,
0x0023, 0x0023, 0x0023, 0x0023,
0x0813, 0x0813, 0x0813, 0x0813,
0x0813, 0x0813, 0x0813, 0x0813,
0x0813, 0x0813, 0x0813, 0x0813,
0x0813, 0x0813, 0x0813, 0x0813,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0xfbe1, 0xfbe1, 0xfbe1, 0xfbe1,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0011,
};
 
unsigned short int dct_coeff_first[256] =
{
0xffff, 0xffff, 0xffff, 0xffff,
0xf7d5, 0xf7d5, 0xf7d5, 0xf7d5,
0x0826, 0x0826, 0x2416, 0x2416,
0x0046, 0x0046, 0x2016, 0x2016,
0x1c15, 0x1c15, 0x1c15, 0x1c15,
0x1815, 0x1815, 0x1815, 0x1815,
0x0425, 0x0425, 0x0425, 0x0425,
0x1415, 0x1415, 0x1415, 0x1415,
0x3417, 0x0067, 0x3017, 0x2c17,
0x0c27, 0x0437, 0x0057, 0x2817,
0x0034, 0x0034, 0x0034, 0x0034,
0x0034, 0x0034, 0x0034, 0x0034,
0x1014, 0x1014, 0x1014, 0x1014,
0x1014, 0x1014, 0x1014, 0x1014,
0x0c14, 0x0c14, 0x0c14, 0x0c14,
0x0c14, 0x0c14, 0x0c14, 0x0c14,
0x0023, 0x0023, 0x0023, 0x0023,
0x0023, 0x0023, 0x0023, 0x0023,
0x0023, 0x0023, 0x0023, 0x0023,
0x0023, 0x0023, 0x0023, 0x0023,
0x0813, 0x0813, 0x0813, 0x0813,
0x0813, 0x0813, 0x0813, 0x0813,
0x0813, 0x0813, 0x0813, 0x0813,
0x0813, 0x0813, 0x0813, 0x0813,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0412, 0x0412, 0x0412, 0x0412,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010,
};
 
/* Macro for filling up the decoding table for mb_addr_inc */
#define ASSIGN1(start, end, step, val, num) \
for (i = start; i < end; i+= step) { \
for (j = 0; j < step; j++) { \
mb_addr_inc[i+j].value = val; \
mb_addr_inc[i+j].num_bits = num; \
} \
val--; \
}
 
 
/*
*--------------------------------------------------------------
*
* init_mb_addr_inc --
*
* Initialize the VLC decoding table for macro_block_address_increment
*
* Results:
* The decoding table for macro_block_address_increment will
* be filled; illegal values will be filled as ERROR.
*
* Side effects:
* The global array mb_addr_inc will be filled.
*
*--------------------------------------------------------------
*/
static void
init_mb_addr_inc()
{
int i, j, val;
 
for (i = 0; i < 8; i++) {
mb_addr_inc[i].value = ERROR;
mb_addr_inc[i].num_bits = 0;
}
 
mb_addr_inc[8].value = MACRO_BLOCK_ESCAPE;
mb_addr_inc[8].num_bits = 11;
 
for (i = 9; i < 15; i++) {
mb_addr_inc[i].value = ERROR;
mb_addr_inc[i].num_bits = 0;
}
 
mb_addr_inc[15].value = MACRO_BLOCK_STUFFING;
mb_addr_inc[15].num_bits = 11;
 
for (i = 16; i < 24; i++) {
mb_addr_inc[i].value = ERROR;
mb_addr_inc[i].num_bits = 0;
}
 
val = 33;
 
ASSIGN1(24, 36, 1, val, 11);
ASSIGN1(36, 48, 2, val, 10);
ASSIGN1(48, 96, 8, val, 8);
ASSIGN1(96, 128, 16, val, 7);
ASSIGN1(128, 256, 64, val, 5);
ASSIGN1(256, 512, 128, val, 4);
ASSIGN1(512, 1024, 256, val, 3);
ASSIGN1(1024, 2048, 1024, val, 1);
}
 
 
/* Macro for filling up the decoding table for mb_type */
#define ASSIGN2(start, end, quant, motion_forward, motion_backward, pattern, intra, num, mb_type) \
for (i = start; i < end; i ++) { \
mb_type[i].mb_quant = quant; \
mb_type[i].mb_motion_forward = motion_forward; \
mb_type[i].mb_motion_backward = motion_backward; \
mb_type[i].mb_pattern = pattern; \
mb_type[i].mb_intra = intra; \
mb_type[i].num_bits = num; \
}
 
/*
*--------------------------------------------------------------
*
* init_mb_type_P --
*
* Initialize the VLC decoding table for macro_block_type in
* predictive-coded pictures.
*
* Results:
* The decoding table for macro_block_type in predictive-coded
* pictures will be filled; illegal values will be filled as ERROR.
*
* Side effects:
* The global array mb_type_P will be filled.
*
*--------------------------------------------------------------
*/
static void
init_mb_type_P()
{
int i;
 
mb_type_P[0].mb_quant = mb_type_P[0].mb_motion_forward
= mb_type_P[0].mb_motion_backward = mb_type_P[0].mb_pattern
= mb_type_P[0].mb_intra = ERROR;
mb_type_P[0].num_bits = 0;
 
ASSIGN2(1, 2, 1, 0, 0, 0, 1, 6, mb_type_P)
ASSIGN2(2, 4, 1, 0, 0, 1, 0, 5, mb_type_P)
ASSIGN2(4, 6, 1, 1, 0, 1, 0, 5, mb_type_P);
ASSIGN2(6, 8, 0, 0, 0, 0, 1, 5, mb_type_P);
ASSIGN2(8, 16, 0, 1, 0, 0, 0, 3, mb_type_P);
ASSIGN2(16, 32, 0, 0, 0, 1, 0, 2, mb_type_P);
ASSIGN2(32, 64, 0, 1, 0, 1, 0, 1, mb_type_P);
}
 
 
 
/*
*--------------------------------------------------------------
*
* init_mb_type_B --
*
* Initialize the VLC decoding table for macro_block_type in
* bidirectionally-coded pictures.
*
* Results:
* The decoding table for macro_block_type in bidirectionally-coded
* pictures will be filled; illegal values will be filled as ERROR.
*
* Side effects:
* The global array mb_type_B will be filled.
*
*--------------------------------------------------------------
*/
static void
init_mb_type_B()
{
int i;
 
mb_type_B[0].mb_quant = mb_type_B[0].mb_motion_forward
= mb_type_B[0].mb_motion_backward = mb_type_B[0].mb_pattern
= mb_type_B[0].mb_intra = ERROR;
mb_type_B[0].num_bits = 0;
 
ASSIGN2(1, 2, 1, 0, 0, 0, 1, 6, mb_type_B);
ASSIGN2(2, 3, 1, 0, 1, 1, 0, 6, mb_type_B);
ASSIGN2(3, 4, 1, 1, 0, 1, 0, 6, mb_type_B);
ASSIGN2(4, 6, 1, 1, 1, 1, 0, 5, mb_type_B);
ASSIGN2(6, 8, 0, 0, 0, 0, 1, 5, mb_type_B);
ASSIGN2(8, 12, 0, 1, 0, 0, 0, 4, mb_type_B);
ASSIGN2(12, 16, 0, 1, 0, 1, 0, 4, mb_type_B);
ASSIGN2(16, 24, 0, 0, 1, 0, 0, 3, mb_type_B);
ASSIGN2(24, 32, 0, 0, 1, 1, 0, 3, mb_type_B);
ASSIGN2(32, 48, 0, 1, 1, 0, 0, 2, mb_type_B);
ASSIGN2(48, 64, 0, 1, 1, 1, 0, 2, mb_type_B);
}
 
 
/* Macro for filling up the decoding tables for motion_vectors */
#define ASSIGN3(start, end, step, val, num) \
for (i = start; i < end; i+= step) { \
for (j = 0; j < step / 2; j++) { \
motion_vectors[i+j].code = val; \
motion_vectors[i+j].num_bits = num; \
} \
for (j = step / 2; j < step; j++) { \
motion_vectors[i+j].code = -val; \
motion_vectors[i+j].num_bits = num; \
} \
val--; \
}
 
 
/*
*--------------------------------------------------------------
*
* init_motion_vectors --
*
* Initialize the VLC decoding table for the various motion
* vectors, including motion_horizontal_forward_code,
* motion_vertical_forward_code, motion_horizontal_backward_code,
* and motion_vertical_backward_code.
*
* Results:
* The decoding table for the motion vectors will be filled;
* illegal values will be filled as ERROR.
*
* Side effects:
* The global array motion_vector will be filled.
*
*--------------------------------------------------------------
*/
static void
init_motion_vectors()
{
int i, j, val = 16;
 
for (i = 0; i < 24; i++) {
motion_vectors[i].code = ERROR;
motion_vectors[i].num_bits = 0;
}
 
ASSIGN3(24, 36, 2, val, 11);
ASSIGN3(36, 48, 4, val, 10);
ASSIGN3(48, 96, 16, val, 8);
ASSIGN3(96, 128, 32, val, 7);
ASSIGN3(128, 256, 128, val, 5);
ASSIGN3(256, 512, 256, val, 4);
ASSIGN3(512, 1024, 512, val, 3);
ASSIGN3(1024, 2048, 1024, val, 1);
}
 
 
 
extern void init_pre_idct();
 
/*
*--------------------------------------------------------------
*
* init_tables --
*
* Initialize all the tables for VLC decoding; this must be
* called when the system is set up before any decoding can
* take place.
*
* Results:
* All the decoding tables will be filled accordingly.
*
* Side effects:
* The corresponding global array for each decoding table
* will be filled.
*
*--------------------------------------------------------------
*/
void
init_tables()
{
 
init_mb_addr_inc();
init_mb_type_P();
init_mb_type_B();
init_motion_vectors();
 
#ifdef FLOATDCT
if (qualityFlag)
init_float_idct();
else
#endif
init_pre_idct();
 
#ifdef ANALYSIS
{
init_stats();
}
#endif
}
 
#if OLDCODE
/*
*--------------------------------------------------------------
*
* DecodeDCTDCSizeLum --
*
* Huffman Decoder for dct_dc_size_luminance; location where
* the result of decoding will be placed is passed as argument.
* The decoded values are obtained by doing a table lookup on
* dct_dc_size_luminance.
*
* Results:
* The decoded value for dct_dc_size_luminance or ERROR for
* unbound values will be placed in the location specified.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
void
decodeDCTDCSizeLum(value)
unsigned int *value;
{
unsigned int index;
 
show_bits5(index);
if (index < 31) {
*value = dct_dc_size_luminance[index].value;
flush_bits(dct_dc_size_luminance[index].num_bits);
}
else {
show_bits9(index);
index -= 0x1f0;
*value = dct_dc_size_luminance1[index].value;
flush_bits(dct_dc_size_luminance1[index].num_bits);
}
}
 
 
 
/*
*--------------------------------------------------------------
*
* DecodeDCTDCSizeChrom --
*
* Huffman Decoder for dct_dc_size_chrominance; location where
* the result of decoding will be placed is passed as argument.
* The decoded values are obtained by doing a table lookup on
* dct_dc_size_chrominance.
*
* Results:
* The decoded value for dct_dc_size_chrominance or ERROR for
* unbound values will be placed in the location specified.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
void
decodeDCTDCSizeChrom(value)
unsigned int *value;
{
unsigned int index;
 
show_bits5(index);
if (index < 31) {
*value = dct_dc_size_chrominance[index].value;
flush_bits(dct_dc_size_chrominance[index].num_bits);
}
else {
show_bits10(index);
index -= 0x3e0;
*value = dct_dc_size_chrominance1[index].value;
flush_bits(dct_dc_size_chrominance1[index].num_bits);
}
}
 
 
/*
*--------------------------------------------------------------
*
* decodeDCTCoeff --
*
* Huffman Decoder for dct_coeff_first and dct_coeff_next;
* locations where the results of decoding: run and level, are to
* be placed and also the type of DCT coefficients, either
* dct_coeff_first or dct_coeff_next, are being passed as argument.
*
* The decoder first examines the next 8 bits in the input stream,
* and perform according to the following cases:
*
* '0000 0000' - examine 8 more bits (i.e. 16 bits total) and
* perform a table lookup on dct_coeff_tbl_0.
* One more bit is then examined to determine the sign
* of level.
*
* '0000 0001' - examine 4 more bits (i.e. 12 bits total) and
* perform a table lookup on dct_coeff_tbl_1.
* One more bit is then examined to determine the sign
* of level.
*
* '0000 0010' - examine 2 more bits (i.e. 10 bits total) and
* perform a table lookup on dct_coeff_tbl_2.
* One more bit is then examined to determine the sign
* of level.
*
* '0000 0011' - examine 2 more bits (i.e. 10 bits total) and
* perform a table lookup on dct_coeff_tbl_3.
* One more bit is then examined to determine the sign
* of level.
*
* otherwise - perform a table lookup on dct_coeff_tbl. If the
* value of run is not ESCAPE, extract one more bit
* to determine the sign of level; otherwise 6 more
* bits will be extracted to obtain the actual value
* of run , and then 8 or 16 bits to get the value of level.
*
*
*
* Results:
* The decoded values of run and level or ERROR for unbound values
* are placed in the locations specified.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
static void
decodeDCTCoeff(dct_coeff_tbl, run, level)
unsigned short int *dct_coeff_tbl;
unsigned int *run;
int *level;
{
unsigned int temp, index /*, num_bits */;
unsigned int value, next32bits, flushed;
 
/*
* Grab the next 32 bits and use it to improve performance of
* getting the bits to parse. Thus, calls are translated as:
*
* show_bitsX <--> next32bits >> (32-X)
* get_bitsX <--> val = next32bits >> (32-flushed-X);
* flushed += X;
* next32bits &= bitMask[flushed];
* flush_bitsX <--> flushed += X;
* next32bits &= bitMask[flushed];
*
*/
show_bits32(next32bits);
flushed = 0;
 
/* show_bits8(index); */
index = next32bits >> 24;
 
if (index > 3) {
value = dct_coeff_tbl[index];
*run = (value & RUN_MASK) >> RUN_SHIFT;
if (*run == END_OF_BLOCK) {
*level = END_OF_BLOCK;
}
else {
/* num_bits = (value & NUM_MASK) + 1; */
/* flush_bits(num_bits); */
flushed = (value & NUM_MASK) + 1;
next32bits &= bitMask[flushed];
if (*run != ESCAPE) {
*level = (value & LEVEL_MASK) >> LEVEL_SHIFT;
/* get_bits1(value); */
/* if (value) *level = -*level; */
if (next32bits >> (31-flushed)) *level = -*level;
flushed++;
/* next32bits &= bitMask[flushed]; last op before update */
}
else { /* *run == ESCAPE */
/* get_bits14(temp); */
temp = next32bits >> (18-flushed);
flushed += 14;
next32bits &= bitMask[flushed];
*run = temp >> 8;
temp &= 0xff;
if (temp == 0) {
/* get_bits8(*level); */
*level = next32bits >> (24-flushed);
flushed += 8;
/* next32bits &= bitMask[flushed]; last op before update */
assert(*level >= 128);
} else if (temp != 128) {
/* Grab sign bit */
*level = ((int) (temp << 24)) >> 24;
} else {
/* get_bits8(*level); */
*level = next32bits >> (24-flushed);
flushed += 8;
/* next32bits &= bitMask[flushed]; last op before update */
*level = *level - 256;
assert(*level <= -128 && *level >= -255);
}
}
/* Update bitstream... */
flush_bits(flushed);
}
}
else {
if (index == 2) {
/* show_bits10(index); */
index = next32bits >> 22;
value = dct_coeff_tbl_2[index & 3];
}
else if (index == 3) {
/* show_bits10(index); */
index = next32bits >> 22;
value = dct_coeff_tbl_3[index & 3];
}
else if (index) { /* index == 1 */
/* show_bits12(index); */
index = next32bits >> 20;
value = dct_coeff_tbl_1[index & 15];
}
else { /* index == 0 */
/* show_bits16(index); */
index = next32bits >> 16;
value = dct_coeff_tbl_0[index & 255];
}
*run = (value & RUN_MASK) >> RUN_SHIFT;
*level = (value & LEVEL_MASK) >> LEVEL_SHIFT;
 
/*
* Fold these operations together to make it fast...
*/
/* num_bits = (value & NUM_MASK) + 1; */
/* flush_bits(num_bits); */
/* get_bits1(value); */
/* if (value) *level = -*level; */
 
flushed = (value & NUM_MASK) + 2;
if ((next32bits >> (32-flushed)) & 0x1) *level = -*level;
 
/* Update bitstream ... */
flush_bits(flushed);
}
}
 
/*
*--------------------------------------------------------------
*
* decodeDCTCoeffFirst --
*
* Huffman Decoder for dct_coeff_first. Locations for the
* decoded results: run and level, are being passed as
* arguments. Actual work is being done by calling DecodeDCTCoeff,
* with the table dct_coeff_first.
*
* Results:
* The decoded values of run and level for dct_coeff_first or
* ERROR for unbound values are placed in the locations given.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
void
decodeDCTCoeffFirst(run, level)
unsigned int *run;
int *level;
{
decodeDCTCoeff(dct_coeff_first, run, level);
}
 
 
 
/*
*--------------------------------------------------------------
*
* decodeDCTCoeffNext --
*
* Huffman Decoder for dct_coeff_first. Locations for the
* decoded results: run and level, are being passed as
* arguments. Actual work is being done by calling DecodeDCTCoeff,
* with the table dct_coeff_next.
*
* Results:
* The decoded values of run and level for dct_coeff_next or
* ERROR for unbound values are placed in the locations given.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
void
decodeDCTCoeffNext(run, level)
unsigned int *run;
int *level;
{
decodeDCTCoeff(dct_coeff_next, run, level);
}
#endif
/shark/trunk/ports/mpeg/mpegvga.pat
0,0 → 1,1206
*** gray.c Tue Feb 2 23:58:35 1993
--- mpegvga/gray.c Sun Oct 17 17:19:39 1993
***************
*** 53,58 ****
--- 53,59 ----
int i, max = w*h/16;
for (i=0; i<max; i++) {
+ /*
out[0] = pixel[lum[0]];
out[1] = pixel[lum[1]];
out[2] = pixel[lum[2]];
***************
*** 69,74 ****
--- 70,81 ----
out[13] = pixel[lum[13]];
out[14] = pixel[lum[14]];
out[15] = pixel[lum[15]];
+ */
+ /* For VGA, pixel[i] = i */
+ *(unsigned *)(&out[0]) = *(unsigned *)(&lum[0]);
+ *(unsigned *)(&out[4]) = *(unsigned *)(&lum[4]);
+ *(unsigned *)(&out[8]) = *(unsigned *)(&lum[8]);
+ *(unsigned *)(&out[12]) = *(unsigned *)(&lum[12]);
out += 16;
lum += 16;
}
*** proto.h Wed Feb 3 16:02:59 1993
--- mpegvga/proto.h Sun Oct 17 16:57:16 1993
***************
*** 49,55 ****
--- 49,57 ----
/* gdith.c */
void InitColor P((void ));
+ /*
int HandleXError P((Display *dpy , XErrorEvent *event ));
+ */
void InstallXErrorHandler P((void ));
void DeInstallXErrorHandler P((void ));
void ResizeDisplay P((int w , int h ));
***************
*** 102,109 ****
--- 104,113 ----
void ColorDitherImage P((unsigned char *lum , unsigned char *cr , unsigned char *cb , unsigned char *out , int rows , int cols ));
/* util32.c */
+ /*
Visual *FindFullColorVisual P((Display *dpy , int *depth ));
Window CreateFullColorWindow P((Display *dpy , int x , int y , int w , int h ));
+ */
/* ordered.c */
void InitOrderedDither P((void ));
*** util.c Tue Feb 2 23:58:38 1993
--- mpegvga/util.c Sun Oct 17 16:48:04 1993
***************
*** 20,25 ****
--- 20,26 ----
*/
#include <stdlib.h>
+ #include <vga.h>
#include "video.h"
#include "proto.h"
#include "util.h"
***************
*** 104,109 ****
--- 105,111 ----
fprintf (stderr, "\n");
perror("Unexpected read error.");
}
+ vga_setmode(TEXT);
exit(1);
}
else if ((status == 0) && (bufLength < 1)) {
***************
*** 119,124 ****
--- 121,127 ----
if (loopFlag) longjmp(env, 1);
DestroyVidStream(curVidStream);
+ vga_setmode(TEXT);
exit(0);
}
#ifdef UTIL2
*** video.c Tue Feb 2 23:58:41 1993
--- mpegvga/video.c Sat Oct 23 14:04:06 1993
***************
*** 24,30 ****
#include <stdio.h>
#include <stdlib.h>
! #include <assert.h>
#ifndef MIPS
#include <sys/time.h>
--- 24,31 ----
#include <stdio.h>
#include <stdlib.h>
! /* #include <assert.h> */
! #define assert(c)
#ifndef MIPS
#include <sys/time.h>
***************
*** 32,37 ****
--- 33,39 ----
#include <sys/types.h>
#include <sys/system.h>
#endif
+ #include <vga.h>
#include "decoders.h"
#include "video.h"
***************
*** 985,990 ****
--- 987,993 ----
if (data != SEQ_START_CODE) {
fprintf(stderr, "This is not an MPEG stream.");
DestroyVidStream(curVidStream);
+ vga_setmode(TEXT);
exit(1);
}
first = 0;
***************
*** 1024,1029 ****
--- 1027,1033 ----
longjmp(env, 1);
DestroyVidStream(curVidStream);
+ vga_setmode(TEXT);
exit(0);
break;
***************
*** 1579,1584 ****
--- 1583,1589 ----
while (vid_stream->ring[i]->locked != 0) {
if (++i >= RING_BUF_SIZE) {
perror("Fatal error. Ring buffer full.");
+ vga_setmode(TEXT);
exit(1);
}
}
*** video.h Tue Feb 2 23:58:41 1993
--- mpegvga/video.h Sun Oct 17 16:56:44 1993
***************
*** 21,28 ****
--- 21,30 ----
#include <stdio.h>
#include <setjmp.h>
+ /*
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+ */
#ifdef SH_MEM
#include <sys/ipc.h>
***************
*** 244,250 ****
extern VidStream *curVidStream;
/* Declarataion of global display pointer. */
! extern Display *display;
/* Shared memory flag. */
extern int shmemFlag;
--- 246,252 ----
extern VidStream *curVidStream;
/* Declarataion of global display pointer. */
! /* extern Display *display; */
/* Shared memory flag. */
extern int shmemFlag;
*** README.linux Sun Jan 15 16:44:10 1995
--- mpegvga/README.linux Sun Jan 15 16:06:09 1995
***************
*** 0 ****
--- 1,49 ----
+
+ This is a port of the Berkeley MPEG Video Software Decoder v2.0 to Linux.
+
+ Two binaries are provided. They require the ld.so shared library loader.
+
+ mpeg_play
+
+ A binary compiled from the stock sources, using the XFree86-2.0 libraries.
+ It was compiled with the flags: -O2 -fomit-frame-pointer -m486 (implicit)
+ using gcc 2.5.4, with some debugging code left out. Uses the X shared memory
+ extension that XFree86 v2.0 provides, which is a big win. The stock sources
+ compile cleanly and trivially.
+
+ mpeg_vga
+
+ A non-X version that uses svgalib. It is slightly faster than the X version
+ with shared memory and can use low resolution graphics modes. Also, with
+ truecolor graphics cards that svgalib supports (Cirrus, ET4000), full color
+ dithering can be used, which is very pretty. The graphics mode to be used can
+ be set with the GSVGAMODE environment variable. Requires svgalib 0.91 or
+ later installed.
+
+ For full color dithering (-dither color), 320x200x16M graphics mode is used
+ if it is available and the picture is small enough; if not, 640x480x16M is
+ used if available. 32K mode probed similarly.
+
+ For most other dithering methods, 320x200x256 standard VGA graphics mode is
+ used if the picture is small enough; 640x480x256 otherwise.
+
+ For mono dithering, 640x480x2 VGA graphics mode is used.
+
+ [NOTE: The previously uploaded version contained patches for some hacked
+ version of the stock sources; sorry for that.]
+ Patches for the stock sources are included (mpegvga.patch). It removes X
+ references, and uses svgalib instead. Also, the speed of gray dithering and
+ full-color dithering has been improved. svgalib v0.91 or later is required to
+ compile; it can be found on sunsite.unc.edu, directory /pub/Linux/libs.
+ [Speed hack have been incorporated into the main source]
+
+ mpeg_play -h (or any other invalid flag) displays dithering and other options.
+
+ Note that with gray dithering, very little time is spent converting from the
+ raw uncompressed data to a screen bitmap suitable for display, making it
+ significantly faster than the other methods.
+
+ The v2.0 source is available on sunsite.unc.edu. For sample MPEG data,
+ mm-ftp.cs.berkeley.edu, /pub/multimedia is one place to look.
+
+ hhanemaa@cs.ruu.nl
*** gdith.c Sun Jan 29 22:17:25 1995
--- mpegvga/gdith.c Sun Jan 29 22:44:59 1995
***************
*** 28,33 ****
--- 28,35 ----
*/
#include <math.h>
+ #include <vga.h>
+ #include <vgagl.h>
#include "video.h"
#include "proto.h"
#include "dither.h"
***************
*** 52,65 ****
extern int ditherType;
! /* Structures used by the X server. */
!
! Display *display;
!
! static XImage *ximage = NULL;
! static Colormap cmap;
! static Window window;
! static GC gc;
/* Frame Rate Info */
extern int framerate;
--- 54,60 ----
extern int ditherType;
! int vgamode = -1;
/* Frame Rate Info */
extern int framerate;
***************
*** 155,351 ****
}
- #ifdef SH_MEM
-
- int gXErrorFlag = 0;
-
- int HandleXError(dpy, event)
- Display *dpy;
- XErrorEvent *event;
- {
- gXErrorFlag = 1;
-
- return 0;
- }
-
- void InstallXErrorHandler()
- {
- int HandleXError();
-
- XSetErrorHandler(HandleXError);
- XFlush(display);
- }
- void DeInstallXErrorHandler()
- {
- XSetErrorHandler(NULL);
- XFlush(display);
- }
- #endif
-
- /*
- *--------------------------------------------------------------
- *
- * ResizeDisplay --
- *
- * Resizes display window.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
void ResizeDisplay(w, h)
int w, h;
{
!
! if (ditherType == NO_DITHER || ditherType == PPM_DITHER) return;
!
! XResizeWindow(display, window, w, h);
! XFlush(display);
}
-
- /*
- *--------------------------------------------------------------
- *
- * MakeWindow --
- *
- * Create X Window
- *
- * Results:
- * Read the code.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
! #ifdef SH_MEM
! int CompletionType = -1;
! #endif
static void
MakeWindow(name)
char *name;
{
! XSizeHints hint;
! unsigned int fg, bg;
! char *hello = "MPEG Play";
! int screen;
! Screen *screen_ptr;
! Window CreateFullColorWindow();
!
! if (ditherType == NO_DITHER || ditherType == PPM_DITHER) return;
!
! display = XOpenDisplay(name);
! if (display == NULL) {
! fprintf(stderr, "Can not open display\n");
! exit(-2);
! }
! #ifdef SH_MEM
! if(shmemFlag)
! CompletionType = XShmGetEventBase(display) + ShmCompletion;
! #endif
! screen = DefaultScreen (display);
! screen_ptr = XDefaultScreenOfDisplay(display);
!
! /* Fill in hint structure */
! hint.x = 200;
! hint.y = 300;
! hint.width = 150;
! hint.height = 150;
! hint.flags = PPosition | PSize;
!
! /* Get some colors */
!
! bg = WhitePixel (display, screen);
! fg = BlackPixel (display, screen);
!
! /* Make the window */
! if (ditherType == FULL_COLOR_DITHER || ditherType==FULL_COLOR2_DITHER) {
! window = CreateFullColorWindow (display, hint.x, hint.y, hint.width, hint.height);
! if (window == 0) {
! fprintf (stderr, "-color option only valid on full color display\n");
! exit (-1);
! }
} else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
! window = XCreateSimpleWindow (display,
! DefaultRootWindow (display),
! hint.x, hint.y,
! hint.width, hint.height,
! 4, fg, bg);
} else {
! XVisualInfo vinfo, *vinfo_ptr;
! Visual *vis;
! XSetWindowAttributes attrib;
! unsigned long attrib_flags=0;
!
! if (!XMatchVisualInfo (display, screen, 8, PseudoColor,
! &vinfo)) {
! if (!XMatchVisualInfo(display, screen, 8, GrayScale,
! &vinfo)) {
! fprintf(stderr, "-requires 8 bit display\n");
! exit(-1);
! }
! }
!
! vis=vinfo.visual;
! if (XDefaultDepthOfScreen(screen_ptr) != 8) {
! attrib_flags |= CWColormap;
! attrib.colormap = XCreateColormap(display, DefaultRootWindow(display),
! vis, AllocNone);
! owncmFlag = TRUE;
! }
!
! attrib.background_pixel = bg;
! attrib.border_pixel = fg;
! attrib.backing_store = NotUseful;
! attrib.save_under = False;
! attrib.background_pixel = bg;
! attrib.border_pixel = bg;
! attrib_flags |= CWBackPixel | CWBorderPixel | CWBackingStore | CWSaveUnder;
! window = XCreateWindow (display,
! DefaultRootWindow (display),
! hint.x, hint.y,
! hint.width, hint.height, 4,
! 8, InputOutput, vis,
! attrib_flags, &attrib);
! }
!
! XSelectInput(display, window, StructureNotifyMask);
!
! /* Tell other applications about this window */
!
! XSetStandardProperties (display, window, hello, hello, None, NULL, 0, &hint);
!
! /* Map window. */
!
! XMapWindow(display, window);
!
! /* Wait for map. */
! while(1) {
! XEvent xev;
!
! XNextEvent(display, &xev);
! if(xev.type == MapNotify && xev.xmap.event == window)
! break;
! }
!
! XSelectInput(display, window, NoEventMask);
}
!
/*
*--------------------------------------------------------------
--- 150,286 ----
}
void ResizeDisplay(w, h)
int w, h;
{
! vga_modeinfo *modeinfo;
! /* Check if current VGA mode is big enough. */
! modeinfo = vga_getmodeinfo(vgamode);
! if (w > modeinfo->width || h > modeinfo->height) {
! int fail = 0;
! if (w > 640 || h > 480)
! fail = 1;
! else
! if (modeinfo->width == 320) {
! fail = 1;
! switch (modeinfo->bytesperpixel) {
! case 1 :
! if (vga_hasmode(G640x480x256)) {
! Palette pal;
! gl_getpalette(&pal);
! vgamode = G640x480x256;
! vga_setmode(vgamode);
! gl_setpalette(&pal);
! gl_setcontextvga(vgamode);
! if (ditherType != GRAY_DITHER)
! gl_clearscreen(255);
! gl_enableclipping();
! fail = 0;
! }
! break;
! case 2 :
! if (vga_hasmode(G640x480x32K)) {
! vgamode = G640x480x32K;
! vga_setmode(vgamode);
! gl_setcontextvga(vgamode);
! gl_enableclipping();
! fail = 0;
! }
! break;
! case 3 :
! if (vga_hasmode(G640x480x16M)) {
! vgamode = G640x480x16M;
! vga_setmode(vgamode);
! gl_setcontextvga(vgamode);
! gl_enableclipping();
! fail = 0;
! }
! break;
! }
! }
! else
! fail = 1;
! if (fail) {
! printf("MPEG screen size too big.\n");
! vga_setmode(TEXT);
! exit(-1);
! }
! }
}
! void
! restoretextmode() {
! vga_setmode(TEXT);
! }
static void
MakeWindow(name)
char *name;
{
! if (ditherType == NO_DITHER) return;
! /* Make the window */
! vga_disabledriverreport();
! vga_init();
! #define FIRSTRES(c) G320x200x##c
! #define SECONDRES(c) G640x480x##c
! if (ditherType == FULL_COLOR_DITHER) {
! /* Look for hicolor/truecolor mode. */
! /* 640x480 resolution makes most animations very small. */
! /* 320x200 is more full-screen, but the distortions are very visible. */
! /* Check default svgalib mode. */
! vgamode = vga_getdefaultmode();
! if (vgamode != -1) {
! if (vga_getmodeinfo(vgamode)->bytesperpixel == 3)
! /* Default mode is a truecolor mode. */
! goto gotvgamode;
! if (vga_getmodeinfo(vgamode)->colors == 32768)
! goto gotvgamode;
! }
! if (vga_hasmode(FIRSTRES(16M)))
! vgamode = FIRSTRES(16M);
! else if (vga_hasmode(SECONDRES(16M)))
! vgamode = SECONDRES(16M);
! else if (vga_hasmode(FIRSTRES(32K)))
! vgamode = FIRSTRES(32K);
! else if (vga_hasmode(SECONDRES(32K)))
! vgamode = SECONDRES(32K);
} else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
! /* set mode suitable for mono display if available */
! if (vga_hasmode(G640x480x2))
! vgamode = G640x480x2;
} else {
! /* set 256-color mode */
! /* Check default svgalib mode. */
! vgamode = vga_getdefaultmode();
! if (vgamode != -1)
! if (vga_getmodeinfo(vgamode)->bytesperpixel == 1)
! /* Default mode is a 256 color mode. */
! goto gotvgamode;
! if (vga_hasmode(FIRSTRES(256)))
! vgamode = FIRSTRES(256);
! else if (vga_hasmode(SECONDRES(256)))
! vgamode = SECONDRES(256);
! }
! if (vgamode == -1) {
! printf("Cannot find suitable SVGA graphics mode for selected dithering.\n");
! exit(-1);
! }
! gotvgamode:
! printf("Using mode %s.\n", vga_getmodename(vgamode));
! vga_setmode(vgamode);
! gl_setcontextvga(vgamode);
! gl_enableclipping();
}
!
/*
*--------------------------------------------------------------
***************
*** 366,429 ****
void InitDisplay(name)
char *name;
{
int ncolors = LUM_RANGE*CB_RANGE*CR_RANGE;
- XColor xcolor;
int i, lum_num, cr_num, cb_num;
! unsigned char r, g, b;
! Colormap dcmap;
if (ditherType == NO_DITHER) return;
- if (noDisplayFlag) return;
MakeWindow(name);
! gc = XCreateGC(display, window, 0, 0);
!
! dcmap = cmap = XDefaultColormap(display, DefaultScreen(display));
!
! xcolor.flags = DoRed | DoGreen | DoBlue;
- if (owncmFlag) goto create_map;
- retry_alloc_colors:
for (i=0; i<ncolors; i++) {
lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE;
cr_num = (i / CB_RANGE)%CR_RANGE;
cb_num = i % CB_RANGE;
ConvertColor(lum_values[lum_num], cr_values[cr_num], cb_values[cb_num], &r, &g, &b);
! xcolor.red = r * 256;
! xcolor.green = g * 256;
! xcolor.blue = b * 256;
!
! if (XAllocColor(display, cmap, &xcolor) == 0 && cmap == dcmap) {
! int j;
! unsigned long tmp_pixel;
! XWindowAttributes xwa;
!
! if (!quietFlag) {
! fprintf(stderr, "Using private colormap.\n");
! }
!
! /* Free colors. */
! for(j = 0; j < i; j ++) {
! tmp_pixel = pixel[j];
! XFreeColors(display, cmap, &tmp_pixel, 1, 0);
! }
!
! create_map:
! XGetWindowAttributes(display, window, &xwa);
! cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
! XSetWindowColormap(display, window, cmap);
!
! goto retry_alloc_colors;
}
! pixel[i] = xcolor.pixel;
}
-
- ximage = NULL;
}
--- 301,336 ----
void InitDisplay(name)
char *name;
{
+ /* For 256 color modes. */
int ncolors = LUM_RANGE*CB_RANGE*CR_RANGE;
int i, lum_num, cr_num, cb_num;
! int r, g, b;
if (ditherType == NO_DITHER) return;
MakeWindow(name);
! gl_setpalettecolor(255, 0, 0, 0); /* black */
! gl_clearscreen(255);
for (i=0; i<ncolors; i++) {
lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE;
cr_num = (i / CB_RANGE)%CR_RANGE;
cb_num = i % CB_RANGE;
+ r = g = b = 0;
ConvertColor(lum_values[lum_num], cr_values[cr_num], cb_values[cb_num], &r, &g, &b);
! if (i > 256) {
! printf("mpeg_vga: not enough colors.\n");
! vga_setmode(TEXT);
! exit(-1);
}
! gl_setpalettecolor(i, r >> 2, g >> 2, b >> 2);
! pixel[i] = i;
}
}
***************
*** 443,572 ****
*--------------------------------------------------------------
*/
! void InitGrayDisplay(name)
! char *name;
! {
! int ncolors = 128;
! XColor xcolor;
! int i;
! Colormap dcmap;
!
! MakeWindow(name);
!
! gc = XCreateGC(display, window, 0, 0);
!
! dcmap = cmap = XDefaultColormap(display, DefaultScreen(display));
!
! xcolor.flags = DoRed | DoGreen | DoBlue;
!
! if (owncmFlag) goto create_map;
! retry_alloc_grays:
! for (i=0; i<ncolors; i++) {
!
! xcolor.red = (i*2) * 256;
! xcolor.green = (i*2) * 256;
! xcolor.blue = (i*2) * 256;
!
! if(XAllocColor(display, cmap, &xcolor) == 0 && cmap == dcmap) {
! int j;
! unsigned long tmp_pixel;
! XWindowAttributes xwa;
!
! if (!quietFlag) {
! fprintf(stderr, "Using private colormap.\n");
! }
!
! /* Free colors. */
! for(j = 0; j < i; j ++) {
! tmp_pixel = pixel[j*2];
! XFreeColors(display, cmap, &tmp_pixel, 1, 0);
! }
!
! create_map:
! XGetWindowAttributes(display, window, &xwa);
! cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
! XSetWindowColormap(display, window, cmap);
!
! goto retry_alloc_grays;
! }
! pixel[(i*2)] = xcolor.pixel;
! pixel[(i*2)+1] = xcolor.pixel;
! }
! ximage = NULL;
! }
!
!
! /*
! *--------------------------------------------------------------
! *
! * InitGray256Display --
! *
! * Initialized display for gray scale dither with 256 levels
! *
! * Results:
! * None.
! *
! * Side effects:
! * None.
! *
! *--------------------------------------------------------------
! */
!
!
! void InitGray256Display(name)
char *name;
{
! int ncolors = 256;
! XColor xcolor;
int i;
- Colormap dcmap;
- int result;
- XWindowAttributes xwa;
MakeWindow(name);
- gc = XCreateGC(display, window, 0, 0);
-
- dcmap = cmap = XDefaultColormap(display, DefaultScreen(display));
-
- xcolor.flags = DoRed | DoGreen | DoBlue;
-
- if (owncmFlag) {
- XGetWindowAttributes(display, window, &xwa);
- cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
- XSetWindowColormap(display, window, cmap);
- }
-
- retry_alloc_grays:
for (i=0; i<ncolors; i++) {
! xcolor.red = i * 256;
! xcolor.green = i * 256;
! xcolor.blue = i * 256;
! if((result=XAllocColor(display, cmap, &xcolor)) == 0 && cmap == dcmap) {
! int j;
! unsigned long tmp_pixel;
!
! if (!quietFlag) {
! fprintf(stderr, "Using private colormap.\n");
! }
!
! /* Free colors. */
! for(j = 0; j < i; j ++) {
! tmp_pixel = pixel[j];
! XFreeColors(display, cmap, &tmp_pixel, 1, 0);
! }
!
! XGetWindowAttributes(display, window, &xwa);
! cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
! XSetWindowColormap(display, window, cmap);
!
! goto retry_alloc_grays;
! }
! pixel[i] = xcolor.pixel;
}
-
- ximage = NULL;
}
--- 350,374 ----
*--------------------------------------------------------------
*/
! #define NUM_COLORS 256
! void InitGrayDisplay(name)
char *name;
{
! int ncolors = NUM_COLORS;
int i;
MakeWindow(name);
for (i=0; i<ncolors; i++) {
! int r, g, b;
! r = i;
! g = i;
! b = i;
!
! gl_setpalettecolor(i, r / 4, g / 4, b / 4);
! pixel[i] = i;
}
}
***************
*** 589,608 ****
void InitMonoDisplay(name)
char *name;
{
- XGCValues xgcv;
MakeWindow(name);
- xgcv.background = BlackPixel(display, DefaultScreen(display));
- xgcv.foreground = WhitePixel(display, DefaultScreen(display));
-
- gc = XCreateGC(display, window, GCForeground | GCBackground, &xgcv);
-
- ximage = NULL;
}
-
/*
*--------------------------------------------------------------
*
--- 391,402 ----
***************
*** 625,632 ****
MakeWindow(name);
- gc = XCreateGC(display, window, 0, 0);
- ximage = NULL;
}
--- 419,424 ----
***************
*** 650,659 ****
ExecuteDisplay(vid_stream)
VidStream *vid_stream;
{
- char dummy;
- Visual *FindFullColorVisual();
- Visual *fc_visual;
- int depth;
static int rate_deal=-1, one_frame_time;
static struct timeval tftarget, tfnow;
int zero=0;
--- 442,447 ----
***************
*** 664,669 ****
--- 452,459 ----
fprintf (stderr, "%d\r", totNumFrames);
}
+ if (ditherType == NO_DITHER) return;
+
if (partialFlag)
if (!((totNumFrames>=startFrame) &&
((endFrame==-1) || (totNumFrames<=endFrame))))
***************
*** 722,790 ****
while ((foo=getchar())!='\n');
}
- if (ditherType == NO_DITHER) return;
if (ditherType == PPM_DITHER) {
ExecutePPM(vid_stream);
return;
}
! if (ximage == NULL) {
!
! if (ditherType == Twox2_DITHER) {
! ximage = XCreateImage(display, None, 8, ZPixmap, 0, &dummy,
! vid_stream->mb_width * 32,
! vid_stream->mb_height * 32, 8, 0);
! } else if (ditherType == FULL_COLOR_DITHER) {
! fc_visual = FindFullColorVisual(display, &depth);
! ximage = XCreateImage (display, fc_visual, depth, ZPixmap,
! 0, &dummy, vid_stream->mb_width * 16,
! vid_stream->mb_height * 16, 32, 0);
! } else if (ditherType == FULL_COLOR2_DITHER) {
! fc_visual = FindFullColorVisual(display, &depth);
! ximage = XCreateImage (display, fc_visual, depth, ZPixmap,
! 0, &dummy, vid_stream->mb_width * 32,
! vid_stream->mb_height * 32, 32, 0);
! } else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
! ximage = XCreateImage (display, None, 1, XYBitmap, 0, &dummy,
! vid_stream->mb_width * 16,
! vid_stream->mb_height * 16, 8, 0);
! ximage->byte_order = MSBFirst;
! ximage->bitmap_bit_order = MSBFirst;
! } else {
! ximage = XCreateImage(display, None, 8, ZPixmap, 0, &dummy,
! vid_stream->mb_width * 16,
! vid_stream->mb_height * 16, 8, 0);
! }
! }
!
! if (!noDisplayFlag) {
! #ifdef SH_MEM
! if (shmemFlag) {
! XShmPutImage(display, window, gc, vid_stream->current->ximage,
! 0, 0, 0, 0,
! vid_stream->current->ximage->width,
! vid_stream->current->ximage->height, True);
! XFlush(display);
!
! while(1) {
! XEvent xev;
!
! XNextEvent(display, &xev);
! if(xev.type == CompletionType)
! break;
! }
! }
! else
! #endif
!
{
! ximage->data = (char *) vid_stream->current->display;
! XPutImage(display, window, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
}
- }
}
-
extern char *inputName;
extern char *strrchr();
--- 512,623 ----
while ((foo=getchar())!='\n');
}
if (ditherType == PPM_DITHER) {
ExecutePPM(vid_stream);
return;
}
! if (!noDisplayFlag)
{
! void *data = (char *) vid_stream->current->display;
! if (ditherType == Twox2_DITHER) {
! /* Twice the size; 256-color mode */
! gl_putbox(0, 0, vid_stream->h_size * 2,
! vid_stream->v_size * 2, data);
! } else if (ditherType == FULL_COLOR_DITHER && BYTESPERPIXEL == 3) {
! /* Tricky conversion. */
! /* The data is padded to 32 bits per pixel, we need 24 bits. */
! int i, w;
! unsigned int *datap;
! void *box;
! unsigned char *boxp;
! datap = data;
! w = vid_stream->h_size;
! box = alloca(vid_stream->v_size * w * 3 + 3);
! boxp = box;
! for (i = 0; i < vid_stream->v_size; i++) {
! int j = 0;
! /* First byte is blue. */
! /* Nasty overlapping memory writes, but it is fast. */
! /* Note that boxp points to bytes, datap to words. */
! while (j + 7 < w) {
! *(unsigned *)boxp = *datap;
! *(unsigned *)(boxp + 3) = *(datap + 1);
! *(unsigned *)(boxp + 6) = *(datap + 2);
! *(unsigned *)(boxp + 9) = *(datap + 3);
! *(unsigned *)(boxp + 12) = *(datap + 4);
! *(unsigned *)(boxp + 15) = *(datap + 5);
! *(unsigned *)(boxp + 18) = *(datap + 6);
! *(unsigned *)(boxp + 21) = *(datap + 7);
! j += 8;
! boxp += 24;
! datap += 8;
! }
! while (j < w) {
! *(unsigned *)boxp = *datap;
! j++;
! boxp += 3;
! datap++;
! }
! }
! gl_putbox(0, 0, vid_stream->h_size, vid_stream->v_size, box);
! } else if (ditherType == FULL_COLOR_DITHER && BYTESPERPIXEL == 2) {
! /* The data is 8-8-8 truecolor padded to 32 bits, we need */
! /* 15-bit 5-5-5 truecolor. Pretty slow conversion. */
! int i, w;
! unsigned int *datap;
! void *box;
! unsigned char *boxp;
! datap = data;
! w = vid_stream->h_size;
! box = alloca(vid_stream->v_size * w * 2 + 3);
! boxp = box;
! for (i = 0; i < vid_stream->v_size; i++) {
! int j = 0;
! /* First byte is blue. */
! /* Note that boxp points to bytes, datap to words. */
! while (j + 1 < w) {
! unsigned r, g, b;
! b = *((unsigned char *)datap);
! g = *((unsigned char *)datap + 1);
! r = *((unsigned char *)datap + 2);
! *(unsigned short *)boxp =
! ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + (b >> 3);
! b = *((unsigned char *)datap + 4);
! g = *((unsigned char *)datap + 5);
! r = *((unsigned char *)datap + 6);
! *(unsigned short *)(boxp + 2) =
! ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + (b >> 3);
! j += 2;
! boxp += 4;
! datap += 2;
! }
! while (j < w) {
! unsigned r, g, b;
! r = *((unsigned char *)datap);
! g = *((unsigned char *)datap + 1);
! g = *((unsigned char *)datap + 2);
! *(unsigned short *)boxp =
! ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + (b >> 3);
! j++;
! boxp += 2;
! datap++;
! }
! }
! gl_putbox(0, 0, vid_stream->h_size, vid_stream->v_size, box);
! } else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
! /* It's MSBFirst, which is what we need. */
! int i;
! for (i = 0; i < vid_stream->v_size; i++)
! vga_drawscansegment(data + i * vid_stream->h_size / 8,
! 0, i, vid_stream->h_size / 8);
! } else {
! /* default 256-color dithering */
! gl_putbox(0, 0, vid_stream->h_size, vid_stream->v_size, data);
! }
}
}
extern char *inputName;
extern char *strrchr();
*** main.c Sun Jan 29 22:17:25 1995
--- mpegvga/main.c Sun Jan 29 22:48:49 1995
***************
*** 128,133 ****
--- 128,134 ----
}
if (curVidStream != NULL)
DestroyVidStream(curVidStream);
+ restoretextmode();
exit(1);
}
#else
***************
*** 140,145 ****
--- 141,147 ----
}
if (curVidStream != NULL)
DestroyVidStream(curVidStream);
+ restoretextmode();
exit(1);
}
#endif
***************
*** 307,324 ****
exit(1);
#endif
}
- else if (strcmp(argv[mark], "-shmem_off") == 0) {
- argc--; mark++;
- shmemFlag = 0;
- }
else if (strcmp(argv[mark], "-quiet") == 0) {
argc--; mark++;
quietFlag = 1;
}
- else if (strcmp(argv[mark], "-owncm") == 0) {
- argc--; mark++;
- owncmFlag = 1;
- }
else if (strcmp(argv[mark], "-step") == 0) {
argc--; mark++;
requireKeypressFlag = 1;
--- 309,318 ----
***************
*** 432,442 ****
break;
case GRAY_DITHER:
- InitGrayDisplay(name);
- break;
-
case GRAY256_DITHER:
! InitGray256Display(name);
break;
case FULL_COLOR_DITHER:
--- 426,433 ----
break;
case GRAY_DITHER:
case GRAY256_DITHER:
! InitGrayDisplay(name);
break;
case FULL_COLOR_DITHER:
***************
*** 483,500 ****
}
- #ifdef SH_MEM
- if (shmemFlag && (display != NULL)) {
- if (!XShmQueryExtension(display)) {
- shmemFlag = 0;
- if (!quietFlag) {
- fprintf(stderr, "Shared memory not supported\n");
- fprintf(stderr, "Reverting to normal Xlib.\n");
- }
- }
- }
- #endif
-
if (setjmp(env) != 0) {
DestroyVidStream(theStream);
--- 474,479 ----
***************
*** 568,575 ****
fprintf(stderr, " [-framerate num]\n");
fprintf(stderr, " [-no_display]\n");
fprintf(stderr, " [-quiet]\n");
- fprintf(stderr, " [-owncm]\n");
- fprintf(stderr, " [-shmem_off]\n");
fprintf(stderr, " [-l_range num]\n");
fprintf(stderr, " [-cr_range num]\n");
fprintf(stderr, " [-cb_range num]\n");
--- 547,552 ----
/shark/trunk/ports/mpeg/hybriderr.c
0,0 → 1,365
/*
* hybriderr.c --
*
* Procedures dealing with hybrid2 dithering, which is hybrid
* dithering with error propagation among pixels.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/* This file contains C code to implement an ordered dither in the
luminance channel and F-S error diffusion on chrominance.
*/
 
#include "video.h"
#include "proto.h"
#include "dither.h"
 
#define DITH_SIZE 16
 
/* Structures used for hybrid dither with errors propogated. */
 
static unsigned char *l_darrays[DITH_SIZE];
static unsigned char *l_darrays0, *l_darrays1, *l_darrays2, *l_darrays3;
static unsigned char *l_darrays4, *l_darrays5, *l_darrays6, *l_darrays7;
static unsigned char *l_darrays8, *l_darrays9, *l_darrays10, *l_darrays11;
static unsigned char *l_darrays12, *l_darrays13, *l_darrays14, *l_darrays15;
static unsigned char cr_fsarray[256*256][4];
static unsigned char cb_fsarray[256*256][4];
static unsigned short c_fserr[256*256][2];
 
/*
*--------------------------------------------------------------
*
* InitHybridErrorDither--
*
* Initializes structures used for hybrid dither algorithm
* with errors propogated on Cr and Cb.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
InitHybridErrorDither()
{
int i, j, k, err_range, threshval;
unsigned char *lmark;
 
 
for (i=0; i<DITH_SIZE; i++) {
lmark = l_darrays[i] = (unsigned char *) malloc(256);
 
for (j=0; j<lum_values[0]; j++) {
*lmark++ = 0;
}
 
for (j=0; j<(LUM_RANGE-1); j++) {
err_range = lum_values[j+1] - lum_values[j];
threshval = ((i * err_range) / DITH_SIZE)+lum_values[j];
 
for (k=lum_values[j]; k<lum_values[j+1]; k++) {
if (k > threshval) *lmark++ = ((j+1) * (CR_RANGE * CB_RANGE));
else *lmark++ = (j * (CR_RANGE * CB_RANGE));
}
}
 
for (j=lum_values[LUM_RANGE-1]; j <256; j++) {
*lmark++ = (LUM_RANGE-1)*(CR_RANGE * CB_RANGE);
}
}
l_darrays0 = l_darrays[0]; l_darrays8 = l_darrays[8];
l_darrays1 = l_darrays[1]; l_darrays9 = l_darrays[9];
l_darrays2 = l_darrays[2]; l_darrays10 = l_darrays[10];
l_darrays3 = l_darrays[3]; l_darrays11 = l_darrays[11];
l_darrays4 = l_darrays[4]; l_darrays12 = l_darrays[12];
l_darrays5 = l_darrays[5]; l_darrays13 = l_darrays[13];
l_darrays6 = l_darrays[6]; l_darrays14 = l_darrays[14];
l_darrays7 = l_darrays[7]; l_darrays15 = l_darrays[15];
{
int cr1, cr2, cr3, cr4, err1, err2;
int cb1, cb2, cb3, cb4, val, nval;
int outerr1, outerr2, outerr3, outerr4;
int inerr1, inerr2, inerr3, inerr4;
unsigned short oe1, oe2, oe3, oe4;
 
for (j=0; j<65536; j+= 256) {
 
inerr1 = (((j & 0xc000) >> 14)*8) - 12;
inerr2 = (((j & 0x3000) >> 12)*8) - 12;
inerr3 = (((j & 0x0c00) >> 10)*8) - 12;
inerr4 = (((j & 0x0300) >> 8) *8) - 12;
 
for (i=0; i<256; i++) {
val = i;
 
nval = val+inerr1+inerr3;
if (nval < 0) nval = 0; else if (nval > 255) nval = 255;
cr1 = ((nval) * CR_RANGE) / 256;
err1 = ((nval) - cr_values[cr1])/2;
err2 = ((nval) - cr_values[cr1]) - err1;
 
nval = val+err1+inerr2;
if (nval < 0) nval = 0; else if (nval > 255) nval = 255;
cr2 = ((nval) * CR_RANGE) / 256;
err1 = ((nval) - cr_values[cr2])/2;
outerr3 = ((nval) - cr_values[cr2])-err1;
 
nval = val+err2+inerr4;
if (nval < 0) nval = 0; else if (nval > 255) nval = 255;
cr3 = ((nval) * CR_RANGE) / 256;
err2 = ((nval) - cr_values[cr3])/2;
outerr1 = ((nval) - cr_values[cr3]) - err2;
 
nval = val+err1+err2;
if (nval < 0) nval = 0; else if (nval > 255) nval = 255;
cr4 = ((nval) * CR_RANGE) / 256;
outerr2 = ((nval) - cr_values[cr4])/2;
outerr4 = ((nval) - cr_values[cr4])-outerr2;
 
cr_fsarray[i+j][0] = cr1*CB_RANGE;
cr_fsarray[i+j][1] = cr2*CB_RANGE;
cr_fsarray[i+j][2] = cr3*CB_RANGE;
cr_fsarray[i+j][3] = cr4*CB_RANGE;
 
if (outerr1 < -16) outerr1++;
else if (outerr1 > 15) outerr1--;
if (outerr2 < -16) outerr2++;
else if (outerr2 > 15) outerr2--;
if (outerr3 < -16) outerr3++;
else if (outerr3 > 15) outerr3--;
if (outerr4 < -16) outerr4++;
else if (outerr4 > 15) outerr4--;
 
oe1 = (outerr1 + 16) / 8;
oe2 = (outerr2 + 16) / 8;
oe3 = (outerr3 + 16) / 8;
oe4 = (outerr4 + 16) / 8;
 
/* This is a debugging check and should be removed if not needed. */
if ((oe1 > 3) || (oe2 > 3) || (oe3 > 3) || (oe4 > 3))
fprintf(stderr, "OE error!!!!\n");
 
 
c_fserr[i+j][0] = ((oe1 << 14) | (oe2 << 12));
 
c_fserr[i+j][1] = ((oe3 << 10) | (oe4 << 8));
}
 
for (i=0; i<256; i++) {
val = i;
nval = val+inerr1+inerr3;
if (nval < 0) nval = 0; else if (nval > 255) nval = 255;
cb1 = ((nval) * CB_RANGE) / 256;
err1 = ((nval) - cb_values[cb1])/2;
err2 = ((nval) - cb_values[cb1]) - err1;
 
nval = val+err1+inerr2;
if (nval < 0) nval = 0; else if (nval > 255) nval = 255;
cb2 = ((nval) * CB_RANGE) / 256;
err1 = ((nval) - cb_values[cb2])/2;
 
nval = val+err2+inerr4;
if (nval < 0) nval = 0; else if (nval > 255) nval = 255;
cb3 = ((nval) * CB_RANGE) / 256;
err2 = ((nval) - cb_values[cb3])/2;
 
nval = val+err1+err2;
if (nval < 0) nval = 0; else if (nval > 255) nval = 255;
cb4 = ((nval) * CB_RANGE) / 256;
 
cb_fsarray[i+j][0] = cb1;
cb_fsarray[i+j][1] = cb2;
cb_fsarray[i+j][2] = cb3;
cb_fsarray[i+j][3] = cb4;
}
}
}
}
 
/*
*--------------------------------------------------------------
*
* HybridErrorDitherImage --
*
* Dithers an image using a hybrid ordered/floyd-steinberg dither.
* Assumptions made:
* 1) The color space is allocated y:cr:cb = 8:4:4
* 2) The spatial resolution of y:cr:cb is 4:1:1
* This dither is almost exactly like the dither implemented in the
* file odith.c (i.e. hybrid dithering) except a quantized amount of
* error is propogated between 2x2 pixel areas in Cr and Cb.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
HybridErrorDitherImage (lum, cr, cb, out, h, w)
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int w, h;
{
unsigned char *l, *r, *b, *o1, *o2;
unsigned char *l2;
static int *cr_row_errs;
static int *cb_row_errs;
int *cr_r_err;
int *cb_r_err;
int cr_c_err;
int cb_c_err;
unsigned char *cr_fsptr;
unsigned char *cb_fsptr;
static int first = 1;
int cr_code, cb_code;
 
int i, j;
int row_advance, row_advance2;
int half_row_advance, half_row_advance2;
 
/* If first time called, allocate error arrays. */
 
if (first) {
cr_row_errs = (int *) malloc((w+5)*sizeof(int));
cb_row_errs = (int *) malloc((w+5)*sizeof(int));
first = 0;
}
 
row_advance = (w << 1) - 1;
row_advance2 = row_advance+2;
half_row_advance = (w>>1)-1;
half_row_advance2 = half_row_advance+2;
 
l = lum;
l2 = lum+w;
r = cr;
b = cb;
o1 = out;
o2 = out+w;
 
memset( (char *) cr_row_errs, 0, (w+5)*sizeof(int));
cr_r_err = cr_row_errs;
cr_c_err = 0;
memset( (char *) cb_row_errs, 0, (w+5)*sizeof(int));
cb_r_err = cb_row_errs;
cb_c_err = 0;
 
for (i=0; i<h; i+=4) {
 
for (j=w; j>0; j-=4) {
 
cr_code = (*cr_r_err | cr_c_err | *r++);
cb_code = (*cb_r_err | cb_c_err | *b++);
 
cr_fsptr = cr_fsarray[cr_code];
cb_fsptr = cb_fsarray[cb_code];
 
*o1++ = pixel[(l_darrays0[*l++] | *cr_fsptr++ | *cb_fsptr++)];
*o1++ = pixel[(l_darrays8[*l++] | *cr_fsptr++ | *cb_fsptr++)];
*o2++ = pixel[(l_darrays12[*l2++] | *cr_fsptr++ | *cb_fsptr++)];
*o2++ = pixel[(l_darrays4[*l2++] | *cr_fsptr++ | *cb_fsptr++)];
 
cr_c_err = c_fserr[cr_code][1];
cb_c_err = c_fserr[cb_code][1];
*cr_r_err++ = c_fserr[cr_code][0];
*cb_r_err++ = c_fserr[cb_code][0];
cr_code = (*cr_r_err | cr_c_err | *r++);
cb_code = (*cb_r_err | cb_c_err | *b++);
 
cr_fsptr = cr_fsarray[cr_code];
cb_fsptr = cb_fsarray[cb_code];
 
*o1++ = pixel[(l_darrays2[*l++] | *cr_fsptr++ | *cb_fsptr++)];
*o1++ = pixel[(l_darrays10[*l++] | *cr_fsptr++ | *cb_fsptr++)];
*o2++ = pixel[(l_darrays14[*l2++] | *cr_fsptr++ | *cb_fsptr++)];
*o2++ = pixel[(l_darrays6[*l2++] | *cr_fsptr++ | *cb_fsptr++)];
 
cr_c_err = c_fserr[cr_code][1];
cb_c_err = c_fserr[cb_code][1];
*cr_r_err++ = c_fserr[cr_code][0];
*cb_r_err++ = c_fserr[cb_code][0];
}
 
l += row_advance; l2 += row_advance;
o1 += row_advance; o2 += row_advance;
cr_c_err = 0;
cb_c_err = 0;
cr_r_err--; cb_r_err--;
r += half_row_advance; b += half_row_advance;
 
for (j=w; j>0; j-=4) {
 
cr_code = (*cr_r_err | cr_c_err | *r--);
cb_code = (*cb_r_err | cb_c_err | *b--);
cr_fsptr = cr_fsarray[cr_code];
cb_fsptr = cb_fsarray[cb_code];
 
*o1-- = pixel[(l_darrays9[*l--] | *cr_fsptr++ | *cb_fsptr++)];
*o1-- = pixel[(l_darrays1[*l--] | *cr_fsptr++ | *cb_fsptr++)];
*o2-- = pixel[(l_darrays5[*l2--] | *cr_fsptr++ | *cb_fsptr++)];
*o2-- = pixel[(l_darrays13[*l2--] | *cr_fsptr++ | *cb_fsptr++)];
 
cr_c_err = c_fserr[cr_code][1];
cb_c_err = c_fserr[cb_code][1];
*cr_r_err-- = c_fserr[cr_code][0];
*cb_r_err-- = c_fserr[cb_code][0];
cr_code = (*cr_r_err | cr_c_err | *r--);
cb_code = (*cb_r_err | cb_c_err | *b--);
cr_fsptr = cr_fsarray[cr_code];
cb_fsptr = cb_fsarray[cb_code];
 
*o1-- = pixel[(l_darrays11[*l--] | *cr_fsptr++ | *cb_fsptr++)];
*o1-- = pixel[(l_darrays3[*l--] | *cr_fsptr++ | *cb_fsptr++)];
*o2-- = pixel[(l_darrays7[*l2--] | *cr_fsptr++ | *cb_fsptr++)];
*o2-- = pixel[(l_darrays15[*l2--] | *cr_fsptr++ | *cb_fsptr++)];
 
cr_c_err = c_fserr[cr_code][1];
cb_c_err = c_fserr[cb_code][1];
*cr_r_err-- = c_fserr[cr_code][0];
*cb_r_err-- = c_fserr[cb_code][0];
 
}
 
l += row_advance2; l2 += row_advance2;
o1 += row_advance2; o2 += row_advance2;
cr_c_err = 0; cb_c_err = 0;
cr_r_err++; cb_r_err++;
r += half_row_advance2; b += half_row_advance2;
}
}
 
 
/shark/trunk/ports/mpeg/fs2.c
0,0 → 1,397
/*
* fs2.c --
*
* Procedures dealing with Floyd-Steinberg dithering with 2 error
* values propagated.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
#include "video.h"
#include "dither.h"
#include "fs2.h"
#include "proto.h"
#ifdef __STDC__
#include <stdlib.h>
#else
#include <malloc.h> /* member of stdlib.h included in header.h */
#endif
 
/* Structures for precomputed error propogation values. */
 
static FS2DithVal lum_index[256];
static FS2DithVal cr_index[256];
static FS2DithVal cb_index[256];
 
 
/*
*--------------------------------------------------------------
*
* InitFS2Dither --
*
* Initializes structures for precomputed 2 error f-s dithering.
* The value field of the structure contains the pixel component
* of the particular channel in question. Thus the addition of
* the value field of a structure in the luminance index, a
* structure in the Cr index, and a structure in the Cb index will
* yeild a color number. This color number can then be transformed
* into a pixel value to be displayed. Each channel can then be
* processed (i.e. dithered) separately, with the results being
* added up and remapped to yield a final pixel value.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void InitFS2Dither()
{
int i;
 
/* For each possible pixel value, precompute propogated error and
store in array.
*/
for (i=0; i<256; i++) {
lum_index[i].value = (i * LUM_RANGE) / 256;
 
lum_index[i].e1 = (i-lum_values[lum_index[i].value]) / 2;
lum_index[i].e3 = (i - lum_values[lum_index[i].value]) - lum_index[i].e1;
 
lum_index[i].value *= LUM_BASE;
 
cr_index[i].value = (i * CR_RANGE) / 256;
 
cr_index[i].e1 = (i - cr_values[cr_index[i].value]) / 2;
cr_index[i].e3 = (i - cr_values[cr_index[i].value]) - cr_index[i].e1 ;
 
cr_index[i].value *= CR_BASE;
 
cb_index[i].value = (i * CB_RANGE) / 256;
 
cb_index[i].e1 = (i - cb_values[cb_index[i].value]) / 2;
cb_index[i].e3 = (i - cb_values[cb_index[i].value]) - cb_index[i].e1;
 
cb_index[i].value *= CB_BASE;
 
}
 
}
 
/*
*--------------------------------------------------------------
*
* DitherImage --
*
* Converts lum, cr, cb image planes into fixed colormap
* space.
*
* Results:
* the display plane is replaced by 8-bit colormap space
* image.
*
* Side effects:
* Hopefully, none.
*
*--------------------------------------------------------------
*/
 
void FS2DitherImage(lum, cr, cb, disp, rows, cols)
unsigned char *lum, *cr, *cb, *disp;
int rows, cols;
{
static char *cur_row_error, *next_row_error;
static int first = 1;
char *cur_row_err_mark, *next_row_err_mark;
char *temp;
int i, j, pixsum, c_cols;
unsigned char *cur_row, *channel, *dest_row;
FS2DithVal *chan_index;
 
/* Allocate error arrays. */
 
if (first) {
cur_row_error = (char *) malloc((unsigned int) cols+2);
next_row_error = (char *) malloc((unsigned int) cols+2);
first = 0;
}
 
/* Initialize error arrays. */
 
memset(cur_row_error, 0, cols+2);
memset(next_row_error, 0, cols+2);
 
/* Use luminance values first. */
 
/* For each two rows, do... */
 
for(i=0; i<rows; i+=2) {
 
/* Establish pointer to current source and destination rows. */
cur_row = lum + (i*cols);
dest_row = disp + (i*cols);
 
/* Establish pointers to error arrays. */
cur_row_err_mark = cur_row_error + 1;
next_row_err_mark = next_row_error + 1;
 
/* For each column within first row do... */
 
for (j=0; j<cols; j++) {
 
/* Calculate pixel value with error. */
 
pixsum = *cur_row + *cur_row_err_mark;
 
/* Bounds check. */
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
 
/* Establish dest value, propogate errors. */
 
*dest_row = lum_index[pixsum].value;
*(cur_row_err_mark+1) += lum_index[pixsum].e1;
*next_row_err_mark += lum_index[pixsum].e3;
 
/* Advance pointers. */
 
cur_row++;
dest_row++;
cur_row_err_mark++;
next_row_err_mark++;
}
 
/* Switch error arrays, so next row errors are now current row errors, and
vice versa.
*/
 
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
 
/* Reset next row errors. */
 
memset(next_row_error, 0, cols+2);
 
/* Establish pointers for second row. This one will be processed right to
left to establish serpantine motion.
*/
 
cur_row += cols-1;
dest_row += cols-1;
cur_row_err_mark = cur_row_error + cols;
next_row_err_mark = next_row_error + cols;
 
/* Process each column... */
 
for (j=0; j<cols; j++) {
 
pixsum = *cur_row + *cur_row_err_mark;
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
*dest_row = lum_index[pixsum].value;
*(cur_row_err_mark-1) += lum_index[pixsum].e1;
*next_row_err_mark += lum_index[pixsum].e3;
cur_row--;
dest_row--;
cur_row_err_mark--;
next_row_err_mark--;
}
 
/* Switch error arrays. */
 
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
 
/* Reset next row errors. */
 
memset(next_row_error, 0, cols+2);
}
 
/* Reset error arrays. */
 
memset(cur_row_error, 0, cols+2);
/* Establish column length divided by two. */
 
c_cols = cols >> 1;
 
/* Set channel to Cr. Use Cr index. */
 
channel = cr;
chan_index = cr_index;
repeat:
 
/* Process each row of chrominance data... */
 
for (i=0; i < rows; i+=2) {
 
/* Establish pointers. */
 
cur_row = channel + ((i>>1)*c_cols);
dest_row = disp + (i*cols);
 
cur_row_err_mark = cur_row_error+1;
next_row_err_mark = next_row_error+1;
 
/* For each column in row... */
 
for (j=0; j<cols; j++) {
int p_val;
 
/* Get pixel value as twos bit complement. */
 
p_val = *cur_row;
 
/* Add error term. */
 
pixsum = *cur_row_err_mark + p_val;
 
/* Bounds check. */
 
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
 
/* Increment dest value. */
 
*dest_row += chan_index[pixsum].value;
 
/* Propogate error values. */
 
*(cur_row_err_mark+1) += chan_index[pixsum].e1;
*next_row_err_mark += chan_index[pixsum].e3;
 
 
/* If count is odd, advance source pointer (Cr and Cb channels are 2:1
subsampled.
*/
 
if (j&1) cur_row++;
 
/* Advance destination and error pointers. */
 
dest_row++;
cur_row_err_mark++;
next_row_err_mark++;
}
 
/* Switch error arrays. */
 
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
 
/* Reset next row errors. */
 
memset(next_row_error, 0, cols+2);
 
/* Re-establish pointers. */
 
cur_row += c_cols-1;
dest_row += cols-1;
cur_row_err_mark = cur_row_error+cols;
next_row_err_mark = next_row_error+cols;
 
/* Process second row right to left. */
 
for (j=0; j<cols; j++) {
int p_val;
 
/* Get source value as twos bit complement. */
 
p_val = *cur_row;
 
/* Add error. */
 
pixsum = *cur_row_err_mark + p_val;
 
/* Bounds check. */
 
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
 
/* Increment dest value. */
 
*dest_row += chan_index[pixsum].value;
 
/* Propogate errors. */
 
*(cur_row_err_mark-1) += chan_index[pixsum].e1;
*next_row_err_mark += chan_index[pixsum].e3;
 
/* If column counters is odd, decrement source pointer. */
 
if (j&1) cur_row--;
 
/* Decrement dest and error pointers. */
 
dest_row--;
cur_row_err_mark--;
next_row_err_mark--;
}
 
/* Switch error arrays. */
 
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
 
/* Reinitialize next row errors. */
 
memset(next_row_error, 0, cols+2);
}
 
/* If Cr channel completed, set channel to Cb and Cb index and repeat. */
 
if (channel == cr) {
channel = cb;
chan_index = cb_index;
memset(cur_row_error, 0, cols+2);
 
goto repeat;
}
 
/* Establish pointer to start of display frame. */
 
dest_row = disp;
 
/* Transform all display values to pixel values. */
 
for (i=0; i<rows; i++) {
for (j=0; j<cols; j++) {
*dest_row = pixel[*dest_row];
dest_row++;
}
}
}
/shark/trunk/ports/mpeg/fs4.c
0,0 → 1,300
/*
* fs4.c --
*
* Procedures dealing with Floyd-Steinberg dithering with 4 error
* values propagated.
*
*/
 
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
 
/* This file contains C code to do YCrCb -> colormap space. */
 
#include "fs4.h"
#include "video.h"
#include "proto.h"
#include "dither.h"
 
/* Structures containing precomputed error terms. */
 
static FS4Dither lum_index[256];
static FS4Dither cr_index[256];
static FS4Dither cb_index[256];
 
/*
*--------------------------------------------------------------
*
* InitFS4Dither --
*
* Initializes structures used for f-s dithering. Precomputes
* error terms.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
 
void
InitFS4Dither()
{
int i;
 
for (i=0; i<256; i++) {
lum_index[i].value = (i * LUM_RANGE) / 256;
 
lum_index[i].e1 = (7 * (i-lum_values[lum_index[i].value])) / 16;
lum_index[i].e2 = (i-lum_values[lum_index[i].value])/16;
lum_index[i].e3 = (5 * (i - lum_values[lum_index[i].value])) / 16;
lum_index[i].e4 = (i-lum_values[lum_index[i].value]) - lum_index[i].e1 -
lum_index[i].e2 - lum_index[i].e3;
 
lum_index[i].value *= LUM_BASE;
 
cr_index[i].value = (i * CR_RANGE) / 256;
 
cr_index[i].e1 = (7 * (i-cr_values[cr_index[i].value])) / 16;
cr_index[i].e2 = (i-cr_values[cr_index[i].value])/16;
cr_index[i].e3 = (5 * (i - cr_values[cr_index[i].value])) / 16;
cr_index[i].e4 = (i-cr_values[cr_index[i].value]) - cr_index[i].e1 -
cr_index[i].e2 - cr_index[i].e3;
cr_index[i].value *= CR_BASE;
 
cb_index[i].value = (i * CB_RANGE) / 256;
 
cb_index[i].e1 = (7 * (i-cb_values[cb_index[i].value])) / 16;
cb_index[i].e2 = (i-cb_values[cb_index[i].value])/16;
cb_index[i].e3 = (5 * (i - cb_values[cb_index[i].value])) / 16;
cb_index[i].e4 = (i-cb_values[cb_index[i].value]) - cb_index[i].e1 -
cb_index[i].e2 - cb_index[i].e3;
cb_index[i].value *= CB_BASE;
 
}
 
}
 
/*
*--------------------------------------------------------------
*
* DitherImage --
*
* Converts lum, cr, cb image planes into fixed colormap
* space. Uses Floyd-Steinberg dithering in serpentine
* pattern with standard 4 errors propogated.
*
* Results:
* The display plane is replaced by 8-bit colormap space
* image.
*
* Side effects:
* Hopefully, none.
*
*--------------------------------------------------------------
*/
 
void
FS4DitherImage(lum, cr, cb, disp, rows, cols)
unsigned char *lum, *cr, *cb, *disp;
int rows, cols;
{
static char *cur_row_error, *next_row_error;
static int first = 1;
char *cur_row_err_mark, *next_row_err_mark;
char *temp;
int i, j, pixsum, c_cols;
unsigned char *cur_row, *channel, *dest_row;
FS4Dither *chan_index;
 
if (first) {
cur_row_error = (char *) malloc(cols+2);
next_row_error = (char *) malloc(cols+2);
first = 0;
}
 
memset(cur_row_error, 0, cols+2);
memset(next_row_error, 0, cols+2);
 
for(i=0; i<rows; i+=2) {
cur_row = lum + (i*cols);
dest_row = disp + (i*cols);
 
cur_row_err_mark = cur_row_error + 1;
next_row_err_mark = next_row_error + 1;
 
for (j=0; j<cols; j++) {
 
pixsum = *cur_row + *cur_row_err_mark;
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
 
*dest_row = lum_index[pixsum].value;
*(cur_row_err_mark+1) += lum_index[pixsum].e1;
*(next_row_err_mark+1) += lum_index[pixsum].e2;
*next_row_err_mark += lum_index[pixsum].e3;
*(next_row_err_mark-1) += lum_index[pixsum].e4;
 
cur_row++;
dest_row++;
cur_row_err_mark++;
next_row_err_mark++;
}
 
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
 
memset(next_row_error, 0, cols+2);
 
cur_row += cols-1;
dest_row += cols-1;
cur_row_err_mark = cur_row_error + cols;
next_row_err_mark = next_row_error + cols;
 
for (j=0; j<cols; j++) {
 
pixsum = *cur_row + *cur_row_err_mark;
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
 
*dest_row = lum_index[pixsum].value;
*(cur_row_err_mark-1) += lum_index[pixsum].e1;
*(next_row_err_mark-1) += lum_index[pixsum].e2;
*next_row_err_mark += lum_index[pixsum].e3;
*(next_row_err_mark+1) += lum_index[pixsum].e4;
 
cur_row--;
dest_row--;
cur_row_err_mark--;
next_row_err_mark--;
}
 
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
 
memset(next_row_error, 0, cols+2);
}
 
memset(cur_row_error, 0, cols+2);
 
c_cols = cols >> 1;
 
channel = cr;
chan_index = cr_index;
 
repeat:
 
for (i=0; i < rows; i+=2) {
cur_row = channel + ((i>>1)*c_cols);
dest_row = disp + (i*cols);
 
cur_row_err_mark = cur_row_error+1;
next_row_err_mark = next_row_error+1;
for (j=0; j<cols; j++) {
int p_val;
 
p_val = *cur_row;
 
pixsum = *cur_row_err_mark + p_val;
 
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
 
*dest_row += chan_index[pixsum].value;
 
*(cur_row_err_mark+1) += chan_index[pixsum].e1;
*(next_row_err_mark+1) += chan_index[pixsum].e2;
*next_row_err_mark += chan_index[pixsum].e3;
*(next_row_err_mark-1) += chan_index[pixsum].e4;
 
 
if (j&1) cur_row++;
dest_row++;
cur_row_err_mark++;
next_row_err_mark++;
}
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
 
memset(next_row_error, 0, cols+2);
 
cur_row += c_cols-1;
dest_row += cols-1;
cur_row_err_mark = cur_row_error+cols;
next_row_err_mark = next_row_error+cols;
 
for (j=0; j<cols; j++) {
int p_val;
 
p_val = *cur_row;
 
pixsum = *cur_row_err_mark + p_val;
 
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
 
*dest_row += chan_index[pixsum].value;
 
*(cur_row_err_mark-1) += chan_index[pixsum].e1;
*(next_row_err_mark-1) += chan_index[pixsum].e2;
*next_row_err_mark += chan_index[pixsum].e3;
*(next_row_err_mark+1) += chan_index[pixsum].e4;
 
if (j&1) cur_row--;
dest_row--;
cur_row_err_mark--;
next_row_err_mark--;
}
 
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
 
memset(next_row_error, 0, cols+2);
}
 
if (channel == cr) {
channel = cb;
chan_index = cb_index;
memset(cur_row_error, 0, cols+2);
 
goto repeat;
}
 
dest_row = disp;
 
 
for (i=0; i<rows; i++) {
for (j=0; j<cols; j++) {
*dest_row = pixel[*dest_row];
dest_row++;
}
}
}
/shark/trunk/ports/mpeg/decoders.h
0,0 → 1,494
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
* decoders.h
*
* This file contains the declarations of structures required for Huffman
* decoding
*
*/
 
/* Include util.h for bit i/o parsing macros. */
 
#include "util.h"
 
/* Code for unbound values in decoding tables */
#define ERROR (-1)
#define DCT_ERROR 63
 
#define MACRO_BLOCK_STUFFING 34
#define MACRO_BLOCK_ESCAPE 35
 
/* Two types of DCT Coefficients */
#define DCT_COEFF_FIRST 0
#define DCT_COEFF_NEXT 1
 
/* Special values for DCT Coefficients */
#define END_OF_BLOCK 62
#define ESCAPE 61
 
/* Structure for an entry in the decoding table of
* macroblock_address_increment */
typedef struct {
int value; /* value for macroblock_address_increment */
int num_bits; /* length of the Huffman code */
} mb_addr_inc_entry;
 
/* Decoding table for macroblock_address_increment */
extern mb_addr_inc_entry mb_addr_inc[2048];
 
 
/* Structure for an entry in the decoding table of macroblock_type */
typedef struct {
unsigned int mb_quant; /* macroblock_quant */
unsigned int mb_motion_forward; /* macroblock_motion_forward */
unsigned int mb_motion_backward; /* macroblock_motion_backward */
unsigned int mb_pattern; /* macroblock_pattern */
unsigned int mb_intra; /* macroblock_intra */
int num_bits; /* length of the Huffman code */
} mb_type_entry;
 
/* Decoding table for macroblock_type in predictive-coded pictures */
extern mb_type_entry mb_type_P[64];
 
/* Decoding table for macroblock_type in bidirectionally-coded pictures */
extern mb_type_entry mb_type_B[64];
 
 
/* Structures for an entry in the decoding table of coded_block_pattern */
typedef struct {
unsigned int cbp; /* coded_block_pattern */
int num_bits; /* length of the Huffman code */
} coded_block_pattern_entry;
 
/* External declaration of coded block pattern table. */
 
extern coded_block_pattern_entry coded_block_pattern[512];
 
 
 
/* Structure for an entry in the decoding table of motion vectors */
typedef struct {
int code; /* value for motion_horizontal_forward_code,
* motion_vertical_forward_code,
* motion_horizontal_backward_code, or
* motion_vertical_backward_code.
*/
int num_bits; /* length of the Huffman code */
} motion_vectors_entry;
 
 
/* Decoding table for motion vectors */
extern motion_vectors_entry motion_vectors[2048];
 
 
/* Structure for an entry in the decoding table of dct_dc_size */
typedef struct {
unsigned int value; /* value of dct_dc_size (luminance or chrominance) */
int num_bits; /* length of the Huffman code */
} dct_dc_size_entry;
 
/* External declaration of dct dc size lumiance table. */
 
extern dct_dc_size_entry dct_dc_size_luminance[32];
extern dct_dc_size_entry dct_dc_size_luminance1[16];
 
/* External declaration of dct dc size chrom table. */
 
extern dct_dc_size_entry dct_dc_size_chrominance[32];
extern dct_dc_size_entry dct_dc_size_chrominance1[32];
 
 
/* DCT coeff tables. */
 
#define RUN_MASK 0xfc00
#define LEVEL_MASK 0x03f0
#define NUM_MASK 0x000f
#define RUN_SHIFT 10
#define LEVEL_SHIFT 4
 
/* External declaration of dct coeff tables. */
 
extern unsigned short int dct_coeff_tbl_0[256];
extern unsigned short int dct_coeff_tbl_1[16];
extern unsigned short int dct_coeff_tbl_2[4];
extern unsigned short int dct_coeff_tbl_3[4];
extern unsigned short int dct_coeff_next[256];
extern unsigned short int dct_coeff_first[256];
 
#define DecodeDCTDCSizeLum(macro_val) \
{ \
unsigned int index; \
\
show_bits5(index); \
\
if (index < 31) { \
macro_val = dct_dc_size_luminance[index].value; \
flush_bits(dct_dc_size_luminance[index].num_bits); \
} \
else { \
show_bits9(index); \
index -= 0x1f0; \
macro_val = dct_dc_size_luminance1[index].value; \
flush_bits(dct_dc_size_luminance1[index].num_bits); \
} \
}
 
#define DecodeDCTDCSizeChrom(macro_val) \
{ \
unsigned int index; \
\
show_bits5(index); \
\
if (index < 31) { \
macro_val = dct_dc_size_chrominance[index].value; \
flush_bits(dct_dc_size_chrominance[index].num_bits); \
} \
else { \
show_bits10(index); \
index -= 0x3e0; \
macro_val = dct_dc_size_chrominance1[index].value; \
flush_bits(dct_dc_size_chrominance1[index].num_bits); \
} \
}
 
#define DecodeDCTCoeff(dct_coeff_tbl, run, level) \
{ \
unsigned int temp, index; \
unsigned int value, next32bits, flushed; \
\
/* \
* Grab the next 32 bits and use it to improve performance of \
* getting the bits to parse. Thus, calls are translated as: \
* \
* show_bitsX <--> next32bits >> (32-X) \
* get_bitsX <--> val = next32bits >> (32-flushed-X); \
* flushed += X; \
* next32bits &= bitMask[flushed]; \
* flush_bitsX <--> flushed += X; \
* next32bits &= bitMask[flushed]; \
* \
* I've streamlined the code a lot, so that we don't have to mask \
* out the low order bits and a few of the extra adds are removed. \
*/ \
show_bits32(next32bits); \
\
/* show_bits8(index); */ \
index = next32bits >> 24; \
\
if (index > 3) { \
value = dct_coeff_tbl[index]; \
run = value >> RUN_SHIFT; \
if (run != END_OF_BLOCK) { \
/* num_bits = (value & NUM_MASK) + 1; */ \
/* flush_bits(num_bits); */ \
if (run != ESCAPE) { \
/* get_bits1(value); */ \
/* if (value) level = -level; */ \
flushed = (value & NUM_MASK) + 2; \
level = (value & LEVEL_MASK) >> LEVEL_SHIFT; \
value = next32bits >> (32-flushed); \
value &= 0x1; \
if (value) level = -level; \
/* next32bits &= ((~0) >> flushed); last op before update */ \
} \
else { /* run == ESCAPE */ \
/* Get the next six into run, and next 8 into temp */ \
/* get_bits14(temp); */ \
flushed = (value & NUM_MASK) + 1; \
temp = next32bits >> (18-flushed); \
/* Normally, we'd ad 14 to flushed, but I've saved a few \
* instr by moving the add below */ \
temp &= 0x3fff; \
run = temp >> 8; \
temp &= 0xff; \
if (temp == 0) { \
/* get_bits8(level); */ \
level = next32bits >> (10-flushed); \
level &= 0xff; \
flushed += 22; \
assert(level >= 128); \
} else if (temp != 128) { \
/* Grab sign bit */ \
flushed += 14; \
level = ((int) (temp << 24)) >> 24; \
} else { \
/* get_bits8(level); */ \
level = next32bits >> (10-flushed); \
level &= 0xff; \
flushed += 22; \
level = level - 256; \
assert(level <= -128 && level >= -255); \
} \
} \
/* Update bitstream... */ \
flush_bits(flushed); \
assert (flushed <= 32); \
} \
} \
else { \
switch (index) { \
case 2: { \
/* show_bits10(index); */ \
index = next32bits >> 22; \
value = dct_coeff_tbl_2[index & 3]; \
break; \
} \
case 3: { \
/* show_bits10(index); */ \
index = next32bits >> 22; \
value = dct_coeff_tbl_3[index & 3]; \
break; \
} \
case 1: { \
/* show_bits12(index); */ \
index = next32bits >> 20; \
value = dct_coeff_tbl_1[index & 15]; \
break; \
} \
default: { /* index == 0 */ \
/* show_bits16(index); */ \
index = next32bits >> 16; \
value = dct_coeff_tbl_0[index & 255]; \
}} \
run = value >> RUN_SHIFT; \
level = (value & LEVEL_MASK) >> LEVEL_SHIFT; \
\
/* \
* Fold these operations together to make it fast... \
*/ \
/* num_bits = (value & NUM_MASK) + 1; */ \
/* flush_bits(num_bits); */ \
/* get_bits1(value); */ \
/* if (value) level = -level; */ \
\
flushed = (value & NUM_MASK) + 2; \
value = next32bits >> (32-flushed); \
value &= 0x1; \
if (value) level = -level; \
\
/* Update bitstream ... */ \
flush_bits(flushed); \
assert (flushed <= 32); \
} \
}
 
#define DecodeDCTCoeffFirst(runval, levelval) \
{ \
DecodeDCTCoeff(dct_coeff_first, runval, levelval); \
}
 
#define DecodeDCTCoeffNext(runval, levelval) \
{ \
DecodeDCTCoeff(dct_coeff_next, runval, levelval); \
}
 
/*
*--------------------------------------------------------------
*
* DecodeMBAddrInc --
*
* Huffman Decoder for macro_block_address_increment; the location
* in which the result will be placed is being passed as argument.
* The decoded value is obtained by doing a table lookup on
* mb_addr_inc.
*
* Results:
* The decoded value for macro_block_address_increment or ERROR
* for unbound values will be placed in the location specified.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
#define DecodeMBAddrInc(val) \
{ \
unsigned int index; \
show_bits11(index); \
val = mb_addr_inc[index].value; \
flush_bits(mb_addr_inc[index].num_bits); \
}
 
/*
*--------------------------------------------------------------
*
* DecodeMotionVectors --
*
* Huffman Decoder for the various motion vectors, including
* motion_horizontal_forward_code, motion_vertical_forward_code,
* motion_horizontal_backward_code, motion_vertical_backward_code.
* Location where the decoded result will be placed is being passed
* as argument. The decoded values are obtained by doing a table
* lookup on motion_vectors.
*
* Results:
* The decoded value for the motion vector or ERROR for unbound
* values will be placed in the location specified.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
 
#define DecodeMotionVectors(value) \
{ \
unsigned int index; \
show_bits11(index); \
value = motion_vectors[index].code; \
flush_bits(motion_vectors[index].num_bits); \
}
/*
*--------------------------------------------------------------
*
* DecodeMBTypeB --
*
* Huffman Decoder for macro_block_type in bidirectionally-coded
* pictures;locations in which the decoded results: macroblock_quant,
* macroblock_motion_forward, macro_block_motion_backward,
* macroblock_pattern, macro_block_intra, will be placed are
* being passed as argument. The decoded values are obtained by
* doing a table lookup on mb_type_B.
*
* Results:
* The various decoded values for macro_block_type in
* bidirectionally-coded pictures or ERROR for unbound values will
* be placed in the locations specified.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
#define DecodeMBTypeB(quant, motion_fwd, motion_bwd, pat, intra) \
{ \
unsigned int index; \
\
show_bits6(index); \
\
quant = mb_type_B[index].mb_quant; \
motion_fwd = mb_type_B[index].mb_motion_forward; \
motion_bwd = mb_type_B[index].mb_motion_backward; \
pat = mb_type_B[index].mb_pattern; \
intra = mb_type_B[index].mb_intra; \
flush_bits(mb_type_B[index].num_bits); \
}
/*
*--------------------------------------------------------------
*
* DecodeMBTypeI --
*
* Huffman Decoder for macro_block_type in intra-coded pictures;
* locations in which the decoded results: macroblock_quant,
* macroblock_motion_forward, macro_block_motion_backward,
* macroblock_pattern, macro_block_intra, will be placed are
* being passed as argument.
*
* Results:
* The various decoded values for macro_block_type in intra-coded
* pictures or ERROR for unbound values will be placed in the
* locations specified.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
#define DecodeMBTypeI(quant, motion_fwd, motion_bwd, pat, intra) \
{ \
unsigned int index; \
static int quantTbl[4] = {ERROR, 1, 0, 0}; \
\
show_bits2(index); \
\
motion_fwd = 0; \
motion_bwd = 0; \
pat = 0; \
intra = 1; \
quant = quantTbl[index]; \
if (index) { \
flush_bits (1 + quant); \
} \
}
/*
*--------------------------------------------------------------
*
* DecodeMBTypeP --
*
* Huffman Decoder for macro_block_type in predictive-coded pictures;
* locations in which the decoded results: macroblock_quant,
* macroblock_motion_forward, macro_block_motion_backward,
* macroblock_pattern, macro_block_intra, will be placed are
* being passed as argument. The decoded values are obtained by
* doing a table lookup on mb_type_P.
*
* Results:
* The various decoded values for macro_block_type in
* predictive-coded pictures or ERROR for unbound values will be
* placed in the locations specified.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
#define DecodeMBTypeP(quant, motion_fwd, motion_bwd, pat, intra) \
{ \
unsigned int index; \
\
show_bits6(index); \
\
quant = mb_type_P[index].mb_quant; \
motion_fwd = mb_type_P[index].mb_motion_forward; \
motion_bwd = mb_type_P[index].mb_motion_backward; \
pat = mb_type_P[index].mb_pattern; \
intra = mb_type_P[index].mb_intra; \
\
flush_bits(mb_type_P[index].num_bits); \
}
/*
*--------------------------------------------------------------
*
* DecodeCBP --
*
* Huffman Decoder for coded_block_pattern; location in which the
* decoded result will be placed is being passed as argument. The
* decoded values are obtained by doing a table lookup on
* coded_block_pattern.
*
* Results:
* The decoded value for coded_block_pattern or ERROR for unbound
* values will be placed in the location specified.
*
* Side effects:
* Bit stream is irreversibly parsed.
*
*--------------------------------------------------------------
*/
#define DecodeCBP(coded_bp) \
{ \
unsigned int index; \
\
show_bits9(index); \
coded_bp = coded_block_pattern[index].cbp; \
flush_bits(coded_block_pattern[index].num_bits); \
}