home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / os2 / mpegenc / src / combine.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-01  |  11.9 KB  |  469 lines

  1. /*===========================================================================*
  2.  * combine.c                                     *
  3.  *                                         *
  4.  *    Procedures to combine frames or GOPS into an MPEG sequence         *
  5.  *                                         *
  6.  * EXPORTED PROCEDURES:                                 *
  7.  *    GOPStoMPEG                                 *
  8.  *    FramesToMPEG                                 *
  9.  *                                         *
  10.  *===========================================================================*/
  11.  
  12. /*
  13.  * Copyright (c) 1993 The Regents of the University of California.
  14.  * All rights reserved.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software and its
  17.  * documentation for any purpose, without fee, and without written agreement is
  18.  * hereby granted, provided that the above copyright notice and the following
  19.  * two paragraphs appear in all copies of this software.
  20.  *
  21.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  22.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  23.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  24.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  *
  26.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  27.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  28.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  29.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  30.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  31.  */
  32.  
  33. /*  
  34.  *  $Header: /n/picasso/users/keving/encode/src/RCS/combine.c,v 1.1 1993/07/22 22:23:43 keving Exp keving $
  35.  *  $Log: combine.c,v $
  36.  * Revision 1.1  1993/07/22  22:23:43  keving
  37.  * nothing
  38.  *
  39.  */
  40.  
  41.  
  42. /*==============*
  43.  * HEADER FILES *
  44.  *==============*/
  45.  
  46. #include "all.h"
  47. #include <time.h>
  48. #include <errno.h>
  49. #include "mtypes.h"
  50. #include "frames.h"
  51. #include "search.h"
  52. #include "mpeg.h"
  53. #ifdef OS2
  54. /* @@@ FAT 8.3 convention */
  55. #include "prototyp.h"
  56. #else
  57. #include "prototypes.h"
  58. #endif
  59. #include "parallel.h"
  60. #include "param.h"
  61. #ifdef OS2
  62. /* @@@ FAT 8.3 convention */
  63. #include "readfram.h"
  64. #else
  65. #include "readframe.h"
  66. #endif
  67. #include "mheaders.h"
  68. #include "fsize.h"
  69. #include "combine.h"
  70.  
  71.  
  72. static int    currentGOP;
  73.  
  74.  
  75. /*==================*
  76.  * GLOBAL VARIABLES *
  77.  *==================*/
  78. extern int  yuvWidth, yuvHeight;
  79. char    currentGOPPath[MAXPATHLEN];
  80. char    currentFramePath[MAXPATHLEN];
  81.  
  82.  
  83. /*===============================*
  84.  * INTERNAL PROCEDURE prototypes *
  85.  *===============================*/
  86.  
  87. static void    AppendFile _ANSI_ARGS_((FILE *outputFile, FILE *inputFile));
  88.  
  89.  
  90. /*=====================*
  91.  * EXPORTED PROCEDURES *
  92.  *=====================*/
  93.  
  94. /*===========================================================================*
  95.  *
  96.  * GOPStoMPEG
  97.  *
  98.  *    convert some number of GOP files into a single MPEG sequence file
  99.  *
  100.  * RETURNS:    nothing
  101.  *
  102.  * SIDE EFFECTS:    none
  103.  *
  104.  *===========================================================================*/
  105. void
  106. GOPStoMPEG(numGOPS, outputFileName, outputFilePtr)
  107.     int numGOPS;
  108.     char *outputFileName;
  109.     FILE *outputFilePtr;
  110. {
  111.     register int index;
  112.     BitBucket *bb;
  113.     char    fileName[1024];
  114.     char    inputFileName[1024];
  115.     FILE *inputFile;
  116.  
  117.     Fsize_Reset();
  118.     Fsize_Note(0, yuvWidth, yuvHeight);
  119.     SetBlocksPerSlice();
  120.     
  121.     bb = Bitio_New(outputFilePtr);
  122.  
  123.     Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ 1,
  124.            /* pict_rate */ -1, /* bit_rate */ -1,
  125.            /* buf_size */ -1, /*c_param_flag */ 1,
  126.            /* iq_matrix */ NULL, /* niq_matrix */ NULL,
  127.            /* ext_data */ NULL, /* ext_data_size */ 0,
  128.            /* user_data */ NULL, /* user_data_size */ 0);
  129.  
  130.     /* it's byte-padded, so we can dump it now */
  131.     Bitio_Flush(bb);
  132.  
  133.     if ( numGOPS > 0 ) {
  134.     for ( index = 0; index < numGOPS; index++ ) {
  135.         GetNthInputFileName(inputFileName, index);
  136.         sprintf(fileName, "%s/%s", currentGOPPath, inputFileName);
  137.  
  138. /* @@@ Open binary mode for OS/2, Andy Key */
  139. #ifdef OS2
  140.         if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
  141. #else
  142.         if ( (inputFile = fopen(fileName, "r")) == NULL ) {
  143. #endif
  144.         fprintf(stderr, "ERROR:  Couldn't read:  %s\n", fileName);
  145.         fflush(stderr);
  146.         exit(1);
  147.         }
  148.     
  149.         fprintf(stdout, "appending file:  %s\n", fileName);
  150.  
  151.         AppendFile(outputFilePtr, inputFile);
  152.     }
  153.     } else {
  154.     index = 0;
  155.     while ( TRUE ) {
  156.         sprintf(fileName, "%s.gop.%d", outputFileName, index);
  157.  
  158. /* @@@ Open binary mode for OS/2, Andy Key */
  159. #ifdef OS2
  160.         if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
  161. #else
  162.         if ( (inputFile = fopen(fileName, "r")) == NULL ) {
  163. #endif
  164.         break;
  165.         }
  166.  
  167.         fprintf(stdout, "appending file:  %s\n", fileName);
  168.  
  169.         AppendFile(outputFilePtr, inputFile);
  170.  
  171.         index++;
  172.     }
  173.     }
  174.  
  175.     bb = Bitio_New(outputFilePtr);
  176.  
  177.     /* SEQUENCE END CODE */
  178.     Mhead_GenSequenceEnder(bb);
  179.  
  180.     Bitio_Flush(bb);
  181.  
  182.     fclose(outputFilePtr);
  183. }
  184.  
  185.  
  186. /*===========================================================================*
  187.  *
  188.  * FramestoMPEG
  189.  *
  190.  *    convert some number of frame files into a single MPEG sequence file
  191.  *
  192.  *    if parallel == TRUE, then when appending a file, blocks until that
  193.  *    file is actually ready
  194.  *
  195.  * RETURNS:    nothing
  196.  *
  197.  * SIDE EFFECTS:    none
  198.  *
  199.  *===========================================================================*/
  200. void
  201. FramesToMPEG(numFrames, outputFileName, outputFile, parallel)
  202.     int numFrames;
  203.     char *outputFileName;
  204.     FILE *outputFile;
  205.     boolean parallel;
  206. {
  207.     register int index;
  208.     BitBucket *bb;
  209.     char    fileName[1024];
  210.     char    inputFileName[1024];
  211.     FILE *inputFile;
  212.     FrameTable *entry, *ptr;
  213.  
  214.     tc_hrs = 0;    tc_min = 0; tc_sec = 0; tc_pict = 0;
  215.  
  216.     Fsize_Reset();
  217.     Fsize_Note(0, yuvWidth, yuvHeight);
  218.     SetBlocksPerSlice();
  219.  
  220.     bb = Bitio_New(outputFile);
  221.     Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ 1,
  222.            /* pict_rate */ -1, /* bit_rate */ -1,
  223.            /* buf_size */ -1, /*c_param_flag */ 1,
  224.            /* iq_matrix */ NULL, /* niq_matrix */ NULL,
  225.            /* ext_data */ NULL, /* ext_data_size */ 0,
  226.            /* user_data */ NULL, /* user_data_size */ 0);
  227.     /* it's byte-padded, so we can dump it now */
  228.     Bitio_Flush(bb);
  229.  
  230.     /* need to do these in the right order!!! */
  231.     /* also need to add GOP headers */
  232.  
  233.     currentGOP = gopSize;
  234.     totalFramesSent = 0;
  235.  
  236.     if ( numFrames > 0 ) {
  237.     for ( index = 0; index < numFrames; index++ ) {
  238.         if ( FRAME_TYPE(index) == 'b' ) {
  239.         continue;
  240.         }
  241.  
  242.         if ( (FRAME_TYPE(index) == 'i') && (currentGOP >= gopSize) ) {
  243.         int closed;
  244.  
  245.         /* first, check to see if closed GOP */
  246.         if ( totalFramesSent == index ) {
  247.             closed = 1;
  248.         } else {
  249.             closed = 0;
  250.         }
  251.  
  252.         fprintf(stdout, "Creating new GOP (closed = %d) after %d frames\n",
  253.             closed, currentGOP);
  254.  
  255.         /* new GOP */
  256.         bb = Bitio_New(outputFile);
  257.         Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0,
  258.                tc_hrs, tc_min, tc_sec, tc_pict,
  259.                closed, /* broken_link */ 0,
  260.                /* ext_data */ NULL, /* ext_data_size */ 0,
  261.                /* user_data */ NULL, /* user_data_size */ 0);
  262.         Bitio_Flush(bb);
  263.         SetGOPStartTime(index);
  264.         
  265.         currentGOP -= gopSize;
  266.         }
  267.  
  268.         if ( parallel ) {
  269.         WaitForOutputFile(index);
  270.         sprintf(fileName, "%s.frame.%d", outputFileName, index);
  271.         } else {
  272.         GetNthInputFileName(inputFileName, index);
  273.         sprintf(fileName, "%s/%s", currentFramePath, inputFileName);
  274.         }
  275.  
  276. /* @@@ Open binary mode for OS/2, Andy Key */
  277. #ifdef OS2
  278.         if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
  279. #else
  280.         if ( (inputFile = fopen(fileName, "r")) == NULL ) {
  281. #endif
  282.         fprintf(stderr, "ERROR:  Couldn't read:  %s\n", fileName);
  283.         fflush(stderr);
  284.         exit(1);
  285.         }
  286.  
  287.         AppendFile(outputFile, inputFile);
  288.  
  289.         currentGOP++;
  290.         IncrementTCTime();
  291.  
  292.         if ( (index != 0) && ((index % framePatternLen) == 0) ) {
  293.         entry = &(frameTable[framePatternLen]);
  294.         } else {
  295.         entry = &(frameTable[index % framePatternLen]);
  296.         }
  297.  
  298.         /* now, follow nextOutput and output B-frames */
  299.         ptr = entry->nextOutput;
  300.         while ( ptr != NULL ) {
  301.         if ( parallel ) {
  302.             WaitForOutputFile(index - (entry->number - ptr->number));
  303.             sprintf(fileName, "%s.frame.%d", outputFileName,
  304.                 index - (entry->number - ptr->number));
  305.         } else {
  306.             GetNthInputFileName(inputFileName,
  307.                     index - (entry->number - ptr->number));
  308.             sprintf(fileName, "%s/%s", currentFramePath, inputFileName);
  309.         }
  310.  
  311. /* @@@ Open binary mode for OS/2, Andy Key */
  312. #ifdef OS2
  313.         if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
  314. #else
  315.         if ( (inputFile = fopen(fileName, "r")) == NULL ) {
  316. #endif
  317.             fprintf(stderr, "ERROR:  Couldn't read:  %s\n", fileName);
  318.             exit(1);
  319.         }
  320.  
  321.         AppendFile(outputFile, inputFile);
  322.             
  323.         currentGOP++;
  324.         IncrementTCTime();
  325.  
  326.         ptr = ptr->nextOutput;
  327.         }
  328.     }
  329.     } else {
  330.     if ( parallel ) {
  331.         fprintf(stderr, "ERROR:  PARALLEL COMBINE WITH 0 FRAMES\n");
  332.         fprintf(stderr, "(please send bug report!)\n");
  333.         exit(1);
  334.     }
  335.  
  336.     index = 0;
  337.     while ( TRUE ) {
  338.         if ( FRAME_TYPE(index) == 'b' ) {
  339.         index++;
  340.         continue;
  341.         }
  342.  
  343.         if ( (FRAME_TYPE(index) == 'i') && (currentGOP >= gopSize) ) {
  344.         int closed;
  345.  
  346.         /* first, check to see if closed GOP */
  347.         if ( totalFramesSent == index ) {
  348.             closed = 1;
  349.         } else {
  350.             closed = 0;
  351.         }
  352.  
  353.         fprintf(stdout, "Creating new GOP (closed = %d) before frame %d\n",
  354.             closed, index);
  355.  
  356.         /* new GOP */
  357.         bb = Bitio_New(outputFile);
  358.         Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0,
  359.                tc_hrs, tc_min, tc_sec, tc_pict,
  360.                closed, /* broken_link */ 0,
  361.                /* ext_data */ NULL, /* ext_data_size */ 0,
  362.                /* user_data */ NULL, /* user_data_size */ 0);
  363.         Bitio_Flush(bb);
  364.         SetGOPStartTime(index);
  365.  
  366.         currentGOP -= gopSize;
  367.         }
  368.  
  369.         sprintf(fileName, "%s.frame.%d", outputFileName, index);
  370.  
  371. /* @@@ Open binary mode for OS/2, Andy Key */
  372. #ifdef OS2
  373.         if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
  374. #else
  375.         if ( (inputFile = fopen(fileName, "r")) == NULL ) {
  376. #endif
  377.         break;
  378.         }
  379.  
  380.         AppendFile(outputFile, inputFile);
  381.  
  382.         currentGOP++;
  383.         IncrementTCTime();
  384.  
  385.         if ( (index != 0) && ((index % framePatternLen) == 0) ) {
  386.         entry = &(frameTable[framePatternLen]);
  387.         } else {
  388.         entry = &(frameTable[index % framePatternLen]);
  389.         }
  390.  
  391.         /* now, follow nextOutput and output B-frames */
  392.         ptr = entry->nextOutput;
  393.         while ( ptr != NULL ) {
  394.         sprintf(fileName, "%s.frame.%d", outputFileName,
  395.             index - (entry->number - ptr->number));
  396.  
  397. /* @@@ Open binary mode for OS/2, Andy Key */
  398. #ifdef OS2
  399.         if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
  400. #else
  401.         if ( (inputFile = fopen(fileName, "r")) == NULL ) {
  402. #endif
  403.             fprintf(stderr, "ERROR:  Couldn't read:  %s\n", fileName);
  404.             fflush(stderr);
  405.             exit(1);
  406.         }
  407.  
  408.         AppendFile(outputFile, inputFile);
  409.             
  410.         currentGOP++;
  411.         IncrementTCTime();
  412.  
  413.         ptr = ptr->nextOutput;
  414.         }
  415.  
  416.         index++;
  417.     }
  418.     }
  419.  
  420.     fprintf(stdout, "Wrote %d frames\n", totalFramesSent);
  421.     fflush(stdout);
  422.  
  423.     bb = Bitio_New(outputFile);
  424.  
  425.     /* SEQUENCE END CODE */
  426.     Mhead_GenSequenceEnder(bb);
  427.  
  428.     Bitio_Flush(bb);
  429.  
  430.     fclose(outputFile);
  431. }
  432.  
  433.  
  434. /*=====================*
  435.  * INTERNAL PROCEDURES *
  436.  *=====================*/
  437.  
  438. /*===========================================================================*
  439.  *
  440.  * AppendFile
  441.  *
  442.  *    appends the output file with the contents of the given input file
  443.  *
  444.  * RETURNS:    nothing
  445.  *
  446.  * SIDE EFFECTS:    none
  447.  *
  448.  *===========================================================================*/
  449. static void
  450. AppendFile(outputFile, inputFile)
  451.     FILE *outputFile;
  452.     FILE *inputFile;
  453. {
  454.     uint8   *data[9999];
  455.     int        readItems;
  456.  
  457.     readItems = 9999;
  458.     while ( readItems == 9999 ) {
  459.     readItems = fread(data, sizeof(uint8), 9999, inputFile);
  460.     if ( readItems > 0 ) {
  461.         fwrite(data, sizeof(uint8), readItems, outputFile);
  462.     }
  463.     }
  464.  
  465.     fclose(inputFile);
  466. }
  467.  
  468.  
  469.