Appendix B – Source Modified by Team

/*===========================================================================*

* parallel.c *

* *

* Procedures to make encoder run in parallel *

* *

* EXPORTED PROCEDURES: *

* StartIOServer *

* StartCombineServer *

* StartDecodeServer *

* SendRemoteFrame *

* GetRemoteFrame *

* StartMasterServer *

* NotifyMasterDone *

* *

*===========================================================================*/

/*

* 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.

*/

/*

* $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/parallel.c,v 1.9 1995/08/16 18:22:08 smoot Exp $

* $Log: parallel.c,v $

* Revision 1.9 1995/08/16 18:22:08 smoot

* indents

*

* Revision 1.8 1995/08/14 22:30:20 smoot

* added safe_fork to allow us to kill kids when we die.

*

* Revision 1.7 1995/08/07 21:46:14 smoot

* spawns the same encoder as it is for combine, etc.

* uses new pattern tables to determine frame types

*

* Revision 1.6 1995/06/21 18:32:14 smoot

* Defined SOMAXCONN when not (LINUX)

* added binary r/w (DOsS!)

* ANSIified bcopy call

*

* Revision 1.5 1995/01/19 23:09:00 eyhung

* Changed copyrights

*

* Revision 1.4 1994/03/15 00:27:11 keving

* nothing

*

* Revision 1.3 1993/12/22 19:19:01 keving

* nothing

*

* Revision 1.2 1993/07/22 22:23:43 keving

* nothing

*

* Revision 1.1 1993/06/30 20:06:09 keving

* nothing

*

*/
 
 

/*==============*

* HEADER FILES *

*==============*/

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/times.h>

#include <time.h>

#include <netinet/in.h>

#include <unistd.h>

#include <netdb.h>

#include <errno.h>

#include <string.h>

#include <signal.h>

#include "all.h"

#include "param.h"

#include "mpeg.h"

#include "prototypes.h"

#include "parallel.h"

#include "readframe.h"

#include "fsize.h"

#include "combine.h"

#include "frames.h"

/***************************/

/* Added mvirgo */

#include <assert.h>

/**************************/
 
 

#define MAX_IO_SERVERS 10

#ifndef SOMAXCONN

#define SOMAXCONN 5

#endif

/*==================*

* CONSTANTS *

*==================*/

#define TERMINATE_PID_SIGNAL SIGTERM /* signal used to terminate forked childs */

#ifndef MAXARGS

#define MAXARGS 1024 /* Max Number of arguments in safe_fork command */

#endif

/*==================*

* STATIC VARIABLES *

*==================*/

static int32 diffTime;

static char rsh[256];

static struct hostent *hostEntry = NULL;

static boolean *frameDone;

static int outputServerSocket;

static int decodeServerSocket;

static boolean parallelPerfect = FALSE;

static int current_max_forked_pid=0;
 
 

/*==================*

* GLOBAL VARIABLES *

*==================*/

extern int yuvHeight, yuvWidth;

extern time_t timeStart, timeEnd;

extern char statFileName[256];

extern FILE *statFile;

extern boolean debugMachines;

extern boolean debugSockets;

int parallelTestFrames = 10;

int parallelTimeChunks = 60;

char *IOhostName;

int ioPortNumber;

int combinePortNumber;

int decodePortNumber;

boolean niceProcesses = FALSE;

boolean forceIalign = FALSE;

int machineNumber = -1;

boolean remoteIO = FALSE;

boolean separateConversion;

time_t IOtime = 0;

extern char encoder_name[];

int ClientPid[MAX_MACHINES+4];

/*===============================*

* INTERNAL PROCEDURE prototypes *

*===============================*/

static void TransmitPortNum _ANSI_ARGS_((char *hostName, int portNum,

int ioPortNum));

static void EndIOServer _ANSI_ARGS_((void));

static void SafeRead _ANSI_ARGS_((int fd, char *buf, int nbyte));

static void SafeWrite _ANSI_ARGS_((int fd, char *buf, int nbyte));

static int CreateListeningSocket _ANSI_ARGS_((int *portNumber));

static int ConnectToSocket _ANSI_ARGS_((char *machineName, int portNum,

struct hostent **hostEnt));

static int safe_fork _ANSI_ARGS_((char *command));

void cleanup_fork _ANSI_ARGS_ ((int dummy));
 
 

/*=====================*

* EXPORTED PROCEDURES *

*=====================*/

/*=================*

* IO SERVER STUFF *

*=================*/
 
 

/*===========================================================================*

*

* SetIOConvert

*

* sets the IO conversion to be separate or not. If separate, then

* some post-processing is done at slave end

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

SetIOConvert(separate)

boolean separate;

{

separateConversion = separate;

}
 
 

/*===========================================================================*

*

* SetParallelPerfect

*

* If this is called, then frames will be divided up completely, and

* evenly (modulo rounding) between all the processors

*

* RETURNS: nothing

*

* SIDE EFFECTS: Sets parallelPerfect ....

*

*===========================================================================*/

void

SetParallelPerfect(val)

boolean val;

{

parallelPerfect = val;

}
 
 

/*===========================================================================*

*

* SetRemoteShell

*

* sets the remote shell program (usually rsh, but different on some

* machines)

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

SetRemoteShell(shell)

char *shell;

{

strcpy(rsh, shell);

}
 
 

/*===========================================================================*

*

* StartIOServer

*

* start-up the IOServer with this process

* handles slave requests for frames, and exits when master tells it to

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

StartIOServer(numInputFiles, parallelHostName, portNum)

int numInputFiles;

char *parallelHostName;

int portNum;

{

int ioPortNum;

int serverSocket;

int otherSock, otherSize;

struct sockaddr otherSocket;

int32 buffer[8];

boolean done = FALSE;

int frameNumber;

MpegFrame *frame;

register int y;

int numBytes;

unsigned char *bigBuffer;

unsigned char smallBuffer[1000];

int bigBufferSize;

FILE *filePtr;

uint32 data;

char inputFileName[1024];

char fileName[1024];

bigBufferSize = 0;

bigBuffer = NULL;

/* once we get IO port num, should transmit it to parallel server */

serverSocket = CreateListeningSocket(&ioPortNum);

if ( debugSockets ) {

fprintf(stdout, "====I/O USING PORT %d\n", ioPortNum);

}

TransmitPortNum(parallelHostName, portNum, ioPortNum);

otherSize = sizeof(otherSocket);

if ( separateConversion ) {

SetFileType(ioConversion); /* for reading */

} else {

SetFileType(inputConversion);

}

/* now, wait until get done signal */

while ( ! done ) {

otherSock = accept(serverSocket, &otherSocket, &otherSize);

if ( otherSock == -1 ) {

fprintf(stderr, "ERROR: I/O SERVER accept returned error %d\n", errno);

exit(1);

}

SafeRead(otherSock, (char *)buffer, 4);

frameNumber = ntohl(buffer[0]);

if ( frameNumber == -1 ) {

done = TRUE;

} else if ( frameNumber == -2 ) {

/* decoded frame to be output to disk */

SafeRead(otherSock, (char *)buffer, 4);

frameNumber = ntohl(buffer[0]);

if ( debugSockets ) {

fprintf(stdout, "INPUT SERVER: GETTING DECODED FRAME %d\n", frameNumber);

fflush(stdout);

}

/* should read frame from socket, then write to disk */

frame = Frame_New(frameNumber, 'i');

Frame_AllocDecoded(frame, TRUE);

for ( y = 0; y < Fsize_y; y++ ) {

SafeRead(otherSock, (char *)frame->decoded_y[y], Fsize_x);

}

for (y = 0; y < (Fsize_y >> 1); y++) { /* U */

SafeRead(otherSock, (char *)frame->decoded_cb[y], (Fsize_x >> 1));

}

for (y = 0; y < (Fsize_y >> 1); y++) { /* V */

SafeRead(otherSock, (char *)frame->decoded_cr[y], (Fsize_x >> 1));

}

/* now output to disk */

WriteDecodedFrame(frame);

Frame_Free(frame);

} else if ( frameNumber == -3 ) {

/* request for decoded frame from disk */

SafeRead(otherSock, (char *)buffer, 4);

frameNumber = ntohl(buffer[0]);

if ( debugSockets ) {

fprintf(stdout, "INPUT SERVER: READING DECODED FRAME %d from DISK\n", frameNumber);

fflush(stdout);

}

/* should read frame from disk, then write to socket */

frame = Frame_New(frameNumber, 'i');

Frame_AllocDecoded(frame, TRUE);

ReadDecodedRefFrame(frame, frameNumber);

/* now write to socket */

for ( y = 0; y < Fsize_y; y++ ) {

SafeWrite(otherSock, (char *)frame->decoded_y[y], Fsize_x);

}

for (y = 0; y < (Fsize_y >> 1); y++) { /* U */

SafeWrite(otherSock, (char *)frame->decoded_cb[y], (Fsize_x >> 1));

}

for (y = 0; y < (Fsize_y >> 1); y++) { /* V */

SafeWrite(otherSock, (char *)frame->decoded_cr[y], (Fsize_x >> 1));

}

Frame_Free(frame);

} else if ( frameNumber == -4 ) {

/* routing output frame from socket to disk */

SafeRead(otherSock, (char *)buffer, 8);

frameNumber = buffer[0];

frameNumber = ntohl(frameNumber);

/* read in number of bytes */

numBytes = buffer[1];

numBytes = ntohl(numBytes);

/* make sure buffer is big enough for data */

if ( numBytes > bigBufferSize ) {

bigBufferSize = numBytes;

if ( bigBuffer != NULL ) {

free(bigBuffer);

}

bigBuffer = (unsigned char *) malloc(bigBufferSize*

sizeof(unsigned char));

}

/* now read in the bytes */

SafeRead(otherSock, (char *) bigBuffer, numBytes);

/* open file to output this stuff to */

sprintf(fileName, "%s.frame.%d", outputFileName, frameNumber);

if ( (filePtr = fopen(fileName, "wb")) == NULL ) {

fprintf(stderr, "ERROR: Could not open output file(3): %s\n",

fileName);

exit(1);

}

/* now write the bytes here */

fwrite(bigBuffer, sizeof(char), numBytes, filePtr);

fclose(filePtr);

if ( debugSockets ) {

fprintf(stdout, "====I/O SERVER: WROTE FRAME %d to disk\n",

frameNumber);

fflush(stdout);

}

} else {

if ( debugSockets ) {

fprintf(stdout, "I/O SERVER GETTING FRAME %d\n", frameNumber);

fflush(stdout);

}

/* should read in frame, then write to socket */

frame = Frame_New(frameNumber, 'i');

if ( separateConversion ) {

GetNthInputFileName(inputFileName, frameNumber);

/* do conversion and send right to the socket */

filePtr = ReadIOConvert(inputFileName);

do {

numBytes = fread(smallBuffer, 1, 1000, filePtr);

if ( numBytes > 0 ) {

data = numBytes;

data = htonl(data);

SafeWrite(otherSock, (char *)&data, 4);

SafeWrite(otherSock, (char *)smallBuffer, numBytes);

}

}

while ( numBytes == 1000 );

if ( strcmp(ioConversion, "*") == 0 ) {

fclose(filePtr);

} else {

pclose(filePtr);

}

} else {

GetNthInputFileName(inputFileName, frameNumber);

ReadFrame(frame, inputFileName, inputConversion, TRUE);

/* should now transmit yuv values */

for (y = 0; y < yuvHeight; y++) { /* Y */

SafeWrite(otherSock, (char *)frame->orig_y[y], yuvWidth);

}

for (y = 0; y < (yuvHeight >> 1); y++) { /* U */

SafeWrite(otherSock, (char *)frame->orig_cb[y], yuvWidth >> 1);

}

for (y = 0; y < (yuvHeight >> 1); y++) { /* V */

SafeWrite(otherSock, (char *)frame->orig_cr[y], yuvWidth >> 1);

}

/* now, make sure we don't leave until other processor read everything */

SafeRead(otherSock, (char *)buffer, 4);

/* should = 0 */

}

if ( debugSockets ) {

fprintf(stdout, "====I/O SERVER: READ FRAME %d\n",

frameNumber);

}

Frame_Free(frame);

}

close(otherSock);

}

close(serverSocket);

if ( debugSockets ) {

fprintf(stdout, "====I/O SERVER: Shutting Down\n");

}

}
 
 

/*===========================================================================*

*

* SendRemoteFrame

*

* called by a slave to the I/O server; sends an encoded frame

* to the server to be sent to disk

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

SendRemoteFrame(frameNumber, bb)

int frameNumber;

BitBucket *bb;

{

int clientSocket;

u_long data;

int negativeFour = -4;

time_t tempTimeStart, tempTimeEnd;

time(&tempTimeStart);

clientSocket = ConnectToSocket(IOhostName, ioPortNumber, &hostEntry);

data = htonl(negativeFour);

SafeWrite(clientSocket, (char *)&data, 4);

data = htonl(frameNumber);

SafeWrite(clientSocket, (char *)&data, 4);

if ( frameNumber != -1 ) {

/* send number of bytes */

data = (bb->totalbits+7)>>3;

data = htonl(data);

SafeWrite(clientSocket, (char *)&data, 4);

/* now send the bytes themselves */

Bitio_WriteToSocket(bb, clientSocket);

}

close(clientSocket);

time(&tempTimeEnd);

IOtime += (tempTimeEnd-tempTimeStart);

}
 
 
 
 
 
 

/*===========================================================================*

*

* NoteFrameDone

*

* called by slave to the Combine server; tells it these frames are

* done

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

NoteFrameDone(frameStart, frameEnd)

int frameStart;

int frameEnd;

{

int clientSocket;

u_long data;

int negativeTwo = -2;

time_t tempTimeStart, tempTimeEnd;

time(&tempTimeStart);

clientSocket = ConnectToSocket(IOhostName, combinePortNumber, &hostEntry);

data = negativeTwo;

data = htonl(negativeTwo);

SafeWrite(clientSocket, (char *)&data, 4);

data = htonl(frameStart);

SafeWrite(clientSocket, (char *)&data, 4);

data = htonl(frameEnd);

SafeWrite(clientSocket, (char *)&data, 4);

close(clientSocket);

time(&tempTimeEnd);

IOtime += (tempTimeEnd-tempTimeStart);

}
 
 

/*===========================================================================*

*

* GetRemoteFrame

*

* called by a slave; gets a remote frame from the I/O server

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

GetRemoteFrame(frame, frameNumber)

MpegFrame *frame;

int frameNumber;

{

FILE *filePtr;

int clientSocket;

unsigned char smallBuffer[1000];

register int y;

int numBytes;

u_long data;

char fileName[256];

Fsize_Note(frameNumber, yuvWidth, yuvHeight);

if ( debugSockets ) {

fprintf(stdout, "MACHINE %s REQUESTING connection for FRAME %d\n",

getenv("HOST"), frameNumber);

fflush(stdout);

}

clientSocket = ConnectToSocket(IOhostName, ioPortNumber, &hostEntry);

data = frameNumber;

data = htonl(data);

SafeWrite(clientSocket, (char *)&data, 4);

if ( frameNumber != -1 ) {

if ( separateConversion ) {

sprintf(fileName, "/tmp/foobar%d", machineNumber);

filePtr = fopen(fileName, "wb");

/* read in stuff, SafeWrite to file, perform local conversion */

do {

SafeRead(clientSocket, (char *)&numBytes, 4);

numBytes = ntohl(numBytes);

SafeRead(clientSocket, (char *)smallBuffer, numBytes);

fwrite(smallBuffer, 1, numBytes, filePtr);

} while ( numBytes == 1000 );

fflush(filePtr);

fclose(filePtr);

/* now do slave conversion */

ReadFrame(frame, fileName, slaveConversion, FALSE);

} else {

Frame_AllocYCC(frame);

if ( debugSockets ) {

fprintf(stdout, "MACHINE %s allocated YCC FRAME %d\n",

getenv("HOST"), frameNumber);

fflush(stdout);

}

/* should now read yuv values */

for (y = 0; y < yuvHeight; y++) { /* Y */

SafeRead(clientSocket, (char *)frame->orig_y[y], yuvWidth);

}

for (y = 0; y < (yuvHeight >> 1); y++) { /* U */

SafeRead(clientSocket, (char *)frame->orig_cb[y], yuvWidth>>1);

}

for (y = 0; y < (yuvHeight >> 1); y++) { /* V */

SafeRead(clientSocket, (char *)frame->orig_cr[y], yuvWidth>>1);

}

}

}

data = 0;

data = htonl(data);

SafeWrite(clientSocket, (char *)&data, 4);

close(clientSocket);

if ( debugSockets ) {

fprintf(stdout, "MACHINE %s READ COMPLETELY FRAME %d\n",

getenv("HOST"), frameNumber);

fflush(stdout);

}

}
 
 

/*===========================================================================*

*

* StartCombineServer

*

* start-up the CombineServer with this process

* handles combination of frames, and tells the

* master when it's done

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

StartCombineServer(numInputFiles, outputFileName, parallelHostName, portNum)

int numInputFiles;

char *outputFileName;

char *parallelHostName;

int portNum;

{

int combinePortNum;

FILE *ofp;

/* once we get Combine port num, should transmit it to parallel server */

outputServerSocket = CreateListeningSocket(&combinePortNum);

if ( debugSockets ) {

fprintf(stdout, "====OUTPUT USING PORT %d\n", combinePortNum);

}

TransmitPortNum(parallelHostName, portNum, combinePortNum);

frameDone = (boolean *) malloc(numInputFiles*sizeof(boolean));

memset((char *)frameDone, 0, numInputFiles*sizeof(boolean));

if ( (ofp = fopen(outputFileName, "wb")) == NULL ) {

fprintf(stderr, "ERROR: Could not open output file!!\n");

fflush(stderr);

exit(1);

}

FramesToMPEG(numInputFiles, outputFileName, ofp, TRUE);

if ( debugSockets ) {

fprintf(stdout, "====COMBINE SERVER: Shutting Down\n");

fflush(stdout);

}

/* tell Master server we are done */

TransmitPortNum(parallelHostName, portNum, combinePortNum);

close(outputServerSocket);

}
 
 

/*===========================================================================*

*

* WaitForOutputFile

*

* keep handling output events until we get the specified frame

* number

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

WaitForOutputFile(number)

int number;

{

int otherSock;

static int otherSize = sizeof(struct sockaddr);

struct sockaddr otherSocket;

int frameNumber;

int32 buffer[8];

int frameStart, frameEnd;

while ( ! frameDone[number] ) {

otherSock = accept(outputServerSocket, &otherSocket, &otherSize);

if ( otherSock == -1 ) {

fprintf(stderr, "ERROR: Combine SERVER accept returned error %d\n", errno);

exit(1);

}

SafeRead(otherSock, (char *)buffer, 4);

frameNumber = ntohl(buffer[0]);

if ( frameNumber == -2 ) {

/* this is notification from non-remote process that a frame is done */

SafeRead(otherSock, (char *)buffer, 8);

frameStart = buffer[0];

frameStart = ntohl(frameStart);

frameEnd = buffer[1];

frameEnd = ntohl(frameEnd);

for ( frameNumber = frameStart; frameNumber <= frameEnd;

frameNumber++ ) {

frameDone[frameNumber] = TRUE;

}

}

close(otherSock);

}

if ( debugSockets ) {

fprintf(stdout, "WAIT FOR FRAME %d over\n", number);

fflush(stdout);

}

}
 
 

/*=====================*

* MASTER SERVER STUFF *

*=====================*/
 
 

/*===========================================================================*

*

* StartMasterServer

*

* start the master server with this process

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

StartMasterServer(numInputFiles, paramFile, outputFileName)

int numInputFiles;

char *paramFile;

char *outputFileName;

{

FILE *filePtr;

register int ind, ind2;

int framesPerMachine;

char command[1024];

char *hostName;

int portNum;

int serverSocket;

boolean finished[MAX_MACHINES];

int numFinished;

int otherSock, otherSize;

struct sockaddr otherSocket;

int seconds;

int32 buffer[8];

int ioPortNum[MAX_IO_SERVERS];

int combinePortNum, decodePortNum;

int nextFrame;

int startFrames[MAX_MACHINES];

int numFrames[MAX_MACHINES];

int lastNumFrames[MAX_MACHINES];

int numSeconds[MAX_MACHINES];

float fps[MAX_MACHINES];

int numMachinesToEstimate;

float framesPerSecond;

float totalFPS, localFPS;

int framesDone;

float avgFPS;

char niceNess[256];

int32 startFrame, endFrame;

int numInputPorts = 0;

int numRemote = SOMAXCONN;

int totalRemote = 0;

time_t startUpBegin, startUpEnd;

time_t shutDownBegin, shutDownEnd;

float timeChunk;

/***********************************/

/*added mvirgo*/

int stall_all;

int savedSeconds[MAX_MACHINES];

int otherSockList[MAX_MACHINES];

struct sockaddr otherSocketList[MAX_MACHINES];

/*************************************/

time(&startUpBegin);

if ( niceProcesses ) {

sprintf(niceNess, "nice");

} else {

niceNess[0] = '\0';

}

time(&timeStart);

PrintStartStats(-1, 0);

/* create a server socket */

hostName = getenv("HOST");

if ( hostName == NULL ) {

fprintf(stderr, "ERROR: Set HOST environment variable\n");

exit(1);

}

hostEntry = gethostbyname(hostName);

if ( hostEntry == NULL ) {

fprintf(stderr, "ERROR: Could not find host %s in database\n",

hostName);

exit(1);

}

hostName = hostEntry->h_name;

serverSocket = CreateListeningSocket(&portNum);

if ( debugSockets ) {

fprintf(stdout, "---USING PORT %d\n", portNum);

}

/* START COMBINE SERVER */

