2 #include "mpeg3protos.h"
12 * Generate table of frame and sample offsets for editing.
16 #define INIT_VECTORS(data, size, allocation, tracks) \
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++) \
25 allocation[k] = 0x100; \
26 data[k] = calloc(1, sizeof(int64_t) * allocation[k]); \
31 #define APPEND_VECTOR(data, size, allocation, track, value) \
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)) \
39 int64_t *new_data = calloc(1, sizeof(int64_t) * (*track_allocation) * 2); \
43 memcpy(new_data, (*track_data), sizeof(int64_t) * (*track_allocation)); \
44 free((*track_data)); \
46 (*track_allocation) *= 2; \
47 (*track_data) = new_data; \
50 (*track_data)[(*track_size)++] = (value); \
53 #define APPEND_VECTOR(data, size, allocation, track, value) \
57 #define DELETE_VECTORS(data, size, allocation, tracks) \
60 for(k = 0; k < tracks; k++) if(data[k]) free(data[k]); \
69 #define PUT_INT32(x) \
71 if(MPEG3_LITTLE_ENDIAN) \
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); \
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); \
90 #define PUT_INT64(x) \
92 if(MPEG3_LITTLE_ENDIAN) \
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); \
105 fwrite(&x, 1, 8, output); \
113 int main(int argc
, char *argv
[])
117 char *src
= 0, *dst
= 0;
118 int astream_override
= -1;
122 fprintf(stderr
, "Create a table of contents for a DVD or mpeg stream.\n"
123 " Usage: [-a audio streams] mpeg3toc <path> <output>\n"
125 " -a override the number of audio streams to scan. Must be less than\n"
126 "the total number of audio streams.\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");
137 for(i
= 1; i
< argc
; i
++)
139 if(!strcmp(argv
[i
], "-a"))
143 astream_override
= atoi(argv
[i
+ 1]);
144 if(astream_override
< 0)
146 fprintf(stderr
, "Total audio streams may not be negative\n");
152 "Using first %d audio streams.\n",
159 fprintf(stderr
, "-a requires an argument.\n");
175 fprintf(stderr
, "Ignoring argument \"%s\"\n", argv
[i
]);
181 fprintf(stderr
, "source path not supplied.\n");
187 fprintf(stderr
, "source path not supplied.\n");
195 fprintf(stderr
, "%s is 0 length. Skipping\n", src
);
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
;
216 int total_samples
= 0;
217 int total_frames
= 0;
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");
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");
240 int sample_count
= MPEG3_AUDIO_CHUNKSIZE
;
244 int64_t title_number
= 0;
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]);
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
);
268 if(position
< MPEG3_IO_SIZE
) position
= MPEG3_IO_SIZE
;
269 // result = (title_number << 56) | (position - MPEG3_IO_SIZE);
273 APPEND_VECTOR(sample_offsets
,
274 total_sample_offsets
,
275 sample_offset_allocation
,
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]);
294 total_samples
+= sample_count
;
295 printf("Audio: title=%lld total_samples=%d ", title_number
, total_samples
);
299 //printf(__FUNCTION__ " 8\n");
303 (int)((double)total_samples
/ sample_rate
* frame_rate
+ 0.5) -
311 //printf(__FUNCTION__ " 9 %d\n", vtracks);
327 for(j
= 0; j
< vtracks
; j
++)
329 mpeg3video_t
*video
= input
->vtrack
[j
]->video
;
330 mpeg3_demuxer_t
*demuxer
= input
->vtrack
[j
]->demuxer
;
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
);
346 int got_keyframe
= 0;
349 if(position
< MPEG3_IO_SIZE
) position
= MPEG3_IO_SIZE
;
350 // result = (title_number << 56) | (position - MPEG3_IO_SIZE);
355 //printf("%llx\n", position);
356 // Store offset of every frame in table
357 APPEND_VECTOR(frame_offsets
,
359 frame_offset_allocation
,
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
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;
389 mpeg3video_get_header(video
, 0);
390 video
->current_repeat
+= 100;
392 if(video
->pict_struct
== TOP_FIELD
)
397 if(video
->pict_struct
== BOTTOM_FIELD
)
402 if(video
->pict_struct
== FRAME_PICTURE
)
404 got_top
= got_bottom
= 1;
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
)
412 }while(!mpeg3_end_of_video(input
, j
) &&
414 total_frame_offsets
[j
] > 1);
419 // Store number of a keyframe in the keyframe number table
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;
441 * if(total_frames > 10000)
454 output
= fopen(dst
, "w");
465 fputc(MPEG3_TOC_VERSION
, output
);
467 if(input
->is_program_stream
)
469 fputc(FILE_TYPE_PROGRAM
, output
);
472 if(input
->is_transport_stream
)
474 fputc(FILE_TYPE_TRANSPORT
, output
);
477 if(input
->is_audio_stream
)
479 fputc(FILE_TYPE_AUDIO
, output
);
482 if(input
->is_video_stream
)
484 fputc(FILE_TYPE_VIDEO
, output
);
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
);
495 PUT_INT32(input
->demuxer
->astream_table
[i
]);
498 if(input
->demuxer
->vstream_table
[i
])
500 fputc(STREAM_VIDEO
, output
);
502 PUT_INT32(input
->demuxer
->vstream_table
[i
]);
508 for(i
= 0; i
< input
->demuxer
->total_titles
; i
++)
511 fputc(TITLE_PATH
, output
);
512 fprintf(output
, input
->demuxer
->titles
[i
]->fs
->path
);
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
);
536 fputc(VTRACK_COUNT
, output
);
540 for(j
= 0; j
< atracks
; j
++)
542 int channels
= mpeg3_audio_channels(input
, j
);
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]);
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
);