r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / libmpeg3 / mpeg3toc.c
blobb7ced9d1f9cbf2045229459231e47532784336db
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>
13 #define INIT_VECTORS(data, size, allocation, tracks) \
14 { \
15 int k; \
16 data = calloc(1, sizeof(int64_t*) * tracks); \
17 size = calloc(1, sizeof(int*) * tracks); \
18 allocation = calloc(1, sizeof(int*) * tracks); \
20 for(k = 0; k < tracks; k++) \
21 { \
22 allocation[k] = 0x100; \
23 data[k] = calloc(1, sizeof(int64_t) * allocation[k]); \
24 } \
27 #if 1
28 #define APPEND_VECTOR(data, size, allocation, track, value) \
29 { \
30 uint64_t **track_data = &(data)[(track)]; \
31 int *track_allocation = &(allocation)[(track)]; \
32 int *track_size = &(size)[(track)]; \
34 if(!(*track_data) || (*track_allocation) <= (*track_size)) \
35 { \
36 int64_t *new_data = calloc(1, sizeof(int64_t) * (*track_allocation) * 2); \
38 if((*track_data)) \
39 { \
40 memcpy(new_data, (*track_data), sizeof(int64_t) * (*track_allocation)); \
41 free((*track_data)); \
42 } \
43 (*track_allocation) *= 2; \
44 (*track_data) = new_data; \
45 } \
47 (*track_data)[(*track_size)++] = (value); \
49 #else
50 #define APPEND_VECTOR(data, size, allocation, track, value) \
52 #endif
54 #define DELETE_VECTORS(data, size, allocation, tracks) \
55 { \
56 int k; \
57 for(k = 0; k < tracks; k++) if(data[k]) free(data[k]); \
58 free(data); \
66 #define PUT_INT32(x) \
67 { \
68 if(MPEG3_LITTLE_ENDIAN) \
69 { \
70 fputc(((unsigned char*)&x)[3], output); \
71 fputc(((unsigned char*)&x)[2], output); \
72 fputc(((unsigned char*)&x)[1], output); \
73 fputc(((unsigned char*)&x)[0], output); \
74 } \
75 else \
76 { \
77 fputc(((unsigned char*)&x)[0], output); \
78 fputc(((unsigned char*)&x)[1], output); \
79 fputc(((unsigned char*)&x)[2], output); \
80 fputc(((unsigned char*)&x)[3], output); \
81 } \
87 #define PUT_INT64(x) \
88 { \
89 if(MPEG3_LITTLE_ENDIAN) \
90 { \
91 fputc(((unsigned char*)&x)[7], output); \
92 fputc(((unsigned char*)&x)[6], output); \
93 fputc(((unsigned char*)&x)[5], output); \
94 fputc(((unsigned char*)&x)[4], output); \
95 fputc(((unsigned char*)&x)[3], output); \
96 fputc(((unsigned char*)&x)[2], output); \
97 fputc(((unsigned char*)&x)[1], output); \
98 fputc(((unsigned char*)&x)[0], output); \
99 } \
100 else \
102 fwrite(&x, 1, 8, output); \
110 int main(int argc, char *argv[])
112 struct stat st;
114 if(argc < 3)
116 fprintf(stderr, "Create a table of contents for a DVD or mpeg stream.\n"
117 " Usage: mpeg3toc <path> <output>\n"
118 "\n"
119 " The path should be absolute unless you plan\n"
120 " to always run your movie editor from the same directory\n"
121 " as the filename. For renderfarms the filesystem prefix\n"
122 " should be / and the movie directory mounted under the same\n"
123 " directory on each node.\n"
124 "Example: mpeg3toc /cd2/video_ts/vts_01_0.ifo titanic.toc\n");
125 exit(1);
130 stat(argv[1], &st);
132 if(!st.st_size)
134 fprintf(stderr, "%s is 0 length. Skipping\n", argv[1]);
136 else
138 int i, j, l;
139 int64_t size;
140 int vtracks;
141 int atracks;
142 mpeg3_t *input;
143 uint64_t **frame_offsets;
144 uint64_t **keyframe_numbers;
145 uint64_t **sample_offsets;
146 int *total_frame_offsets;
147 int *total_sample_offsets;
148 int *total_keyframe_numbers;
149 int *frame_offset_allocation;
150 int *sample_offset_allocation;
151 int *keyframe_numbers_allocation;
152 int done = 0;
153 double sample_rate;
154 double frame_rate;
155 FILE *output;
156 int total_samples = 0;
157 int total_frames = 0;
158 int rewind = 1;
160 //printf(__FUNCTION__ " 1\n");
161 input = mpeg3_open(argv[1]);
162 output = fopen(argv[2], "w");
164 //printf(__FUNCTION__ " 2\n");
165 vtracks = mpeg3_total_vstreams(input);
166 atracks = mpeg3_total_astreams(input);
168 if(atracks) sample_rate = mpeg3_sample_rate(input, 0);
169 if(vtracks) frame_rate = mpeg3_frame_rate(input, 0);
171 //printf(__FUNCTION__ " 3\n");
172 // Handle titles
173 INIT_VECTORS(frame_offsets, total_frame_offsets, frame_offset_allocation, vtracks);
174 INIT_VECTORS(keyframe_numbers, total_keyframe_numbers, keyframe_numbers_allocation, vtracks);
175 INIT_VECTORS(sample_offsets, total_sample_offsets, sample_offset_allocation, atracks);
177 //printf(__FUNCTION__ " 4\n");
178 while(!done)
180 int sample_count = MPEG3_AUDIO_CHUNKSIZE;
181 int frame_count;
182 int have_audio = 0;
183 int have_video = 0;
184 int64_t title_number = 0;
186 // Store current position and read sample_count from each atrack
187 for(j = 0; j < atracks; j++)
189 //printf(__FUNCTION__ " 3 %d\n", total_sample_offsets[j]);
190 if(rewind)
192 mpeg3_demuxer_t *demuxer = input->atrack[j]->demuxer;
193 mpeg3demux_seek_byte(demuxer, 0);
196 if(!mpeg3_end_of_audio(input, j))
198 // Don't want to maintain separate vectors for offset and title.
199 title_number = mpeg3demux_tell_title(input->atrack[j]->demuxer);
200 int64_t position = mpeg3demux_tell(input->atrack[j]->demuxer);
201 int64_t result;
202 if(position < MPEG3_IO_SIZE) position = MPEG3_IO_SIZE;
203 result = (title_number << 56) | (position - MPEG3_IO_SIZE);
205 have_audio = 1;
206 APPEND_VECTOR(sample_offsets,
207 total_sample_offsets,
208 sample_offset_allocation,
210 result);
213 //printf(__FUNCTION__ " 6 %d\n", j);
214 // Throw away samples
215 mpeg3_read_audio(input,
219 sample_count, /* Number of samples to decode */
222 //printf(__FUNCTION__ " 7 %d\n", total_sample_offsets[j]);
225 if(j == atracks - 1)
227 total_samples += sample_count;
228 printf("Audio: title=%lld total_samples=%d ", title_number, total_samples);
232 //printf(__FUNCTION__ " 8\n");
233 if(have_audio)
235 frame_count =
236 (int)((double)total_samples / sample_rate * frame_rate + 0.5) -
237 total_frames;
239 else
241 frame_count = 1;
244 //printf(__FUNCTION__ " 9 %d\n", vtracks);
245 for(j = 0; j < vtracks; j++)
247 mpeg3video_t *video = input->vtrack[j]->video;
248 mpeg3_demuxer_t *demuxer = input->vtrack[j]->demuxer;
249 if(rewind)
251 mpeg3demux_seek_byte(demuxer, 0);
255 for(l = 0; l < frame_count; l++)
257 if(!mpeg3_end_of_video(input, j))
259 int64_t title_number = mpeg3demux_tell_title(demuxer);
260 int64_t position = mpeg3demux_tell(demuxer);
261 int64_t result;
262 uint32_t code = 0;
263 int got_top = 0;
264 int got_bottom = 0;
265 int got_keyframe = 0;
266 int fields = 0;
268 if(position < MPEG3_IO_SIZE) position = MPEG3_IO_SIZE;
269 result = (title_number << 56) | (position - MPEG3_IO_SIZE);
270 have_video = 1;
274 // Store offset of every frame in table
275 APPEND_VECTOR(frame_offsets,
276 total_frame_offsets,
277 frame_offset_allocation,
279 result);
283 // Search for next frame start.
284 if(total_frame_offsets[j] == 1)
286 // Assume first frame is an I-frame and put its number in the keyframe number
287 // table.
288 APPEND_VECTOR(keyframe_numbers,
289 total_keyframe_numbers,
290 keyframe_numbers_allocation,
296 // Skip the first frame.
297 mpeg3video_get_header(video, 0);
298 video->current_repeat += 100;
304 // Get next frame
307 mpeg3video_get_header(video, 0);
308 video->current_repeat += 100;
310 if(video->pict_struct == TOP_FIELD)
312 got_top = 1;
314 else
315 if(video->pict_struct == BOTTOM_FIELD)
317 got_bottom = 1;
319 else
320 if(video->pict_struct == FRAME_PICTURE)
322 got_top = got_bottom = 1;
324 fields++;
326 // The way we do it, the I frames have the top field but both the I frame and
327 // subsequent P frame make the keyframe.
328 if(video->pict_type == I_TYPE)
329 got_keyframe = 1;
330 //printf(__FUNCTION__ " 10 %d %d %d\n", video->pict_type, got_top, got_bottom);
331 }while(!mpeg3_end_of_video(input, j) &&
332 !got_bottom &&
333 total_frame_offsets[j] > 1);
338 // Store number of a keyframe in the keyframe number table
339 if(got_keyframe)
340 APPEND_VECTOR(keyframe_numbers,
341 total_keyframe_numbers,
342 keyframe_numbers_allocation,
344 total_frame_offsets[j] - 1);
346 if(j == vtracks - 1 && l == frame_count - 1)
348 total_frames += frame_count;
349 printf("Video: title=%lld total_frames=%d ", title_number, total_frames);
355 if(!have_audio && !have_video) done = 1;
357 printf("\r");
358 fflush(stdout);
360 * if(total_frames > 10000)
362 * printf("\n");
363 * return 0;
369 rewind = 0;
374 // Write file type
375 fputc('T', output);
376 fputc('O', output);
377 fputc('C', output);
378 fputc(' ', output);
381 if(input->is_program_stream)
383 fputc(FILE_TYPE_PROGRAM, output);
385 else
386 if(input->is_transport_stream)
388 fputc(FILE_TYPE_TRANSPORT, output);
390 else
391 if(input->is_audio_stream)
393 fputc(FILE_TYPE_AUDIO, output);
395 else
396 if(input->is_video_stream)
398 fputc(FILE_TYPE_VIDEO, output);
401 // Write stream ID's
402 // Only program and transport streams have these
403 for(i = 0; i < MPEG3_MAX_STREAMS; i++)
405 if(input->demuxer->astream_table[i])
407 fputc(STREAM_AUDIO, output);
408 PUT_INT32(i);
409 PUT_INT32(input->demuxer->astream_table[i]);
412 if(input->demuxer->vstream_table[i])
414 fputc(STREAM_VIDEO, output);
415 PUT_INT32(i);
416 PUT_INT32(input->demuxer->vstream_table[i]);
421 // Write titles
422 for(i = 0; i < input->demuxer->total_titles; i++)
424 // Path
425 fputc(TITLE_PATH, output);
426 fprintf(output, input->demuxer->titles[i]->fs->path);
427 fputc(0, output);
428 // Total bytes
429 PUT_INT64(input->demuxer->titles[i]->total_bytes);
430 // Byte offsets of cells
431 PUT_INT32(input->demuxer->titles[i]->timecode_table_size);
432 for(j = 0; j < input->demuxer->titles[i]->timecode_table_size; j++)
434 PUT_INT64(input->demuxer->titles[i]->timecode_table[j].start_byte);
435 PUT_INT64(input->demuxer->titles[i]->timecode_table[j].end_byte);
436 PUT_INT32(input->demuxer->titles[i]->timecode_table[j].program);
447 fputc(ATRACK_COUNT, output);
448 PUT_INT32(atracks);
450 fputc(VTRACK_COUNT, output);
451 PUT_INT32(vtracks);
453 // Audio streams
454 for(j = 0; j < atracks; j++)
456 int channels = mpeg3_audio_channels(input, j);
457 PUT_INT32(channels);
458 PUT_INT32(total_sample_offsets[j]);
459 for(i = 0; i < total_sample_offsets[j]; i++)
461 PUT_INT64(sample_offsets[j][i]);
462 //printf("Audio: offset=%016llx\n", sample_offsets[j][i]);
466 // Video streams
467 for(j = 0; j < vtracks; j++)
469 PUT_INT32(total_frame_offsets[j]);
470 for(i = 0; i < total_frame_offsets[j]; i++)
472 PUT_INT64(frame_offsets[j][i]);
473 //printf("Video: offset=%016llx\n", frame_offsets[j][i]);
476 PUT_INT32(total_keyframe_numbers[j]);
477 for(i = 0; i < total_keyframe_numbers[j]; i++)
479 PUT_INT64(keyframe_numbers[j][i]);
480 //printf("Video: keyframe=%lld\n", keyframe_numbers[j][i]);
487 DELETE_VECTORS(frame_offsets, total_frame_offsets, frame_offset_allocation, vtracks);
488 DELETE_VECTORS(keyframe_numbers, total_keyframe_numbers, keyframe_numbers_allocation, vtracks);
489 DELETE_VECTORS(sample_offsets, total_sample_offsets, sample_offset_allocation, atracks);
492 mpeg3_close(input);
493 fclose(output);
499 return 0;