sprintf(command, "%s -max_machines %d -output_server %s %d %d %s",

encoder_name, numMachines, hostName, portNum, numInputFiles, paramFile);

safe_fork(command);

/* should now listen for connection from Combine server */

otherSize = sizeof(otherSocket);

otherSock = accept(serverSocket, &otherSocket, &otherSize);

if ( otherSock == -1 ) {

fprintf(stderr, "ERROR: MASTER SERVER accept returned error %d\n", errno);

exit(1);

}

SafeRead(otherSock, (char *)(&combinePortNum), 4);

combinePortNum = ntohl(combinePortNum);

combinePortNumber = combinePortNum;

close(otherSock);

if ( debugSockets ) {

fprintf(stdout, "---MASTER SERVER: Combine port number = %d\n",

combinePortNum);

}

/* START DECODE SERVER if necessary */

if ( referenceFrame == DECODED_FRAME ) {

sprintf(command, "%s -max_machines %d -decode_server %s %d %d %s",

encoder_name, numMachines, hostName, portNum, numInputFiles, paramFile);

safe_fork(command);

/* should now listen for connection from Decode server */

otherSize = sizeof(otherSocket);

otherSock = accept(serverSocket, &otherSocket, &otherSize);

if ( otherSock == -1 ) {

fprintf(stderr, "ERROR: MASTER SERVER accept returned error %d\n", errno);

exit(1);

}

SafeRead(otherSock, (char *)(&decodePortNum), 4);

decodePortNum = ntohl(decodePortNum);

close(otherSock);

if ( debugSockets ) {

fprintf(stdout, "---MASTER SERVER: Decode port number = %d\n",

decodePortNum);

}

}

/* we are doing whole thing (if not, see above) */

framesPerMachine = numInputFiles/numMachines;

numFinished = 0;

/* count number of remote machines */

for ( ind = 0; ind < numMachines; ind++ ) {

fps[ind] = -1.0; /* illegal value as flag */

if ( remote[ind] ) {

totalRemote++;

}

}

/* DO INITIAL TIME TESTS */

nextFrame = 0;

for ( ind = 0; ind < numMachines; ind++ ) {

if ( (totalRemote != 0) && (numRemote == SOMAXCONN) ) {

/* Create an I/O server */

sprintf(command, "%s -max_machines %d -io_server %s %d %s",

encoder_name, numMachines, hostName, portNum, paramFile);

safe_fork(command);

/* should now listen for connection from I/O server */

otherSize = sizeof(otherSocket);

otherSock = accept(serverSocket, &otherSocket, &otherSize);

if ( otherSock == -1 ) {

fprintf(stderr, "ERROR: MASTER SERVER accept returned error %d\n", errno);

exit(1);

}

SafeRead(otherSock, (char *)(&ioPortNum[numInputPorts]), 4);

ioPortNum[numInputPorts] = ntohl(ioPortNum[numInputPorts]);

close(otherSock);

if ( debugSockets ) {

fprintf(stdout, "---MASTER SERVER: I/O port number = %d\n",

ioPortNum[numInputPorts]);

}

numInputPorts++;

numRemote = 0;

}

finished[ind] = FALSE;

numSeconds[ind] = 0;

startFrame = nextFrame;

if ( parallelPerfect ) {

endFrame = startFrame+((numInputFiles-startFrame)/

(numMachines-ind)) -1;

if ( forceIalign ) {

while (FType_Type(endFrame) != 'i') {endFrame++;}

}

/* always give at least 1 frame */

if ( endFrame < startFrame ) {

endFrame = startFrame;

}

/* make sure not out of bounds */

if ( endFrame >= numInputFiles ) {

endFrame = numInputFiles-1;

}

} else if ( forceIalign ) {

endFrame = startFrame+framePatternLen-1;

while (FType_Type(endFrame) != 'i') {endFrame++;}

} else {

endFrame = startFrame+parallelTestFrames-1;

}

/***************************/

/* Added mvirgo: Give each of three slaves a frame. One gets 2 to

make the combine server happy. Make sure there are

enough to go around. */

assert (numMachines == 3);

assert (numInputFiles >= 3);

startFrame = ind;

endFrame = ind;

/****************************/

if ( remote[ind] ) {

sprintf(command, "%s %s -l %s %s %s -child %s %d %d %d %d %d %d -frames %d %d %s",

rsh,

machineName[ind], userName[ind], niceNess,

executable[ind],

hostName, portNum, ioPortNum[numInputPorts-1],

combinePortNum, decodePortNum, ind,

remote[ind],

startFrame, endFrame,

remoteParamFile[ind]);

numRemote++;

totalRemote--;

} else {

sprintf(command, "%s %s -l %s %s %s -child %s %d %d %d %d %d %d -frames %d %d %s",

rsh,

machineName[ind], userName[ind], niceNess,

executable[ind],

hostName, portNum, ioPortNum[numInputPorts-1],

combinePortNum, decodePortNum, ind,

remote[ind],

startFrame, endFrame,

paramFile);

}

if ( debugMachines ) {

fprintf(stdout, "---%s: frames %d to %d\n",

machineName[ind],

startFrame, endFrame);

}

safe_fork(command);

nextFrame = endFrame+1;

startFrames[ind] = startFrame;

numFrames[ind] = endFrame-startFrame+1;

lastNumFrames[ind] = endFrame-startFrame+1;

}

framesDone = 0;

time(&startUpEnd);

/* now, wait for other processes to finish and boss them around */

while ( numFinished != numMachines ) {

/***************************************************/

/* added mvirgo: block while all children complete */

for (stall_all = 0; stall_all < numMachines; stall_all++) {

otherSize = sizeof(otherSocketList[stall_all]);

otherSock = accept(serverSocket, &(otherSocketList[stall_all]),

&otherSize);

if ( otherSock == -1 ) {

fprintf(stderr, "ERROR: MASTER SERVER 2 accept returned error %d\n", errno);

exit(1);

}

SafeRead(otherSock, (char *)buffer, 8);

/**** Do the assignments in original order ***/

otherSockList[ntohl(buffer[0])] = otherSock;

savedSeconds[ntohl(buffer[0])] = ntohl(buffer[1]);

}

for (stall_all = 0; stall_all < numMachines; stall_all++) {

otherSock = otherSockList[stall_all];

ind = stall_all;

seconds = savedSeconds[ind];

/****************************************************/

NoteFrameDone(startFrames[ind],

startFrames[ind]+lastNumFrames[ind]-1);

numSeconds[ind] += seconds;

fps[ind] = (float)numFrames[ind]/(float)numSeconds[ind];

if ( seconds != 0 )

framesPerSecond = (float)lastNumFrames[ind]/(float)seconds;

else

framesPerSecond = (float)lastNumFrames[ind]*2.0;

framesDone += lastNumFrames[ind];

if ( nextFrame >= numInputFiles ) {

buffer[0] = htonl(-1);

buffer[1] = htonl(0);

SafeWrite(otherSock, (char *)buffer, 8);

numFinished++;

if ( debugMachines ) {

fprintf(stdout, "---%s FINISHED job (%f fps) (%d/%d done): DONE\n",

machineName[ind], framesPerSecond, numFinished,

numMachines);

}

} else {

if (numSeconds[ind] != 0) {

avgFPS = (float)numFrames[ind]/(float)numSeconds[ind];

} else {

avgFPS = 0.1; /* arbitrary small value */

}

startFrame = nextFrame;

if ( parallelTimeChunks == -1 ) { /* TAPER STUFF */

/* estimate time left */

/* frames left = numInputFiles-nextFrame */

totalFPS = 0.0;

numMachinesToEstimate = 0;

for ( ind2 = 0; ind2 < numMachines; ind2++ ) {

if ( fps[ind2] < 0.0 ) {

numMachinesToEstimate++;

} else {

totalFPS += fps[ind2];

}

}

totalFPS = (float)numMachines*

(totalFPS/(float)(numMachines-numMachinesToEstimate));

timeChunk = (float)(numInputFiles-nextFrame)/totalFPS;

fprintf(stdout, "ASSIGNING %s %.2f seconds of work\n",

machineName[ind], timeChunk);

fflush(stdout);

endFrame = nextFrame +

(int)((float)timeChunk*avgFPS) - 1;

} else {

endFrame = nextFrame +

(int)((float)parallelTimeChunks*avgFPS) - 1;

}

if ( forceIalign ) {

while (FType_Type(endFrame) != 'i') {endFrame++;}

}

if ( endFrame < startFrame ) { /* always give at least 1 frame */

endFrame = startFrame;

}

/*******************************************************/

/* added mvirgo: _always_ give one frame */

/******************************************************/

endFrame = startFrame;

if ( endFrame >= numInputFiles ) {

endFrame = numInputFiles-1;

}

nextFrame = endFrame+1;

startFrames[ind] = startFrame;

numFrames[ind] += (endFrame-startFrame+1);

lastNumFrames[ind] = (endFrame-startFrame+1);

if ( debugMachines ) {

fprintf(stdout, "---%s FINISHED job (%f fps) (%d/%d done): next: %d to %d\n",

machineName[ind], framesPerSecond, numFinished,

numMachines, startFrame, endFrame);

}

buffer[0] = htonl(startFrame);

buffer[1] = htonl(endFrame);

SafeWrite(otherSock, (char *)buffer, 8);

}

close(otherSock);

if ( debugMachines ) {

fprintf(stdout, "---FRAMES DONE: %d\tFARMED OUT: %d\tLEFT: %d\n",

framesDone, nextFrame-framesDone, numInputFiles-nextFrame);

}

} /*added mvirgo: close the inner for loop */

}

time(&shutDownBegin);

/* end all input servers */

IOhostName = hostName;

for ( ind = 0; ind < numInputPorts; ind++ ) {

ioPortNumber = ioPortNum[ind];

EndIOServer();

}

/* now wait for CombineServer to tell us they're done */

otherSize = sizeof(otherSocket);

otherSock = accept(serverSocket, &otherSocket, &otherSize);

if ( otherSock == -1 ) {

fprintf(stderr, "ERROR: MASTER SERVER accept returned error %d\n", errno);

exit(1);

}

SafeRead(otherSock, (char *)buffer, 4);

close(otherSock);

close(serverSocket);

time(&timeEnd);

diffTime = (int32)(timeEnd-timeStart);

time(&shutDownEnd);

for ( ind2 = 0; ind2 < 2; ind2++ ) {

if ( ind2 == 0 ) {

filePtr = stdout;

} else if ( statFile != NULL ) {

filePtr = statFile;

} else {

continue;

}

fprintf(filePtr, "\n\n");

fprintf(filePtr, "PARALLEL SUMMARY\n");

fprintf(filePtr, "----------------\n");

fprintf(filePtr, "\n");

fprintf(filePtr, "START UP TIME: %d seconds\n",

(int)startUpEnd-(int)startUpBegin);

fprintf(filePtr, "SHUT DOWN TIME: %d seconds\n",

(int)shutDownEnd-(int)shutDownBegin);

fprintf(filePtr, "%14s\tFrames\tSeconds\tFrames Per Second\tSelf Time\n",

"MACHINE");

fprintf(filePtr, "--------------\t------\t-------\t-----------------\t---------\n");

totalFPS = 0.0;

for ( ind = 0; ind < numMachines; ind++ ) {

localFPS = (float)numFrames[ind]/(float)numSeconds[ind];

fprintf(filePtr, "%14s\t%d\t%d\t%f\t\t%d\n",

machineName[ind], numFrames[ind], numSeconds[ind],

localFPS, (int)((float)numInputFiles/localFPS));

totalFPS += localFPS;

}

fprintf(filePtr, "--------------\t------\t-------\t-----------------\t---------\n");

fprintf(filePtr, "%14s\t\t%d\t%f\n", "OPTIMAL",

(int)((float)numInputFiles/totalFPS),

totalFPS);

fprintf(filePtr, "%14s\t\t%d\t%f\n", "ACTUAL", diffTime,

(float)numInputFiles/(float)diffTime);

fprintf(filePtr, "\n\n");

}

if ( statFile != NULL ) {

fclose(statFile);

}

}
 
 

/*===========================================================================*

*

* NotifyMasterDone

*

* called by a slave process; tells the master process it is done

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

boolean

NotifyMasterDone(hostName, portNum, machineNumber, seconds, frameStart,

frameEnd)

char *hostName;

int portNum;

int machineNumber;

int seconds;

int *frameStart;

int *frameEnd;

{

int clientSocket;

int32 buffer[8];

time_t tempTimeStart, tempTimeEnd;

time(&tempTimeStart);

clientSocket = ConnectToSocket(hostName, portNum, &hostEntry);

buffer[0] = htonl(machineNumber);

buffer[1] = htonl(seconds);

SafeWrite(clientSocket, (char *)buffer, 8);

SafeRead(clientSocket, (char *)buffer, 8);

*frameStart = ntohl(buffer[0]);

*frameEnd = ntohl(buffer[1]);

close(clientSocket);

time(&tempTimeEnd);

IOtime += (tempTimeEnd-tempTimeStart);

return ((*frameStart) >= 0);

}
 
 

/*===========================================================================*

*

* StartDecodeServer

*

* start-up the DecodeServer with this process

* handles transfer of decoded frames to/from processes, and exits

* when master tells it to

* this is necessary only if referenceFrame == DECODED_FRAME

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

StartDecodeServer(numInputFiles, decodeFileName, parallelHostName, portNum)

int numInputFiles;

char *decodeFileName;

char *parallelHostName;

int portNum;

{

int otherSock, otherSize;

struct sockaddr otherSocket;

int decodePortNum;

int32 buffer[8];

int frameReady;

boolean *ready;

int *waitMachine;

int *waitPort;

int *waitList;

int slaveNumber;

int slavePort;

int waitPtr;

struct hostent *nullHost = NULL;

int clientSocket;

/* should keep list of port numbers to notify when frames become ready */

ready = (boolean *) calloc(numInputFiles, sizeof(boolean));

waitMachine = (int *) calloc(numInputFiles, sizeof(int));

waitPort = (int *) malloc(numMachines*sizeof(int));

waitList = (int *) calloc(numMachines, sizeof(int));

/* once we get Decode port num, should transmit it to parallel server */

decodeServerSocket = CreateListeningSocket(&decodePortNum);

if ( debugSockets ) {

fprintf(stdout, "====DECODE USING PORT %d\n", decodePortNum);

}

TransmitPortNum(parallelHostName, portNum, decodePortNum);

frameDone = (boolean *) malloc(numInputFiles*sizeof(boolean));

memset((char *)frameDone, 0, numInputFiles*sizeof(boolean));

/* wait for ready signals and requests */

while ( TRUE ) {

otherSize = sizeof(otherSocket);

otherSock = accept(decodeServerSocket, &otherSocket, &otherSize);

if ( otherSock == -1 ) {

fprintf(stderr, "ERROR: DECODE SERVER accept returned error %d\n", errno);

exit(1);

}

SafeRead(otherSock, (char *)buffer, 4);

frameReady = buffer[0];

frameReady = ntohl(frameReady);

if ( frameReady == -2 ) {

SafeRead(otherSock, (char *)buffer, 4);

frameReady = buffer[0];

frameReady = ntohl(frameReady);

if ( debugSockets ) {

fprintf(stdout, "====DECODE SERVER: REQUEST FOR %d\n", frameReady);

fflush(stdout);

}

/* now respond if it's ready yet */

buffer[0] = frameDone[frameReady];

buffer[0] = htonl(buffer[0]);

SafeWrite(otherSock, (char *)buffer, 4);

if ( ! frameDone[frameReady] ) {

/* read machine number, port number */

SafeRead(otherSock, (char *)buffer, 8);

slaveNumber = buffer[0];

slaveNumber = ntohl(slaveNumber);

slavePort = buffer[1];

slavePort = ntohl(slavePort);

if ( debugSockets ) {

fprintf(stdout, "WAITING: SLAVE %d, PORT %d\n",

slaveNumber, slavePort);

}

waitPort[slaveNumber] = slavePort;

if ( waitMachine[frameReady] == 0 ) {

waitMachine[frameReady] = slaveNumber+1;

} else {

/* someone already waiting for this frame */

/* follow list of waiters to the end */

waitPtr = waitMachine[frameReady]-1;

while ( waitList[waitPtr] != 0 ) {

waitPtr = waitList[waitPtr]-1;

}

waitList[waitPtr] = slaveNumber+1;

waitList[slaveNumber] = 0;

}

}

} else {

frameDone[frameReady] = TRUE;

if ( debugSockets ) {

fprintf(stdout, "====DECODE SERVER: FRAME %d READY\n", frameReady);

fflush(stdout);

}

if ( waitMachine[frameReady] ) {

/* need to notify one or more machines it's ready */

waitPtr = waitMachine[frameReady]-1;

while ( waitPtr >= 0 ) {

clientSocket = ConnectToSocket(machineName[waitPtr],

waitPort[waitPtr],

&nullHost);

close(clientSocket);

waitPtr = waitList[waitPtr]-1;

}

}

}

close(otherSock);

}

if ( debugSockets ) {

fprintf(stdout, "====DECODE SERVER: Shutting Down\n");

fflush(stdout);

}

/* tell Master server we are done */

TransmitPortNum(parallelHostName, portNum, decodePortNum);

close(decodeServerSocket);

}
 
 

/*=====================*

* INTERNAL PROCEDURES *

*=====================*/
 
 

/*===========================================================================*

*

* TransmitPortNum

*

* called by the I/O or Combine server; transmits the appropriate

* port number to the master

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

static void

TransmitPortNum(hostName, portNum, newPortNum)

char *hostName;

int portNum;

int newPortNum;

{

int clientSocket;

u_long data;

clientSocket = ConnectToSocket(hostName, portNum, &hostEntry);

data = htonl(newPortNum);

SafeWrite(clientSocket, (char *) &data, 4);

close(clientSocket);

}
 
 

/*===========================================================================*

*

* SafeRead

*

* safely read from the given socket; the procedure keeps reading until

* it gets the number of bytes specified

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

static void

SafeRead(fd, buf, nbyte)

int fd;

char *buf;

int nbyte;

{

int numRead;

int result;

numRead = 0;

while ( numRead != nbyte ) {

result = read(fd, &buf[numRead], nbyte-numRead);

if ( result == -1 ) {

fprintf(stderr, "ERROR: read (of %d bytes (total %d) ) returned error %d\n",

nbyte-numRead, nbyte, errno);

exit(1);

}

numRead += result;

}

}
 
 

/*===========================================================================*

*

* SafeWrite

*

* safely write to the given socket; the procedure keeps writing until

* it sends the number of bytes specified

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

static void

SafeWrite(fd, buf, nbyte)

int fd;

char *buf;

int nbyte;

{

int numWritten;

int result;

numWritten = 0;

while ( numWritten != nbyte ) {

result = write(fd, &buf[numWritten], nbyte-numWritten);

if ( result == -1 ) {

fprintf(stderr, "ERROR: read (of %d bytes (total %d) ) returned error %d\n",

nbyte-numWritten, nbyte, errno);

exit(1);

}

numWritten += result;

}

}
 
 

/*===========================================================================*

*

* EndIOServer

*

* called by the master process -- tells the I/O server to commit

* suicide

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

static void

EndIOServer()

{

/* send signal to IO server: -1 as frame number */

GetRemoteFrame(NULL, -1);

}
 
 

/*===========================================================================*

*

* NotifyDecodeServerReady

*

* called by a slave to the Decode Server to tell it a decoded frame

* is ready and waiting

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

NotifyDecodeServerReady(id)

int id;

{

int clientSocket;

u_long data;

time_t tempTimeStart, tempTimeEnd;

time(&tempTimeStart);

clientSocket = ConnectToSocket(IOhostName, decodePortNumber, &hostEntry);

data = htonl(id);

SafeWrite(clientSocket, (char *)&data, 4);

close(clientSocket);

time(&tempTimeEnd);

IOtime += (tempTimeEnd-tempTimeStart);

}
 
 

/*===========================================================================*

*

* WaitForDecodedFrame

*

* blah blah blah

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

WaitForDecodedFrame(id)

int id;

{

int clientSocket;

u_long data;

int negativeTwo = -2;

int ready;

/* wait for a decoded frame */

if ( debugSockets ) {

fprintf(stdout, "WAITING FOR DECODED FRAME %d\n", id);

}

clientSocket = ConnectToSocket(IOhostName, decodePortNumber, &hostEntry);

/* first, tell DecodeServer we're waiting for this frame */

data = negativeTwo;

data = htonl(negativeTwo);

SafeWrite(clientSocket, (char *)&data, 4);

data = htonl(id);

SafeWrite(clientSocket, (char *)&data, 4);

SafeRead(clientSocket, (char *)&data, 4);

ready = data;

ready = ntohl(ready);

if ( ! ready ) {

int waitSocket;

int waitPort;

int otherSock, otherSize;

struct sockaddr otherSocket;

/* it's not ready; set up a connection and wait for decode server */

waitSocket = CreateListeningSocket(&waitPort);

/* tell decode server where we are */

data = machineNumber;

data = ntohl(data);

SafeWrite(clientSocket, (char *)&data, 4);

data = waitPort;

data = ntohl(data);

SafeWrite(clientSocket, (char *)&data, 4);

close(clientSocket);

if ( debugSockets ) {

fprintf(stdout, "SLAVE: WAITING ON SOCKET %d\n", waitPort);

fflush(stdout);

}

otherSize = sizeof(otherSocket);

otherSock = accept(waitSocket, &otherSocket, &otherSize);

if ( otherSock == -1 ) {

fprintf(stderr, "ERROR: I/O SERVER accept returned error %d\n", errno);

exit(1);

}

/* should we verify this is decode server? */

/* for now, we won't */

close(otherSock);

close(waitSocket);

} else {

close(clientSocket);

}

