ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/freemol/trunk/src/mpeg_encode/src/combine.c
Revision: 22
Committed: Mon Jul 7 22:16:37 2008 UTC (11 years, 4 months ago) by wdelano
File size: 12935 byte(s)
Log Message:
initial checkin of mpeg_encode source
Line User Rev File contents
1 wdelano 22 /*===========================================================================*
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) 1995 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/project/mpeg/mpeg_dist/mpeg_encode/RCS/combine.c,v 1.9 1995/08/07 21:42:38 smoot Exp $
35     * $Log: combine.c,v $
36     * Revision 1.9 1995/08/07 21:42:38 smoot
37     * Sleeps when files do not exist.
38     * renamed index to idx
39     *
40     * Revision 1.8 1995/06/21 22:20:45 smoot
41     * added a sleep for NFS to complete file writes
42     *
43     * Revision 1.7 1995/06/08 20:23:19 smoot
44     * added "b"'s to fopen so PCs are happy
45     *
46     * Revision 1.6 1995/01/19 23:07:22 eyhung
47     * Changed copyrights
48     *
49     * Revision 1.5 1995/01/16 07:53:55 eyhung
50     * Added realQuiet
51     *
52     * Revision 1.4 1994/11/12 02:11:46 keving
53     * nothing
54     *
55     * Revision 1.3 1994/03/15 00:27:11 keving
56     * nothing
57     *
58     * Revision 1.2 1993/12/22 19:19:01 keving
59     * nothing
60     *
61     * Revision 1.1 1993/07/22 22:23:43 keving
62     * nothing
63     *
64     */
65    
66    
67     /*==============*
68     * HEADER FILES *
69     *==============*/
70    
71     #include "all.h"
72     #include <time.h>
73     #include <errno.h>
74     #include "mtypes.h"
75     #include "frames.h"
76     #include "search.h"
77     #include "mpeg.h"
78     #include "prototypes.h"
79     #include "parallel.h"
80     #include "param.h"
81     #include "readframe.h"
82     #include "mheaders.h"
83     #include "fsize.h"
84     #include "combine.h"
85     #include <unistd.h>
86    
87     /* note, remove() might not have a prototype in the standard header files,
88     * but it really should -- it's not my fault!
89     */
90    
91    
92     static int currentGOP;
93    
94     #define READ_ATTEMPTS 5 /* number of times (seconds) to retry an input file */
95    
96     /*==================*
97     * GLOBAL VARIABLES *
98     *==================*/
99     extern int yuvWidth, yuvHeight;
100     char currentGOPPath[MAXPATHLEN];
101     char currentFramePath[MAXPATHLEN];
102    
103    
104     /*===============================*
105     * INTERNAL PROCEDURE prototypes *
106     *===============================*/
107    
108     static void AppendFile _ANSI_ARGS_((FILE *outputFile, FILE *inputFile));
109    
110    
111     /*=====================*
112     * EXPORTED PROCEDURES *
113     *=====================*/
114    
115     /*===========================================================================*
116     *
117     * GOPStoMPEG
118     *
119     * convert some number of GOP files into a single MPEG sequence file
120     *
121     * RETURNS: nothing
122     *
123     * SIDE EFFECTS: none
124     *
125     *===========================================================================*/
126     void
127     GOPStoMPEG(numGOPS, outputFileName, outputFilePtr)
128     int numGOPS;
129     char *outputFileName;
130     FILE *outputFilePtr;
131     {
132     register int ind;
133     BitBucket *bb;
134     char fileName[1024];
135     char inputFileName[1024];
136     FILE *inputFile;
137     int q;
138    
139     {
140     /* Why is this reset called? */
141     int x=Fsize_x, y=Fsize_y;
142     Fsize_Reset();
143     Fsize_Note(0, yuvWidth, yuvHeight);
144     if (Fsize_x == 0 || Fsize_y == 0) {
145     Fsize_Note(0, x, y);
146     }}
147    
148     bb = Bitio_New(outputFilePtr);
149    
150     Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ aspectRatio,
151     /* pict_rate */ frameRate, /* bit_rate */ -1,
152     /* buf_size */ -1, /*c_param_flag */ 1,
153     /* iq_matrix */ customQtable, /* niq_matrix */ customNIQtable,
154     /* ext_data */ NULL, /* ext_data_size */ 0,
155     /* user_data */ NULL, /* user_data_size */ 0);
156    
157     /* it's byte-padded, so we can dump it now */
158     Bitio_Flush(bb);
159    
160     if ( numGOPS > 0 ) {
161     for ( ind = 0; ind < numGOPS; ind++ ) {
162     GetNthInputFileName(inputFileName, ind);
163     sprintf(fileName, "%s/%s", currentGOPPath, inputFileName);
164    
165     for (q = 0; q < READ_ATTEMPTS; ++q ) {
166     if ( (inputFile = fopen(fileName, "rb")) != NULL ) break;
167     fprintf(stderr, "ERROR: Couldn't read (GOPStoMPEG): %s retry %d\n",
168     fileName, q);
169     fflush(stderr);
170     sleep(1);
171     }
172     if (q == READ_ATTEMPTS) {
173     fprintf(stderr, "Giving up (%d attepmts).\n", READ_ATTEMPTS);
174     exit(1);
175     }
176    
177     if (! realQuiet) {
178     fprintf(stdout, "appending file: %s\n", fileName);
179     }
180    
181     AppendFile(outputFilePtr, inputFile);
182     }
183     } else {
184     ind = 0;
185     while ( TRUE ) {
186     sprintf(fileName, "%s.gop.%d", outputFileName, ind);
187    
188     if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
189     break;
190     }
191    
192     if (! realQuiet) {
193     fprintf(stdout, "appending file: %s\n", fileName);
194     }
195    
196     AppendFile(outputFilePtr, inputFile);
197    
198     ind++;
199     }
200     }
201    
202     bb = Bitio_New(outputFilePtr);
203    
204     /* SEQUENCE END CODE */
205     Mhead_GenSequenceEnder(bb);
206    
207     Bitio_Flush(bb);
208    
209     fclose(outputFilePtr);
210     }
211    
212    
213     /*===========================================================================*
214     *
215     * FramestoMPEG
216     *
217     * convert some number of frame files into a single MPEG sequence file
218     *
219     * if parallel == TRUE, then when appending a file, blocks until that
220     * file is actually ready
221     *
222     * RETURNS: nothing
223     *
224     * SIDE EFFECTS: none
225     *
226     *===========================================================================*/
227     void
228     FramesToMPEG(numFrames, outputFileName, outputFile, parallel)
229     int numFrames;
230     char *outputFileName;
231     FILE *outputFile;
232     boolean parallel;
233     {
234     register int ind;
235     BitBucket *bb;
236     char fileName[1024];
237     char inputFileName[1024];
238     FILE *inputFile;
239     int pastRefNum = -1;
240     int futureRefNum = -1;
241     int q;
242    
243     tc_hrs = 0; tc_min = 0; tc_sec = 0; tc_pict = 0; tc_extra = 0;
244    
245     {
246     /* Why is this reset called? */
247     int x=Fsize_x, y=Fsize_y;
248     Fsize_Reset();
249     Fsize_Note(0, yuvWidth, yuvHeight);
250     if (Fsize_x == 0 || Fsize_y == 0) {
251     Fsize_Note(0, x, y);
252     }}
253     SetBlocksPerSlice();
254    
255     bb = Bitio_New(outputFile);
256     Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ aspectRatio,
257     /* pict_rate */ frameRate, /* bit_rate */ -1,
258     /* buf_size */ -1, /*c_param_flag */ 1,
259     /* iq_matrix */ qtable, /* niq_matrix */ niqtable,
260     /* ext_data */ NULL, /* ext_data_size */ 0,
261     /* user_data */ NULL, /* user_data_size */ 0);
262     /* it's byte-padded, so we can dump it now */
263     Bitio_Flush(bb);
264    
265     /* need to do these in the right order!!! */
266     /* also need to add GOP headers */
267    
268     currentGOP = gopSize;
269     totalFramesSent = 0;
270    
271     if ( numFrames > 0 ) {
272     for ( ind = 0; ind < numFrames; ind++ ) {
273     if ( FRAME_TYPE(ind) == 'b' ) {
274     continue;
275     }
276    
277     pastRefNum = futureRefNum;
278     futureRefNum = ind;
279    
280     if ( (FRAME_TYPE(ind) == 'i') && (currentGOP >= gopSize) ) {
281     int closed;
282    
283     /* first, check to see if closed GOP */
284     if ( totalFramesSent == ind ) {
285     closed = 1;
286     } else {
287     closed = 0;
288     }
289    
290     if (! realQuiet) {
291     fprintf(stdout, "Creating new GOP (closed = %d) after %d frames\n",
292     closed, currentGOP);
293     }
294    
295     /* new GOP */
296     bb = Bitio_New(outputFile);
297     Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0,
298     tc_hrs, tc_min, tc_sec, tc_pict,
299     closed, /* broken_link */ 0,
300     /* ext_data */ NULL, /* ext_data_size */ 0,
301     /* user_data */ NULL, /* user_data_size */ 0);
302     Bitio_Flush(bb);
303     SetGOPStartTime(ind);
304    
305     currentGOP -= gopSize;
306     }
307    
308     if ( parallel ) {
309     WaitForOutputFile(ind);
310     sprintf(fileName, "%s.frame.%d", outputFileName, ind);
311     } else {
312     GetNthInputFileName(inputFileName, ind);
313     sprintf(fileName, "%s/%s", currentFramePath, inputFileName);
314     }
315    
316     for (q = 0; q < READ_ATTEMPTS; ++q ) {
317     if ( (inputFile = fopen(fileName, "rb")) != NULL ) break;
318     fprintf(stderr, "ERROR: Couldn't read 2: %s retry %d\n", fileName, q);
319     fflush(stderr);
320     sleep(1);
321     }
322     if (q == READ_ATTEMPTS) {
323     fprintf(stderr, "Giving up (%d attepmts).\n", READ_ATTEMPTS);
324     exit(1);
325     }
326    
327     AppendFile(outputFile, inputFile);
328     if ( parallel ) {
329     remove(fileName);
330     }
331    
332     currentGOP++;
333     IncrementTCTime();
334    
335     /* now, output the B-frames */
336     if ( pastRefNum != -1 ) {
337     register int bNum;
338    
339     for ( bNum = pastRefNum+1; bNum < futureRefNum; bNum++ ) {
340     if ( parallel ) {
341     WaitForOutputFile(bNum);
342     sprintf(fileName, "%s.frame.%d", outputFileName, bNum);
343     } else {
344     GetNthInputFileName(inputFileName, bNum);
345     sprintf(fileName, "%s/%s", currentFramePath, inputFileName);
346     }
347    
348    
349     for (q = 0; q < READ_ATTEMPTS; ++q ) {
350     if ( (inputFile = fopen(fileName, "rb")) != NULL ) break;
351     fprintf(stderr, "ERROR: Couldn't read (bNum=%d): %s retry %d\n",
352     bNum, fileName, q);
353     fflush(stderr);
354     sleep(1);
355     }
356     if (q == READ_ATTEMPTS) {
357     fprintf(stderr, "Giving up (%d attepmts).\n", READ_ATTEMPTS);
358     exit(1);
359     }
360    
361     AppendFile(outputFile, inputFile);
362     if ( parallel ) {
363     remove(fileName);
364     }
365    
366     currentGOP++;
367     IncrementTCTime();
368     }
369     }
370     }
371     } else {
372     if ( parallel ) {
373     fprintf(stderr, "ERROR: PARALLEL COMBINE WITH 0 FRAMES\n");
374     fprintf(stderr, "(please send bug report!)\n");
375     exit(1);
376     }
377    
378     ind = 0;
379     while ( TRUE ) {
380     if ( FRAME_TYPE(ind) == 'b' ) {
381     ind++;
382     continue;
383     }
384    
385     if ( (FRAME_TYPE(ind) == 'i') && (currentGOP >= gopSize) ) {
386     int closed;
387    
388     /* first, check to see if closed GOP */
389     if ( totalFramesSent == ind ) {
390     closed = 1;
391     } else {
392     closed = 0;
393     }
394    
395     if (! realQuiet) {
396     fprintf(stdout, "Creating new GOP (closed = %d) before frame %d\n",
397     closed, ind);
398     }
399    
400     /* new GOP */
401     bb = Bitio_New(outputFile);
402     Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0,
403     tc_hrs, tc_min, tc_sec, tc_pict,
404     closed, /* broken_link */ 0,
405     /* ext_data */ NULL, /* ext_data_size */ 0,
406     /* user_data */ NULL, /* user_data_size */ 0);
407     Bitio_Flush(bb);
408     SetGOPStartTime(ind);
409    
410     currentGOP -= gopSize;
411     }
412    
413     sprintf(fileName, "%s.frame.%d", outputFileName, ind);
414    
415     if ( (inputFile = fopen(fileName, "rb")) == NULL ) {
416     break;
417     }
418    
419     AppendFile(outputFile, inputFile);
420     if ( parallel ) {
421     remove(fileName);
422     }
423    
424     currentGOP++;
425     IncrementTCTime();
426    
427     /* now, output the B-frames */
428     if ( pastRefNum != -1 ) {
429     register int bNum;
430    
431     for ( bNum = pastRefNum+1; bNum < futureRefNum; bNum++ ) {
432     sprintf(fileName, "%s.frame.%d", outputFileName, bNum);
433    
434     for (q = 0; q < READ_ATTEMPTS; ++q ) {
435     if ( (inputFile = fopen(fileName, "rb")) != NULL ) break;
436     fprintf(stderr, "ERROR: Couldn't read (FramestoMPEG): %s retry %d\n",
437     fileName, q);
438     fflush(stderr);
439     sleep(1);
440     }
441     if (q == READ_ATTEMPTS) {
442     fprintf(stderr, "Giving up (%d attepmts).\n", READ_ATTEMPTS);
443     exit(1);
444     }
445    
446     AppendFile(outputFile, inputFile);
447     if ( parallel ) {
448     remove(fileName);
449     }
450    
451     currentGOP++;
452     IncrementTCTime();
453     }
454     }
455    
456     ind++;
457     }
458     }
459    
460     if (! realQuiet) {
461     fprintf(stdout, "Wrote %d frames\n", totalFramesSent);
462     fflush(stdout);
463     }
464    
465     bb = Bitio_New(outputFile);
466    
467     /* SEQUENCE END CODE */
468     Mhead_GenSequenceEnder(bb);
469    
470     Bitio_Flush(bb);
471    
472     fclose(outputFile);
473     }
474    
475    
476     /*=====================*
477     * INTERNAL PROCEDURES *
478     *=====================*/
479    
480     /*===========================================================================*
481     *
482     * AppendFile
483     *
484     * appends the output file with the contents of the given input file
485     *
486     * RETURNS: nothing
487     *
488     * SIDE EFFECTS: none
489     *
490     *===========================================================================*/
491     static void
492     AppendFile(outputFile, inputFile)
493     FILE *outputFile;
494     FILE *inputFile;
495     {
496     uint8 data[9999];
497     int readItems;
498    
499     readItems = 9999;
500     while ( readItems == 9999 ) {
501     readItems = fread(data, sizeof(uint8), 9999, inputFile);
502     if ( readItems > 0 ) {
503     fwrite(data, sizeof(uint8), readItems, outputFile);
504     }
505     }
506    
507     fclose(inputFile);
508     }