r585: Fixed faad detection for latest version of faad
[cinelerra_cv/mob.git] / libmpeg3 / mpeg3toc.c
blob47e312da27a2a6f671760d7cfaf0e129715216b9
1 #include "libmpeg3.h"
2 #include "mpeg3protos.h"
4 #include <stdint.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <sys/stat.h>
12 * Generate table of frame and sample offsets for editing.
16 #define INIT_VECTORS(data, size, allocation, tracks) \
17 { \
18 int k; \
19 data = calloc(1, sizeof(int64_t*) * tracks); \
20 size = calloc(1, sizeof(int*) * tracks); \
21 allocation = calloc(1, sizeof(int*) * tracks); \
23 for(k = 0; k < tracks; k++) \
24 { \
25 allocation[k] = 0x100; \
26 data[k] = calloc(1, sizeof(int64_t) * allocation[k]); \
27 } \
30 #if 1
31 #define APPEND_VECTOR(data, size, allocation, track, value) \
32 { \
33 uint64_t **track_data = &(data)[(track)]; \
34 int *track_allocation = &(allocation)[(track)]; \
35 int *track_size = &(size)[(track)]; \
37 if(!(*track_data) || (*track_allocation) <= (*track_size)) \
38 { \
39 int64_t *new_data = calloc(1, sizeof(int64_t) * (*track_allocation) * 2); \
41 if((*track_data)) \
42 { \
43 memcpy(new_data, (*track_data), sizeof(int64_t) * (*track_allocation)); \
44 free((*track_data)); \
45 } \
46 (*track_allocation) *= 2; \
47 (*track_data) = new_data; \
48 } \
50 (*track_data)[(*track_size)++] = (value); \
52 #else
53 #define APPEND_VECTOR(data, size, allocation, track, value) \
55 #endif
57 #define DELETE_VECTORS(data, size, allocation, tracks) \
58 { \
59 int k; \
60 for(k = 0; k < tracks; k++) if(data[k]) free(data[k]); \
61 free(data); \
69 #define PUT_INT32(x) \
70 { \
71 if(MPEG3_LITTLE_ENDIAN) \
72 { \
73 fputc(((unsigned char*)&x)[3], output); \
74 fputc(((unsigned char*)&x)[2], output); \
75 fputc(((unsigned char*)&x)[1], output); \
76 fputc(((unsigned char*)&x)[0], output); \
77 } \
78 else \
79 { \
80 fputc(((unsigned char*)&x)[0], output); \
81 fputc(((unsigned char*)&x)[1], output); \
82 fputc(((unsigned char*)&x)[2], output); \
83 fputc(((unsigned char*)&x)[3], output); \
84 } \
90 #define PUT_INT64(x) \
91 { \
92 if(MPEG3_LITTLE_ENDIAN) \
93 { \
94 fputc(((unsigned char*)&x)[7], output); \
95 fputc(((unsigned char*)&x)[6], output); \
96 fputc(((unsigned char*)&x)[5], output); \
97 fputc(((unsigned char*)&x)[4], output); \
98 fputc(((unsigned char*)&x)[3], output); \
99 fputc(((unsigned char*)&x)[2], output); \
100 fputc(((unsigned char*)&x)[1], output); \
101 fputc(((unsigned char*)&x)[0], output); \
103 else \
105 fwrite(&x, 1, 8, output); \
113 int main(int argc, char *argv[])
115 struct stat st;
116 int i, j, l;
117 char *src = 0, *dst = 0;
118 int astream_override = -1;
120 if(argc < 3)
122 fprintf(stderr, "Create a table of contents for a DVD or mpeg stream.\n"
123 " Usage: [-a audio streams] mpeg3toc <path> <output>\n"
124 "\n"
125 " -a override the number of audio streams to scan. Must be less than\n"
126 "the total number of audio streams.\n"
127 "\n"
128 " The path should be absolute unless you plan\n"
129 " to always run your movie editor from the same directory\n"
130 " as the filename. For renderfarms the filesystem prefix\n"
131 " should be / and the movie directory mounted under the same\n"
132 " directory on each node.\n"
133 "Example: mpeg3toc /cd2/video_ts/vts_01_0.ifo titanic.toc\n");
134 exit(1);
137 for(i = 1; i < argc; i++)
139 if(!strcmp(argv[i], "-a"))
141 if(i < argc - 1)
143 astream_override = atoi(argv[i + 1]);
144 if(astream_override < 0)
146 fprintf(stderr, "Total audio streams may not be negative\n");
147 exit(1);
149 else
151 fprintf(stderr,
152 "Using first %d audio streams.\n",
153 astream_override);
155 i++;
157 else
159 fprintf(stderr, "-a requires an argument.\n");
160 exit(1);
163 else
164 if(!src)
166 src = argv[i];
168 else
169 if(!dst)
171 dst = argv[i];
173 else
175 fprintf(stderr, "Ignoring argument \"%s\"\n", argv[i]);
179 if(!src)
181 fprintf(stderr, "source path not supplied.\n");
182 exit(1);
185 if(!dst)
187 fprintf(stderr, "source path not supplied.\n");
188 exit(1);
191 stat(src, &st);
193 if(!st.st_size)
195 fprintf(stderr, "%s is 0 length. Skipping\n", src);
197 else
199 int64_t size;
200 int vtracks;
201 int atracks;
202 mpeg3_t *input;
203 uint64_t **frame_offsets;
204 uint64_t **keyframe_numbers;
205 uint64_t **sample_offsets;
206 int *total_frame_offsets;
207 int *total_sample_offsets;
208 int *total_keyframe_numbers;
209 int *frame_offset_allocation;
210 int *sample_offset_allocation;
211 int *keyframe_numbers_allocation;
212 int done = 0;
213 double sample_rate;
214 double frame_rate;
215 FILE *output;
216 int total_samples = 0;
217 int total_frames = 0;
218 int rewind = 1;
220 //printf(__FUNCTION__ " 1\n");
221 input = mpeg3_open(src);
223 //printf(__FUNCTION__ " 2\n");
224 vtracks = mpeg3_total_vstreams(input);
225 atracks = mpeg3_total_astreams(input);
226 if(astream_override >= 0) atracks = astream_override;
228 if(atracks) sample_rate = mpeg3_sample_rate(input, 0);
229 if(vtracks) frame_rate = mpeg3_frame_rate(input, 0);
231 //printf(__FUNCTION__ " 3\n");
232 // Handle titles
233 INIT_VECTORS(frame_offsets, total_frame_offsets, frame_offset_allocation, vtracks);
234 INIT_VECTORS(keyframe_numbers, total_keyframe_numbers, keyframe_numbers_allocation, vtracks);
235 INIT_VECTORS(sample_offsets, total_sample_offsets, sample_offset_allocation, atracks);
237 //printf(__FUNCTION__ " 4\n");
238 while(!done)
240 int sample_count = MPEG3_AUDIO_CHUNKSIZE;
241 int frame_count;
242 int have_audio = 0;
243 int have_video = 0;
244 int64_t title_number = 0;
251 // Audio section
252 // Store current position and read sample_count from each atrack
253 for(j = 0; j < atracks; j++)
255 //printf(__FUNCTION__ " 3 %d\n", total_sample_offsets[j]);
256 if(rewind)
258 mpeg3_demuxer_t *demuxer = input->atrack[j]->demuxer;
259 mpeg3demux_seek_byte(demuxer, 0);
262 if(!mpeg3_end_of_audio(input, j))
264 // Don't want to maintain separate vectors for offset and title.
265 int64_t position = mpeg3demux_tell_byte(input->atrack[j]->demuxer);
266 int64_t result;
268 if(position < MPEG3_IO_SIZE) position = MPEG3_IO_SIZE;
269 // result = (title_number << 56) | (position - MPEG3_IO_SIZE);
270 result = position;
272 have_audio = 1;
273 APPEND_VECTOR(sample_offsets,
274 total_sample_offsets,
275 sample_offset_allocation,
277 result);
280 //printf(__FUNCTION__ " 6 %d\n", j);
281 // Throw away samples
282 mpeg3_read_audio(input,
286 sample_count, /* Number of samples to decode */
289 //printf(__FUNCTION__ " 7 %d\n", total_sample_offsets[j]);
292 if(j == atracks - 1)
294 total_samples += sample_count;
295 printf("Audio: title=%lld total_samples=%d ", title_number, total_samples);
299 //printf(__FUNCTION__ " 8\n");
300 if(have_audio)
302 frame_count =
303 (int)((double)total_samples / sample_rate * frame_rate + 0.5) -
304 total_frames;
306 else
308 frame_count = 1;
311 //printf(__FUNCTION__ " 9 %d\n", vtracks);
326 // Video section
327 for(j = 0; j < vtracks; j++)
329 mpeg3video_t *video = input->vtrack[j]->video;
330 mpeg3_demuxer_t *demuxer = input->vtrack[j]->demuxer;
331 if(rewind)
333 mpeg3demux_seek_byte(demuxer, 0);
337 for(l = 0; l < frame_count; l++)
339 if(!mpeg3_end_of_video(input, j))
341 int64_t position = mpeg3demux_tell_byte(demuxer);
342 int64_t result;
343 uint32_t code = 0;
344 int got_top = 0;
345 int got_bottom = 0;
346 int got_keyframe = 0;
347 int fields = 0;
349 if(position < MPEG3_IO_SIZE) position = MPEG3_IO_SIZE;
350 // result = (title_number << 56) | (position - MPEG3_IO_SIZE);
351 result = position;
352 have_video = 1;
355 //printf("%llx\n", position);
356 // Store offset of every frame in table
357 APPEND_VECTOR(frame_offsets,
358 total_frame_offsets,
359 frame_offset_allocation,
361 result);
365 // Search for next frame start.
366 if(total_frame_offsets[j] == 1)
368 // Assume first frame is an I-frame and put its number in the keyframe number
369 // table.
370 APPEND_VECTOR(keyframe_numbers,
371 total_keyframe_numbers,
372 keyframe_numbers_allocation,
378 // Skip the first frame.
379 mpeg3video_get_header(video, 0);
380 video->current_repeat += 100;
386 // Get next frame
389 mpeg3video_get_header(video, 0);
390 video->current_repeat += 100;
392 if(video->pict_struct == TOP_FIELD)
394 got_top = 1;
396 else
397 if(video->pict_struct == BOTTOM_FIELD)
399 got_bottom = 1;
401 else
402 if(video->pict_struct == FRAME_PICTURE)
404 got_top = got_bottom = 1;
406 fields++;
408 // The way we do it, the I frames have the top field but both the I frame and
409 // subsequent P frame make the keyframe.
410 if(video->pict_type == I_TYPE)
411 got_keyframe = 1;
412 }while(!mpeg3_end_of_video(input, j) &&
413 !got_bottom &&
414 total_frame_offsets[j] > 1);
419 // Store number of a keyframe in the keyframe number table
420 if(got_keyframe)
421 APPEND_VECTOR(keyframe_numbers,
422 total_keyframe_numbers,
423 keyframe_numbers_allocation,
425 total_frame_offsets[j] - 1);
427 if(j == vtracks - 1 && l == frame_count - 1)
429 total_frames += frame_count;
430 printf("Video: title=%lld total_frames=%d ", title_number, total_frames);
436 if(!have_audio && !have_video) done = 1;
438 printf("\r");
439 fflush(stdout);
441 * if(total_frames > 10000)
443 * printf("\n");
444 * return 0;
450 rewind = 0;
454 output = fopen(dst, "w");
458 // Write file type
459 fputc('T', output);
460 fputc('O', output);
461 fputc('C', output);
462 fputc(' ', output);
464 // Write version
465 fputc(MPEG3_TOC_VERSION, output);
467 if(input->is_program_stream)
469 fputc(FILE_TYPE_PROGRAM, output);
471 else
472 if(input->is_transport_stream)
474 fputc(FILE_TYPE_TRANSPORT, output);
476 else
477 if(input->is_audio_stream)
479 fputc(FILE_TYPE_AUDIO, output);
481 else
482 if(input->is_video_stream)
484 fputc(FILE_TYPE_VIDEO, output);
487 // Write stream ID's
488 // Only program and transport streams have these
489 for(i = 0; i < MPEG3_MAX_STREAMS; i++)
491 if(input->demuxer->astream_table[i])
493 fputc(STREAM_AUDIO, output);
494 PUT_INT32(i);
495 PUT_INT32(input->demuxer->astream_table[i]);
498 if(input->demuxer->vstream_table[i])
500 fputc(STREAM_VIDEO, output);
501 PUT_INT32(i);
502 PUT_INT32(input->demuxer->vstream_table[i]);
507 // Write titles
508 for(i = 0; i < input->demuxer->total_titles; i++)
510 // Path
511 fputc(TITLE_PATH, output);
512 fprintf(output, input->demuxer->titles[i]->fs->path);
513 fputc(0, output);
514 // Total bytes
515 PUT_INT64(input->demuxer->titles[i]->total_bytes);
516 // Byte offsets of cells
517 PUT_INT32(input->demuxer->titles[i]->cell_table_size);
518 for(j = 0; j < input->demuxer->titles[i]->cell_table_size; j++)
520 PUT_INT64(input->demuxer->titles[i]->cell_table[j].start_byte);
521 PUT_INT64(input->demuxer->titles[i]->cell_table[j].end_byte);
522 PUT_INT32(input->demuxer->titles[i]->cell_table[j].program);
533 fputc(ATRACK_COUNT, output);
534 PUT_INT32(atracks);
536 fputc(VTRACK_COUNT, output);
537 PUT_INT32(vtracks);
539 // Audio streams
540 for(j = 0; j < atracks; j++)
542 int channels = mpeg3_audio_channels(input, j);
543 PUT_INT32(channels);
544 PUT_INT32(total_sample_offsets[j]);
545 for(i = 0; i < total_sample_offsets[j]; i++)
547 PUT_INT64(sample_offsets[j][i]);
548 //printf("Audio: offset=%016llx\n", sample_offsets[j][i]);
552 // Video streams
553 for(j = 0; j < vtracks; j++)
555 PUT_INT32(total_frame_offsets[j]);
556 for(i = 0; i < total_frame_offsets[j]; i++)
558 PUT_INT64(frame_offsets[j][i]);
559 //printf("Video: offset=%016llx\n", frame_offsets[j][i]);
562 PUT_INT32(total_keyframe_numbers[j]);
563 for(i = 0; i < total_keyframe_numbers[j]; i++)
565 PUT_INT64(keyframe_numbers[j][i]);
566 //printf("Video: keyframe=%lld\n", keyframe_numbers[j][i]);
573 DELETE_VECTORS(frame_offsets, total_frame_offsets, frame_offset_allocation, vtracks);
574 DELETE_VECTORS(keyframe_numbers, total_keyframe_numbers, keyframe_numbers_allocation, vtracks);
575 DELETE_VECTORS(sample_offsets, total_sample_offsets, sample_offset_allocation, atracks);
578 mpeg3_close(input);
579 fclose(output);
585 return 0;