if ( debugSockets ) {

fprintf(stdout, "YE-HA FRAME %d IS NOW READY\n", id);

}

}
 
 

/*===========================================================================*

*

* CreateListeningSocket

*

* create a socket, using the first unused port number we can find

*

* RETURNS: the socket; portNumber is modified appropriately

*

* SIDE EFFECTS: none

*

*===========================================================================*/

static int

CreateListeningSocket(portNumber)

int *portNumber;

{

int resultSocket;

u_short tempShort;

int result;

struct sockaddr_in nameEntry;

resultSocket = socket(AF_INET, SOCK_STREAM, 0);

if ( resultSocket == -1 ) {

fprintf(stderr, "ERROR: Call to socket() gave error %d\n", errno);

exit(1);

}

memset((char *) &nameEntry, 0, sizeof(nameEntry));

nameEntry.sin_family = AF_INET;

/* find a port number that isn't used */

(*portNumber) = 2048;

do {

(*portNumber)++;

tempShort = (*portNumber);

nameEntry.sin_port = htons(tempShort);

result = bind(resultSocket, (struct sockaddr *) &nameEntry,

sizeof(struct sockaddr));

}

while ( result == -1 );

/* would really like to wait for 1+numMachines machines, but this is max

* allowable, unfortunately

*/

result = listen(resultSocket, SOMAXCONN);

if ( result == -1 ) {

fprintf(stderr, "ERROR: call to listen() gave error %d\n", errno);

exit(1);

}

return resultSocket;

}
 
 

/*===========================================================================*

*

* ConnectToSocket

*

* creates a socket and connects it to the specified socket

* hostEnt either is the host entry, or is NULL and needs to be

* found by using machineName

*

* RETURNS: the socket

*

* SIDE EFFECTS: none

*

*===========================================================================*/

static int

ConnectToSocket(machineName, portNum, hostEnt)

char *machineName;

int portNum;

struct hostent **hostEnt;

{

int resultSocket;

int result;

u_short tempShort;

struct sockaddr_in nameEntry;

if ( (*hostEnt) == NULL ) {

(*hostEnt) = gethostbyname(machineName);

if ( (*hostEnt) == NULL ) {

fprintf(stderr, "ERROR: Couldn't get host by name (%s)\n",

machineName);

exit(1);

}

}

resultSocket = socket(AF_INET, SOCK_STREAM, 0);

if ( resultSocket == -1 ) {

fprintf(stderr, "ERROR: socket returned error %d\n", errno);

exit(1);

}

nameEntry.sin_family = AF_INET;

memset((void *) nameEntry.sin_zero, 0, 8);

memcpy((void *) &(nameEntry.sin_addr.s_addr),

(void *) (*hostEnt)->h_addr_list[0],

(size_t) (*hostEnt)->h_length);

tempShort = portNum;

nameEntry.sin_port = htons(tempShort);

result = connect(resultSocket, (struct sockaddr *) &nameEntry,

sizeof(struct sockaddr));

if ( result == -1 ) {

fprintf(stderr, "ERROR: connect (ConnectToSocket, port %d) from machine %s returned error %d\n",

portNum, getenv("HOST"), errno);

exit(1);

}

return resultSocket;

}
 
 

/*===========================================================================*

*

* SendDecodedFrame

*

* Send the frame to the decode server.

*

* RETURNS: nothing

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

SendDecodedFrame(frame)

MpegFrame *frame;

{

int clientSocket;

register int y;

int negativeTwo = -2;

uint32 data;

/* send to IOServer */

clientSocket = ConnectToSocket(IOhostName, ioPortNumber, &hostEntry);

data = negativeTwo;

data = htonl(data);

SafeWrite(clientSocket, (char *)&data, 4);

data = frame->id;

data = htonl(data);

SafeWrite(clientSocket, (char *)&data, 4);

for ( y = 0; y < Fsize_y; y++ ) {

SafeWrite(clientSocket, (char *)frame->decoded_y[y], Fsize_x);

}

for (y = 0; y < (Fsize_y >> 1); y++) { /* U */

SafeWrite(clientSocket, (char *)frame->decoded_cb[y], (Fsize_x >> 1));

}

for (y = 0; y < (Fsize_y >> 1); y++) { /* V */

SafeWrite(clientSocket, (char *)frame->decoded_cr[y], (Fsize_x >> 1));

}

close(clientSocket);

}
 
 

/*===========================================================================*

*

* GetRemoteDecodedFrame

*

* get the decoded frame from the decode server.

*

* RETURNS: nothing

*

* SIDE EFFECTS:

*

*===========================================================================*/

void

GetRemoteDecodedRefFrame(frame, frameNumber)

MpegFrame *frame;

int frameNumber;

{

int clientSocket;

register int y;

int negativeThree = -3;

uint32 data;

/* send to IOServer */

clientSocket = ConnectToSocket(IOhostName, ioPortNumber, &hostEntry);

/* ask IOServer for decoded frame */

data = negativeThree;

data = htonl(data);

SafeWrite(clientSocket, (char *)&data, 4);

data = frame->id;

data = htonl(data);

SafeWrite(clientSocket, (char *)&data, 4);

for ( y = 0; y < Fsize_y; y++ ) {

SafeRead(clientSocket, (char *)frame->decoded_y[y], Fsize_x);

}

for (y = 0; y < (Fsize_y >> 1); y++) { /* U */

SafeRead(clientSocket, (char *)frame->decoded_cb[y], (Fsize_x >> 1));

}

for (y = 0; y < (Fsize_y >> 1); y++) { /* V */

SafeRead(clientSocket, (char *)frame->decoded_cr[y], (Fsize_x >> 1));

}

close(clientSocket);

}
 
 

/*********

routines handling forks, execs, PIDs and signals

save, system-style forks

apian@ise.fhg.de

*******/
 
 

/*===========================================================================*

*

* cleanup_fork

*

* Kill all the children, to be used when we get killed

*

* RETURNS: nothing

*

* SIDE EFFECTS: kills other processes

*

*===========================================================================*/

void cleanup_fork( dummy ) /* try to kill all child processes */

int dummy;

{

register int i;

for (i = 0; i < current_max_forked_pid; ++i ) {

#ifdef DEBUG_FORK

fprintf(stderr, "cleanup_fork: killing PID %d\n", ClientPid[i]);

#endif

if (kill(ClientPid[i], TERMINATE_PID_SIGNAL)) {

fprintf(stderr, "cleanup_fork: killed PID=%d failed (errno %d)\n",

ClientPid[i], errno);

}

}

}

/*===========================================================================*

*

* safe_fork

*

* fork a command

*

* RETURNS: success/failure

*

* SIDE EFFECTS: Fork the command, and save to PID so you can kil it later!

*

*===========================================================================*/

static int safe_fork(command) /* fork child process and remember its PID */

char *command;

{

static int init=0;

char *argis[MAXARGS];

register int i=1;

if (!(argis[0] = strtok(command, " \t"))) return(0); /* tokenize */

while ((argis[i] = strtok(NULL, " \t")) && i < MAXARGS) ++i;

argis[i] = NULL;

#ifdef DEBUG_FORK

{register int i=0;

fprintf(stderr, "Command %s becomes:\n", command);

while(argis[i]) {fprintf(stderr, "--%s--\n", argis[i]); ++i;} }

#endif

if (!init) { /* register clean-up routine */

signal (SIGQUIT, cleanup_fork);

signal (SIGTERM, cleanup_fork);

signal (SIGINT , cleanup_fork);

init=1;

}

if (-1 == (ClientPid[current_max_forked_pid] = fork()) ) {

perror("safe_fork: fork failed ");

return(-1);

}

if( !ClientPid[current_max_forked_pid]) { /* we are in child process */

execvp(argis[0], argis );

perror("safe_fork child: exec failed ");

exit(1);

}

#ifdef DEBUG_FORK

fprintf(stderr, "parallel: forked PID=%d\n", ClientPid[current_max_forked_pid]);

#endif

current_max_forked_pid++;

return(0);

}
 
 

/*===========================================================================*

* block.c *

* *

* Block routines *

* *

* EXPORTED PROCEDURES: *

* ComputeDiffDCTBlock *

* ComputeDiffDCTs *

* ComputeMotionBlock *

* ComputeMotionLumBlock *

* LumBlockMAD *

* LumMotionError *

* LumMotionErrorSubSampled *

* LumAddMotionError *

* AddMotionBlock *

* BlockToData *

* BlockifyFrame *

* *

* NOTES: MAD = Mean Absolute Difference *

* *

*===========================================================================*/

/*

* 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.

*/

/*

* $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/block.c,v 1.16 1995/08/07 21:43:29 smoot Exp $

* $Log: block.c,v $

* Revision 1.16 1995/08/07 21:43:29 smoot

* restructured lumdiff so it read better and used a switch instead of ifs

*

* Revision 1.15 1995/06/21 22:21:16 smoot

* added TUNEing options

*

* Revision 1.14 1995/05/08 22:47:45 smoot

* typechecking better

*

* Revision 1.13 1995/05/08 22:44:14 smoot

* added prototypes (postdct.h)

*

* Revision 1.12 1995/05/02 21:44:07 smoot

* added tuneing parameters

*

* Revision 1.11 1995/03/31 23:50:45 smoot

* removed block bound (moved to opts.c)

*

* Revision 1.10 1995/03/29 20:12:39 smoot

* added block_bound for TUNEing

*

* Revision 1.9 1995/02/01 21:43:55 smoot

* cleanup

*

* Revision 1.8 1995/01/19 23:52:43 smoot

* Made computeDiffDCTs able to rule out changes to the pattern (diff too small)

*

* Revision 1.7 1995/01/19 23:07:17 eyhung

* Changed copyrights

*

* Revision 1.6 1994/11/12 02:11:44 keving

* nothing

*

* Revision 1.5 1993/12/22 19:19:01 keving

* nothing

*

* Revision 1.5 1993/12/22 19:19:01 keving

* nothing

*

* Revision 1.4 1993/07/22 22:23:43 keving

* nothing

*

* Revision 1.3 1993/06/30 20:06:09 keving

* nothing

*

* Revision 1.2 1993/06/03 21:08:08 keving

* nothing

*

* Revision 1.1 1993/04/08 21:31:59 keving

* nothing

*

*/
 
 

/*==============*

* HEADER FILES *

*==============*/

#include "all.h"

#include "mtypes.h"

#include "frames.h"

#include "bitio.h"

#include "prototypes.h"

#include "fsize.h"

#include "opts.h"

#include "postdct.h"

#undef ABS

#define ABS(x) ((x < 0) ? (-x) : x)

#define TRUNCATE_UINT8(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x))

/*==================*

* GLOBAL VARIABLES *

*==================*/
 
 

extern Block **dct, **dctb, **dctr;

/*===========================*

* COMPUTE DCT OF DIFFERENCE *

*===========================*/

/*===========================================================================*

*

* ComputeDiffDCTBlock

*

* compute current-motionBlock, take the DCT, and put the difference

* back into current

*

* RETURNS: current block modified

*

* SIDE EFFECTS: none

*

*===========================================================================*/

boolean

ComputeDiffDCTBlock(current, dest, motionBlock)

Block current, dest, motionBlock;

{

register int x, y, diff = 0;

for ( y = 0; y < 8; y++ ) {

for ( x = 0; x < 8; x++ ) {

current[y][x] -= motionBlock[y][x];

diff += ABS(current[y][x]);

}

}

/* Kill the block if change is too small */

/* (block_bound defaults to 128, see opts.c) */

if (diff < block_bound) return FALSE;

mp_fwd_dct_block2(current, dest);

return TRUE;

}

/*===========================================================================*

*

* ComputeDiffDCTs

*

* appropriate (according to pattern, the coded block pattern) blocks

* of 'current' are diff'ed and DCT'd.

*

* RETURNS: current blocks modified

*

* SIDE EFFECTS: Can remove too-small difference blocks from pattern

*

* PRECONDITIONS: appropriate blocks of 'current' have not yet been

* modified

*

*===========================================================================*/

void

ComputeDiffDCTs(current, prev, by, bx, my, mx, pattern)

MpegFrame *current;

MpegFrame *prev;

int by;

int bx;

int my;

int mx;

int *pattern;

{

Block motionBlock;

if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n");

if ( *pattern & 0x20 ) {

ComputeMotionBlock(prev->ref_y, by, bx, my, mx, motionBlock);

if (!ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], motionBlock))

*pattern^=0x20;

}

if ( *pattern & 0x10 ) {

ComputeMotionBlock(prev->ref_y, by, bx+1, my, mx, motionBlock);

if (!ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], motionBlock))

*pattern^=0x10;

}

if ( *pattern & 0x8 ) {

ComputeMotionBlock(prev->ref_y, by+1, bx, my, mx, motionBlock);

if (!ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], motionBlock))

*pattern^=0x8;

}

if ( *pattern & 0x4 ) {

ComputeMotionBlock(prev->ref_y, by+1, bx+1, my, mx, motionBlock);

if (!ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], motionBlock))

*pattern^=0x4;

}

if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "c\n");

if ( *pattern & 0x2 ) {

ComputeMotionBlock(prev->ref_cb, by >> 1, bx >> 1, my/2, mx/2, motionBlock);

if (!ComputeDiffDCTBlock(current->cb_blocks[by >> 1][bx >> 1], dctb[by >> 1][bx >> 1], motionBlock))

*pattern^=0x2;

}

if ( *pattern & 0x1 ) {

ComputeMotionBlock(prev->ref_cr, by >> 1, bx >> 1, my/2, mx/2, motionBlock);

if (!ComputeDiffDCTBlock(current->cr_blocks[by >> 1][bx >> 1], dctr[by >> 1][bx >> 1], motionBlock))

*pattern^=0x1;

}

}
 
 

/*======================*

* COMPUTE MOTION BLOCK *

*======================*/

/*===========================================================================*

*

* ComputeMotionBlock

*

* compute the motion-compensated block

*

* RETURNS: motionBlock

*

* SIDE EFFECTS: none

*

* PRECONDITIONS: motion vector MUST be valid

*

* NOTE: could try to speed this up using halfX, halfY, halfBoth,

* but then would have to compute for chrominance, and it's just

* not worth the trouble (this procedure is not called relatively

* often -- a constant number of times per macroblock)

*

*===========================================================================*/

void

ComputeMotionBlock(prev, by, bx, my, mx, motionBlock)

uint8 **prev;

int by;

int bx;

int my;

int mx;

Block motionBlock;

{

register int fy, fx;

register int y;

register int16 *destPtr;

register uint8 *srcPtr;

register uint8 *srcPtr2;

boolean xHalf, yHalf;

xHalf = (ABS(mx) % 2 == 1);

yHalf = (ABS(my) % 2 == 1);

MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx);

if ( xHalf && yHalf ) {

/* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and

(fy-1)+y+1 = fy+y

*/

if ( my < 0 ) {

fy--;

}

if ( mx < 0 ) {

fx--;

}

for ( y = 0; y < 8; y++ ) {

destPtr = motionBlock[y];

srcPtr = &(prev[fy+y][fx]);

srcPtr2 = &(prev[fy+y+1][fx]);

destPtr[0] = (srcPtr[0]+srcPtr[1]+srcPtr2[0]+srcPtr2[1]+2)>>2;

destPtr[1] = (srcPtr[1]+srcPtr[2]+srcPtr2[1]+srcPtr2[2]+2)>>2;

destPtr[2] = (srcPtr[2]+srcPtr[3]+srcPtr2[2]+srcPtr2[3]+2)>>2;

destPtr[3] = (srcPtr[3]+srcPtr[4]+srcPtr2[3]+srcPtr2[4]+2)>>2;

destPtr[4] = (srcPtr[4]+srcPtr[5]+srcPtr2[4]+srcPtr2[5]+2)>>2;

destPtr[5] = (srcPtr[5]+srcPtr[6]+srcPtr2[5]+srcPtr2[6]+2)>>2;

destPtr[6] = (srcPtr[6]+srcPtr[7]+srcPtr2[6]+srcPtr2[7]+2)>>2;

destPtr[7] = (srcPtr[7]+srcPtr[8]+srcPtr2[7]+srcPtr2[8]+2)>>2;

}

} else if ( xHalf ) {

if ( mx < 0 ) {

fx--;

}

for ( y = 0; y < 8; y++ ) {

destPtr = motionBlock[y];

srcPtr = &(prev[fy+y][fx]);

destPtr[0] = (srcPtr[0]+srcPtr[1]+1)>>1;

destPtr[1] = (srcPtr[1]+srcPtr[2]+1)>>1;

destPtr[2] = (srcPtr[2]+srcPtr[3]+1)>>1;

destPtr[3] = (srcPtr[3]+srcPtr[4]+1)>>1;

destPtr[4] = (srcPtr[4]+srcPtr[5]+1)>>1;

destPtr[5] = (srcPtr[5]+srcPtr[6]+1)>>1;

destPtr[6] = (srcPtr[6]+srcPtr[7]+1)>>1;

destPtr[7] = (srcPtr[7]+srcPtr[8]+1)>>1;

}

} else if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

for ( y = 0; y < 8; y++ ) {

destPtr = motionBlock[y];

srcPtr = &(prev[fy+y][fx]);

srcPtr2 = &(prev[fy+y+1][fx]);

destPtr[0] = (srcPtr[0]+srcPtr2[0]+1)>>1;

destPtr[1] = (srcPtr[1]+srcPtr2[1]+1)>>1;

destPtr[2] = (srcPtr[2]+srcPtr2[2]+1)>>1;

destPtr[3] = (srcPtr[3]+srcPtr2[3]+1)>>1;

destPtr[4] = (srcPtr[4]+srcPtr2[4]+1)>>1;

destPtr[5] = (srcPtr[5]+srcPtr2[5]+1)>>1;

destPtr[6] = (srcPtr[6]+srcPtr2[6]+1)>>1;

destPtr[7] = (srcPtr[7]+srcPtr2[7]+1)>>1;

}

} else {

for ( y = 0; y < 8; y++ ) {

destPtr = motionBlock[y];

srcPtr = &(prev[fy+y][fx]);

destPtr[0] = (uint8) srcPtr[0];

destPtr[1] = (uint8) srcPtr[1];

destPtr[2] = (uint8) srcPtr[2];

destPtr[3] = (uint8) srcPtr[3];

destPtr[4] = (uint8) srcPtr[4];

destPtr[5] = (uint8) srcPtr[5];

destPtr[6] = (uint8) srcPtr[6];

destPtr[7] = (uint8) srcPtr[7];

}

}

}
 
 

/*===========================================================================*

*

* ComputeMotionLumBlock

*

* compute the motion-compensated luminance block

*

* RETURNS: motionBlock

*

* SIDE EFFECTS: none

*

* PRECONDITIONS: motion vector MUST be valid

*

* NOTE: see ComputeMotionBlock

*

*===========================================================================*/

void

ComputeMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock)

MpegFrame *prevFrame;

int by;

int bx;

int my;

int mx;

LumBlock motionBlock;

{

register uint8 *across;

register int32 *macross;

register int y;

uint8 **prev;

int fy, fx;

boolean xHalf, yHalf;

xHalf = (ABS(mx) % 2 == 1);

yHalf = (ABS(my) % 2 == 1);

MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);

if ( xHalf ) {

if ( mx < 0 ) {

fx--;

}

if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfBoth;

} else {

prev = prevFrame->halfX;

}

} else if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfY;

} else {

prev = prevFrame->ref_y;

}

for ( y = 0; y < 16; y++ ) {

across = &(prev[fy+y][fx]);

macross = motionBlock[y];

macross[0] = across[0];

macross[1] = across[1];

macross[2] = across[2];

macross[3] = across[3];

macross[4] = across[4];

macross[5] = across[5];

macross[6] = across[6];

macross[7] = across[7];

macross[8] = across[8];

macross[9] = across[9];

macross[10] = across[10];

macross[11] = across[11];

macross[12] = across[12];

macross[13]= across[13];

macross[14] = across[14];

macross[15] = across[15];

}

/* this is what's really happening, in slow motion:

*

* for ( y = 0; y < 16; y++, py++ )

* for ( x = 0; x < 16; x++, px++ )

* motionBlock[y][x] = prev[fy+y][fx+x];

*

*/

}
 
 

/*=======================*

* BASIC ERROR FUNCTIONS *

*=======================*/
 
 

/*===========================================================================*

*

* LumBlockMAD

*

* return the MAD of two luminance blocks

*

* RETURNS: the MAD, if less than bestSoFar, or

* some number bigger if not

*

* SIDE EFFECTS: none

*

*===========================================================================*/

int32

LumBlockMAD(currentBlock, motionBlock, bestSoFar)

LumBlock currentBlock;

LumBlock motionBlock;

int32 bestSoFar;

{

register int32 diff = 0; /* max value of diff is 255*256 = 65280 */

register int32 localDiff;

register int y, x;

for ( y = 0; y < 16; y++ ) {

for ( x = 0; x < 16; x++ ) {

localDiff = currentBlock[y][x] - motionBlock[y][x];

diff += ABS(localDiff);

}

if ( diff > bestSoFar ) {

return diff;

}

}

return (int32)diff;

}
 
 

/*===========================================================================*

*

* MMXMotionError

* (modified mvirgo)

*

* return the MAD of the currentBlock and the motion-compensated block

* (without TUNEing)

*

* RETURNS: the MAD, if less than bestSoFar, or

* some number bigger if not

*

* SIDE EFFECTS: none

*

* PRECONDITIONS: motion vector MUST be valid

*

* NOTES: this is the procedure that is called the most, and should therefore

* be the most optimized!!!

*

*===========================================================================*/

int32

MMXMotionError(currentBlock, prevFrame, by, bx, my, mx, bestSoFar)

SmallBlock currentBlock;

MpegFrame *prevFrame;

