2 #include "mpeg3protos.h"
13 #define INIT_VECTORS(data, size, allocation, tracks) \
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++) \
22 allocation[k] = 0x100; \
23 data[k] = calloc(1, sizeof(int64_t) * allocation[k]); \
28 #define APPEND_VECTOR(data, size, allocation, track, value) \
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)) \
36 int64_t *new_data = calloc(1, sizeof(int64_t) * (*track_allocation) * 2); \
40 memcpy(new_data, (*track_data), sizeof(int64_t) * (*track_allocation)); \
41 free((*track_data)); \
43 (*track_allocation) *= 2; \
44 (*track_data) = new_data; \
47 (*track_data)[(*track_size)++] = (value); \
50 #define APPEND_VECTOR(data, size, allocation, track, value) \
54 #define DELETE_VECTORS(data, size, allocation, tracks) \
57 for(k = 0; k < tracks; k++) if(data[k]) free(data[k]); \
66 #define PUT_INT32(x) \
68 if(MPEG3_LITTLE_ENDIAN) \
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); \
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); \
87 #define PUT_INT64(x) \
89 if(MPEG3_LITTLE_ENDIAN) \
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); \
102 fwrite(&x, 1, 8, output); \
110 int main(int argc
, char *argv
[])
116 fprintf(stderr
, "Create a table of contents for a DVD or mpeg stream.\n"
117 " Usage: mpeg3toc <path> <output>\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");
134 fprintf(stderr
, "%s is 0 length. Skipping\n", argv
[1]);
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
;
156 int total_samples
= 0;
157 int total_frames
= 0;
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");
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");
180 int sample_count
= MPEG3_AUDIO_CHUNKSIZE
;
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]);
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
);
202 if(position
< MPEG3_IO_SIZE
) position
= MPEG3_IO_SIZE
;
203 result
= (title_number
<< 56) | (position
- MPEG3_IO_SIZE
);
206 APPEND_VECTOR(sample_offsets
,
207 total_sample_offsets
,
208 sample_offset_allocation
,
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]);
227 total_samples
+= sample_count
;
228 printf("Audio: title=%lld total_samples=%d ", title_number
, total_samples
);
232 //printf(__FUNCTION__ " 8\n");
236 (int)((double)total_samples
/ sample_rate
* frame_rate
+ 0.5) -
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
;
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
);
265 int got_keyframe
= 0;
268 if(position
< MPEG3_IO_SIZE
) position
= MPEG3_IO_SIZE
;
269 result
= (title_number
<< 56) | (position
- MPEG3_IO_SIZE
);
274 // Store offset of every frame in table
275 APPEND_VECTOR(frame_offsets
,
277 frame_offset_allocation
,
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
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;
307 mpeg3video_get_header(video
, 0);
308 video
->current_repeat
+= 100;
310 if(video
->pict_struct
== TOP_FIELD
)
315 if(video
->pict_struct
== BOTTOM_FIELD
)
320 if(video
->pict_struct
== FRAME_PICTURE
)
322 got_top
= got_bottom
= 1;
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
)
330 //printf(__FUNCTION__ " 10 %d %d %d\n", video->pict_type, got_top, got_bottom);
331 }while(!mpeg3_end_of_video(input
, j
) &&
333 total_frame_offsets
[j
] > 1);
338 // Store number of a keyframe in the keyframe number table
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;
360 * if(total_frames > 10000)
381 if(input
->is_program_stream
)
383 fputc(FILE_TYPE_PROGRAM
, output
);
386 if(input
->is_transport_stream
)
388 fputc(FILE_TYPE_TRANSPORT
, output
);
391 if(input
->is_audio_stream
)
393 fputc(FILE_TYPE_AUDIO
, output
);
396 if(input
->is_video_stream
)
398 fputc(FILE_TYPE_VIDEO
, output
);
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
);
409 PUT_INT32(input
->demuxer
->astream_table
[i
]);
412 if(input
->demuxer
->vstream_table
[i
])
414 fputc(STREAM_VIDEO
, output
);
416 PUT_INT32(input
->demuxer
->vstream_table
[i
]);
422 for(i
= 0; i
< input
->demuxer
->total_titles
; i
++)
425 fputc(TITLE_PATH
, output
);
426 fprintf(output
, input
->demuxer
->titles
[i
]->fs
->path
);
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
);
450 fputc(VTRACK_COUNT
, output
);
454 for(j
= 0; j
< atracks
; j
++)
456 int channels
= mpeg3_audio_channels(input
, j
);
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]);
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
);