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, 3 months ago) by wdelano
File size: 12935 byte(s)
Log Message:
initial checkin of mpeg_encode source
Line File contents
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) 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 }