int by;

int bx;

int my;

int mx;

int32 bestSoFar;

{

int32 adiff = 0, diff = 0; /* max value of diff is 255*256 = 65280 */

int32 localDiff;

uint8 *across;

uint8 *cacross;

long long *macross, *mcacross;

long long CMULT = 0x0001000100010001;

int y;

uint8 **prev;

int fy, fx;

boolean xHalf, yHalf;

xHalf = (ABS(mx) % 2 == 1);

yHalf = (ABS(my) % 2 == 1);

MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);

if ( xHalf ) {

if ( mx < 0 ) {

fx--;

}

if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfBoth;

} else {

prev = prevFrame->halfX;

}

} else if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfY;

} else {

prev = prevFrame->ref_y;

}

switch (SearchCompareMode) {

case DEFAULT_SEARCH: /* Default. */

/* this is what's happening:

* ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock);

* for ( y = 0; y < 16; y++ )

* for ( x = 0; x < 16; x++ )

* {

* localDiff = currentBlock[y][x] - lumMotionBlock[y][x];

* diff += ABS(localDiff);

* }

*/
 
 

__asm__ volatile

("pxor %%mm7, %%mm7;

pxor %%mm6, %%mm6"

: );
 
 

for ( y = 0; y < 16; y++ ) {

macross = (long long *)&(prev[fy+y][fx]);

mcacross = (long long *)currentBlock[y];
 
 
 
 

__asm__ volatile

("movl %0, %%edx;

movq 0(%%edx), %%mm0;

movl %1, %%edx;

movq 0(%%edx), %%mm1;

movq %%mm0, %%mm2;

movq 8(%%edx), %%mm3;

psubusb %%mm1, %%mm0;

psubusb %%mm2, %%mm1;

movl %0, %%edx;

movq 8(%%edx), %%mm4;

por %%mm1, %%mm0;

movq %%mm3, %%mm5;

movq %%mm0, %%mm1;

psubusb %%mm4, %%mm3;

punpcklbw %%mm6, %%mm0;

psubusb %%mm5, %%mm4;

psrlq $0x20, %%mm1;

por %%mm4, %%mm3;

punpcklbw %%mm6, %%mm1;

movq %%mm3, %%mm4;

punpcklbw %%mm6, %%mm3;

paddw %%mm0, %%mm7;

psrlq $0x20, %%mm4;

paddw %%mm1, %%mm7;

punpcklbw %%mm6, %%mm4;

paddw %%mm3, %%mm7;

paddw %%mm4, %%mm7"

:

: "m" (macross), "m" (mcacross)

: "edx");

} /* End the for loop */

__asm__ volatile

("pmaddwd %1, %%mm7;

movq %%mm7, %%mm0;

punpckldq %%mm6, %%mm0;

punpckhdq %%mm6, %%mm7;

paddd %%mm0, %%mm7;

movd %%mm7, %0"

: "=m" (diff)

: "m" (CMULT));

break;

case LOCAL_DCT: {

Block dctdiff[4], dctquant[4];

FlatBlock quant;

int x, i, tmp;

int distortion=0, datarate=0;

int pq = GetPQScale();

for (y = 0; y < 16; y++) {

across = &(prev[fy+y][fx]);

cacross = currentBlock[y];

for (x = 0; x < 16; x++) {

dctdiff[(x>7)+2*(y>7)][y%8][x%8] = cacross[x]-across[x];

}}

/* Calculate rate */

for (i = 0; i < 4; i++) {

mp_fwd_dct_block2(dctdiff[i], dctdiff[i]);

if (Mpost_QuantZigBlock(dctdiff[i], quant, pq, FALSE) == MPOST_ZERO) {

/* no sense in continuing */

memset((char *)dctquant[i], 0, sizeof(Block));

} else {

Mpost_UnQuantZigBlock(quant, dctquant[i], pq, FALSE);

mpeg_jrevdct((int16 *)dctquant[i]);

datarate += CalcRLEHuffLength(quant);

}

}

/* Calculate distortion */

for (y = 0; y < 16; y++) {

across = &(prev[fy+y][fx]);

cacross = currentBlock[y];

for (x = 0; x < 16; x++) {

tmp = across[x] - cacross[x] + dctquant[(x>7)+2*(y>7)][y%8][x%8];

distortion += tmp*tmp;

}}

distortion /= 256;

distortion *= LocalDCTDistortScale;

datarate *= LocalDCTRateScale;

diff = (int) sqrt(distortion*distortion + datarate*datarate);

break;

}

case NO_DC_SEARCH: {

extern int32 niqtable[];

int pq = niqtable[0]*GetPQScale();

for ( y = 0; y < 16; y++ ) {

across = &(prev[fy+y][fx]);

cacross = currentBlock[y];

localDiff = across[0]-cacross[0]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[1]-cacross[1]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[2]-cacross[2]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[3]-cacross[3]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[4]-cacross[4]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[5]-cacross[5]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[6]-cacross[6]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[7]-cacross[7]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[8]-cacross[8]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[9]-cacross[9]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[10]-cacross[10]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[11]-cacross[11]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[12]-cacross[12]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[13]-cacross[13]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[14]-cacross[14]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[15]-cacross[15]; diff += localDiff; adiff += ABS(localDiff);

}

diff /= 64*pq; /* diff is now the DC difference (with QSCALE 1) */

adiff -= 64*pq*ABS(diff);

diff = adiff;

}

break;

case DO_Mean_Squared_Distortion:

for ( y = 0; y < 16; y++ ) {

across = &(prev[fy+y][fx]);

cacross = currentBlock[y];

localDiff = across[0]-cacross[0]; diff += localDiff*localDiff;

localDiff = across[1]-cacross[1]; diff += localDiff*localDiff;

localDiff = across[2]-cacross[2]; diff += localDiff*localDiff;

localDiff = across[3]-cacross[3]; diff += localDiff*localDiff;

localDiff = across[4]-cacross[4]; diff += localDiff*localDiff;

localDiff = across[5]-cacross[5]; diff += localDiff*localDiff;

localDiff = across[6]-cacross[6]; diff += localDiff*localDiff;

localDiff = across[7]-cacross[7]; diff += localDiff*localDiff;

localDiff = across[8]-cacross[8]; diff += localDiff*localDiff;

localDiff = across[9]-cacross[9]; diff += localDiff*localDiff;

localDiff = across[10]-cacross[10]; diff += localDiff*localDiff;

localDiff = across[11]-cacross[11]; diff += localDiff*localDiff;

localDiff = across[12]-cacross[12]; diff += localDiff*localDiff;

localDiff = across[13]-cacross[13]; diff += localDiff*localDiff;

localDiff = across[14]-cacross[14]; diff += localDiff*localDiff;

localDiff = across[15]-cacross[15]; diff += localDiff*localDiff;

if ( diff > bestSoFar ) {

return diff;

}

}

break;

} /* End of Switch */

return diff;

}
 
 
 
 

/*===========================================================================*

*

* LumMotionError

*

* return the MAD of the currentBlock and the motion-compensated block

* (without TUNEing)

*

* RETURNS: the MAD, if less than bestSoFar, or

* some number bigger if not

*

* SIDE EFFECTS: none

*

* PRECONDITIONS: motion vector MUST be valid

*

* NOTES: this is the procedure that is called the most, and should therefore

* be the most optimized!!!

*

*===========================================================================*/

int32

LumMotionError(currentBlock, prevFrame, by, bx, my, mx, bestSoFar)

LumBlock currentBlock;

MpegFrame *prevFrame;

int by;

int bx;

int my;

int mx;

int32 bestSoFar;

{

register int32 adiff = 0, diff = 0; /* max value of diff is 255*256 = 65280 */

register int32 localDiff;

register uint8 *across;

register int32 *cacross;

register int y;

uint8 **prev;

int fy, fx;

boolean xHalf, yHalf;

xHalf = (ABS(mx) % 2 == 1);

yHalf = (ABS(my) % 2 == 1);

MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);

if ( xHalf ) {

if ( mx < 0 ) {

fx--;

}

if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfBoth;

} else {

prev = prevFrame->halfX;

}

} else if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfY;

} else {

prev = prevFrame->ref_y;

}

switch (SearchCompareMode) {

case DEFAULT_SEARCH: /* Default. */

/* this is what's happening:

* ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock);

* for ( y = 0; y < 16; y++ )

* for ( x = 0; x < 16; x++ )

* {

* localDiff = currentBlock[y][x] - lumMotionBlock[y][x];

* diff += ABS(localDiff);

* }

*/

for ( y = 0; y < 16; y++ ) {

across = &(prev[fy+y][fx]);

cacross = currentBlock[y];

localDiff = across[0]-cacross[0]; diff += ABS(localDiff);

localDiff = across[1]-cacross[1]; diff += ABS(localDiff);

localDiff = across[2]-cacross[2]; diff += ABS(localDiff);

localDiff = across[3]-cacross[3]; diff += ABS(localDiff);

localDiff = across[4]-cacross[4]; diff += ABS(localDiff);

localDiff = across[5]-cacross[5]; diff += ABS(localDiff);

localDiff = across[6]-cacross[6]; diff += ABS(localDiff);

localDiff = across[7]-cacross[7]; diff += ABS(localDiff);

localDiff = across[8]-cacross[8]; diff += ABS(localDiff);

localDiff = across[9]-cacross[9]; diff += ABS(localDiff);

localDiff = across[10]-cacross[10]; diff += ABS(localDiff);

localDiff = across[11]-cacross[11]; diff += ABS(localDiff);

localDiff = across[12]-cacross[12]; diff += ABS(localDiff);

localDiff = across[13]-cacross[13]; diff += ABS(localDiff);

localDiff = across[14]-cacross[14]; diff += ABS(localDiff);

localDiff = across[15]-cacross[15]; diff += ABS(localDiff);

if ( diff > bestSoFar ) {

return diff;

}

}

break;

case LOCAL_DCT: {

Block dctdiff[4], dctquant[4];

FlatBlock quant;

int x, i, tmp;

int distortion=0, datarate=0;

int pq = GetPQScale();

for (y = 0; y < 16; y++) {

across = &(prev[fy+y][fx]);

cacross = currentBlock[y];

for (x = 0; x < 16; x++) {

dctdiff[(x>7)+2*(y>7)][y%8][x%8] = cacross[x]-across[x];

}}

/* Calculate rate */

for (i = 0; i < 4; i++) {

mp_fwd_dct_block2(dctdiff[i], dctdiff[i]);

if (Mpost_QuantZigBlock(dctdiff[i], quant, pq, FALSE) == MPOST_ZERO) {

/* no sense in continuing */

memset((char *)dctquant[i], 0, sizeof(Block));

} else {

Mpost_UnQuantZigBlock(quant, dctquant[i], pq, FALSE);

mpeg_jrevdct((int16 *)dctquant[i]);

datarate += CalcRLEHuffLength(quant);

}

}

/* Calculate distortion */

for (y = 0; y < 16; y++) {

across = &(prev[fy+y][fx]);

cacross = currentBlock[y];

for (x = 0; x < 16; x++) {

tmp = across[x] - cacross[x] + dctquant[(x>7)+2*(y>7)][y%8][x%8];

distortion += tmp*tmp;

}}

distortion /= 256;

distortion *= LocalDCTDistortScale;

datarate *= LocalDCTRateScale;

diff = (int) sqrt(distortion*distortion + datarate*datarate);

break;

}

case NO_DC_SEARCH: {

extern int32 niqtable[];

int pq = niqtable[0]*GetPQScale();

for ( y = 0; y < 16; y++ ) {

across = &(prev[fy+y][fx]);

cacross = currentBlock[y];

localDiff = across[0]-cacross[0]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[1]-cacross[1]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[2]-cacross[2]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[3]-cacross[3]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[4]-cacross[4]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[5]-cacross[5]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[6]-cacross[6]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[7]-cacross[7]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[8]-cacross[8]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[9]-cacross[9]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[10]-cacross[10]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[11]-cacross[11]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[12]-cacross[12]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[13]-cacross[13]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[14]-cacross[14]; diff += localDiff; adiff += ABS(localDiff);

localDiff = across[15]-cacross[15]; diff += localDiff; adiff += ABS(localDiff);

}

diff /= 64*pq; /* diff is now the DC difference (with QSCALE 1) */

adiff -= 64*pq*ABS(diff);

diff = adiff;

}

break;

case DO_Mean_Squared_Distortion:

for ( y = 0; y < 16; y++ ) {

across = &(prev[fy+y][fx]);

cacross = currentBlock[y];

localDiff = across[0]-cacross[0]; diff += localDiff*localDiff;

localDiff = across[1]-cacross[1]; diff += localDiff*localDiff;

localDiff = across[2]-cacross[2]; diff += localDiff*localDiff;

localDiff = across[3]-cacross[3]; diff += localDiff*localDiff;

localDiff = across[4]-cacross[4]; diff += localDiff*localDiff;

localDiff = across[5]-cacross[5]; diff += localDiff*localDiff;

localDiff = across[6]-cacross[6]; diff += localDiff*localDiff;

localDiff = across[7]-cacross[7]; diff += localDiff*localDiff;

localDiff = across[8]-cacross[8]; diff += localDiff*localDiff;

localDiff = across[9]-cacross[9]; diff += localDiff*localDiff;

localDiff = across[10]-cacross[10]; diff += localDiff*localDiff;

localDiff = across[11]-cacross[11]; diff += localDiff*localDiff;

localDiff = across[12]-cacross[12]; diff += localDiff*localDiff;

localDiff = across[13]-cacross[13]; diff += localDiff*localDiff;

localDiff = across[14]-cacross[14]; diff += localDiff*localDiff;

localDiff = across[15]-cacross[15]; diff += localDiff*localDiff;

if ( diff > bestSoFar ) {

return diff;

}

}

break;

} /* End of Switch */

return diff;

}
 
 

/*===========================================================================*

*

* LumAddMotionError

*

* return the MAD of the currentBlock and the average of the blockSoFar

* and the motion-compensated block (this is used for B-frame searches)

*

* RETURNS: the MAD, if less than bestSoFar, or

* some number bigger if not

*

* SIDE EFFECTS: none

*

* PRECONDITIONS: motion vector MUST be valid

*

*===========================================================================*/

int32

LumAddMotionError(currentBlock, blockSoFar, prevFrame, by, bx, my, mx,

bestSoFar)

LumBlock currentBlock;

LumBlock blockSoFar;

MpegFrame *prevFrame;

int by;

int bx;

int my;

int mx;

int32 bestSoFar;

{

register int32 diff = 0; /* max value of diff is 255*256 = 65280 */

register int32 localDiff;

register uint8 *across;

register int32 *bacross;

register int32 *cacross;

register int y;

uint8 **prev;

int fy, fx;

boolean xHalf, yHalf;

xHalf = (ABS(mx) % 2 == 1);

yHalf = (ABS(my) % 2 == 1);

MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);

if ( xHalf ) {

if ( mx < 0 ) {

fx--;

}

if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfBoth;

} else {

prev = prevFrame->halfX;

}

} else if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfY;

} else {

prev = prevFrame->ref_y;

}

/* do we add 1 before dividing by two? Yes -- see MPEG-1 doc page 46 */

#define ADD_ADD_DIFF(d,l,a,b,c,i) \

l = ((a[i]+b[i]+1)>>1)-c[i]; \

d += ABS(l)

for ( y = 0; y < 16; y++ ) {

across = &(prev[fy+y][fx]);

bacross = blockSoFar[y];

cacross = currentBlock[y];

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,0);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,1);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,2);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,3);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,4);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,5);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,6);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,7);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,8);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,9);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,10);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,11);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,12);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,13);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,14);

ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,15);

if ( diff > bestSoFar ) {

return diff;

}

}

/* this is what's happening:

*

* ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock);

*

* for ( y = 0; y < 16; y++ )

* for ( x = 0; x < 16; x++ )

* {

* localDiff = currentBlock[y][x] - lumMotionBlock[y][x];

* diff += ABS(localDiff);

* }

*

*/

return diff;

}
 
 

/*===========================================================================*

*

* AddMotionBlock

*

* adds the motion-compensated block to the given block

*

* RETURNS: block modified

*

* SIDE EFFECTS: none

*

* PRECONDITIONS: motion vector MUST be valid

*

*===========================================================================*/

void

AddMotionBlock(block, prev, by, bx, my, mx)

Block block;

uint8 **prev;

int by;

int bx;

int my;

int mx;

{

int fy, fx;

int x, y;

boolean xHalf, yHalf;

xHalf = (ABS(mx) % 2 == 1);

yHalf = (ABS(my) % 2 == 1);

MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx);

if ( xHalf && yHalf ) {

/* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and

(fy-1)+y+1 = fy+y

*/

if ( my < 0 ) {

fy--;

}

if ( mx < 0 ) {

fx--;

}

for ( y = 0; y < 8; y++ ) {

for ( x = 0; x < 8; x++ ) {

block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+

prev[fy+y+1][fx+x]+prev[fy+y+1][fx+x+1]+2)>>2;

}

}

} else if ( xHalf ) {

if ( mx < 0 ) {

fx--;

}

for ( y = 0; y < 8; y++ ) {

for ( x = 0; x < 8; x++ ) {

block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+1)>>1;

}

}

} else if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

for ( y = 0; y < 8; y++ ) {

for ( x = 0; x < 8; x++ ) {

block[y][x] += (prev[fy+y][fx+x]+prev[fy+y+1][fx+x]+1)>>1;

}

}

} else {

for ( y = 0; y < 8; y++ ) {

for ( x = 0; x < 8; x++ ) {

block[y][x] += (int16)prev[fy+y][fx+x];

}

}

}

}
 
 

/*===========================================================================*

*

* AddBMotionBlock

*

* adds the motion-compensated B-frame block to the given block

*

* RETURNS: block modified

*

* SIDE EFFECTS: none

*

* PRECONDITIONS: motion vectors MUST be valid

*

*===========================================================================*/

void

AddBMotionBlock(block, prev, next, by, bx, mode, fmy, fmx, bmy, bmx)

Block block;

uint8 **prev;

uint8 **next;

int by;

int bx;

int mode;

int fmy;

int fmx;

int bmy;

int bmx;

{

int x, y;

Block prevBlock, nextBlock;

if ( mode == MOTION_FORWARD ) {

AddMotionBlock(block, prev, by, bx, fmy, fmx);

} else if ( mode == MOTION_BACKWARD ) {

AddMotionBlock(block, next, by, bx, bmy, bmx);

} else {

ComputeMotionBlock(prev, by, bx, fmy, fmx, prevBlock);

ComputeMotionBlock(next, by, bx, bmy, bmx, nextBlock);

for ( y = 0; y < 8; y++ ) {

for ( x = 0; x < 8; x++ ) {

block[y][x] += (prevBlock[y][x]+nextBlock[y][x]+1)/2;

}

}

}

}
 
 

/*===========================================================================*

*

* BlockToData

*

* copies the given block into the appropriate data area

*

* RETURNS: data modified

*

* SIDE EFFECTS: none

*

*===========================================================================*/

void

BlockToData(data, block, by, bx)

uint8 **data;

Block block;

int by;

int bx;

{

register int x, y;

register int fy, fx;

register int16 blockItem;

BLOCK_TO_FRAME_COORD(by, bx, fy, fx);

for ( y = 0; y < 8; y++ ) {

for ( x = 0; x < 8; x++ ) {

blockItem = block[y][x];

data[fy+y][fx+x] = TRUNCATE_UINT8(blockItem);

}

}

}
 
 

/*===========================================================================*

*

* BlockifyFrame

*

* copies data into appropriate blocks

*

* RETURNS: mf modified

*

* SIDE EFFECTS: none

*

* NOTES: probably shouldn't be in this file

*

*===========================================================================*/

void

BlockifyFrame(framePtr)

MpegFrame *framePtr;

{

register int dctx, dcty;

register int x, y;

register int bx, by;

register int fy, fx;

register int16 *destPtr;

register uint8 *srcPtr;

register int16 *destPtr2;

register uint8 *srcPtr2;

Block *blockPtr;

Block *blockPtr2;

dctx = Fsize_x / DCTSIZE;

dcty = Fsize_y / DCTSIZE;

/*

* copy y data into y_blocks

*/

for (by = 0; by < dcty; by++) {

fy = by*DCTSIZE;

for (bx = 0; bx < dctx; bx++) {

fx = bx*DCTSIZE;

blockPtr = (Block *) &(framePtr->y_blocks[by][bx][0][0]);

for (y = 0; y < DCTSIZE; y++) {

destPtr = &((*blockPtr)[y][0]);

srcPtr = &(framePtr->orig_y[fy+y][fx]);

for (x = 0; x < DCTSIZE; x++) {

destPtr[x] = srcPtr[x];

}

}

}

}

/*

* copy cr/cb data into cr/cb_blocks

*/

for (by = 0; by < (dcty >> 1); by++) {

fy = by*DCTSIZE;

for (bx = 0; bx < (dctx >> 1); bx++) {

fx = bx*DCTSIZE;

blockPtr = (Block *) &(framePtr->cr_blocks[by][bx][0][0]);

blockPtr2 = (Block *) &(framePtr->cb_blocks[by][bx][0][0]);

for (y = 0; y < DCTSIZE; y++) {

destPtr = &((*blockPtr)[y][0]);

srcPtr = &(framePtr->orig_cr[fy+y][fx]);

destPtr2 = &((*blockPtr2)[y][0]);

srcPtr2 = &(framePtr->orig_cb[fy+y][fx]);

for (x = 0; x < DCTSIZE; x++) {

destPtr[x] = srcPtr[x];

destPtr2[x] = srcPtr2[x];

}

}

}

}

}
 
 

