Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

combine.c

Go to the documentation of this file.
00001 /*===========================================================================*
00002  * combine.c                                                                 *
00003  *                                                                           *
00004  *      Procedures to combine frames or GOPS into an MPEG sequence           *
00005  *                                                                           *
00006  * EXPORTED PROCEDURES:                                                      *
00007  *      GOPStoMPEG                                                           *
00008  *      FramesToMPEG                                                         *
00009  *                                                                           *
00010  *===========================================================================*/
00011 
00012 /*
00013  * Copyright (c) 1995 The Regents of the University of California.
00014  * All rights reserved.
00015  *
00016  * Permission to use, copy, modify, and distribute this software and its
00017  * documentation for any purpose, without fee, and without written agreement is
00018  * hereby granted, provided that the above copyright notice and the following
00019  * two paragraphs appear in all copies of this software.
00020  *
00021  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
00022  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00023  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
00024  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025  *
00026  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00027  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00028  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00029  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
00030  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00031  */
00032 
00033 /*  
00034  *  $Header: /misc/elrond0/share/cvs/AFNI/src/mpeg_encodedir/combine.c,v 1.4 2004/04/02 15:12:40 rwcox Exp $
00035  *  $Log: combine.c,v $
00036  *  Revision 1.4  2004/04/02 15:12:40  rwcox
00037  *  Cput
00038  *
00039  *  Revision 1.3  2003/12/23 13:50:08  rwcox
00040  *  Cput
00041  *
00042  *  Revision 1.2  2003/12/03 14:46:14  rwcox
00043  *  Cput
00044  *
00045  *  Revision 1.1  2001/12/17 16:11:53  rwcox
00046  *  Cadd
00047  *
00048  *  Revision 1.9  1995/08/07 21:42:38  smoot
00049  *  Sleeps when files do not exist.
00050  *  renamed index to idx
00051  *
00052  *  Revision 1.8  1995/06/21 22:20:45  smoot
00053  *  added a sleep for NFS to complete file writes
00054  *
00055  * Revision 1.7  1995/06/08  20:23:19  smoot
00056  * added "b"'s to fopen so PCs are happy
00057  *
00058  * Revision 1.6  1995/01/19  23:07:22  eyhung
00059  * Changed copyrights
00060  *
00061  * Revision 1.5  1995/01/16  07:53:55  eyhung
00062  * Added realQuiet
00063  *
00064  * Revision 1.4  1994/11/12  02:11:46  keving
00065  * nothing
00066  *
00067  * Revision 1.3  1994/03/15  00:27:11  keving
00068  * nothing
00069  *
00070  * Revision 1.2  1993/12/22  19:19:01  keving
00071  * nothing
00072  *
00073  * Revision 1.1  1993/07/22  22:23:43  keving
00074  * nothing
00075  *
00076  */
00077 
00078 
00079 /*==============*
00080  * HEADER FILES *
00081  *==============*/
00082 
00083 #include "all.h"
00084 #include <time.h>
00085 #include <errno.h>
00086 #include "mtypes.h"
00087 #include "frames.h"
00088 #include "search.h"
00089 #include "mpeg.h"
00090 #include "prototypes.h"
00091 #include "parallel.h"
00092 #include "param.h"
00093 #include "readframe.h"
00094 #include "mheaders.h"
00095 #include "fsize.h"
00096 #include "combine.h"
00097 #include <unistd.h>
00098 
00099 /* note, remove() might not have a prototype in the standard header files,
00100  * but it really should -- it's not my fault!
00101  */
00102 
00103 
00104 static int      currentGOP;
00105 
00106 #define READ_ATTEMPTS 5 /* number of times (seconds) to retry an input file */
00107 
00108 /*==================*
00109  * GLOBAL VARIABLES *
00110  *==================*/
00111 extern int  yuvWidth, yuvHeight;
00112 char    currentGOPPath[MAXPATHLEN];
00113 char    currentFramePath[MAXPATHLEN];
00114 
00115 
00116 /*===============================*
00117  * INTERNAL PROCEDURE prototypes *
00118  *===============================*/
00119 
00120 static void     AppendFile _ANSI_ARGS_((FILE *outputFile, FILE *inputFile));
00121 
00122 
00123 /*=====================*
00124  * EXPORTED PROCEDURES *
00125  *=====================*/
00126 
00127 /*===========================================================================*
00128  *
00129  * GOPStoMPEG
00130  *
00131  *      convert some number of GOP files into a single MPEG sequence file
00132  *
00133  * RETURNS:     nothing
00134  *
00135  * SIDE EFFECTS:    none
00136  *
00137  *===========================================================================*/
00138 void
00139 GOPStoMPEG(numGOPS, outputFileName, outputFilePtr)
00140     int numGOPS;
00141     char *outputFileName;
00142     FILE *outputFilePtr;
00143 {
00144     register int ind;
00145     BitBucket *bb;
00146     char    fileName[1024];
00147     char    inputFileName[1024];
00148     FILE *inputFile;
00149     int q;
00150 
00151     {
00152       /* Why is this reset called? */
00153       int x=Fsize_x, y=Fsize_y;
00154       Fsize_Reset();
00155       Fsize_Note(0, yuvWidth, yuvHeight);
00156       if (Fsize_x == 0 || Fsize_y == 0) {
00157         Fsize_Note(0, x, y);
00158       }}
00159     
00160     bb = Bitio_New(outputFilePtr);
00161 
00162     Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ aspectRatio,
00163                /* pict_rate */ frameRate, /* bit_rate */ -1,
00164                /* buf_size */ -1, /*c_param_flag */ 1,
00165                /* iq_matrix */ customQtable, /* niq_matrix */ customNIQtable,
00166                /* ext_data */ NULL, /* ext_data_size */ 0,
00167                /* user_data */ NULL, /* user_data_size */ 0);
00168 
00169     /* it's byte-padded, so we can dump it now */
00170     Bitio_Flush(bb);
00171 
00172     if ( numGOPS > 0 ) {
00173         for ( ind = 0; ind < numGOPS; ind++ ) {
00174             GetNthInputFileName(inputFileName, ind);
00175             sprintf(fileName, "%s/%s", currentGOPPath, inputFileName);
00176 
00177             for (q = 0;   q < READ_ATTEMPTS;  ++q ) {
00178               if ( (inputFile = fopen(fileName, "rb")) != NULL ) break;
00179               fprintf(stderr, "ERROR:  Couldn't read (GOPStoMPEG):  %s retry %d\n", 
00180                       fileName, q);
00181               fflush(stderr);
00182               sleep(1);
00183             }
00184             if (q == READ_ATTEMPTS) {
00185               fprintf(stderr, "Giving up (%d attepmts).\n", READ_ATTEMPTS);
00186               exit(1);
00187             }
00188             
00189             if (! realQuiet) {
00190                 fprintf(stdout, "appending file:  %s\n", fileName);
00191             }
00192 
00193             AppendFile(outputFilePtr, inputFile);
00194         }
00195     } else {
00196         ind = 0;
00197         while ( TRUE ) {
00198             sprintf(fileName, "%s.gop.%d", outputFileName, ind);
00199 
00200             if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
00201                 break;
00202             }
00203 
00204             if (! realQuiet) {
00205                 fprintf(stdout, "appending file:  %s\n", fileName);
00206             }
00207 
00208             AppendFile(outputFilePtr, inputFile);
00209 
00210             ind++;
00211         }
00212     }
00213 
00214     bb = Bitio_New(outputFilePtr);
00215 
00216     /* SEQUENCE END CODE */
00217     Mhead_GenSequenceEnder(bb);
00218 
00219     Bitio_Flush(bb);
00220 
00221     fclose(outputFilePtr);
00222 }
00223 
00224 
00225 /*===========================================================================*
00226  *
00227  * FramestoMPEG
00228  *
00229  *      convert some number of frame files into a single MPEG sequence file
00230  *
00231  *      if parallel == TRUE, then when appending a file, blocks until that
00232  *      file is actually ready
00233  *
00234  * RETURNS:     nothing
00235  *
00236  * SIDE EFFECTS:    none
00237  *
00238  *===========================================================================*/
00239 void
00240 FramesToMPEG(numFrames, outputFileName, outputFile, parallel)
00241     int numFrames;
00242     char *outputFileName;
00243     FILE *outputFile;
00244     boolean parallel;
00245 {
00246     register int ind;
00247     BitBucket *bb;
00248     char    fileName[1024];
00249     char    inputFileName[1024];
00250     FILE *inputFile;
00251     int pastRefNum = -1;
00252     int futureRefNum = -1;
00253     int q;
00254 
00255     tc_hrs = 0; tc_min = 0; tc_sec = 0; tc_pict = 0; tc_extra = 0;
00256 
00257     {
00258       /* Why is this reset called? */
00259       int x=Fsize_x, y=Fsize_y;
00260       Fsize_Reset();
00261       Fsize_Note(0, yuvWidth, yuvHeight);
00262       if (Fsize_x == 0 || Fsize_y == 0) {
00263         Fsize_Note(0, x, y);
00264       }}
00265     SetBlocksPerSlice();
00266 
00267     bb = Bitio_New(outputFile);
00268     Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ aspectRatio,
00269                /* pict_rate */ frameRate, /* bit_rate */ -1,
00270                /* buf_size */ -1, /*c_param_flag */ 1,
00271                /* iq_matrix */ qtable, /* niq_matrix */ niqtable,
00272                /* ext_data */ NULL, /* ext_data_size */ 0,
00273                /* user_data */ NULL, /* user_data_size */ 0);
00274     /* it's byte-padded, so we can dump it now */
00275     Bitio_Flush(bb);
00276 
00277     /* need to do these in the right order!!! */
00278     /* also need to add GOP headers */
00279 
00280     currentGOP = gopSize;
00281     totalFramesSent = 0;
00282 
00283     if ( numFrames > 0 ) {
00284         for ( ind = 0; ind < numFrames; ind++ ) {
00285             if ( FRAME_TYPE(ind) == 'b' ) {
00286                 continue;
00287             }
00288 
00289             pastRefNum = futureRefNum;
00290             futureRefNum = ind;
00291 
00292             if ( (FRAME_TYPE(ind) == 'i') && (currentGOP >= gopSize) ) {
00293                 int closed;
00294 
00295                 /* first, check to see if closed GOP */
00296                 if ( totalFramesSent == ind ) {
00297                     closed = 1;
00298                 } else {
00299                     closed = 0;
00300                 }
00301 
00302                 if (! realQuiet) {
00303                         fprintf(stdout, "Creating new GOP (closed = %d) after %d frames\n",
00304                                 closed, currentGOP);
00305                 }
00306 
00307                 /* new GOP */
00308                 bb = Bitio_New(outputFile);
00309                 Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0,
00310                            tc_hrs, tc_min, tc_sec, tc_pict,
00311                            closed, /* broken_link */ 0,
00312                            /* ext_data */ NULL, /* ext_data_size */ 0,
00313                            /* user_data */ NULL, /* user_data_size */ 0);
00314                 Bitio_Flush(bb);
00315                 SetGOPStartTime(ind);
00316                 
00317                 currentGOP -= gopSize;
00318             }
00319 
00320             if ( parallel ) {
00321                 WaitForOutputFile(ind);
00322                 sprintf(fileName, "%s.frame.%d", outputFileName, ind);
00323             } else {
00324                 GetNthInputFileName(inputFileName, ind);
00325                 sprintf(fileName, "%s/%s", currentFramePath, inputFileName);
00326             }
00327 
00328             for (q = 0;   q < READ_ATTEMPTS;  ++q ) {
00329               if ( (inputFile = fopen(fileName, "rb")) != NULL ) break;
00330               fprintf(stderr, "ERROR:  Couldn't read 2:  %s retry %d\n", fileName, q);
00331               fflush(stderr);
00332               sleep(1);
00333             }
00334             if (q == READ_ATTEMPTS) {
00335               fprintf(stderr, "Giving up (%d attepmts).\n", READ_ATTEMPTS);
00336               exit(1);
00337             }
00338             
00339             AppendFile(outputFile, inputFile);
00340             if ( parallel ) {
00341                 remove(fileName);
00342             }
00343 
00344             currentGOP++;
00345             IncrementTCTime();
00346 
00347             /* now, output the B-frames */
00348             if ( pastRefNum != -1 ) {
00349                 register int bNum;
00350 
00351                 for ( bNum = pastRefNum+1; bNum < futureRefNum; bNum++ ) {
00352                     if ( parallel ) {
00353                         WaitForOutputFile(bNum);
00354                         sprintf(fileName, "%s.frame.%d", outputFileName, bNum);
00355                     } else {
00356                         GetNthInputFileName(inputFileName, bNum);
00357                         sprintf(fileName, "%s/%s", currentFramePath, inputFileName);
00358                     }
00359 
00360 
00361                     for (q = 0;   q < READ_ATTEMPTS;  ++q ) {
00362                       if ( (inputFile = fopen(fileName, "rb")) != NULL ) break;
00363                       fprintf(stderr, "ERROR:  Couldn't read (bNum=%d):  %s retry %d\n", 
00364                               bNum, fileName, q);
00365                       fflush(stderr);
00366                       sleep(1);
00367                     }
00368                     if (q == READ_ATTEMPTS) {
00369                       fprintf(stderr, "Giving up (%d attepmts).\n", READ_ATTEMPTS);
00370                       exit(1);
00371                     }
00372                     
00373                     AppendFile(outputFile, inputFile);
00374                     if ( parallel ) {
00375                         remove(fileName);
00376                     }
00377                         
00378                     currentGOP++;
00379                     IncrementTCTime();
00380                 }
00381             }
00382         }
00383     } else {
00384         if ( parallel ) {
00385             fprintf(stderr, "ERROR:  PARALLEL COMBINE WITH 0 FRAMES\n");
00386             fprintf(stderr, "(please send bug report!)\n");
00387             exit(1);
00388         }
00389 
00390         ind = 0;
00391         while ( TRUE ) {
00392             if ( FRAME_TYPE(ind) == 'b' ) {
00393                 ind++;
00394                 continue;
00395             }
00396 
00397             if ( (FRAME_TYPE(ind) == 'i') && (currentGOP >= gopSize) ) {
00398                 int closed;
00399 
00400                 /* first, check to see if closed GOP */
00401                 if ( totalFramesSent == ind ) {
00402                     closed = 1;
00403                 } else {
00404                     closed = 0;
00405                 }
00406 
00407                 if (! realQuiet) {
00408                 fprintf(stdout, "Creating new GOP (closed = %d) before frame %d\n",
00409                         closed, ind);
00410                 }
00411 
00412                 /* new GOP */
00413                 bb = Bitio_New(outputFile);
00414                 Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0,
00415                            tc_hrs, tc_min, tc_sec, tc_pict,
00416                            closed, /* broken_link */ 0,
00417                            /* ext_data */ NULL, /* ext_data_size */ 0,
00418                            /* user_data */ NULL, /* user_data_size */ 0);
00419                 Bitio_Flush(bb);
00420                 SetGOPStartTime(ind);
00421 
00422                 currentGOP -= gopSize;
00423             }
00424 
00425             sprintf(fileName, "%s.frame.%d", outputFileName, ind);
00426 
00427             if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
00428                 break;
00429             }
00430 
00431             AppendFile(outputFile, inputFile);
00432             if ( parallel ) {
00433                 remove(fileName);
00434             }
00435 
00436             currentGOP++;
00437             IncrementTCTime();
00438 
00439             /* now, output the B-frames */
00440             if ( pastRefNum != -1 ) {
00441                 register int bNum;
00442 
00443                 for ( bNum = pastRefNum+1; bNum < futureRefNum; bNum++ ) {
00444                     sprintf(fileName, "%s.frame.%d", outputFileName, bNum);
00445 
00446                     for (q = 0;   q < READ_ATTEMPTS;  ++q ) {
00447                       if ( (inputFile = fopen(fileName, "rb")) != NULL ) break;
00448                       fprintf(stderr, "ERROR:  Couldn't read (FramestoMPEG):  %s retry %d\n", 
00449                               fileName, q);
00450                       fflush(stderr);
00451                       sleep(1);
00452                     }
00453                     if (q == READ_ATTEMPTS) {
00454                       fprintf(stderr, "Giving up (%d attepmts).\n", READ_ATTEMPTS);
00455                       exit(1);
00456                     }
00457 
00458                     AppendFile(outputFile, inputFile);
00459                     if ( parallel ) {
00460                         remove(fileName);
00461                     }
00462 
00463                     currentGOP++;
00464                     IncrementTCTime();
00465                 }
00466             }
00467 
00468             ind++;
00469         }
00470     }
00471 
00472     if (! realQuiet) {
00473         fprintf(stdout, "Wrote %d frames\n", totalFramesSent);
00474         fflush(stdout);
00475     }
00476 
00477     bb = Bitio_New(outputFile);
00478 
00479     /* SEQUENCE END CODE */
00480     Mhead_GenSequenceEnder(bb);
00481 
00482     Bitio_Flush(bb);
00483 
00484     fclose(outputFile);
00485 }
00486 
00487 
00488 /*=====================*
00489  * INTERNAL PROCEDURES *
00490  *=====================*/
00491 
00492 /*===========================================================================*
00493  *
00494  * AppendFile
00495  *
00496  *      appends the output file with the contents of the given input file
00497  *
00498  * RETURNS:     nothing
00499  *
00500  * SIDE EFFECTS:    none
00501  *
00502  *===========================================================================*/
00503 static void
00504 AppendFile(outputFile, inputFile)
00505     FILE *outputFile;
00506     FILE *inputFile;
00507 {
00508     uint8   data[9999];
00509     int     readItems;
00510 
00511     readItems = 9999;
00512     while ( readItems == 9999 ) {
00513         readItems = fread(data, sizeof(uint8), 9999, inputFile);
00514         if ( readItems > 0 ) {
00515             fwrite(data, sizeof(uint8), readItems, outputFile);
00516         }
00517     }
00518 
00519     fclose(inputFile);
00520 }
00521 
00522 
 

Powered by Plone

This site conforms to the following standards: