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