/*===========================================================================*

* *

* UNUSED PROCEDURES *

* *

* The following procedures are all unused by the encoder *

* *

* They are listed here for your convenience. You might want to use *

* them if you experiment with different search techniques *

* *

*===========================================================================*/

#ifdef UNUSED_PROCEDURES

/* this procedure calculates the subsampled motion block (obviously)

*

* for speed, this procedure is probably not called anywhere (it is

* incorporated directly into LumDiffA, LumDiffB, etc.

*

* but leave it here anyway for clarity

*

* (startY, startX) = (0,0) for A....(0,1) for B...(1,0) for C...(1,1) for D

*

*/

void

ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock,

startY, startX)

MpegFrame *prevFrame;

int by;

int bx;

int my;

int mx;

LumBlock motionBlock;

int startY;

int startX;

{

register uint8 *across;

register int32 *macross;

register int32 *lastx;

register int y;

uint8 **prev;

int fy, fx;

boolean xHalf, yHalf;

xHalf = (ABS(mx) % 2 == 1);

yHalf = (ABS(my) % 2 == 1);

MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);

if ( xHalf ) {

if ( mx < 0 ) {

fx--;

}

if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfBoth;

} else {

prev = prevFrame->halfX;

}

} else if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfY;

} else {

prev = prevFrame->ref_y;

}

for ( y = startY; y < 16; y += 2 ) {

across = &(prev[fy+y][fx+startX]);

macross = &(motionBlock[y][startX]);

lastx = &(motionBlock[y][16]);

while ( macross < lastx ) {

(*macross) = (*across);

across += 2;

macross += 2;

}

}

/* this is what's really going on in slow motion:

*

* for ( y = startY; y < 16; y += 2 )

* for ( x = startX; x < 16; x += 2 )

* motionBlock[y][x] = prev[fy+y][fx+x];

*

*/

}
 
 

/*===========================================================================*

*

* LumMotionErrorSubSampled

*

* return the MAD of the currentBlock and the motion-compensated block,

* subsampled 4:1 with given starting coordinates (startY, startX)

*

* RETURNS: the MAD

*

* SIDE EFFECTS: none

*

* PRECONDITIONS: motion vector MUST be valid

*

* NOTES: this procedure is never called. Instead, see subsample.c. This

* procedure is provided only for possible use in extensions

*

*===========================================================================*/

int32

LumMotionErrorSubSampled(currentBlock, prevFrame, by, bx, my, mx, startY,

startX)

LumBlock currentBlock;

MpegFrame *prevFrame;

int by;

int bx;

int my;

int mx;

int startY;

int startX;

{

register int32 diff = 0; /* max value of diff is 255*256 = 65280 */

register int32 localDiff;

register int32 *cacross;

register uint8 *macross;

register int32 *lastx;

register int y;

uint8 **prev;

int fy, fx;

boolean xHalf, yHalf;

xHalf = (ABS(mx) % 2 == 1);

yHalf = (ABS(my) % 2 == 1);

MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);

if ( xHalf ) {

if ( mx < 0 ) {

fx--;

}

if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfBoth;

} else {

prev = prevFrame->halfX;

}

} else if ( yHalf ) {

if ( my < 0 ) {

fy--;

}

prev = prevFrame->halfY;

} else {

prev = prevFrame->ref_y;

}

for ( y = startY; y < 16; y += 2 ) {

macross = &(prev[fy+y][fx+startX]);

cacross = &(currentBlock[y][startX]);

lastx = &(currentBlock[y][16]);

while ( cacross < lastx ) {

localDiff = (*cacross)-(*macross);

diff += ABS(localDiff);

macross += 2;

cacross += 2;

}

}

/* this is what's really happening:

*

* ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx,

* lumMotionBlock, startY, startX);

*

* for ( y = startY; y < 16; y += 2 )

* for ( x = startX; x < 16; x += 2 )

* {

* localDiff = currentBlock[y][x] - lumMotionBlock[y][x];

* diff += ABS(localDiff);

* }

*

*/

return (int32)diff;

}
 
 

#endif /* UNUSED_PROCEDURES */

#include <assert.h>
 
 

/*===========================================================================*

* psearch.c *

* *

* Procedures concerned with the P-frame motion search *

* *

* EXPORTED PROCEDURES: *

* SetPixelSearch *

* SetPSearchAlg *

* SetSearchRange *

* MotionSearchPreComputation *

* PMotionSearch *

* PSearchName *

* PSubSampleSearch *

* PLogarithmicSearch *

* *

*===========================================================================*/

/*

* 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.

*/

/*

* $Header: /u/smoot/md/mpeg_encode/RCS/psearch.c,v 1.9 1995/01/19 23:09:12 eyhung Exp $

* $Log: psearch.c,v $

* Revision 1.9 1995/01/19 23:09:12 eyhung

* Changed copyrights

*

* Revision 1.9 1995/01/19 23:09:12 eyhung

* Changed copyrights

*

* Revision 1.8 1994/12/07 00:40:36 smoot

* Added seperate P and B search ranges

*

* Revision 1.7 1994/11/12 02:09:45 eyhung

* full pixel bug

* fixed on lines 512 and 563

*

* Revision 1.6 1994/03/15 00:27:11 keving

* nothing

*

* Revision 1.5 1993/12/22 19:19:01 keving

* nothing

*

* Revision 1.4 1993/07/22 22:23:43 keving

* nothing

*

* Revision 1.3 1993/06/30 20:06:09 keving

* nothing

*

* Revision 1.2 1993/06/03 21:08:08 keving

* nothing

*

* Revision 1.1 1993/03/02 18:27:05 keving

* nothing

*

*/
 
 

/*==============*

* HEADER FILES *

*==============*/

#include "all.h"

#include "mtypes.h"

#include "frames.h"

#include "search.h"

#include "prototypes.h"

#include "fsize.h"

#include "param.h"
 
 

/*==================*

* STATIC VARIABLES *

*==================*/

/* none */
 
 

/*==================*

* GLOBAL VARIABLES *

*==================*/

int **pmvHistogram = NULL; /* histogram of P-frame motion vectors */

int **bbmvHistogram = NULL; /* histogram of B-frame motion vectors */

int **bfmvHistogram = NULL; /* histogram of B-frame motion vectors */

int pixelFullSearch;

int searchRangeP,searchRangeB;

int psearchAlg;
 
 

/*===============================*

* INTERNAL PROCEDURE prototypes *

*===============================*/
 
 

/*=====================*

* EXPORTED PROCEDURES *

*=====================*/

/*===========================================================================*

*

* PMotionSearch

*

* compute the best P-frame motion vector we can

*

*

* RETURNS: TRUE = motion vector valid

* FALSE = motion vector invalid; should code I-block

*

* PRECONDITIONS: The relevant block in 'current' is valid (it has not

* been dct'd). Thus, the data in 'current' can be

* accesed through y_blocks, cr_blocks, and cb_blocks.

* This is not the case for the blocks in 'prev.'

* Therefore, references into 'prev' should be done

* through the struct items ref_y, ref_cr, ref_cb

*

* POSTCONDITIONS: current, prev should be unchanged.

* Some computation could be saved by requiring

* the dct'd difference to be put into current's block

* elements here, depending on the search technique.

* However, it was decided that it mucks up the code

* organization a little, and the saving in computation

* would be relatively little (if any).

*

* NOTES: the search procedure need not check the (0,0) motion vector

* the calling procedure has a preference toward (0,0) and it

* will check it itself

*

* SIDE EFFECTS: none

*

*===========================================================================*/

boolean

PMotionSearch(currentBlock, prev, by, bx, motionY, motionX)

LumBlock currentBlock;

MpegFrame *prev;

int by;

int bx;

int *motionY;

int *motionX;

{

/* CALL SEARCH PROCEDURE */

switch(psearchAlg) {

case PSEARCH_SUBSAMPLE:

PSubSampleSearch(currentBlock, prev, by, bx, motionY, motionX, searchRangeP);

break;

case PSEARCH_EXHAUSTIVE:

PLocalSearch(currentBlock, prev, by, bx, motionY, motionX,

0x7fffffff, searchRangeP);

break;

case PSEARCH_LOGARITHMIC:

PLogarithmicSearch(currentBlock, prev, by, bx, motionY, motionX, searchRangeP);

break;

case PSEARCH_TWOLEVEL:

PTwoLevelSearch(currentBlock, prev, by, bx, motionY, motionX,

0x7fffffff, searchRangeP);

break;

default:

fprintf(stderr, "ILLEGAL PSEARCH ALG: %d\n", psearchAlg);

exit(1);

}

return TRUE;

}
 
 

/*===========================================================================*

*

* SetPixelSearch

*

* set the pixel search type (half or full)

*

* RETURNS: nothing

*

* SIDE EFFECTS: pixelFullSearch

*

*===========================================================================*/

void

SetPixelSearch(searchType)

char *searchType;

{

if ( (strcmp(searchType, "FULL") == 0 ) || ( strcmp(searchType, "WHOLE") == 0 )) {

pixelFullSearch = TRUE;

} else if ( strcmp(searchType, "HALF") == 0 ) {

pixelFullSearch = FALSE;

} else {

fprintf(stderr, "ERROR: Invalid pixel search type: %s\n",

searchType);

exit(1);

}

}
 
 

/*===========================================================================*

*

* SetPSearchAlg

*

* set the P-search algorithm

*

* RETURNS: nothing

*

* SIDE EFFECTS: psearchAlg

*

*===========================================================================*/

void

SetPSearchAlg(alg)

char *alg;

{

if ( strcmp(alg, "EXHAUSTIVE") == 0 ) {

psearchAlg = PSEARCH_EXHAUSTIVE;

} else if (strcmp(alg, "SUBSAMPLE") == 0 ) {

psearchAlg = PSEARCH_SUBSAMPLE;

} else if ( strcmp(alg, "LOGARITHMIC") == 0 ) {

psearchAlg = PSEARCH_LOGARITHMIC;

} else if ( strcmp(alg, "TWOLEVEL") == 0 ) {

psearchAlg = PSEARCH_TWOLEVEL;

} else {

fprintf(stderr, "ERROR: Invalid psearch algorithm: %s\n", alg);

exit(1);

}

}
 
 

/*===========================================================================*

*

* PSearchName

*

* returns a string containing the name of the search algorithm

*

* RETURNS: pointer to the string

*

* SIDE EFFECTS: none

*

*===========================================================================*/

char *

PSearchName()

{

switch(psearchAlg) {

case PSEARCH_EXHAUSTIVE:

return "EXHAUSTIVE";

case PSEARCH_SUBSAMPLE:

return "SUBSAMPLE";

case PSEARCH_LOGARITHMIC:

return "LOGARITHMIC";

case PSEARCH_TWOLEVEL:

return "TWOLEVEL";

default:

exit(1);

break;

}

}
 
 

/*===========================================================================*

*

* SetSearchRange

*

* sets the range of the search to the given number of pixels

*

* RETURNS: nothing

*

* SIDE EFFECTS: searchRange*, fCode

*

*===========================================================================*/

void

SetSearchRange(pixelsP,pixelsB)

int pixelsP,pixelsB;

{

register int index;

searchRangeP = 2*pixelsP; /* +/- 'pixels' pixels */

searchRangeB = 2*pixelsB;

searchRangeB = 2*pixelsB;

if ( computeMVHist ) {

int max_search;

max_search=(searchRangeP>searchRangeB) ?

((searchRangeP>searchRangeB)?searchRangeP:searchRangeB)

: ((searchRangeB>searchRangeB)?searchRangeB:searchRangeB);

pmvHistogram = (int **) malloc((2*searchRangeP+3)*sizeof(int *));

bbmvHistogram = (int **) malloc((2*searchRangeB+3)*sizeof(int *));

bfmvHistogram = (int **) malloc((2*searchRangeB+3)*sizeof(int *));

for ( index = 0; index < 2*max_search+3; index++ ) {

pmvHistogram[index] = (int *) calloc(2*searchRangeP+3, sizeof(int));

bbmvHistogram[index] = (int *) calloc(2*searchRangeB+3, sizeof(int));

bfmvHistogram[index] = (int *) calloc(2*searchRangeB+3, sizeof(int));

}

}

}
 
 

/*===========================================================================*

*

* USER-MODIFIABLE

*

* MotionSearchPreComputation

*

* do whatever you want here; this is called once per frame, directly

* after reading

*

* RETURNS: whatever

*

* SIDE EFFECTS: whatever

*

*===========================================================================*/

void

MotionSearchPreComputation(frame)

MpegFrame *frame;

{

/* do nothing */

}
 
 

/*===========================================================================*

*

* PSubSampleSearch

*

* uses the subsampling algorithm to compute the P-frame vector

*

* RETURNS: motion vector

*

* SIDE EFFECTS: none

*

* REFERENCE: Liu and Zaccarin: New Fast Algorithms for the Estimation

* of Block Motion Vectors, IEEE Transactions on Circuits

* and Systems for Video Technology, Vol. 3, No. 2, 1993.

*

*===========================================================================*/

int32

PSubSampleSearch(currentBlock, prev, by, bx, motionY, motionX, searchRange)

LumBlock currentBlock;

MpegFrame *prev;

int by;

int bx;

int *motionY;

int *motionX;

int searchRange;

{

register int mx, my;

int32 diff, bestBestDiff;

int stepSize;

register int x;

int bestMY[4], bestMX[4], bestDiff[4];

int leftMY, leftMX;

int rightMY, rightMX;

stepSize = (pixelFullSearch ? 2 : 1);

COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX);

if ( searchRange < rightMY ) {

rightMY = searchRange;

}

if ( searchRange < rightMX ) {

rightMX = searchRange;

}

for ( x = 0; x < 4; x++ ) {

bestMY[x] = 0;

bestMX[x] = 0;

bestDiff[x] = 0x7fffffff;

}

/* do A pattern */

for ( my = -searchRange; my < rightMY; my += 2*stepSize ) {

if ( my < leftMY ) {

continue;

}

for ( mx = -searchRange; mx < rightMX; mx += 2*stepSize ) {

if ( mx < leftMX ) {

continue;

}

diff = LumMotionErrorA(currentBlock, prev, by, bx, my, mx, bestDiff[0]);

if ( diff < bestDiff[0] ) {

bestMY[0] = my;

bestMX[0] = mx;

bestDiff[0] = diff;

}

}

}

/* do B pattern */

for ( my = stepSize-searchRange; my < rightMY; my += 2*stepSize ) {

if ( my < leftMY ) {

continue;

}

for ( mx = -searchRange; mx < rightMX; mx += 2*stepSize ) {

if ( mx < leftMX ) {

continue;

}

diff = LumMotionErrorB(currentBlock, prev, by, bx, my, mx, bestDiff[1]);

if ( diff < bestDiff[1] ) {

bestMY[1] = my;

bestMX[1] = mx;

bestDiff[1] = diff;

}

}

}

/* do C pattern */

for ( my = stepSize-searchRange; my < rightMY; my += 2*stepSize ) {

if ( my < leftMY ) {

continue;

}

for ( mx = stepSize-searchRange; mx < rightMX; mx += 2*stepSize ) {

if ( mx < leftMX ) {

continue;

}

diff = LumMotionErrorC(currentBlock, prev, by, bx, my, mx, bestDiff[2]);

if ( diff < bestDiff[2] ) {

bestMY[2] = my;

bestMX[2] = mx;

bestDiff[2] = diff;

}

}

}

/* do D pattern */

for ( my = -searchRange; my < rightMY; my += 2*stepSize ) {

if ( my < leftMY ) {

continue;

}

for ( mx = stepSize-searchRange; mx < rightMX; mx += 2*stepSize ) {

if ( mx < leftMX ) {

continue;

}

diff = LumMotionErrorD(currentBlock, prev, by, bx, my, mx, bestDiff[3]);

if ( diff < bestDiff[3] ) {

bestMY[3] = my;

bestMX[3] = mx;

bestDiff[3] = diff;

}

}

}

/* first check old motion */

if ( (*motionY >= leftMY) && (*motionY < rightMY) &&

(*motionX >= leftMX) && (*motionX < rightMX) ) {

bestBestDiff = LumMotionError(currentBlock, prev, by, bx, *motionY, *motionX, 0x7fffffff);

} else {

bestBestDiff = 0x7fffffff;

}

/* look at Error of 4 different motion vectors */

for ( x = 0; x < 4; x++ ) {

bestDiff[x] = LumMotionError(currentBlock, prev, by, bx,

bestMY[x], bestMX[x], bestBestDiff);

if ( bestDiff[x] < bestBestDiff ) {

bestBestDiff = bestDiff[x];

*motionY = bestMY[x];

*motionX = bestMX[x];

}

}

return bestBestDiff;

}
 
 

/*===========================================================================*

*

* PLogarithmicSearch

*

* uses logarithmic search to compute the P-frame vector

*

* RETURNS: motion vector

*

* SIDE EFFECTS: none

*

* REFERENCE: MPEG-I specification, pages 32-33

*

*===========================================================================*/

int32

PLogarithmicSearch(currentBlock, prev, by, bx, motionY, motionX, searchRange)

LumBlock currentBlock;

MpegFrame *prev;

int by;

int bx;

int *motionY;

int *motionX;

int searchRange;

{

register int mx, my;

int32 diff, bestDiff;

int stepSize;

int leftMY, leftMX;

int rightMY, rightMX;

int tempRightMY, tempRightMX;

int spacing;

int centerX, centerY;

int newCenterX, newCenterY;

/*************************************************************************/

/* Added mvirgo: Need byte sized pixels for mmx loads */

SmallBlock smallLumBlock;

int horIndex, vertIndex;

for (horIndex = 0; horIndex < 16; horIndex++)

for (vertIndex = 0; vertIndex < 16; vertIndex++)

smallLumBlock[horIndex][vertIndex] = (uint8) currentBlock[horIndex][vertIndex];

/************************************************************************/

stepSize = (pixelFullSearch ? 2 : 1);

COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX);

bestDiff = 0x7fffffff;

/* grid spacing */

if ( stepSize == 2 ) { /* make sure spacing is even */

spacing = (searchRange+1)/2;

if ( (spacing % 2) != 0 ) {

spacing--;

}

} else {

spacing = (searchRange+1)/2;

}

centerX = 0;

centerY = 0;

while ( spacing >= stepSize ) {

newCenterY = centerY;

newCenterX = centerX;

tempRightMY = rightMY;

if ( centerY+spacing+1 < tempRightMY ) {

tempRightMY = centerY+spacing+1;

}

tempRightMX = rightMX;

if ( centerX+spacing+1 < tempRightMX ) {

tempRightMX = centerX+spacing+1;

}

for ( my = centerY-spacing; my < tempRightMY; my += spacing ) {

if ( my < leftMY ) {

continue;

}

for ( mx = centerX-spacing; mx < tempRightMX; mx += spacing ) {

if ( mx < leftMX ) {

continue;

}

/**************************************************************************/

/* Changed mvirgo */

/* old --

** diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff);

*/

/* new -- use enhanced difference calculation */

diff = MMXMotionError(smallLumBlock, prev, by, bx, my, mx, bestDiff);
 
 

/**************************************************************************/

if ( diff < bestDiff ) {

newCenterY = my;

newCenterX = mx;

bestDiff = diff;

}

}

}

centerY = newCenterY;

centerX = newCenterX;

if ( stepSize == 2 ) { /* make sure spacing is even */

if ( spacing == 2 ) {

spacing = 0;

} else {

spacing = (spacing+1)/2;

if ( (spacing % 2) != 0 ) {

spacing--;

}

}

} else {

if ( spacing == 1 ) {

spacing = 0;

} else {

spacing = (spacing+1)/2;

}

}

}

/* check old motion -- see if it's better */

if ( (*motionY >= leftMY) && (*motionY < rightMY) &&

(*motionX >= leftMX) && (*motionX < rightMX) ) {

diff = LumMotionError(currentBlock, prev, by, bx, *motionY, *motionX, bestDiff);

} else {

diff = 0x7fffffff;

}

if ( bestDiff < diff ) {

*motionY = centerY;

*motionX = centerX;

} else {

bestDiff = diff;

}

return bestDiff;

}
 
 

/*===========================================================================*

*

* PLocalSearch

*

* uses local exhaustive search to compute the P-frame vector

*

* RETURNS: motion vector

*

* SIDE EFFECTS: none

*

*===========================================================================*/

int32

PLocalSearch(currentBlock, prev, by, bx, motionY, motionX, bestSoFar, searchRange)

LumBlock currentBlock;

MpegFrame *prev;

int by;

int bx;

int *motionY;

int *motionX;

int32 bestSoFar;

int searchRange;

{

register int mx, my;

int32 diff, bestDiff;

int stepSize;

int leftMY, leftMX;

int rightMY, rightMX;

int distance;

int tempRightMY, tempRightMX;

stepSize = (pixelFullSearch ? 2 : 1);

COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX);

/* try old motion vector first */

if ( VALID_MOTION(*motionY, *motionX) ) {

bestDiff = LumMotionError(currentBlock, prev, by, bx, *motionY, *motionX, bestSoFar);

if ( bestSoFar < bestDiff ) {

bestDiff = bestSoFar;

}

} else {

*motionY = 0;

*motionX = 0;

bestDiff = bestSoFar;

}

/* try a spiral pattern */

for ( distance = stepSize; distance <= searchRange;

distance += stepSize ) {

tempRightMY = rightMY;

if ( distance < tempRightMY ) {

tempRightMY = distance;

}

tempRightMX = rightMX;

if ( distance < tempRightMX ) {

tempRightMX = distance;

}

/* do top, bottom */

for ( my = -distance; my < tempRightMY;

my += max(tempRightMY+distance-stepSize, stepSize) ) {

if ( my < leftMY ) {

continue;

}

for ( mx = -distance; mx < tempRightMX; mx += stepSize ) {

if ( mx < leftMX ) {

continue;

}

diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff);

if ( diff < bestDiff ) {

*motionY = my;

*motionX = mx;

bestDiff = diff;

}

}

}

