/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(¶mFrame,&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(¤t, (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(¤t,(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); \ |
} |