00001
00002
00003
00004 #if 1
00005
00006
00007 #include "libmpeg3.h"
00008
00009 #include <stdint.h>
00010 #include <stdio.h>
00011 #include <string.h>
00012 #include <stdlib.h>
00013
00014
00015
00016
00017
00018 int main(int argc, char *argv[])
00019 {
00020 int i, j, l;
00021 char *src = 0, *dst = 0;
00022 int verbose = 0;
00023
00024 if(argc < 3)
00025 {
00026 fprintf(stderr, "Table of contents generator version %d.%d.%d\n"
00027 "Create a table of contents for a DVD or mpeg stream.\n"
00028 "Usage: mpeg3toc <path> <output>\n"
00029 "\n"
00030 "-v Print tracking information\n"
00031 "\n"
00032 "The path should be absolute unless you plan\n"
00033 "to always run your movie editor from the same directory\n"
00034 "as the filename. For renderfarms the filesystem prefix\n"
00035 "should be / and the movie directory mounted under the same\n"
00036 "directory on each node.\n\n"
00037 "Example: mpeg3toc -v /cdrom/video_ts/vts_01_0.ifo titanic.toc\n",
00038 mpeg3_major(),
00039 mpeg3_minor(),
00040 mpeg3_release());
00041 exit(1);
00042 }
00043
00044 for(i = 1; i < argc; i++)
00045 {
00046 if(!strcmp(argv[i], "-v"))
00047 {
00048 verbose = 1;
00049 }
00050 else
00051 if(argv[i][0] == '-')
00052 {
00053 fprintf(stderr, "Unrecognized command %s\n", argv[i]);
00054 exit(1);
00055 }
00056 else
00057 if(!src)
00058 {
00059 src = argv[i];
00060 }
00061 else
00062 if(!dst)
00063 {
00064 dst = argv[i];
00065 }
00066 else
00067 {
00068 fprintf(stderr, "Ignoring argument \"%s\"\n", argv[i]);
00069 }
00070 }
00071
00072 if(!src)
00073 {
00074 fprintf(stderr, "source path not supplied.\n");
00075 exit(1);
00076 }
00077
00078 if(!dst)
00079 {
00080 fprintf(stderr, "destination path not supplied.\n");
00081 exit(1);
00082 }
00083
00084
00085
00086 int64_t total_bytes;
00087 mpeg3_t *file = mpeg3_start_toc(src, dst, &total_bytes);
00088 if(!file) exit(1);
00089 struct timeval new_time;
00090 struct timeval prev_time;
00091 struct timeval start_time;
00092 struct timeval current_time;
00093 gettimeofday(&prev_time, 0);
00094 gettimeofday(&start_time, 0);
00095
00096
00097 while(1)
00098 {
00099 int64_t bytes_processed = 0;
00100 mpeg3_do_toc(file, &bytes_processed);
00101
00102 gettimeofday(&new_time, 0);
00103 if(verbose && new_time.tv_sec - prev_time.tv_sec > 1)
00104 {
00105 gettimeofday(¤t_time, 0);
00106 int64_t elapsed_seconds = current_time.tv_sec - start_time.tv_sec;
00107 int64_t total_seconds = elapsed_seconds * total_bytes / bytes_processed;
00108 int64_t eta = total_seconds - elapsed_seconds;
00109 fprintf(stderr, "%lld%% ETA: %dm%ds \r",
00110 bytes_processed * 100 / total_bytes,
00111 eta / 60,
00112 eta % 60);
00113 fflush(stdout);
00114 prev_time = new_time;
00115 }
00116
00117 if(bytes_processed >= total_bytes) break;
00118 }
00119
00120 mpeg3_stop_toc(file);
00121 gettimeofday(¤t_time, 0);
00122 int64_t elapsed = current_time.tv_sec - start_time.tv_sec;
00123 if(verbose)
00124 {
00125 fprintf(stderr, "%dm%ds elapsed \n",
00126 elapsed / 60,
00127 elapsed % 60);
00128 }
00129
00130 return 0;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139 #else
00140
00141
00142
00143
00144
00145 #include "libmpeg3.h"
00146 #include "mpeg3protos.h"
00147
00148 #include <stdint.h>
00149 #include <stdio.h>
00150 #include <string.h>
00151 #include <stdlib.h>
00152 #include <sys/stat.h>
00153
00154
00155
00156
00157
00158
00159
00160 #define INIT_VECTORS(data, size, allocation, tracks) \
00161 { \
00162 int k; \
00163 data = calloc(1, sizeof(int64_t*) * tracks); \
00164 size = calloc(1, sizeof(int*) * tracks); \
00165 allocation = calloc(1, sizeof(int*) * tracks); \
00166 \
00167 for(k = 0; k < tracks; k++) \
00168 { \
00169 allocation[k] = 0x100; \
00170 data[k] = calloc(1, sizeof(int64_t) * allocation[k]); \
00171 } \
00172 }
00173
00174 #if 1
00175 #define APPEND_VECTOR(data, size, allocation, track, value) \
00176 { \
00177 uint64_t **track_data = &(data)[(track)]; \
00178 int *track_allocation = &(allocation)[(track)]; \
00179 int *track_size = &(size)[(track)]; \
00180 \
00181 if(!(*track_data) || (*track_allocation) <= (*track_size)) \
00182 { \
00183 int64_t *new_data = calloc(1, sizeof(int64_t) * (*track_allocation) * 2); \
00184 \
00185 if((*track_data)) \
00186 { \
00187 memcpy(new_data, (*track_data), sizeof(int64_t) * (*track_allocation)); \
00188 free((*track_data)); \
00189 } \
00190 (*track_allocation) *= 2; \
00191 (*track_data) = new_data; \
00192 } \
00193 \
00194 (*track_data)[(*track_size)++] = (value); \
00195 }
00196 #else
00197 #define APPEND_VECTOR(data, size, allocation, track, value) \
00198 ;
00199 #endif
00200
00201 #define DELETE_VECTORS(data, size, allocation, tracks) \
00202 { \
00203 int k; \
00204 for(k = 0; k < tracks; k++) if(data[k]) free(data[k]); \
00205 free(data); \
00206 }
00207
00208
00209
00210
00211
00212
00213 #define PUT_INT32(x) \
00214 { \
00215 if(MPEG3_LITTLE_ENDIAN) \
00216 { \
00217 fputc(((unsigned char*)&x)[3], output); \
00218 fputc(((unsigned char*)&x)[2], output); \
00219 fputc(((unsigned char*)&x)[1], output); \
00220 fputc(((unsigned char*)&x)[0], output); \
00221 } \
00222 else \
00223 { \
00224 fputc(((unsigned char*)&x)[0], output); \
00225 fputc(((unsigned char*)&x)[1], output); \
00226 fputc(((unsigned char*)&x)[2], output); \
00227 fputc(((unsigned char*)&x)[3], output); \
00228 } \
00229 }
00230
00231
00232
00233
00234 #define PUT_INT64(x) \
00235 { \
00236 if(MPEG3_LITTLE_ENDIAN) \
00237 { \
00238 fputc(((unsigned char*)&x)[7], output); \
00239 fputc(((unsigned char*)&x)[6], output); \
00240 fputc(((unsigned char*)&x)[5], output); \
00241 fputc(((unsigned char*)&x)[4], output); \
00242 fputc(((unsigned char*)&x)[3], output); \
00243 fputc(((unsigned char*)&x)[2], output); \
00244 fputc(((unsigned char*)&x)[1], output); \
00245 fputc(((unsigned char*)&x)[0], output); \
00246 } \
00247 else \
00248 { \
00249 fwrite(&x, 1, 8, output); \
00250 } \
00251 }
00252
00253
00254
00255
00256
00257 int main(int argc, char *argv[])
00258 {
00259 struct stat st;
00260 int i, j, l;
00261 char *src = 0, *dst = 0;
00262 int astream_override = -1;
00263
00264 if(argc < 3)
00265 {
00266 fprintf(stderr, "Create a table of contents for a DVD or mpeg stream.\n"
00267 " Usage: [-a audio streams] mpeg3toc <path> <output>\n"
00268 "\n"
00269 " -a override the number of audio streams to scan. Must be less than\n"
00270 "the total number of audio streams.\n"
00271 "\n"
00272 " The path should be absolute unless you plan\n"
00273 " to always run your movie editor from the same directory\n"
00274 " as the filename. For renderfarms the filesystem prefix\n"
00275 " should be / and the movie directory mounted under the same\n"
00276 " directory on each node.\n"
00277 "Example: mpeg3toc /cd2/video_ts/vts_01_0.ifo titanic.toc\n");
00278 exit(1);
00279 }
00280
00281 for(i = 1; i < argc; i++)
00282 {
00283 if(!strcmp(argv[i], "-a"))
00284 {
00285 if(i < argc - 1)
00286 {
00287 astream_override = atoi(argv[i + 1]);
00288 if(astream_override < 0)
00289 {
00290 fprintf(stderr, "Total audio streams may not be negative\n");
00291 exit(1);
00292 }
00293 else
00294 {
00295 fprintf(stderr,
00296 "Using first %d audio streams.\n",
00297 astream_override);
00298 }
00299 i++;
00300 }
00301 else
00302 {
00303 fprintf(stderr, "-a requires an argument.\n");
00304 exit(1);
00305 }
00306 }
00307 else
00308 if(!src)
00309 {
00310 src = argv[i];
00311 }
00312 else
00313 if(!dst)
00314 {
00315 dst = argv[i];
00316 }
00317 else
00318 {
00319 fprintf(stderr, "Ignoring argument \"%s\"\n", argv[i]);
00320 }
00321 }
00322
00323 if(!src)
00324 {
00325 fprintf(stderr, "source path not supplied.\n");
00326 exit(1);
00327 }
00328
00329 if(!dst)
00330 {
00331 fprintf(stderr, "source path not supplied.\n");
00332 exit(1);
00333 }
00334
00335 stat(src, &st);
00336
00337 if(!st.st_size)
00338 {
00339 fprintf(stderr, "%s is 0 length. Skipping\n", src);
00340 }
00341 else
00342 {
00343 int64_t size;
00344 int vtracks;
00345 int atracks;
00346 mpeg3_t *input;
00347 uint64_t **frame_offsets;
00348 uint64_t **keyframe_numbers;
00349 uint64_t **sample_offsets;
00350 int *total_frame_offsets;
00351 int *total_sample_offsets;
00352 int *total_keyframe_numbers;
00353 int *frame_offset_allocation;
00354 int *sample_offset_allocation;
00355 int *keyframe_numbers_allocation;
00356 int done = 0;
00357 double sample_rate;
00358 double frame_rate;
00359 FILE *output;
00360 int total_samples = 0;
00361 int total_frames = 0;
00362 int rewind = 1;
00363
00364
00365 input = mpeg3_open(src);
00366
00367
00368 vtracks = mpeg3_total_vstreams(input);
00369 atracks = mpeg3_total_astreams(input);
00370 if(astream_override >= 0) atracks = astream_override;
00371
00372 if(atracks) sample_rate = mpeg3_sample_rate(input, 0);
00373 if(vtracks) frame_rate = mpeg3_frame_rate(input, 0);
00374
00375
00376
00377 INIT_VECTORS(frame_offsets, total_frame_offsets, frame_offset_allocation, vtracks);
00378 INIT_VECTORS(keyframe_numbers, total_keyframe_numbers, keyframe_numbers_allocation, vtracks);
00379 INIT_VECTORS(sample_offsets, total_sample_offsets, sample_offset_allocation, atracks);
00380
00381
00382 while(!done)
00383 {
00384 int sample_count = MPEG3_AUDIO_CHUNKSIZE;
00385 int frame_count;
00386 int have_audio = 0;
00387 int have_video = 0;
00388 int64_t title_number = 0;
00389
00390
00391
00392
00393
00394
00395
00396
00397 for(j = 0; j < atracks; j++)
00398 {
00399
00400 if(rewind)
00401 {
00402 mpeg3_demuxer_t *demuxer = input->atrack[j]->demuxer;
00403 mpeg3demux_seek_byte(demuxer, 0);
00404
00405 }
00406
00407 if(!mpeg3_end_of_audio(input, j))
00408 {
00409
00410 int64_t position = mpeg3demux_tell_byte(input->atrack[j]->demuxer);
00411 int64_t result;
00412
00413 if(position < MPEG3_IO_SIZE) position = MPEG3_IO_SIZE;
00414 result = position;
00415
00416 have_audio = 1;
00417 APPEND_VECTOR(sample_offsets,
00418 total_sample_offsets,
00419 sample_offset_allocation,
00420 j,
00421 result);
00422
00423
00424
00425
00426 mpeg3_read_audio(input,
00427 0,
00428 0,
00429 0,
00430 sample_count,
00431 j);
00432
00433 printf("\n%lld %lld\n",
00434 mpeg3demux_tell_byte(input->atrack[j]->demuxer),
00435 mpeg3demux_movie_size(input->atrack[j]->demuxer));
00436
00437 }
00438
00439 if(j == atracks - 1)
00440 {
00441 total_samples += sample_count;
00442 fprintf(stderr, "Audio: title=%lld total_samples=%d ", title_number, total_samples);
00443 }
00444 }
00445
00446
00447 if(have_audio)
00448 {
00449 frame_count =
00450 (int)((double)total_samples / sample_rate * frame_rate + 0.5) -
00451 total_frames;
00452 }
00453 else
00454 {
00455 frame_count = 1;
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 for(j = 0; j < vtracks; j++)
00475 {
00476 mpeg3video_t *video = input->vtrack[j]->video;
00477 mpeg3_demuxer_t *demuxer = input->vtrack[j]->demuxer;
00478 if(rewind)
00479 {
00480 mpeg3demux_seek_byte(demuxer, 0);
00481 }
00482
00483
00484 for(l = 0; l < frame_count; l++)
00485 {
00486 if(!mpeg3_end_of_video(input, j))
00487 {
00488
00489 int64_t position = mpeg3demux_tell_byte(demuxer) - 2048;
00490 int64_t result;
00491 uint32_t code = 0;
00492 int got_top = 0;
00493 int got_bottom = 0;
00494 int got_keyframe = 0;
00495 int fields = 0;
00496
00497 if(position < MPEG3_IO_SIZE) position = MPEG3_IO_SIZE;
00498 result = position;
00499 have_video = 1;
00500
00501
00502
00503
00504 APPEND_VECTOR(frame_offsets,
00505 total_frame_offsets,
00506 frame_offset_allocation,
00507 j,
00508 result);
00509
00510
00511
00512
00513 if(total_frame_offsets[j] == 1)
00514 {
00515
00516
00517 APPEND_VECTOR(keyframe_numbers,
00518 total_keyframe_numbers,
00519 keyframe_numbers_allocation,
00520 j,
00521 0);
00522
00523
00524
00525
00526 mpeg3video_get_header(video, 0);
00527 video->current_repeat += 100;
00528 }
00529
00530
00531
00532
00533
00534 do
00535 {
00536 mpeg3video_get_header(video, 0);
00537 video->current_repeat += 100;
00538
00539 if(video->pict_struct == TOP_FIELD)
00540 {
00541 got_top = 1;
00542 }
00543 else
00544 if(video->pict_struct == BOTTOM_FIELD)
00545 {
00546 got_bottom = 1;
00547 }
00548 else
00549 if(video->pict_struct == FRAME_PICTURE)
00550 {
00551 got_top = got_bottom = 1;
00552 }
00553 fields++;
00554
00555
00556
00557 if(video->pict_type == I_TYPE)
00558 got_keyframe = 1;
00559 }while(!mpeg3_end_of_video(input, j) &&
00560 !got_bottom &&
00561 total_frame_offsets[j] > 1);
00562
00563
00564
00565
00566
00567 if(got_keyframe)
00568 APPEND_VECTOR(keyframe_numbers,
00569 total_keyframe_numbers,
00570 keyframe_numbers_allocation,
00571 j,
00572 total_frame_offsets[j] - 1);
00573
00574 if(j == vtracks - 1 && l == frame_count - 1)
00575 {
00576 total_frames += frame_count;
00577 fprintf(stderr, "Video: title=%lld total_frames=%d (%.1f \%)", title_number, total_frames,100*((float)position)/((float) mpeg3demux_movie_size(demuxer)));
00578 }
00579 }
00580 }
00581 }
00582
00583 if(!have_audio && !have_video) done = 1;
00584
00585 fprintf(stderr, "\r");
00586 fflush(stderr);
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 rewind = 0;
00598 }
00599
00600
00601 output = fopen(dst, "w");
00602
00603
00604
00605
00606 fputc('T', output);
00607 fputc('O', output);
00608 fputc('C', output);
00609 fputc(' ', output);
00610
00611
00612 fputc(MPEG3_TOC_VERSION, output);
00613
00614 if(input->is_program_stream)
00615 {
00616 fputc(FILE_TYPE_PROGRAM, output);
00617 }
00618 else
00619 if(input->is_transport_stream)
00620 {
00621 fputc(FILE_TYPE_TRANSPORT, output);
00622 }
00623 else
00624 if(input->is_audio_stream)
00625 {
00626 fputc(FILE_TYPE_AUDIO, output);
00627 }
00628 else
00629 if(input->is_video_stream)
00630 {
00631 fputc(FILE_TYPE_VIDEO, output);
00632 }
00633
00634
00635
00636 for(i = 0; i < MPEG3_MAX_STREAMS; i++)
00637 {
00638 if(input->demuxer->astream_table[i])
00639 {
00640 fputc(STREAM_AUDIO, output);
00641 PUT_INT32(i);
00642 PUT_INT32(input->demuxer->astream_table[i]);
00643 }
00644
00645 if(input->demuxer->vstream_table[i])
00646 {
00647 fputc(STREAM_VIDEO, output);
00648 PUT_INT32(i);
00649 PUT_INT32(input->demuxer->vstream_table[i]);
00650 }
00651 }
00652
00653
00654
00655 for(i = 0; i < input->demuxer->total_titles; i++)
00656 {
00657 mpeg3_title_t *title = input->demuxer->titles[i];
00658
00659 fputc(TITLE_PATH, output);
00660 fprintf(output, title->fs->path);
00661 fputc(0, output);
00662
00663 PUT_INT64(title->total_bytes);
00664
00665 PUT_INT32(input->demuxer->titles[i]->cell_table_size);
00666 for(j = 0; j < title->cell_table_size; j++)
00667 {
00668 mpeg3_cell_t *cell = &title->cell_table[j];
00669 PUT_INT64(cell->title_start);
00670 PUT_INT64(cell->title_end);
00671 PUT_INT64(cell->program_start);
00672 PUT_INT64(cell->program_end);
00673 PUT_INT32(cell->program);
00674 }
00675 }
00676
00677
00678
00679
00680
00681
00682
00683
00684 fputc(ATRACK_COUNT, output);
00685 PUT_INT32(atracks);
00686
00687 fputc(VTRACK_COUNT, output);
00688 PUT_INT32(vtracks);
00689
00690
00691 for(j = 0; j < atracks; j++)
00692 {
00693 int channels = mpeg3_audio_channels(input, j);
00694 PUT_INT32(channels);
00695 PUT_INT32(total_sample_offsets[j]);
00696 for(i = 0; i < total_sample_offsets[j]; i++)
00697 {
00698 PUT_INT64(sample_offsets[j][i]);
00699
00700 }
00701 }
00702
00703
00704 for(j = 0; j < vtracks; j++)
00705 {
00706 PUT_INT32(total_frame_offsets[j]);
00707 for(i = 0; i < total_frame_offsets[j]; i++)
00708 {
00709 PUT_INT64(frame_offsets[j][i]);
00710
00711 }
00712
00713 PUT_INT32(total_keyframe_numbers[j]);
00714 for(i = 0; i < total_keyframe_numbers[j]; i++)
00715 {
00716 PUT_INT64(keyframe_numbers[j][i]);
00717
00718 }
00719 }
00720
00721
00722
00723
00724 DELETE_VECTORS(frame_offsets, total_frame_offsets, frame_offset_allocation, vtracks);
00725 DELETE_VECTORS(keyframe_numbers, total_keyframe_numbers, keyframe_numbers_allocation, vtracks);
00726 DELETE_VECTORS(sample_offsets, total_sample_offsets, sample_offset_allocation, atracks);
00727
00728
00729 mpeg3_close(input);
00730 fclose(output);
00731 }
00732
00733
00734
00735
00736 return 0;
00737 }
00738
00739
00740
00741
00742
00743
00744 #endif