/* do left, right */

for ( mx = -distance; mx < tempRightMX;

mx += max(tempRightMX+distance-stepSize, stepSize) ) {

if ( mx < leftMX ) {

continue;

}

for ( my = -distance+stepSize; my < tempRightMY-stepSize;

my += stepSize ) {

if ( my < leftMY ) {

continue;

}

diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff);

if ( diff < bestDiff ) {

*motionY = my;

*motionX = mx;

bestDiff = diff;

}

}

}

}

return bestDiff;

}
 
 

/*===========================================================================*

*

* PTwoLevelSearch

*

* uses two-level search to compute the P-frame vector

* first does exhaustive full-pixel search, then looks at neighboring

* half-pixel motion vectors

*

* RETURNS: motion vector

*

* SIDE EFFECTS: none

*

*===========================================================================*/

int32

PTwoLevelSearch(currentBlock, prev, by, bx, motionY, motionX, bestSoFar, searchRange)

LumBlock currentBlock;

MpegFrame *prev;

int by;

int bx;

int *motionY;

int *motionX;

int32 bestSoFar;

int searchRange;

{

register int mx, my;

register int loopInc;

int32 diff, bestDiff;

int leftMY, leftMX;

int rightMY, rightMX;

int distance;

int tempRightMY, tempRightMX;

int xOffset, yOffset;

/* exhaustive full-pixel search first */

COMPUTE_MOTION_BOUNDARY(by,bx,2,leftMY,leftMX,rightMY,rightMX);

rightMY--;

rightMX--;

/* convert vector into full-pixel vector */

if ( *motionY > 0 ) {

if ( ((*motionY) % 2) == 1 ) {

(*motionY)--;

}

} else if ( ((-(*motionY)) % 2) == 1 ) {

(*motionY)++;

}

if ( *motionX > 0 ) {

if ( ((*motionX) % 2) == 1 ) {

(*motionX)--;

}

} else if ( ((-(*motionX)) % 2) == 1 ) {

(*motionX)++;

}

/* try old motion vector first */

if ( VALID_MOTION(*motionY, *motionX) ) {

bestDiff = LumMotionError(currentBlock, prev, by, bx, *motionY, *motionX, bestSoFar);

if ( bestSoFar < bestDiff ) {

bestDiff = bestSoFar;

}

} else {

*motionY = 0;

*motionX = 0;

bestDiff = bestSoFar;

}

rightMY++;

rightMX++;

/* try a spiral pattern */

for ( distance = 2; distance <= searchRange; distance += 2 ) {

tempRightMY = rightMY;

if ( distance < tempRightMY ) {

tempRightMY = distance;

}

tempRightMX = rightMX;

if ( distance < tempRightMX ) {

tempRightMX = distance;

}

/* do top, bottom */

loopInc = max(tempRightMY+distance-2, 2);

for ( my = -distance; my < tempRightMY; my += loopInc ) {

if ( my < leftMY ) {

continue;

}

for ( mx = -distance; mx < tempRightMX; mx += 2 ) {

if ( mx < leftMX ) {

continue;

}

diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff);

if ( diff < bestDiff ) {

*motionY = my;

*motionX = mx;

bestDiff = diff;

}

}

}

/* do left, right */

loopInc = max(tempRightMX+distance-2, 2);

for ( mx = -distance; mx < tempRightMX; mx += loopInc ) {

if ( mx < leftMX ) {

continue;

}

for ( my = -distance+2; my < tempRightMY-2; my += 2 ) {

if ( my < leftMY ) {

continue;

}

diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff);

if ( diff < bestDiff ) {

*motionY = my;

*motionX = mx;

bestDiff = diff;

}

}

}

}

/* now look at neighboring half-pixels */

my = *motionY;

mx = *motionX;

rightMY--;

rightMX--;

for ( yOffset = -1; yOffset <= 1; yOffset++ ) {

for ( xOffset = -1; xOffset <= 1; xOffset++ ) {

if ( (yOffset == 0) && (xOffset == 0) )

continue;

if ( VALID_MOTION(my+yOffset, mx+xOffset) &&

((diff = LumMotionError(currentBlock, prev, by, bx,

my+yOffset, mx+xOffset, bestDiff)) < bestDiff) ) {

*motionY = my+yOffset;

*motionX = mx+xOffset;

bestDiff = diff;

}

}

}

return bestDiff;

}
 
 

void

ShowPMVHistogram(fpointer)

FILE *fpointer;

{

register int x, y;

int *columnTotals;

int rowTotal;

columnTotals = (int *) calloc(2*searchRangeP+3, sizeof(int));

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, " ");

for ( y = 0; y < 2*searchRange+3; y++ ) {

fprintf(fpointer, "%3d ", y-searchRangeP-1);

}

fprintf(fpointer, "\n");

#endif

for ( x = 0; x < 2*searchRangeP+3; x++ ) {

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, "%3d ", x-searchRangeP-1);

#endif

rowTotal = 0;

for ( y = 0; y < 2*searchRangeP+3; y++ ) {

fprintf(fpointer, "%3d ", pmvHistogram[x][y]);

rowTotal += pmvHistogram[x][y];

columnTotals[y] += pmvHistogram[x][y];

}

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, "%4d\n", rowTotal);

#else

fprintf(fpointer, "\n");

#endif

}

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, "Tot ");

for ( y = 0; y < 2*searchRangeP+3; y++ ) {

fprintf(fpointer, "%3d ", columnTotals[y]);

}

#endif

fprintf(fpointer, "\n");

}
 
 

void

ShowBBMVHistogram(fpointer)

FILE *fpointer;

{

register int x, y;

int *columnTotals;

int rowTotal;

fprintf(fpointer, "B-frame Backwards:\n");

columnTotals = (int *) calloc(2*searchRangeB+3, sizeof(int));

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, " ");

for ( y = 0; y < 2*searchRangeB+3; y++ ) {

fprintf(fpointer, "%3d ", y-searchRangeB-1);

}

fprintf(fpointer, "\n");

#endif

for ( x = 0; x < 2*searchRangeB+3; x++ ) {

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, "%3d ", x-searchRangeB-1);

#endif

rowTotal = 0;

for ( y = 0; y < 2*searchRangeB+3; y++ ) {

fprintf(fpointer, "%3d ", bbmvHistogram[x][y]);

rowTotal += bbmvHistogram[x][y];

columnTotals[y] += bbmvHistogram[x][y];

}

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, "%4d\n", rowTotal);

#else

fprintf(fpointer, "\n");

#endif

}

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, "Tot ");

for ( y = 0; y < 2*searchRangeB+3; y++ ) {

fprintf(fpointer, "%3d ", columnTotals[y]);

}

#endif

fprintf(fpointer, "\n");

}
 
 

void

ShowBFMVHistogram(fpointer)

FILE *fpointer;

{

register int x, y;

int *columnTotals;

int rowTotal;

fprintf(fpointer, "B-frame Forwards:\n");

columnTotals = (int *) calloc(2*searchRangeB+3, sizeof(int));

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, " ");

for ( y = 0; y < 2*searchRangeB+3; y++ ) {

fprintf(fpointer, "%3d ", y-searchRangeB-1);

}

fprintf(fpointer, "\n");

#endif

for ( x = 0; x < 2*searchRangeB+3; x++ ) {

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, "%3d ", x-searchRangeB-1);

#endif

rowTotal = 0;

for ( y = 0; y < 2*searchRangeB+3; y++ ) {

fprintf(fpointer, "%3d ", bfmvHistogram[x][y]);

rowTotal += bfmvHistogram[x][y];

columnTotals[y] += bfmvHistogram[x][y];

}

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, "%4d\n", rowTotal);

#else

fprintf(fpointer, "\n");

#endif

}

#ifdef COMPLETE_DISPLAY

fprintf(fpointer, "Tot ");

for ( y = 0; y < 2*searchRangeB+3; y++ ) {

fprintf(fpointer, "%3d ", columnTotals[y]);

}

#endif

fprintf(fpointer, "\n");

}
 
 

/*=====================*

* INTERNAL PROCEDURES *

*=====================*/

/* none */

/*===========================================================================*

* mtypes.h *

* *

* MPEG data types *

* *

*===========================================================================*/

/*

* 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.

*/

/*

* $Header: /u/smoot/md/mpeg_encode/headers/RCS/mtypes.h,v 1.12 1995/04/14 23:12:11 smoot Exp $

* $Log: mtypes.h,v $

* Revision 1.12 1995/04/14 23:12:11 smoot

* added ChromBlock for future color MV searches

*

* Revision 1.11 1995/01/19 23:55:05 eyhung

* Changed copyrights

*

* Revision 1.10 1994/11/14 22:48:57 smoot

* added defines for Specifics operation

*

* Revision 1.9 1994/11/12 02:12:52 keving

* nothing

*

* Revision 1.8 1993/07/22 22:24:23 keving

* nothing

*

* Revision 1.7 1993/07/09 00:17:23 keving

* nothing

*

* Revision 1.6 1993/06/03 21:08:53 keving

* nothing

*

* Revision 1.5 1993/02/17 23:18:20 dwallach

* checkin prior to keving's joining the project

*

* Revision 1.4 1993/01/18 10:20:02 dwallach

* *** empty log message ***

*

* Revision 1.3 1993/01/18 10:17:29 dwallach

* RCS headers installed, code indented uniformly

*

* Revision 1.3 1993/01/18 10:17:29 dwallach

* RCS headers installed, code indented uniformly

*

*/
 
 

#ifndef MTYPES_INCLUDED

#define MTYPES_INCLUDED
 
 

/*==============*

* HEADER FILES *

*==============*/

#include "general.h"

#include "dct.h"
 
 

/*===========*

* CONSTANTS *

*===========*/

#define TYPE_BOGUS 0 /* for the header of the circular list */

#define TYPE_VIRGIN 1

#define STATUS_EMPTY 0

#define STATUS_LOADED 1

#define STATUS_WRITTEN 2
 
 

/*==================*

* TYPE DEFINITIONS *

*==================*/

/*

* your basic Block type

*/

typedef int16 Block[DCTSIZE][DCTSIZE];

typedef int16 FlatBlock[DCTSIZE_SQ];

typedef uint8 SmallBlock[16][16]; /*added mvirgo */

typedef int32 LumBlock[2*DCTSIZE][2*DCTSIZE];

typedef int32 ChromBlock[DCTSIZE][DCTSIZE];

/*========*

* MACROS *

*========*/

#ifdef ABS

#undef ABS

#endif

#define ABS(x) (((x)<0)?-(x):(x))

#ifdef HEINOUS_DEBUG_MODE

#define DBG_PRINT(x) {printf x; fflush(stdout);}

#else

#define DBG_PRINT(x)

#endif

#define ERRCHK(bool, str) {if(!(bool)) {perror(str); exit(1);}}

/* For Specifics */

typedef struct detalmv_def {

int typ,fx,fy,bx,by;

} BlockMV;

#define TYP_SKIP 0

#define TYP_FORW 1

#define TYP_BACK 2

#define TYP_BOTH 3
 
 

#endif /* MTYPES_INCLUDED */
 
 

/*===========================================================================*

* frames.h *

* *

* stuff dealing with frames *

* *

*===========================================================================*/

/*

* 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.

*/

/*

* $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/frames.h,v 1.13 1995/08/15 23:43:04 smoot Exp $

* $Log: frames.h,v $

* Revision 1.13 1995/08/15 23:43:04 smoot

* *** empty log message ***

*

* Revision 1.12 1995/04/14 23:13:18 smoot

* Reorganized for better rate control. Added overflow in DCT values

* handling.

*

* Revision 1.11 1995/01/19 23:54:46 smoot

* allow computediffdcts to un-assert parts of the pattern

*

* Revision 1.10 1995/01/16 07:43:10 eyhung

* Added realQuiet

*

* Revision 1.9 1995/01/10 23:15:28 smoot

* Fixed searchRange lack of def

*

* Revision 1.8 1994/11/15 00:55:36 smoot

* added printMSE

*

* Revision 1.7 1994/11/14 22:51:02 smoot

* added specifics flag. Added BlockComputeSNR parameters

*

* Revision 1.6 1994/11/01 05:07:23 darryl

* with rate control changes added

*

* Revision 1.1 1994/09/27 01:02:55 darryl

* Initial revision

*

* Revision 1.5 1993/07/22 22:24:23 keving

* nothing

*

* Revision 1.4 1993/07/09 00:17:23 keving

* nothing

*

* Revision 1.3 1993/06/03 21:08:53 keving

* nothing

*

* Revision 1.2 1993/03/02 19:00:27 keving

* nothing

*

* Revision 1.1 1993/02/19 20:15:51 keving

* nothing

*

*/
 
 

#ifndef FRAMES_INCLUDED

#define FRAMES_INCLUDED

/*==============*

* HEADER FILES *

*==============*/

#include "ansi.h"

#include "mtypes.h"

#include "mheaders.h"

#include "frame.h"
 
 

/*===========*

* CONSTANTS *

*===========*/

#define I_FRAME 1

#define P_FRAME 2

#define B_FRAME 3

#define LUM_BLOCK 0

#define CHROM_BLOCK 1

#define CR_BLOCK 2

#define CB_BLOCK 3

#define MOTION_FORWARD 0

#define MOTION_BACKWARD 1

#define MOTION_INTERPOLATE 2
 
 

#define USE_HALF 0

#define USE_FULL 1

/* motion vector stuff */

#define FORW_F_CODE fCode /* from picture header */

#define BACK_F_CODE fCode

#define FORW_F (1 << (FORW_F_CODE - 1))

#define BACK_F (1 << (BACK_F_CODE - 1))

#define RANGE_NEG (-(1 << (3 + FORW_F_CODE)))

#define RANGE_POS ((1 << (3 + FORW_F_CODE))-1)

#define MODULUS (1 << (4 + FORW_F_CODE))

#define ORIGINAL_FRAME 0

#define DECODED_FRAME 1
 
 

/*=======================*

* STRUCTURE DEFINITIONS *

*=======================*/

typedef struct FrameTableStruct {

/* the following are all initted once and never changed */

/* (they depend only on the pattern */

char typ;

struct FrameTableStruct *next;

struct FrameTableStruct *prev;

/* nextOutput is a pointer to next frame table entry to output */

struct FrameTableStruct *nextOutput;

boolean freeNow; /* TRUE iff no frames point back to this */

int number;

int bFrameNumber; /* actual frame number, if a b-frame */

} FrameTable;
 
 

/*==================*

* TYPE DEFINITIONS *

*==================*/

typedef struct dct_data_tye_struct {

char useMotion;

char pattern, mode;

int fmotionX, fmotionY, bmotionX, bmotionY;

} dct_data_type;

void EncodeYDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb));

void EncodeCDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb));
 
 

/*========*

* MACROS *

*========*/

#define FRAME_TYPE(num) framePattern[num % framePatternLen]

/* return ceiling(a/b) where a, b are ints, using temp value c */

#define int_ceil_div(a,b,c) ((b*(c = a/b) < a) ? (c+1) : c)

#define int_floor_div(a,b,c) ((b*(c = a/b) > a) ? (c-1) : c)

/* assumes many things:

* block indices are (y,x)

* variables y_dc_pred, cr_dc_pred, and cb_dc_pred

* flat block fb exists

*/

#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) { \

boolean overflow, overflowChange=FALSE; \

int overflowValue = 0; \

do { \

overflow = Mpost_QuantZigBlock(dct[y][x], fb[0], \

qscale, TRUE)==MPOST_OVERFLOW; \

overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1], \

qscale, TRUE)==MPOST_OVERFLOW; \

overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2], \

qscale, TRUE)==MPOST_OVERFLOW; \

overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3], \

qscale, TRUE)==MPOST_OVERFLOW; \

overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], \

fb[4], qscale, TRUE)==MPOST_OVERFLOW; \

overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], \

fb[5], qscale, TRUE)==MPOST_OVERFLOW; \

if ((overflow) && (qscale!=31)) { \

overflowChange = TRUE; overflowValue++; \

qscale++; \

} else overflow = FALSE; \

} while (overflow); \

Mhead_GenMBHeader(bb, \

frameType /* pict_code_type */, mbAI /* addr_incr */, \

qscale /* q_scale */, \

0 /* forw_f_code */, 0 /* back_f_code */, \

0 /* horiz_forw_r */, 0 /* vert_forw_r */, \

0 /* horiz_back_r */, 0 /* vert_back_r */, \

0 /* motion_forw */, 0 /* m_horiz_forw */, \

0 /* m_vert_forw */, 0 /* motion_back */, \

0 /* m_horiz_back */, 0 /* m_vert_back */, \

0 /* mb_pattern */, TRUE /* mb_intra */); \

\

/* Y blocks */ \

EncodeYDC(fb[0][0], &y_dc_pred, bb); \

Mpost_RLEHuffIBlock(fb[0], bb); \

EncodeYDC(fb[1][0], &y_dc_pred, bb); \

Mpost_RLEHuffIBlock(fb[1], bb); \

EncodeYDC(fb[2][0], &y_dc_pred, bb); \

Mpost_RLEHuffIBlock(fb[2], bb); \

EncodeYDC(fb[3][0], &y_dc_pred, bb); \

Mpost_RLEHuffIBlock(fb[3], bb); \

\

/* CB block */ \

EncodeCDC(fb[4][0], &cb_dc_pred, bb); \

Mpost_RLEHuffIBlock(fb[4], bb); \

\

/* CR block */ \

EncodeCDC(fb[5][0], &cr_dc_pred, bb); \

Mpost_RLEHuffIBlock(fb[5], bb); \

if (overflowChange) qscale -= overflowValue; \

}

#define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) { \

x1 = (bx1)*DCTSIZE; \

x2 = (bx2)*DCTSIZE; \

}

#define MOTION_TO_FRAME_COORD(bx1, bx2, mx1, mx2, x1, x2) { \

x1 = (bx1)*DCTSIZE+(mx1); \

x2 = (bx2)*DCTSIZE+(mx2); \

}

#define COORD_IN_FRAME(fy,fx, type) \

((type == LUM_BLOCK) ? \

((fy >= 0) && (fx >= 0) && (fy < Fsize_y) && (fx < Fsize_x)) : \

((fy >= 0) && (fx >= 0) && (fy < (Fsize_y>>1)) && (fx < (Fsize_x>>1))))

#define ENCODE_MOTION_VECTOR(x,y,xq, yq, xr, yr, f) { \

int tempC; \

\

if ( x < RANGE_NEG ) tempX = x + MODULUS; \

else if ( x > RANGE_POS ) tempX = x - MODULUS; \

else tempX = x; \

\

if ( y < RANGE_NEG ) tempY = y + MODULUS; \

else if ( y > RANGE_POS ) tempY = y - MODULUS; \

else tempY = y; \

\

if ( tempX >= 0 ) { \

xq = int_ceil_div(tempX, f, tempC); \

xr = f - 1 + tempX - xq*f; \

} else { \

xq = int_floor_div(tempX, f, tempC); \

xr = f - 1 - tempX + xq*f; \

} \

\

if ( tempY >= 0 ) { \

yq = int_ceil_div(tempY, f, tempC); \

yr = f - 1 + tempY - yq*f; \

} else { \

yq = int_floor_div(tempY, f, tempC); \

yr = f - 1 - tempY + yq*f; \

} \

}
 
 

#define DoQuant(bit, src, dest) \

if (pattern & bit) { \

switch (Mpost_QuantZigBlock(src, dest, QScale, FALSE)) { \

case MPOST_NON_ZERO: \

break; \

case MPOST_ZERO: \

pattern ^= bit; \

break; \

case MPOST_OVERFLOW: \

if (QScale != 31) { \

QScale++; \

overflowChange = TRUE; \

overflowValue++; \

goto calc_blocks; \

} \

break; \

} \

}

/*===============================*

* EXTERNAL PROCEDURE prototypes *

*===============================*/

void ComputeBMotionLumBlock _ANSI_ARGS_((MpegFrame *prev, MpegFrame *next,

int by, int bx, int mode, int fmy, int fmx,

int bmy, int bmx, LumBlock motionBlock));

int BMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, MpegFrame *next,

int by, int bx, int *fmy, int *fmx, int *bmy, int *bmx, int oldMode));
 
 

void ComputeDiffDCTs _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, int by, int bx,

int my, int mx, int *pattern));

int ComputeDiffDCTBlock _ANSI_ARGS_((Block current, Block dest, Block motionBlock));

void ComputeMotionBlock _ANSI_ARGS_((uint8 **prev, int by, int bx, int my, int mx,

Block motionBlock));

void ComputeMotionLumBlock _ANSI_ARGS_((MpegFrame *prevFrame, int by,

int bx, int my, int mx,

LumBlock motionBlock));

int32 ComputeBlockMAD _ANSI_ARGS_((Block current, Block prev));

void GenIFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *mf));

void GenPFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *current, MpegFrame *prev));

void GenBFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *curr, MpegFrame *prev, MpegFrame *next));

void AllocDctBlocks _ANSI_ARGS_((void ));

float ShowIFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer));

float ShowPFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer));

float ShowBFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer));
 
 

/* DIFFERENCE FUNCTIONS */

int32 LumBlockMAD _ANSI_ARGS_((LumBlock currentBlock, LumBlock motionBlock, int32 bestSoFar));

int32 LumBlockMSE _ANSI_ARGS_((LumBlock currentBlock, LumBlock motionBlock, int32 bestSoFar));

/*added mvirgo */

int32 MMXMotionError _ANSI_ARGS_((SmallBlock currentBlock, MpegFrame *prev,

int by, int bx, int my, int mx,

int32 bestSoFar));

int32 LumMotionError _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev,

int by, int bx, int my, int mx,

int32 bestSoFar));

int32 LumAddMotionError _ANSI_ARGS_((LumBlock currentBlock,

LumBlock blockSoFar, MpegFrame *prev,

int by, int bx, int my, int mx,

int32 bestSoFar));

int32 LumMotionErrorA _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame,

int by, int bx, int my, int mx,

int32 bestSoFar));

int32 LumMotionErrorB _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame,

int by, int bx, int my, int mx,

int32 bestSoFar));

int32 LumMotionErrorC _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame,

int by, int bx, int my, int mx,

int32 bestSoFar));

int32 LumMotionErrorD _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame,

int by, int bx, int my, int mx,

int32 bestSoFar));

int32 LumMotionErrorSubSampled _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prevFrame,

int by, int bx, int my, int mx,

int startY, int startX));

void BlockComputeSNR _ANSI_ARGS_((MpegFrame *current,

float *snr, float *psnr));

int32 time_elapsed _ANSI_ARGS_((void));

void AllocDctBlocks _ANSI_ARGS_((void));

/*==================*

* GLOBAL VARIABLES *

*==================*/

extern int pixelFullSearch;

extern int searchRangeP,searchRangeB;

extern int qscaleI;

extern int gopSize;

extern int slicesPerFrame;

extern int blocksPerSlice;

extern int referenceFrame;

extern int specificsOn;

extern int quietTime; /* shut up for at least quietTime seconds;

* negative means shut up forever

*/

extern boolean realQuiet; /* TRUE = no messages to stdout */

extern boolean frameSummary; /* TRUE = frame summaries should be printed */

extern boolean printSNR;

extern boolean printMSE;

extern boolean decodeRefFrames; /* TRUE = should decode I and P frames */

extern int fCodeI,fCodeP,fCodeB;

extern boolean forceEncodeLast;

extern int TIME_RATE;

#endif /* FRAMES_INCLUDED */

#

# 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.

#

#

# $Header: /n/video/199/eyhung/encode/RCS/Makefile,v 1.7 1995/02/02 02:25:51 eyhung Exp $

#

##############################################################################

#

# Configurable items

#

################################################################

# PROFILING # use -pg or -p if and only if you want to profile #

################################################################

PROFLAG =

##############

# JPEG STUFF #

##############

JPEG_LIB = jpeg/libjpeg.a

JPEG_DIR = -Ijpeg

JPEG_LIB_DIR = -Ljpeg

MP_JPEG_OBJS = jpeg.o

MP_JPEG_SRCS = jpeg.c

####################################################################

# DEBUGGING # use -g if and only if you want to debug, else use -O #

####################################################################

#DEBUGFLAG = -g

DEBUGFLAG = -O

###############################################################################

# MISSING PROTOTYES # use -DMISSING_PROTOS if your standard headers are wrong #

###############################################################################

PROTOFLAG =

#PROTOFLAG = -DMISSING_PROTOS

#################

# INCLUDE FILES #

#################

INCLUDEDIR = -Iheaders -I/usr/include $(JPEG_DIR)

############################################################################

# LIBRARIES # specify library directories; need jpg lib and maybe pbm #

############################################################################

#LIBDIRS = -L$(PBMLIBDIR) $(JPEG_LIB_DIR)

LIBDIRS = $(JPEG_LIB_DIR)

#####################################################################

# COMPILER # specify compiler; should be ANSI-compliant if possible #

#####################################################################

CC = gcc

################################################

# MAKE # command to use for the "make" command #

################################################

MAKE = make

###################################################

# COMPILER FLAGS # modify for different compilers #

###################################################

# use -DLONG_32 iff

# 1) long's are 32 bits and

# 2) int's are not

#

# if you don't have <netinet/in.h> then you must define one of the following

# -DFORCE_BIG_ENDIAN

# -DFORCE_LITTLE_ENDIAN

#

# if you are using a non-ANSI compiler, then use:

# -DNON_ANSI_COMPILER

#

# one other option:

# -DHEINOUS_DEBUG_MODE

#

# listed below are some suggested CFLAG lines for various compilers

#

# gcc

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) -Wall -Wmissing-prototypes $(PROFLAG) $(PROTOFLAG)

# gcc-strict

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) -pedantic -Wall -Waggregate-return -Wtraditional -Wshadow -Wpointer-arith -Wno-parentheses -Wwrite-strings -Wconversion -Wcast-qual -Wcast-align -Wnested-externs -Wuninitialized -Wmissing-prototypes $(PROFLAG) $(PROTOFLAG)

# SUN cc

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) $(PROFLAG) $(PROTOFLAG) -DNON_ANSI_COMPILER

# HP cc

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) $(PROFLAG) $(PROTOFLAG) -DNON_ANSI_COMPILER

# HP gcc

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) $(PROFLAG)

# DEC ALPHA cc

#CFLAGS = $(INCLUDEDIR) -Olimit 1200 $(DEBUGFLAG) $(PROFLAG) $(PROTOFLAG)

# DEC Ultrix gcc

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) -Wall -Wmissing-prototypes $(PROFLAG) $(PROTOFLAG) -DMIPS

# SGI cc

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) $(PROFLAG) $(PROTOFLAG) -cckr -DIRIX

# Intel-based SVR4.0 cc

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) $(PROFLAG) $(PROTOFLAG) -DLONG_32 -DSVR4 -DSYSV386

# Intel-based SCO Unix

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) $(PROFLAG) $(PROTOFLAG) -Dsco -m486

# linux CFLAGS

CFLAGS = $(INCLUDEDIR) -m486 -fomit-frame-pointer -ffast-math -finline-functions $(DEBUGFLAG) $(PROFLAG) $(PROTOFLAG) -DLONG_32 -DSYSV -DLINUX

# IBM RS/6000 cc

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) $(PROFLAG) $(PROTOFLAG)

# DOS

#CFLAGS = $(INCLUDEDIR) $(DEBUGFLAG) -O1 -DSYSV -DFORCE_LITTLE_ENDIAN -w-rvl -w-rch -w-eff -w-ccc -w-par -w-use -w-aus -w-pro $(PROFLAG) $(PROTOFLAG)
 
 

#########################################################################

# LIBRARIES # same for most machines; may need to add stuff for sockets #

#########################################################################

# this works for most machines

LIBS = $(JPEG_LIB) -lm

# Solaris

#LIBS = $(JPEG_LIB) -lm -lsocket -lnsl

# Intel-based SVR4.0

#LIBS = $(JPEG_LIB) -lm -lsocket -lnsl -lgen

# Intel-based SCO Unix

#LIBS = $(JPEG_LIB) -lX11 -lsocket -lmalloc -lPW -lc_s -lm
 
 

###############

# OTHER STUFF #

###############

#PURIFY = purify -cache-dir=/tmp

PURIFY =

#

# End of configurable options. Just type make and have fun.

##############################################################################

MP_BASE_OBJS = mfwddct.o postdct.o huff.o bitio.o mheaders.o

MP_BASE_SRCS = mfwddct.c postdct.c huff.c bitio.c mheaders.c

MP_ENCODE_OBJS = iframe.o pframe.o bframe.o psearch.o bsearch.o block.o

MP_ENCODE_SRCS = iframe.c pframe.c bframe.c psearch.c bsearch.c block.c

MP_OTHER_OBJS = mpeg.o subsample.o param.o rgbtoycc.o \

readframe.o combine.o jrevdct.o frame.o fsize.o frametype.o \

libpnmrw.o specifics.o rate.o opts.o

MP_OTHER_SRCS = mpeg.c subsample.c param.c rgbtoycc.c \

readframe.c combine.c jrevdct.c frame.c fsize.c frametype.c \

libpnmrw.c specifics.c rate.c opts.c

MP_PARALLEL_OBJS = parallel.o

MP_PARALLEL_SRCS = parallel.c

MP_ALL_SRCS = $(MP_BASE_SRCS) $(MP_OTHER_SRCS) $(MP_ENCODE_SRCS) \

$(MP_PARALLEL_SRCS) $(MP_JPEG_SRCS) main.c

MP_ALL_OBJS = $(MP_BASE_OBJS) $(MP_OTHER_OBJS) $(MP_ENCODE_OBJS) \

$(MP_PARALLEL_OBJS) $(MP_JPEG_OBJS) main.o

MP_INCLUDE = mproto.h mtypes.h huff.h bitio.h

MP_MISC = Makefile huff.table parse_huff.pl

all: mpeg_encode

#########

# TESTS #

#########

test:

rm -f /tmp/ts.stat

./mpeg_encode -stat /tmp/ts.stat ./tst/ts.param

csh ./tst/diffscript /tmp/ts.stat ./tst/ts.stat /tmp/ts.mpg ./tst/ts.mpg

testd:

rm -f /tmp/tsd.stat

./mpeg_encode -stat /tmp/tsd.stat ./tst/tsd.param

csh ./tst/diffscript /tmp/tsd.stat ./tst/tsd.stat /tmp/tsd.mpg ./tst/tsd.mpg

test_all: test testd

############

# BINARIES #

############

mpeg_encode: $(MP_ALL_OBJS) $(JPEG_LIB)

$(PURIFY) $(CC) $(CFLAGS) -o $@ $(MP_ALL_OBJS) $(LIBDIRS) $(LIBS)

strip mpeg_encode

profile: $(MP_ALL_OBJS)

$(PURIFY) $(CC) -Bstatic -pg $(CFLAGS) -o $@ $(MP_ALL_OBJS) $(LIBDIRS) $(LIBS)

#########

# OTHER #

#########

# make JPEG compile itself

jpeg/libjpeg.a:

(cd jpeg; $(MAKE) libjpeg.a)

#

# Perl is necessary if you want to modify the Huffman RLE encoding table.

#

PERL = perl

# The following stuff is for the Huffman encoding tables. It's commented-out

# because you probably don't want to change this. If you do, then uncommment

# it.

#

# huff.h: huff.c

#

# huff.c: parse_huff.pl huff.table

# $(PERL) parse_huff.pl huff.table

headers.o: headers.c

$(CC) $(CFLAGS) -c headers.c

depend: huff.c

makedepend -- $(CFLAGS) -- $(MP_ALL_SRCS)

wc:; wc -l *.[ch] headers/*.h *.pl *.table

ci:; ci -l $(MP_ALL_SRCS) $(MP_INCLUDE) $(MP_MISC)

tags: $(MP_ALL_SRCS)

ctags -t $(MP_ALL_SRCS)

etags -f TAGS -t $(MP_ALL_SRCS) headers/*.h

new:

rm -f *.o core *~ gmon.out

$(MAKE) depend

clean:

-rm -f *.o core *~ gmon.out

$(MAKE) depend

-$(MAKE) tags

#

# WARNING: this assumes you're using GNU indent...

#

indent:; indent -T FILE -T int8 -T int16 -T int32 -T uint8 -T uint16 -T uint32 -T BitBucket -T MpegFrame -T Block -T FlatBlock $(MP_ALL_SRCS)

spotless: clean

rm -f huff.c huff.h *.pure.a

cd jpeg; $(MAKE) clean

##############################################################################

# DO NOT DELETE THIS LINE -- make depend depends on it.

mfwddct.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

mfwddct.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

mfwddct.o: /usr/include/stdlib.h /usr/include/features.h

mfwddct.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

mfwddct.o: /usr/include/errno.h /usr/include/linux/errno.h

mfwddct.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

mfwddct.o: /usr/include/huge_val.h /usr/include/endian.h

mfwddct.o: /usr/include/bytesex.h /usr/include/nan.h

mfwddct.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

mfwddct.o: /usr/include/values.h /usr/include/ieee754.h

mfwddct.o: /usr/include/ieee854.h /usr/include/memory.h /usr/include/string.h

mfwddct.o: /usr/include/limits.h /usr/include/posix1_lim.h

mfwddct.o: /usr/include/linux/limits.h /usr/include/posix2_lim.h

mfwddct.o: /usr/include/time.h /usr/include/sys/time.h

mfwddct.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

mfwddct.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

mfwddct.o: /usr/include/linux/time.h /usr/include/sys/types.h

mfwddct.o: /usr/include/sys/bitypes.h headers/libpnmrw.h

mfwddct.o: /usr/include/malloc.h headers/ansi.h headers/general.h

mfwddct.o: headers/dct.h headers/mtypes.h headers/opts.h

postdct.o: /usr/include/assert.h /usr/include/features.h

postdct.o: /usr/include/sys/cdefs.h headers/all.h /usr/include/stdio.h

postdct.o: /usr/include/libio.h /usr/include/_G_config.h

postdct.o: /usr/include/stdlib.h

postdct.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

postdct.o: /usr/include/errno.h /usr/include/linux/errno.h

postdct.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

postdct.o: /usr/include/huge_val.h /usr/include/endian.h

postdct.o: /usr/include/bytesex.h /usr/include/nan.h

postdct.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

postdct.o: /usr/include/values.h /usr/include/ieee754.h

postdct.o: /usr/include/ieee854.h /usr/include/memory.h /usr/include/string.h

postdct.o: /usr/include/limits.h /usr/include/posix1_lim.h

postdct.o: /usr/include/linux/limits.h /usr/include/posix2_lim.h

postdct.o: /usr/include/time.h /usr/include/sys/time.h

postdct.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

postdct.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

postdct.o: /usr/include/linux/time.h /usr/include/sys/types.h

postdct.o: /usr/include/sys/bitypes.h headers/libpnmrw.h

postdct.o: /usr/include/malloc.h headers/ansi.h headers/general.h

postdct.o: headers/mtypes.h headers/dct.h headers/bitio.h huff.h

postdct.o: headers/postdct.h headers/opts.h

huff.o: headers/mtypes.h headers/general.h headers/dct.h headers/ansi.h

huff.o: huff.h

bitio.o: /usr/include/assert.h /usr/include/features.h

bitio.o: /usr/include/sys/cdefs.h headers/all.h /usr/include/stdio.h

bitio.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/stdlib.h

bitio.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

bitio.o: /usr/include/errno.h /usr/include/linux/errno.h

bitio.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

bitio.o: /usr/include/huge_val.h /usr/include/endian.h /usr/include/bytesex.h

bitio.o: /usr/include/nan.h

bitio.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

bitio.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

bitio.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

bitio.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

bitio.o: /usr/include/posix2_lim.h /usr/include/time.h

bitio.o: /usr/include/sys/time.h /usr/include/linux/types.h

bitio.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

bitio.o: /usr/include/asm/types.h /usr/include/linux/time.h

bitio.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

bitio.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

bitio.o: headers/general.h headers/byteorder.h /usr/include/netinet/in.h

bitio.o: /usr/include/sys/socket.h /usr/include/linux/socket.h

bitio.o: /usr/include/asm/socket.h /usr/include/asm/sockios.h

bitio.o: /usr/include/linux/sockios.h /usr/include/linux/uio.h

bitio.o: /usr/include/linux/in.h /usr/include/asm/byteorder.h headers/bitio.h

bitio.o: headers/mtypes.h headers/dct.h

mheaders.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

mheaders.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

mheaders.o: /usr/include/stdlib.h /usr/include/features.h

mheaders.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

mheaders.o: /usr/include/errno.h /usr/include/linux/errno.h

mheaders.o: /usr/include/asm/errno.h /usr/include/alloca.h

mheaders.o: /usr/include/math.h /usr/include/huge_val.h /usr/include/endian.h

mheaders.o: /usr/include/bytesex.h /usr/include/nan.h

mheaders.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

mheaders.o: /usr/include/values.h /usr/include/ieee754.h

mheaders.o: /usr/include/ieee854.h /usr/include/memory.h

mheaders.o: /usr/include/string.h /usr/include/limits.h

mheaders.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

mheaders.o: /usr/include/posix2_lim.h /usr/include/time.h

mheaders.o: /usr/include/sys/time.h /usr/include/linux/types.h

mheaders.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

mheaders.o: /usr/include/asm/types.h /usr/include/linux/time.h

mheaders.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

mheaders.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

mheaders.o: headers/general.h headers/bitio.h headers/frames.h

mheaders.o: headers/mtypes.h headers/dct.h headers/mheaders.h headers/frame.h

mpeg.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

mpeg.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

mpeg.o: /usr/include/stdlib.h /usr/include/features.h

mpeg.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

mpeg.o: /usr/include/errno.h /usr/include/linux/errno.h

mpeg.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

mpeg.o: /usr/include/huge_val.h /usr/include/endian.h /usr/include/bytesex.h

mpeg.o: /usr/include/nan.h

mpeg.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

mpeg.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

mpeg.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

mpeg.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

mpeg.o: /usr/include/posix2_lim.h /usr/include/time.h /usr/include/sys/time.h

mpeg.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

mpeg.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

mpeg.o: /usr/include/linux/time.h /usr/include/sys/types.h

mpeg.o: /usr/include/sys/bitypes.h headers/libpnmrw.h /usr/include/malloc.h

mpeg.o: headers/ansi.h headers/general.h /usr/include/unistd.h

mpeg.o: /usr/include/posix_opt.h /usr/include/gnu/types.h

mpeg.o: /usr/include/confname.h headers/mtypes.h headers/dct.h

mpeg.o: headers/frames.h headers/mheaders.h headers/bitio.h headers/frame.h

mpeg.o: headers/search.h headers/mpeg.h headers/prototypes.h

mpeg.o: headers/parallel.h headers/param.h headers/readframe.h

mpeg.o: headers/fsize.h headers/rate.h /usr/include/sys/stat.h

mpeg.o: /usr/include/linux/stat.h

subsample.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

subsample.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

subsample.o: /usr/include/stdlib.h /usr/include/features.h

subsample.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

subsample.o: /usr/include/errno.h /usr/include/linux/errno.h

subsample.o: /usr/include/asm/errno.h /usr/include/alloca.h

subsample.o: /usr/include/math.h /usr/include/huge_val.h

subsample.o: /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h

subsample.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

subsample.o: /usr/include/values.h /usr/include/ieee754.h

subsample.o: /usr/include/ieee854.h /usr/include/memory.h

subsample.o: /usr/include/string.h /usr/include/limits.h

subsample.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

subsample.o: /usr/include/posix2_lim.h /usr/include/time.h

subsample.o: /usr/include/sys/time.h /usr/include/linux/types.h

subsample.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

subsample.o: /usr/include/asm/types.h /usr/include/linux/time.h

subsample.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

subsample.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

subsample.o: headers/general.h headers/mtypes.h headers/dct.h

subsample.o: headers/frames.h headers/mheaders.h headers/bitio.h

subsample.o: headers/frame.h headers/prototypes.h

param.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

param.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

param.o: /usr/include/stdlib.h /usr/include/features.h

param.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

param.o: /usr/include/errno.h /usr/include/linux/errno.h

param.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

param.o: /usr/include/huge_val.h /usr/include/endian.h /usr/include/bytesex.h

param.o: /usr/include/nan.h

param.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

param.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

param.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

param.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

param.o: /usr/include/posix2_lim.h /usr/include/time.h

param.o: /usr/include/sys/time.h /usr/include/linux/types.h

param.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

param.o: /usr/include/asm/types.h /usr/include/linux/time.h

param.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

param.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

param.o: headers/general.h headers/mtypes.h headers/dct.h headers/mpeg.h

param.o: headers/frame.h headers/search.h headers/prototypes.h

param.o: headers/parallel.h headers/bitio.h headers/param.h

param.o: headers/readframe.h headers/fsize.h headers/frames.h

param.o: headers/mheaders.h headers/jpeg.h /usr/include/ctype.h

param.o: headers/rate.h headers/opts.h

rgbtoycc.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

rgbtoycc.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

rgbtoycc.o: /usr/include/stdlib.h /usr/include/features.h

rgbtoycc.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

rgbtoycc.o: /usr/include/errno.h /usr/include/linux/errno.h

rgbtoycc.o: /usr/include/asm/errno.h /usr/include/alloca.h

rgbtoycc.o: /usr/include/math.h /usr/include/huge_val.h /usr/include/endian.h

rgbtoycc.o: /usr/include/bytesex.h /usr/include/nan.h

rgbtoycc.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

rgbtoycc.o: /usr/include/values.h /usr/include/ieee754.h

rgbtoycc.o: /usr/include/ieee854.h /usr/include/memory.h

rgbtoycc.o: /usr/include/string.h /usr/include/limits.h

rgbtoycc.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

rgbtoycc.o: /usr/include/posix2_lim.h /usr/include/time.h

rgbtoycc.o: /usr/include/sys/time.h /usr/include/linux/types.h

rgbtoycc.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

rgbtoycc.o: /usr/include/asm/types.h /usr/include/linux/time.h

rgbtoycc.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

rgbtoycc.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

rgbtoycc.o: headers/general.h headers/frame.h headers/mtypes.h headers/dct.h

rgbtoycc.o: headers/fsize.h headers/rgbtoycc.h

readframe.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

readframe.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

readframe.o: /usr/include/stdlib.h /usr/include/features.h

readframe.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

readframe.o: /usr/include/errno.h /usr/include/linux/errno.h

readframe.o: /usr/include/asm/errno.h /usr/include/alloca.h

readframe.o: /usr/include/math.h /usr/include/huge_val.h

readframe.o: /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h

readframe.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

readframe.o: /usr/include/values.h /usr/include/ieee754.h

readframe.o: /usr/include/ieee854.h /usr/include/memory.h

readframe.o: /usr/include/string.h /usr/include/limits.h

readframe.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

readframe.o: /usr/include/posix2_lim.h /usr/include/time.h

readframe.o: /usr/include/sys/time.h /usr/include/linux/types.h

readframe.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

readframe.o: /usr/include/asm/types.h /usr/include/linux/time.h

readframe.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

readframe.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

readframe.o: headers/general.h /usr/include/ctype.h /usr/include/unistd.h

readframe.o: /usr/include/posix_opt.h /usr/include/gnu/types.h

readframe.o: /usr/include/confname.h headers/mtypes.h headers/dct.h

readframe.o: headers/frames.h headers/mheaders.h headers/bitio.h

readframe.o: headers/frame.h headers/prototypes.h headers/parallel.h

readframe.o: headers/param.h headers/readframe.h headers/fsize.h

readframe.o: headers/rgbtoycc.h headers/jpeg.h headers/opts.h

combine.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

combine.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

combine.o: /usr/include/stdlib.h /usr/include/features.h

combine.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

combine.o: /usr/include/errno.h /usr/include/linux/errno.h

combine.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

combine.o: /usr/include/huge_val.h /usr/include/endian.h

combine.o: /usr/include/bytesex.h /usr/include/nan.h

combine.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

combine.o: /usr/include/values.h /usr/include/ieee754.h

combine.o: /usr/include/ieee854.h /usr/include/memory.h /usr/include/string.h

combine.o: /usr/include/limits.h /usr/include/posix1_lim.h

combine.o: /usr/include/linux/limits.h /usr/include/posix2_lim.h

combine.o: /usr/include/time.h /usr/include/sys/time.h

combine.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

combine.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

combine.o: /usr/include/linux/time.h /usr/include/sys/types.h

combine.o: /usr/include/sys/bitypes.h headers/libpnmrw.h

combine.o: /usr/include/malloc.h headers/ansi.h headers/general.h

combine.o: headers/mtypes.h headers/dct.h headers/frames.h headers/mheaders.h

combine.o: headers/bitio.h headers/frame.h headers/search.h headers/mpeg.h

combine.o: headers/prototypes.h headers/parallel.h headers/param.h

combine.o: headers/readframe.h headers/fsize.h headers/combine.h

combine.o: /usr/include/unistd.h /usr/include/posix_opt.h

combine.o: /usr/include/gnu/types.h /usr/include/confname.h

jrevdct.o: /usr/include/memory.h /usr/include/features.h

jrevdct.o: /usr/include/sys/cdefs.h /usr/include/string.h

jrevdct.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h headers/all.h

jrevdct.o: /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h

jrevdct.o: /usr/include/stdlib.h /usr/include/errno.h

jrevdct.o: /usr/include/linux/errno.h /usr/include/asm/errno.h

jrevdct.o: /usr/include/alloca.h /usr/include/math.h /usr/include/huge_val.h

jrevdct.o: /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h

jrevdct.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

jrevdct.o: /usr/include/values.h /usr/include/ieee754.h

jrevdct.o: /usr/include/ieee854.h /usr/include/limits.h

jrevdct.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

jrevdct.o: /usr/include/posix2_lim.h /usr/include/time.h

jrevdct.o: /usr/include/sys/time.h /usr/include/linux/types.h

jrevdct.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

jrevdct.o: /usr/include/asm/types.h /usr/include/linux/time.h

jrevdct.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

jrevdct.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

jrevdct.o: headers/general.h headers/dct.h

frame.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

frame.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

frame.o: /usr/include/stdlib.h /usr/include/features.h

frame.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

frame.o: /usr/include/errno.h /usr/include/linux/errno.h

frame.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

frame.o: /usr/include/huge_val.h /usr/include/endian.h /usr/include/bytesex.h

frame.o: /usr/include/nan.h

frame.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

frame.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

frame.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

frame.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

frame.o: /usr/include/posix2_lim.h /usr/include/time.h

frame.o: /usr/include/sys/time.h /usr/include/linux/types.h

frame.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

frame.o: /usr/include/asm/types.h /usr/include/linux/time.h

frame.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

frame.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

frame.o: headers/general.h headers/mtypes.h headers/dct.h headers/frames.h

frame.o: headers/mheaders.h headers/bitio.h headers/frame.h headers/fsize.h

fsize.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

fsize.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

fsize.o: /usr/include/stdlib.h /usr/include/features.h

fsize.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

fsize.o: /usr/include/errno.h /usr/include/linux/errno.h

fsize.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

fsize.o: /usr/include/huge_val.h /usr/include/endian.h /usr/include/bytesex.h

fsize.o: /usr/include/nan.h

fsize.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

fsize.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

fsize.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

fsize.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

fsize.o: /usr/include/posix2_lim.h /usr/include/time.h

fsize.o: /usr/include/sys/time.h /usr/include/linux/types.h

fsize.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

fsize.o: /usr/include/asm/types.h /usr/include/linux/time.h

fsize.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

fsize.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

fsize.o: headers/general.h headers/fsize.h headers/dct.h

frametype.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

frametype.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

frametype.o: /usr/include/stdlib.h /usr/include/features.h

frametype.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

frametype.o: /usr/include/errno.h /usr/include/linux/errno.h

frametype.o: /usr/include/asm/errno.h /usr/include/alloca.h

frametype.o: /usr/include/math.h /usr/include/huge_val.h

frametype.o: /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h

frametype.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

frametype.o: /usr/include/values.h /usr/include/ieee754.h

frametype.o: /usr/include/ieee854.h /usr/include/memory.h

frametype.o: /usr/include/string.h /usr/include/limits.h

frametype.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

frametype.o: /usr/include/posix2_lim.h /usr/include/time.h

frametype.o: /usr/include/sys/time.h /usr/include/linux/types.h

frametype.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

frametype.o: /usr/include/asm/types.h /usr/include/linux/time.h

frametype.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

frametype.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

frametype.o: headers/general.h headers/prototypes.h headers/frame.h

frametype.o: headers/mtypes.h headers/dct.h headers/frames.h

frametype.o: headers/mheaders.h headers/bitio.h headers/param.h

libpnmrw.o: /usr/include/stdio.h /usr/include/libio.h

libpnmrw.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

libpnmrw.o: headers/libpnmrw.h /usr/include/malloc.h /usr/include/features.h

libpnmrw.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

libpnmrw.o: /usr/include/string.h

specifics.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

specifics.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

specifics.o: /usr/include/stdlib.h /usr/include/features.h

specifics.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

specifics.o: /usr/include/errno.h /usr/include/linux/errno.h

specifics.o: /usr/include/asm/errno.h /usr/include/alloca.h

specifics.o: /usr/include/math.h /usr/include/huge_val.h

specifics.o: /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h

specifics.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

specifics.o: /usr/include/values.h /usr/include/ieee754.h

specifics.o: /usr/include/ieee854.h /usr/include/memory.h

specifics.o: /usr/include/string.h /usr/include/limits.h

specifics.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

specifics.o: /usr/include/posix2_lim.h /usr/include/time.h

specifics.o: /usr/include/sys/time.h /usr/include/linux/types.h

specifics.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

specifics.o: /usr/include/asm/types.h /usr/include/linux/time.h

specifics.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

specifics.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

specifics.o: headers/general.h headers/mtypes.h headers/dct.h

specifics.o: headers/frames.h headers/mheaders.h headers/bitio.h

specifics.o: headers/frame.h headers/fsize.h headers/specifics.h

specifics.o: headers/prototypes.h

rate.o: /usr/include/sys/times.h /usr/include/features.h

rate.o: /usr/include/sys/cdefs.h /usr/include/sys/types.h

rate.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

rate.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

rate.o: /usr/include/sys/bitypes.h /usr/include/time.h

rate.o: /usr/include/sys/time.h /usr/include/linux/time.h

rate.o: /usr/include/linux/times.h headers/all.h /usr/include/stdio.h

rate.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/stdlib.h

rate.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

rate.o: /usr/include/errno.h /usr/include/linux/errno.h

rate.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

rate.o: /usr/include/huge_val.h /usr/include/endian.h /usr/include/bytesex.h

rate.o: /usr/include/nan.h

rate.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

rate.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

rate.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

rate.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

rate.o: /usr/include/posix2_lim.h headers/libpnmrw.h /usr/include/malloc.h

rate.o: headers/ansi.h headers/general.h headers/mtypes.h headers/dct.h

rate.o: headers/bitio.h headers/frames.h headers/mheaders.h headers/frame.h

rate.o: headers/prototypes.h headers/param.h headers/fsize.h

rate.o: headers/postdct.h headers/mpeg.h headers/parallel.h headers/rate.h

opts.o: /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h

opts.o: /usr/include/sys/cdefs.h /usr/include/string.h

opts.o: /usr/include/features.h

opts.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h headers/opts.h

opts.o: headers/general.h headers/ansi.h headers/mtypes.h headers/dct.h

opts.o: /usr/include/malloc.h /usr/include/math.h /usr/include/huge_val.h

opts.o: /usr/include/endian.h /usr/include/bytesex.h /usr/include/nan.h

opts.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

opts.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

iframe.o: /usr/include/sys/times.h /usr/include/features.h

iframe.o: /usr/include/sys/cdefs.h /usr/include/sys/types.h

iframe.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

iframe.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

iframe.o: /usr/include/sys/bitypes.h /usr/include/time.h

iframe.o: /usr/include/sys/time.h /usr/include/linux/time.h

iframe.o: /usr/include/linux/times.h /usr/include/sys/param.h

iframe.o: /usr/include/limits.h /usr/include/posix1_lim.h

iframe.o: /usr/include/linux/limits.h /usr/include/posix2_lim.h

iframe.o: /usr/include/linux/param.h /usr/include/asm/param.h headers/all.h

iframe.o: /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h

iframe.o: /usr/include/stdlib.h

iframe.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

iframe.o: /usr/include/errno.h /usr/include/linux/errno.h

iframe.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

iframe.o: /usr/include/huge_val.h /usr/include/endian.h

iframe.o: /usr/include/bytesex.h /usr/include/nan.h

iframe.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

iframe.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

iframe.o: /usr/include/memory.h /usr/include/string.h headers/libpnmrw.h

iframe.o: /usr/include/malloc.h headers/ansi.h headers/general.h

iframe.o: headers/mtypes.h headers/dct.h headers/frames.h headers/mheaders.h

iframe.o: headers/bitio.h headers/frame.h headers/prototypes.h headers/mpeg.h

iframe.o: headers/param.h headers/fsize.h headers/parallel.h

iframe.o: headers/postdct.h headers/rate.h headers/opts.h

pframe.o: /usr/include/assert.h /usr/include/features.h

pframe.o: /usr/include/sys/cdefs.h /usr/include/sys/param.h

pframe.o: /usr/include/limits.h /usr/include/posix1_lim.h

pframe.o: /usr/include/linux/limits.h /usr/include/posix2_lim.h

pframe.o: /usr/include/linux/param.h /usr/include/asm/param.h

pframe.o: /usr/include/sys/types.h /usr/include/linux/types.h

pframe.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

pframe.o: /usr/include/asm/types.h /usr/include/sys/bitypes.h headers/all.h

pframe.o: /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h

pframe.o: /usr/include/stdlib.h

pframe.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

pframe.o: /usr/include/errno.h /usr/include/linux/errno.h

pframe.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

pframe.o: /usr/include/huge_val.h /usr/include/endian.h

pframe.o: /usr/include/bytesex.h /usr/include/nan.h

pframe.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

pframe.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

pframe.o: /usr/include/memory.h /usr/include/string.h /usr/include/time.h

pframe.o: /usr/include/sys/time.h /usr/include/linux/time.h

pframe.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

pframe.o: headers/general.h headers/mtypes.h headers/dct.h headers/bitio.h

pframe.o: headers/frames.h headers/mheaders.h headers/frame.h

pframe.o: headers/prototypes.h headers/param.h headers/fsize.h

pframe.o: headers/postdct.h headers/mpeg.h headers/parallel.h headers/rate.h

pframe.o: headers/opts.h

bframe.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

bframe.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

bframe.o: /usr/include/stdlib.h /usr/include/features.h

bframe.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

bframe.o: /usr/include/errno.h /usr/include/linux/errno.h

bframe.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

bframe.o: /usr/include/huge_val.h /usr/include/endian.h

bframe.o: /usr/include/bytesex.h /usr/include/nan.h

bframe.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

bframe.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

bframe.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

bframe.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

bframe.o: /usr/include/posix2_lim.h /usr/include/time.h

bframe.o: /usr/include/sys/time.h /usr/include/linux/types.h

bframe.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

bframe.o: /usr/include/asm/types.h /usr/include/linux/time.h

bframe.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

bframe.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

bframe.o: headers/general.h /usr/include/sys/param.h

bframe.o: /usr/include/linux/param.h /usr/include/asm/param.h

bframe.o: /usr/include/assert.h headers/mtypes.h headers/dct.h

bframe.o: headers/bitio.h headers/frames.h headers/mheaders.h headers/frame.h

bframe.o: headers/prototypes.h headers/fsize.h headers/param.h

bframe.o: headers/postdct.h headers/rate.h headers/opts.h

psearch.o: /usr/include/assert.h /usr/include/features.h

psearch.o: /usr/include/sys/cdefs.h headers/all.h /usr/include/stdio.h

psearch.o: /usr/include/libio.h /usr/include/_G_config.h

psearch.o: /usr/include/stdlib.h

psearch.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

psearch.o: /usr/include/errno.h /usr/include/linux/errno.h

psearch.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

psearch.o: /usr/include/huge_val.h /usr/include/endian.h

psearch.o: /usr/include/bytesex.h /usr/include/nan.h

psearch.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

psearch.o: /usr/include/values.h /usr/include/ieee754.h

psearch.o: /usr/include/ieee854.h /usr/include/memory.h /usr/include/string.h

psearch.o: /usr/include/limits.h /usr/include/posix1_lim.h

psearch.o: /usr/include/linux/limits.h /usr/include/posix2_lim.h

psearch.o: /usr/include/time.h /usr/include/sys/time.h

psearch.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

psearch.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

psearch.o: /usr/include/linux/time.h /usr/include/sys/types.h

psearch.o: /usr/include/sys/bitypes.h headers/libpnmrw.h

psearch.o: /usr/include/malloc.h headers/ansi.h headers/general.h

psearch.o: headers/mtypes.h headers/dct.h headers/frames.h headers/mheaders.h

psearch.o: headers/bitio.h headers/frame.h headers/search.h

psearch.o: headers/prototypes.h headers/fsize.h headers/param.h

bsearch.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

bsearch.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

bsearch.o: /usr/include/stdlib.h /usr/include/features.h

bsearch.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

bsearch.o: /usr/include/errno.h /usr/include/linux/errno.h

bsearch.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

bsearch.o: /usr/include/huge_val.h /usr/include/endian.h

bsearch.o: /usr/include/bytesex.h /usr/include/nan.h

bsearch.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

bsearch.o: /usr/include/values.h /usr/include/ieee754.h

bsearch.o: /usr/include/ieee854.h /usr/include/memory.h /usr/include/string.h

bsearch.o: /usr/include/limits.h /usr/include/posix1_lim.h

bsearch.o: /usr/include/linux/limits.h /usr/include/posix2_lim.h

bsearch.o: /usr/include/time.h /usr/include/sys/time.h

bsearch.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

bsearch.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

bsearch.o: /usr/include/linux/time.h /usr/include/sys/types.h

bsearch.o: /usr/include/sys/bitypes.h headers/libpnmrw.h

bsearch.o: /usr/include/malloc.h headers/ansi.h headers/general.h

bsearch.o: headers/mtypes.h headers/dct.h headers/frames.h headers/mheaders.h

bsearch.o: headers/bitio.h headers/frame.h headers/search.h headers/fsize.h

block.o: headers/all.h /usr/include/stdio.h /usr/include/libio.h

block.o: /usr/include/_G_config.h /usr/include/sys/cdefs.h

block.o: /usr/include/stdlib.h /usr/include/features.h

block.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

block.o: /usr/include/errno.h /usr/include/linux/errno.h

block.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

block.o: /usr/include/huge_val.h /usr/include/endian.h /usr/include/bytesex.h

block.o: /usr/include/nan.h

block.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

block.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

block.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

block.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

block.o: /usr/include/posix2_lim.h /usr/include/time.h

block.o: /usr/include/sys/time.h /usr/include/linux/types.h

block.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

block.o: /usr/include/asm/types.h /usr/include/linux/time.h

block.o: /usr/include/sys/types.h /usr/include/sys/bitypes.h

block.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

block.o: headers/general.h headers/mtypes.h headers/dct.h headers/frames.h

block.o: headers/mheaders.h headers/bitio.h headers/frame.h

block.o: headers/prototypes.h headers/fsize.h headers/opts.h

block.o: headers/postdct.h

parallel.o: /usr/include/sys/types.h /usr/include/linux/types.h

parallel.o: /usr/include/linux/posix_types.h /usr/include/asm/posix_types.h

parallel.o: /usr/include/asm/types.h /usr/include/sys/bitypes.h

parallel.o: /usr/include/sys/socket.h /usr/include/features.h

parallel.o: /usr/include/sys/cdefs.h /usr/include/linux/socket.h

parallel.o: /usr/include/asm/socket.h /usr/include/asm/sockios.h

parallel.o: /usr/include/linux/sockios.h /usr/include/linux/uio.h

parallel.o: /usr/include/sys/times.h /usr/include/time.h

parallel.o: /usr/include/sys/time.h /usr/include/linux/time.h

parallel.o: /usr/include/linux/times.h /usr/include/netinet/in.h

parallel.o: /usr/include/linux/in.h /usr/include/asm/byteorder.h

parallel.o: /usr/include/unistd.h /usr/include/posix_opt.h

parallel.o: /usr/include/gnu/types.h

parallel.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

parallel.o: /usr/include/confname.h /usr/include/netdb.h /usr/include/paths.h

parallel.o: /usr/include/errno.h /usr/include/linux/errno.h

parallel.o: /usr/include/asm/errno.h /usr/include/string.h

parallel.o: /usr/include/signal.h /usr/include/linux/signal.h

parallel.o: /usr/include/asm/signal.h headers/all.h /usr/include/stdio.h

parallel.o: /usr/include/libio.h /usr/include/_G_config.h

parallel.o: /usr/include/stdlib.h /usr/include/alloca.h /usr/include/math.h

parallel.o: /usr/include/huge_val.h /usr/include/endian.h

parallel.o: /usr/include/bytesex.h /usr/include/nan.h

parallel.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

parallel.o: /usr/include/values.h /usr/include/ieee754.h

parallel.o: /usr/include/ieee854.h /usr/include/memory.h

parallel.o: /usr/include/limits.h /usr/include/posix1_lim.h

parallel.o: /usr/include/linux/limits.h /usr/include/posix2_lim.h

parallel.o: headers/libpnmrw.h /usr/include/malloc.h headers/ansi.h

parallel.o: headers/general.h headers/param.h headers/mpeg.h headers/mtypes.h

parallel.o: headers/dct.h headers/frame.h headers/prototypes.h

parallel.o: headers/parallel.h headers/bitio.h headers/readframe.h

parallel.o: headers/fsize.h headers/combine.h headers/frames.h

parallel.o: headers/mheaders.h

jpeg.o: /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h

jpeg.o: /usr/include/sys/cdefs.h headers/all.h /usr/include/stdlib.h

jpeg.o: /usr/include/features.h

jpeg.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

jpeg.o: /usr/include/errno.h /usr/include/linux/errno.h

jpeg.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

jpeg.o: /usr/include/huge_val.h /usr/include/endian.h /usr/include/bytesex.h

jpeg.o: /usr/include/nan.h

jpeg.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

jpeg.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

jpeg.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

jpeg.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

jpeg.o: /usr/include/posix2_lim.h /usr/include/time.h /usr/include/sys/time.h

jpeg.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

jpeg.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

jpeg.o: /usr/include/linux/time.h /usr/include/sys/types.h

jpeg.o: /usr/include/sys/bitypes.h headers/libpnmrw.h /usr/include/malloc.h

jpeg.o: headers/ansi.h headers/general.h headers/mtypes.h headers/dct.h

jpeg.o: headers/frames.h headers/mheaders.h headers/bitio.h headers/frame.h

jpeg.o: headers/prototypes.h headers/param.h headers/readframe.h

jpeg.o: headers/fsize.h headers/rgbtoycc.h headers/jpeg.h jpeg/jpeglib.h

jpeg.o: jpeg/jconfig.h jpeg/jmorecfg.h

main.o: /usr/include/assert.h /usr/include/features.h

main.o: /usr/include/sys/cdefs.h headers/all.h /usr/include/stdio.h

main.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/stdlib.h

main.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/stddef.h

main.o: /usr/include/errno.h /usr/include/linux/errno.h

main.o: /usr/include/asm/errno.h /usr/include/alloca.h /usr/include/math.h

main.o: /usr/include/huge_val.h /usr/include/endian.h /usr/include/bytesex.h

main.o: /usr/include/nan.h

main.o: /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h

main.o: /usr/include/values.h /usr/include/ieee754.h /usr/include/ieee854.h

main.o: /usr/include/memory.h /usr/include/string.h /usr/include/limits.h

main.o: /usr/include/posix1_lim.h /usr/include/linux/limits.h

main.o: /usr/include/posix2_lim.h /usr/include/time.h /usr/include/sys/time.h

main.o: /usr/include/linux/types.h /usr/include/linux/posix_types.h

main.o: /usr/include/asm/posix_types.h /usr/include/asm/types.h

main.o: /usr/include/linux/time.h /usr/include/sys/types.h

main.o: /usr/include/sys/bitypes.h headers/libpnmrw.h /usr/include/malloc.h

main.o: headers/ansi.h headers/general.h headers/mtypes.h headers/dct.h

main.o: headers/mpeg.h headers/frame.h headers/search.h headers/prototypes.h

main.o: headers/param.h headers/parallel.h headers/bitio.h

main.o: headers/readframe.h headers/combine.h headers/frames.h

main.o: headers/mheaders.h headers/jpeg.h headers/specifics.h headers/opts.h