00001 #include "libmpeg3.h"
00002 #include "mpeg3protos.h"
00003
00004 #include <errno.h>
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <string.h>
00008 #include <sys/stat.h>
00009
00010
00011
00012 #define PUT_INT32(x) \
00013 { \
00014 uint32_t temp = x; \
00015 if(MPEG3_LITTLE_ENDIAN) \
00016 { \
00017 fputc(((unsigned char*)&temp)[3], file->toc_fd); \
00018 fputc(((unsigned char*)&temp)[2], file->toc_fd); \
00019 fputc(((unsigned char*)&temp)[1], file->toc_fd); \
00020 fputc(((unsigned char*)&temp)[0], file->toc_fd); \
00021 } \
00022 else \
00023 { \
00024 fwrite(&temp, 1, 4, file->toc_fd); \
00025 } \
00026 }
00027
00028
00029
00030
00031 #define PUT_INT64(x) \
00032 { \
00033 uint64_t temp = x; \
00034 if(MPEG3_LITTLE_ENDIAN) \
00035 { \
00036 fputc(((unsigned char*)&temp)[7], file->toc_fd); \
00037 fputc(((unsigned char*)&temp)[6], file->toc_fd); \
00038 fputc(((unsigned char*)&temp)[5], file->toc_fd); \
00039 fputc(((unsigned char*)&temp)[4], file->toc_fd); \
00040 fputc(((unsigned char*)&temp)[3], file->toc_fd); \
00041 fputc(((unsigned char*)&temp)[2], file->toc_fd); \
00042 fputc(((unsigned char*)&temp)[1], file->toc_fd); \
00043 fputc(((unsigned char*)&temp)[0], file->toc_fd); \
00044 } \
00045 else \
00046 { \
00047 fwrite(&temp, 1, 8, file->toc_fd); \
00048 } \
00049 }
00050
00051
00052 static uint32_t read_int32(unsigned char *buffer, int *position)
00053 {
00054 uint32_t temp;
00055
00056 if(MPEG3_LITTLE_ENDIAN)
00057 {
00058 ((unsigned char*)&temp)[3] = buffer[(*position)++];
00059 ((unsigned char*)&temp)[2] = buffer[(*position)++];
00060 ((unsigned char*)&temp)[1] = buffer[(*position)++];
00061 ((unsigned char*)&temp)[0] = buffer[(*position)++];
00062 }
00063 else
00064 {
00065 ((unsigned char*)&temp)[0] = buffer[(*position)++];
00066 ((unsigned char*)&temp)[1] = buffer[(*position)++];
00067 ((unsigned char*)&temp)[2] = buffer[(*position)++];
00068 ((unsigned char*)&temp)[3] = buffer[(*position)++];
00069 }
00070
00071 return temp;
00072 }
00073
00074
00075 static uint64_t read_int64(unsigned char *buffer, int *position)
00076 {
00077 uint64_t temp;
00078
00079 if(MPEG3_LITTLE_ENDIAN)
00080 {
00081 ((unsigned char*)&temp)[7] = buffer[(*position)++];
00082 ((unsigned char*)&temp)[6] = buffer[(*position)++];
00083 ((unsigned char*)&temp)[5] = buffer[(*position)++];
00084 ((unsigned char*)&temp)[4] = buffer[(*position)++];
00085 ((unsigned char*)&temp)[3] = buffer[(*position)++];
00086 ((unsigned char*)&temp)[2] = buffer[(*position)++];
00087 ((unsigned char*)&temp)[1] = buffer[(*position)++];
00088 ((unsigned char*)&temp)[0] = buffer[(*position)++];
00089 }
00090 else
00091 {
00092 ((unsigned char*)&temp)[0] = buffer[(*position)++];
00093 ((unsigned char*)&temp)[1] = buffer[(*position)++];
00094 ((unsigned char*)&temp)[2] = buffer[(*position)++];
00095 ((unsigned char*)&temp)[3] = buffer[(*position)++];
00096 ((unsigned char*)&temp)[4] = buffer[(*position)++];
00097 ((unsigned char*)&temp)[5] = buffer[(*position)++];
00098 ((unsigned char*)&temp)[6] = buffer[(*position)++];
00099 ((unsigned char*)&temp)[7] = buffer[(*position)++];
00100 }
00101
00102 return temp;
00103 }
00104
00105 static int read_data(unsigned char *buffer,
00106 int *position,
00107 unsigned char *output,
00108 int bytes)
00109 {
00110 memcpy(output, buffer + *position, bytes);
00111 *position += bytes;
00112 }
00113
00114
00115
00116 static void complete_path(char *result, char *toc_path, char *path)
00117 {
00118 strcpy(result, path);
00119
00120 if(path[0] != '/')
00121 {
00122
00123 char *ptr = strrchr(toc_path, '/');
00124
00125 if(ptr)
00126 {
00127
00128 strcpy(result, toc_path);
00129 strcpy(&result[ptr - toc_path + 1], path);
00130 }
00131 }
00132 }
00133
00134 int mpeg3_read_toc(mpeg3_t *file,
00135 int *atracks_return,
00136 int *vtracks_return)
00137 {
00138 unsigned char *buffer;
00139 int buffer_size;
00140 int file_type;
00141 int position = 4;
00142 int stream_type;
00143 int i, j;
00144 int is_vfs = 0;
00145 int vfs_len = strlen(RENDERFARM_FS_PREFIX);
00146 int toc_version;
00147 int64_t current_byte = 0;
00148 char *ext;
00149 const int debug = 0;
00150
00151
00152 if(!strncmp(file->fs->path, RENDERFARM_FS_PREFIX, vfs_len))
00153 is_vfs = 1;
00154
00155 buffer_size = mpeg3io_total_bytes(file->fs);
00156 buffer = malloc(buffer_size);
00157 mpeg3io_seek(file->fs, 0);
00158 mpeg3io_read_data(buffer, buffer_size, file->fs);
00159
00160
00161 if((toc_version = read_int32(buffer, &position)) != MPEG3_TOC_VERSION)
00162 {
00163 free(buffer);
00164 fprintf(stderr,
00165 "mpeg3_read_toc: invalid TOC version %x\n",
00166 toc_version);
00167 return MPEG3_INVALID_TOC_VERSION;
00168 }
00169
00170
00171
00172 int done = 0;
00173 while(!done && position <= buffer_size - 4)
00174 {
00175
00176 int section_type = read_int32(buffer, &position);
00177
00178 switch(section_type)
00179 {
00180 case FILE_TYPE_PROGRAM:
00181 file->is_program_stream = 1;
00182 break;
00183 case FILE_TYPE_TRANSPORT:
00184 file->is_transport_stream = 1;
00185 break;
00186 case FILE_TYPE_AUDIO:
00187 file->is_audio_stream = 1;
00188 break;
00189 case FILE_TYPE_VIDEO:
00190 file->is_video_stream = 1;
00191 break;
00192
00193 case FILE_INFO:
00194 {
00195 char string[MPEG3_STRLEN];
00196 char string2[MPEG3_STRLEN];
00197 memcpy(string, &buffer[position], MPEG3_STRLEN);
00198 complete_path(string2, file->fs->path, string);
00199
00200 position += MPEG3_STRLEN;
00201 file->source_date = read_int64(buffer, &position);
00202 int64_t current_date = mpeg3_calculate_source_date(string2);
00203
00204
00205
00206
00207
00208
00209 if(current_date != file->source_date)
00210 {
00211 fprintf(stderr, "read_toc: date mismatch\n");
00212 free(buffer);
00213 return MPEG3_TOC_DATE_MISMATCH;
00214 }
00215 break;
00216 }
00217
00218 case STREAM_AUDIO:
00219 {
00220 int number;
00221 int stream_id;
00222 number = read_int32(buffer, &position);
00223 stream_id = read_int32(buffer, &position);
00224 file->demuxer->astream_table[number] = stream_id;
00225 break;
00226 }
00227
00228 case STREAM_VIDEO:
00229 {
00230 int number;
00231 int stream_id;
00232
00233 number = read_int32(buffer, &position);
00234 stream_id = read_int32(buffer, &position);
00235 file->demuxer->vstream_table[number] = stream_id;
00236 break;
00237 }
00238
00239
00240 case ATRACK_COUNT:
00241 *atracks_return = read_int32(buffer, &position);
00242 file->channel_counts = calloc(sizeof(int), *atracks_return);
00243 file->sample_offsets = calloc(sizeof(int64_t*), *atracks_return);
00244 file->total_sample_offsets = calloc(sizeof(int), *atracks_return);
00245 file->audio_eof = calloc(sizeof(int64_t), *atracks_return);
00246 file->total_samples = calloc(sizeof(int64_t), *atracks_return);
00247 file->indexes = calloc(sizeof(mpeg3_index_t*), *atracks_return);
00248 file->total_indexes = *atracks_return;
00249 for(i = 0; i < *atracks_return; i++)
00250 {
00251 file->audio_eof[i] = read_int64(buffer, &position);
00252 file->channel_counts[i] = read_int32(buffer, &position);
00253 file->total_sample_offsets[i] = read_int32(buffer, &position);
00254 file->total_samples[i] = read_int64(buffer, &position);
00255
00256 if(file->total_samples[i] < 1) file->total_samples[i] = 1;
00257 file->sample_offsets[i] = malloc(file->total_sample_offsets[i] * sizeof(int64_t));
00258 for(j = 0; j < file->total_sample_offsets[i]; j++)
00259 {
00260 file->sample_offsets[i][j] = read_int64(buffer, &position);
00261 }
00262
00263 mpeg3_index_t *index = file->indexes[i] = mpeg3_new_index();
00264 index->index_size = read_int32(buffer, &position);
00265 index->index_zoom = read_int32(buffer, &position);
00266
00267 int channels = index->index_channels = file->channel_counts[i];
00268 if(channels)
00269 {
00270 index->index_data = calloc(sizeof(float*), channels);
00271 for(j = 0; j < channels; j++)
00272 {
00273 index->index_data[j] = calloc(sizeof(float),
00274 index->index_size * 2);
00275 read_data(buffer,
00276 &position,
00277 (unsigned char*)index->index_data[j],
00278 sizeof(float) * index->index_size * 2);
00279 }
00280 }
00281 }
00282 break;
00283
00284 case VTRACK_COUNT:
00285 *vtracks_return = read_int32(buffer, &position);
00286 file->frame_offsets = calloc(sizeof(int64_t*), *vtracks_return);
00287 file->total_frame_offsets = calloc(sizeof(int), *vtracks_return);
00288 file->keyframe_numbers = calloc(sizeof(int64_t*), *vtracks_return);
00289 file->total_keyframe_numbers = calloc(sizeof(int), *vtracks_return);
00290 file->video_eof = calloc(sizeof(int64_t), *vtracks_return);
00291 for(i = 0; i < *vtracks_return; i++)
00292 {
00293 file->video_eof[i] = read_int64(buffer, &position);
00294 file->total_frame_offsets[i] = read_int32(buffer, &position);
00295 file->frame_offsets[i] = malloc(file->total_frame_offsets[i] * sizeof(int64_t));
00296 if(debug) printf("mpeg3_read_toc 62 %d %d %lld\n",
00297 file->total_frame_offsets[i], position, buffer_size);
00298 for(j = 0; j < file->total_frame_offsets[i]; j++)
00299 {
00300 file->frame_offsets[i][j] = read_int64(buffer, &position);
00301
00302 }
00303
00304 if(debug) printf("mpeg3_read_toc 64\n");
00305
00306 file->total_keyframe_numbers[i] = read_int32(buffer, &position);
00307 file->keyframe_numbers[i] = malloc(file->total_keyframe_numbers[i] * sizeof(int64_t));
00308 for(j = 0; j < file->total_keyframe_numbers[i]; j++)
00309 {
00310 file->keyframe_numbers[i][j] = read_int64(buffer, &position);
00311 }
00312 }
00313 break;
00314
00315 case STRACK_COUNT:
00316 {
00317 file->total_sstreams = read_int32(buffer, &position);
00318 for(i = 0; i < file->total_sstreams; i++)
00319 {
00320 int id = read_int32(buffer, &position);
00321 mpeg3_strack_t *strack = file->strack[i] = mpeg3_new_strack(id);
00322 strack->total_offsets = read_int32(buffer, &position);
00323 strack->offsets = malloc(sizeof(int64_t) * strack->total_offsets);
00324 strack->allocated_offsets = strack->total_offsets;
00325 for(j = 0; j < strack->total_offsets; j++)
00326 {
00327 strack->offsets[j] = read_int64(buffer, &position);
00328 }
00329 }
00330 break;
00331 }
00332
00333 case TITLE_PATH:
00334 {
00335 char string[MPEG3_STRLEN];
00336 int string_len = 0;
00337 mpeg3_title_t *title;
00338 FILE *test_fd;
00339 if(debug) printf("mpeg3_read_toc 11\n");
00340
00341
00342 if(is_vfs)
00343 {
00344 strcpy(string, RENDERFARM_FS_PREFIX);
00345 string_len = vfs_len;
00346 }
00347 memcpy(string, buffer + position, MPEG3_STRLEN);
00348 position += MPEG3_STRLEN;
00349
00350
00351 if(debug) printf("mpeg3_read_toc 11 position=%x\n", position);
00352 ext = strrchr(string, '.');
00353 if(ext && !strncasecmp(ext, ".m2ts", 5))
00354 file->is_bd = 1;
00355 if(debug) printf("mpeg3_read_toc 12\n");
00356
00357
00358 test_fd = fopen(string, "r");
00359 if(debug) printf("mpeg3_read_toc 20\n");
00360 if(test_fd)
00361 {
00362 fclose(test_fd);
00363 }
00364 else
00365 {
00366
00367
00368 if((!is_vfs && string[0] != '/') ||
00369 (is_vfs && string[vfs_len] != '/'))
00370 {
00371
00372 char *ptr = strrchr(file->fs->path, '/');
00373 if(ptr)
00374 {
00375 char string2[MPEG3_STRLEN];
00376
00377
00378 strcpy(string2, file->fs->path);
00379 if(!is_vfs)
00380 strcpy(&string2[ptr - file->fs->path + 1], string);
00381 else
00382 strcpy(&string2[ptr - file->fs->path + 1], string + vfs_len);
00383
00384 test_fd = fopen(string2, "r");
00385 if(test_fd)
00386 {
00387 fclose(test_fd);
00388 strcpy(string, string2);
00389 }
00390 else
00391 {
00392 fprintf(stderr,
00393 "read_toc: failed to open %s or %s\n",
00394 string,
00395 string2);
00396 return 1;
00397 }
00398 }
00399 else
00400 {
00401 fprintf(stderr,
00402 "read_toc: failed to open %s\n",
00403 string);
00404 return 1;
00405 }
00406 }
00407 else
00408 {
00409 fprintf(stderr,
00410 "read_toc: failed to open %s\n",
00411 string);
00412 return 1;
00413 }
00414 }
00415
00416 if(debug) printf("mpeg3_read_toc 30\n");
00417 title =
00418 file->demuxer->titles[file->demuxer->total_titles++] =
00419 mpeg3_new_title(file, string);
00420
00421 title->total_bytes = read_int64(buffer, &position);
00422 title->start_byte = current_byte;
00423 title->end_byte = title->start_byte + title->total_bytes;
00424 current_byte = title->end_byte;
00425
00426
00427 title->cell_table_size =
00428 title->cell_table_allocation =
00429 read_int32(buffer, &position);
00430
00431 title->cell_table = calloc(title->cell_table_size, sizeof(mpeg3_cell_t));
00432 for(i = 0; i < title->cell_table_size; i++)
00433 {
00434 mpeg3_cell_t *cell = &title->cell_table[i];
00435 cell->title_start = read_int64(buffer, &position);
00436 cell->title_end = read_int64(buffer, &position);
00437 cell->program_start = read_int64(buffer, &position);
00438 cell->program_end = read_int64(buffer, &position);
00439 cell->program = read_int32(buffer, &position);
00440
00441
00442
00443
00444
00445
00446
00447
00448 }
00449
00450 break;
00451 }
00452
00453 case IFO_PALETTE:
00454 for(i = 0; i < 16; i++)
00455 {
00456 file->palette[i * 4 + 0] = (unsigned char)buffer[position++];
00457 file->palette[i * 4 + 1] = (unsigned char)buffer[position++];
00458 file->palette[i * 4 + 2] = (unsigned char)buffer[position++];
00459 file->palette[i * 4 + 3] = (unsigned char)buffer[position++];
00460
00461
00462
00463
00464
00465
00466
00467
00468 }
00469 file->have_palette = 1;
00470 break;
00471 }
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 free(buffer);
00485 if(debug) printf("mpeg3_read_toc 90\n");
00486
00487
00488
00489 mpeg3demux_open_title(file->demuxer, 0);
00490 if(debug) printf("mpeg3_read_toc 100\n");
00491
00492 return 0;
00493 }
00494
00495
00496 mpeg3_t* mpeg3_start_toc(char *path, char *toc_path, int64_t *total_bytes)
00497 {
00498 *total_bytes = 0;
00499 mpeg3_t *file = mpeg3_new(path);
00500
00501
00502 file->toc_fd = fopen(toc_path, "w");
00503 if(!file->toc_fd)
00504 {
00505 printf("mpeg3_start_toc: can't open \"%s\". %s\n",
00506 toc_path,
00507 strerror(errno));
00508 mpeg3_delete(file);
00509 return 0;
00510 }
00511
00512
00513 file->source_date = mpeg3_calculate_source_date(path);
00514 file->seekable = 0;
00515
00516
00517 if(mpeg3io_open_file(file->fs))
00518 {
00519 mpeg3_delete(file);
00520 return 0;
00521 }
00522
00523
00524 int toc_atracks = 0, toc_vtracks = 0;
00525 if(mpeg3_get_file_type(file, 0, 0, 0))
00526 {
00527 mpeg3_delete(file);
00528 return 0;
00529 }
00530
00531
00532
00533
00534 if(!file->demuxer->total_titles)
00535 {
00536 mpeg3_title_t *title;
00537 title = file->demuxer->titles[0] = mpeg3_new_title(file, file->fs->path);
00538 file->demuxer->total_titles = 1;
00539 mpeg3demux_open_title(file->demuxer, 0);
00540 title->total_bytes = mpeg3io_total_bytes(title->fs);
00541 title->start_byte = 0;
00542 title->end_byte = title->total_bytes;
00543 mpeg3_new_cell(title,
00544 0,
00545 title->end_byte,
00546 0,
00547 title->end_byte,
00548 0);
00549 }
00550
00551
00552 mpeg3demux_seek_byte(file->demuxer, 0);
00553 file->demuxer->read_all = 1;
00554 *total_bytes = mpeg3demux_movie_size(file->demuxer);
00555
00556
00557 return file;
00558 }
00559
00560 void mpeg3_set_index_bytes(mpeg3_t *file, int64_t bytes)
00561 {
00562 file->index_bytes = bytes;
00563 }
00564
00565
00566
00567
00568
00569 static void divide_index(mpeg3_t *file, int track_number)
00570 {
00571 if(file->total_indexes <= track_number) return;
00572
00573
00574 int i, j;
00575 mpeg3_atrack_t *atrack = file->atrack[track_number];
00576 mpeg3_index_t *index = file->indexes[track_number];
00577
00578
00579 index->index_size /= 2;
00580 index->index_zoom *= 2;
00581 for(i = 0; i < index->index_channels; i++)
00582 {
00583 float *current_channel = index->index_data[i];
00584 float *out = current_channel;
00585 float *in = current_channel;
00586
00587 for(j = 0; j < index->index_size; j++)
00588 {
00589 float max = MAX(in[0], in[2]);
00590 float min = MIN(in[1], in[3]);
00591 *out++ = max;
00592 *out++ = min;
00593 in += 4;
00594 }
00595 }
00596
00597 }
00598
00599
00600
00601
00602 int mpeg3_update_index(mpeg3_t *file,
00603 int track_number,
00604 int flush)
00605 {
00606 int i, j, k;
00607 mpeg3_atrack_t *atrack = file->atrack[track_number];
00608 mpeg3_index_t *index = file->indexes[track_number];
00609
00610
00611 while((flush && atrack->audio->output_size) ||
00612 (!flush && atrack->audio->output_size > MPEG3_AUDIO_CHUNKSIZE))
00613 {
00614 int fragment = MPEG3_AUDIO_CHUNKSIZE;
00615 if(atrack->audio->output_size < fragment)
00616 fragment = atrack->audio->output_size;
00617
00618 int index_fragments = fragment /
00619 index->index_zoom;
00620 if(flush) index_fragments++;
00621
00622 int new_index_samples;
00623 new_index_samples = index_fragments +
00624 index->index_size;
00625
00626
00627 if(index->index_allocated &&
00628 index->index_channels < atrack->channels)
00629 {
00630 float **new_index_data = calloc(sizeof(float*), atrack->channels);
00631 for(i = 0; i < index->index_channels; i++)
00632 {
00633 new_index_data[i] = index->index_data[i];
00634 }
00635 for(i = index->index_channels; i < atrack->channels; i++)
00636 {
00637 new_index_data[i] = calloc(sizeof(float),
00638 index->index_allocated * 2);
00639 }
00640 index->index_channels = atrack->channels;
00641 free(index->index_data);
00642 index->index_data = new_index_data;
00643 }
00644
00645
00646 if(new_index_samples > index->index_allocated)
00647 {
00648
00649 index->index_allocated = new_index_samples * 2;
00650 if(!index->index_data)
00651 {
00652 index->index_data = calloc(sizeof(float*), atrack->channels);
00653 }
00654
00655
00656 for(i = 0; i < atrack->channels; i++)
00657 index->index_data[i] = realloc(index->index_data[i],
00658 index->index_allocated * sizeof(float) * 2);
00659 index->index_channels = atrack->channels;
00660 }
00661
00662
00663
00664
00665 for(i = 0; i < atrack->channels; i++)
00666 {
00667 float *in_channel = atrack->audio->output[i];
00668 float *out_channel = index->index_data[i] +
00669 index->index_size * 2;
00670 float min = 0;
00671 float max = 0;
00672
00673
00674 for(j = 0; j < index_fragments; j++)
00675 {
00676 int remaining_fragment = fragment - j * index->index_zoom;
00677
00678 if(remaining_fragment < index->index_zoom)
00679 {
00680 for(k = 0; k < remaining_fragment; k++)
00681 {
00682 if(k == 0)
00683 {
00684 min = max = *in_channel++;
00685 }
00686 else
00687 {
00688 if(*in_channel > max) max = *in_channel;
00689 else
00690 if(*in_channel < min) min = *in_channel;
00691 in_channel++;
00692 }
00693 }
00694 }
00695 else
00696 {
00697 min = max = *in_channel++;
00698 for(k = 1; k < index->index_zoom; k++)
00699 {
00700 if(*in_channel > max) max = *in_channel;
00701 else
00702 if(*in_channel < min) min = *in_channel;
00703 in_channel++;
00704 }
00705 }
00706 *out_channel++ = max;
00707 *out_channel++ = min;
00708 }
00709 }
00710
00711 index->index_size = new_index_samples;
00712
00713
00714 mpeg3_shift_audio(atrack->audio, fragment);
00715
00716
00717
00718 mpeg3_append_samples(atrack, atrack->prev_offset);
00719
00720
00721 atrack->current_position += fragment;
00722 }
00723
00724
00725 if(index->index_size * atrack->channels * sizeof(float) * 2 >
00726 file->index_bytes &&
00727 !(index->index_size % 2))
00728 {
00729 divide_index(file, track_number);
00730 }
00731 }
00732
00733
00734
00735 static int handle_audio(mpeg3_t *file,
00736 int track_number)
00737 {
00738 int i, j, k;
00739 mpeg3_atrack_t *atrack = file->atrack[track_number];
00740
00741
00742 atrack->audio_eof = mpeg3demux_tell_byte(file->demuxer);
00743
00744
00745 if(file->demuxer->audio_size)
00746 mpeg3demux_append_data(atrack->demuxer,
00747 file->demuxer->audio_buffer,
00748 file->demuxer->audio_size);
00749 else
00750 if(file->demuxer->data_size)
00751 mpeg3demux_append_data(atrack->demuxer,
00752 file->demuxer->data_buffer,
00753 file->demuxer->data_size);
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 mpeg3audio_decode_audio(atrack->audio,
00776 0,
00777 0,
00778 0,
00779 MPEG3_AUDIO_HISTORY);
00780
00781
00782
00783 mpeg3_update_index(file, track_number, 0);
00784
00785 return 0;
00786 }
00787
00788
00789 static int handle_video(mpeg3_t *file,
00790 mpeg3_vtrack_t *vtrack)
00791 {
00792 mpeg3video_t *video = vtrack->video;
00793
00794
00795
00796 vtrack->video_eof = mpeg3demux_tell_byte(file->demuxer);
00797
00798
00799 if(file->demuxer->video_size)
00800 mpeg3demux_append_data(vtrack->demuxer,
00801 file->demuxer->video_buffer,
00802 file->demuxer->video_size);
00803 else
00804 if(file->demuxer->data_size)
00805 mpeg3demux_append_data(vtrack->demuxer,
00806 file->demuxer->data_buffer,
00807 file->demuxer->data_size);
00808
00809
00810 if(vtrack->demuxer->data_size - vtrack->demuxer->data_position <
00811 MPEG3_VIDEO_STREAM_SIZE) return 0;
00812
00813
00814
00815
00816 unsigned char *ptr = &vtrack->demuxer->data_buffer[
00817 vtrack->demuxer->data_position];
00818 uint32_t code = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
00819 ptr += 4;
00820
00821 while(vtrack->demuxer->data_size - vtrack->demuxer->data_position >
00822 MPEG3_VIDEO_STREAM_SIZE)
00823 {
00824 if(code == MPEG3_SEQUENCE_START_CODE ||
00825 code == MPEG3_GOP_START_CODE ||
00826 code == MPEG3_PICTURE_START_CODE)
00827 {
00828 if(vtrack->prev_frame_offset == -1) vtrack->prev_frame_offset = vtrack->prev_offset;
00829
00830
00831
00832
00833 if(!mpeg3video_get_header(video, 0))
00834 {
00835 if(video->pict_struct == BOTTOM_FIELD ||
00836 video->pict_struct == FRAME_PICTURE ||
00837 !video->pict_struct)
00838 {
00839 int is_keyframe = (video->pict_type == I_TYPE);
00840
00841
00842 mpeg3_append_frame(vtrack, vtrack->prev_frame_offset, is_keyframe);
00843 video->current_repeat += 100;
00844 while(video->repeat_count - video->current_repeat >= 100)
00845 {
00846 mpeg3_append_frame(vtrack, vtrack->prev_frame_offset, is_keyframe);
00847 video->current_repeat += 100;
00848 }
00849
00850
00851 mpeg3demux_shift_data(vtrack->demuxer, vtrack->demuxer->data_position);
00852
00853
00854 ptr = &vtrack->demuxer->data_buffer[
00855 vtrack->demuxer->data_position];
00856 code = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
00857 ptr += 4;
00858
00859 vtrack->prev_frame_offset = -1;
00860 }
00861 else
00862 {
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 break;
00877 }
00878 }
00879 else
00880 {
00881
00882 break;
00883 }
00884 }
00885 else
00886 {
00887 vtrack->demuxer->data_position++;
00888
00889
00890 ptr = &vtrack->demuxer->data_buffer[vtrack->demuxer->data_position];
00891 code = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
00892 }
00893 }
00894
00895 vtrack->demuxer->data_position -= 4;
00896 mpeg3demux_shift_data(vtrack->demuxer, vtrack->demuxer->data_position);
00897
00898
00899 return 0;
00900 }
00901
00902
00903 static void handle_subtitle(mpeg3_t *file)
00904 {
00905 int i, j;
00906 int got_one = 1;
00907 while(got_one)
00908 {
00909 got_one = 0;
00910
00911 mpeg3_subtitle_t *subtitle = 0;
00912 mpeg3_strack_t *strack = 0;
00913 for(i = 0; i < mpeg3_subtitle_tracks(file); i++)
00914 {
00915 strack = mpeg3_get_strack(file, i);
00916 if((subtitle = mpeg3_get_subtitle(strack)))
00917 {
00918 got_one = 1;
00919 break;
00920 }
00921 }
00922
00923
00924 if(subtitle)
00925 {
00926
00927 mpeg3_append_subtitle_offset(strack, subtitle->offset);
00928
00929
00930
00931 mpeg3_pop_subtitle(strack, 0, 1);
00932 }
00933 }
00934 }
00935
00936 int mpeg3_do_toc(mpeg3_t *file, int64_t *bytes_processed)
00937 {
00938 int i, j, k;
00939
00940 int64_t start_byte;
00941
00942 start_byte = mpeg3demux_tell_byte(file->demuxer);
00943
00944
00945 int result = mpeg3_read_next_packet(file->demuxer);
00946
00947
00948
00949 int program = mpeg3demux_tell_program(file->demuxer);
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 if(program == 0)
00967 {
00968
00969 int custom_id = file->demuxer->custom_id;
00970 int got_it = 0;
00971
00972
00973
00974
00975 if(file->demuxer->got_subtitle)
00976 {
00977 handle_subtitle(file);
00978 }
00979
00980
00981
00982
00983 if(file->demuxer->got_audio ||
00984 file->is_transport_stream ||
00985 file->is_audio_stream)
00986 {
00987 for(i = 0; i < file->total_astreams && !got_it; i++)
00988 {
00989 mpeg3_atrack_t *atrack = file->atrack[i];
00990 if(custom_id == atrack->pid)
00991 {
00992
00993
00994
00995
00996
00997
00998 handle_audio(file, i);
00999 atrack->prev_offset = start_byte;
01000 got_it = 1;
01001 break;
01002 }
01003 }
01004
01005 if(!got_it && ((file->demuxer->got_audio &&
01006 file->demuxer->astream_table[custom_id]) ||
01007 file->is_audio_stream))
01008 {
01009 mpeg3_atrack_t *atrack =
01010 file->atrack[file->total_astreams] =
01011 mpeg3_new_atrack(file,
01012 custom_id,
01013 file->demuxer->astream_table[custom_id],
01014 file->demuxer,
01015 file->total_astreams);
01016
01017 if(atrack)
01018 {
01019
01020 file->total_indexes++;
01021 file->indexes = realloc(file->indexes,
01022 file->total_indexes * sizeof(mpeg3_index_t*));
01023 file->indexes[file->total_indexes - 1] =
01024 mpeg3_new_index();
01025
01026
01027 file->total_astreams++;
01028
01029 mpeg3_append_samples(atrack, start_byte);
01030 handle_audio(file, file->total_astreams - 1);
01031 atrack->prev_offset = start_byte;
01032 }
01033 }
01034
01035 }
01036
01037
01038 if(file->demuxer->got_video ||
01039 file->is_transport_stream ||
01040 file->is_video_stream)
01041 {
01042 got_it = 0;
01043 for(i = 0; i < file->total_vstreams && !got_it; i++)
01044 {
01045 mpeg3_vtrack_t *vtrack = file->vtrack[i];
01046 if(vtrack->pid == custom_id)
01047 {
01048
01049 handle_video(file, vtrack);
01050 vtrack->prev_offset = start_byte;
01051 got_it = 1;
01052 break;
01053 }
01054 }
01055
01056
01057
01058 if(!got_it && ((file->demuxer->got_video &&
01059 file->demuxer->vstream_table[custom_id]) ||
01060 file->is_video_stream))
01061 {
01062 mpeg3_vtrack_t *vtrack =
01063 file->vtrack[file->total_vstreams] =
01064 mpeg3_new_vtrack(file,
01065 custom_id,
01066 file->demuxer,
01067 file->total_vstreams);
01068
01069
01070 if(vtrack)
01071 {
01072 file->total_vstreams++;
01073
01074 mpeg3_append_frame(vtrack, start_byte, 1);
01075 handle_video(file, vtrack);
01076 vtrack->prev_offset = start_byte;
01077 }
01078 }
01079 }
01080 }
01081
01082
01083
01084 *bytes_processed = mpeg3demux_tell_byte(file->demuxer);
01085
01086 }
01087
01088
01089
01090
01091
01092
01093
01094 void mpeg3_stop_toc(mpeg3_t *file)
01095 {
01096
01097 int i, j, k;
01098 for(i = 0; i < file->total_astreams; i++)
01099 {
01100 mpeg3_atrack_t *atrack = file->atrack[i];
01101 mpeg3_append_samples(atrack, atrack->prev_offset);
01102 }
01103
01104
01105 for(i = 0; i < file->total_astreams; i++)
01106 mpeg3_update_index(file, i, 1);
01107
01108
01109 int max_scale = 1;
01110 for(i = 0; i < file->total_astreams; i++)
01111 {
01112 mpeg3_atrack_t *atrack = file->atrack[i];
01113 mpeg3_index_t *index = file->indexes[i];
01114 if(index->index_data && index->index_zoom > max_scale)
01115 max_scale = index->index_zoom;
01116 }
01117
01118 for(i = 0; i < file->total_astreams; i++)
01119 {
01120 mpeg3_atrack_t *atrack = file->atrack[i];
01121 mpeg3_index_t *index = file->indexes[i];
01122 if(index->index_data && index->index_zoom < max_scale)
01123 {
01124 while(index->index_zoom < max_scale)
01125 divide_index(file, i);
01126 }
01127 }
01128
01129
01130
01131
01132
01133 int done = 0;
01134 while(!done)
01135 {
01136 done = 1;
01137 for(i = 0; i < file->total_astreams - 1; i++)
01138 {
01139 mpeg3_atrack_t *atrack1 = file->atrack[i];
01140 mpeg3_atrack_t *atrack2 = file->atrack[i + 1];
01141 if(atrack1->pid > atrack2->pid)
01142 {
01143 done = 0;
01144 file->atrack[i + 1] = atrack1;
01145 file->atrack[i] = atrack2;
01146 mpeg3_index_t *index1 = file->indexes[i];
01147 mpeg3_index_t *index2 = file->indexes[i + 1];
01148 file->indexes[i] = index2;
01149 file->indexes[i + 1] = index1;
01150 }
01151 }
01152 }
01153
01154
01155 done = 0;
01156 while(!done)
01157 {
01158 done = 1;
01159 for(i = 0; i < file->total_vstreams - 1; i++)
01160 {
01161 mpeg3_vtrack_t *vtrack1 = file->vtrack[i];
01162 mpeg3_vtrack_t *vtrack2 = file->vtrack[i + 1];
01163 if(vtrack1->pid > vtrack2->pid)
01164 {
01165 done = 0;
01166 file->vtrack[i + 1] = vtrack1;
01167 file->vtrack[i] = vtrack2;
01168 }
01169 }
01170 }
01171
01172
01173
01174
01175
01176 fputc('T', file->toc_fd);
01177 fputc('O', file->toc_fd);
01178 fputc('C', file->toc_fd);
01179 fputc(' ', file->toc_fd);
01180
01181
01182 PUT_INT32(MPEG3_TOC_VERSION);
01183
01184
01185 if(file->is_program_stream)
01186 {
01187 PUT_INT32(FILE_TYPE_PROGRAM);
01188 }
01189 else
01190 if(file->is_transport_stream)
01191 {
01192 PUT_INT32(FILE_TYPE_TRANSPORT);
01193 }
01194 else
01195 if(file->is_audio_stream)
01196 {
01197 PUT_INT32(FILE_TYPE_AUDIO);
01198 }
01199 else
01200 if(file->is_video_stream)
01201 {
01202 PUT_INT32(FILE_TYPE_VIDEO);
01203 }
01204
01205
01206
01207 PUT_INT32(FILE_INFO);
01208 fprintf(file->toc_fd, file->fs->path);
01209 for(j = strlen(file->fs->path); j < MPEG3_STRLEN; j++)
01210 fputc(0, file->toc_fd);
01211 PUT_INT64(file->source_date);
01212
01213
01214
01215 for(i = 0; i < MPEG3_MAX_STREAMS; i++)
01216 {
01217 if(file->demuxer->astream_table[i])
01218 {
01219 PUT_INT32(STREAM_AUDIO);
01220 PUT_INT32(i);
01221 PUT_INT32(file->demuxer->astream_table[i]);
01222 }
01223
01224 if(file->demuxer->vstream_table[i])
01225 {
01226 PUT_INT32(STREAM_VIDEO);
01227 PUT_INT32(i);
01228 PUT_INT32(file->demuxer->vstream_table[i]);
01229 }
01230 }
01231
01232
01233 for(i = 0; i < file->demuxer->total_titles; i++)
01234 {
01235 mpeg3_title_t *title = file->demuxer->titles[i];
01236
01237 PUT_INT32(TITLE_PATH);
01238
01239 fprintf(file->toc_fd, title->fs->path);
01240
01241
01242 for(j = strlen(title->fs->path); j < MPEG3_STRLEN; j++)
01243 fputc(0, file->toc_fd);
01244
01245 PUT_INT64(title->total_bytes);
01246
01247 PUT_INT32(file->demuxer->titles[i]->cell_table_size);
01248 for(j = 0; j < title->cell_table_size; j++)
01249 {
01250 mpeg3_cell_t *cell = &title->cell_table[j];
01251
01252 PUT_INT64(cell->title_start);
01253 PUT_INT64(cell->title_end);
01254 PUT_INT64(cell->program_start);
01255 PUT_INT64(cell->program_end);
01256 PUT_INT32(cell->program);
01257 }
01258 }
01259
01260
01261 PUT_INT32(ATRACK_COUNT);
01262 PUT_INT32(file->total_astreams);
01263
01264
01265 for(j = 0; j < file->total_astreams; j++)
01266 {
01267 mpeg3_atrack_t *atrack = file->atrack[j];
01268 PUT_INT64(atrack->audio_eof);
01269 PUT_INT32(atrack->channels);
01270 PUT_INT32(atrack->total_sample_offsets);
01271
01272 PUT_INT64(atrack->current_position);
01273
01274 for(i = 0; i < atrack->total_sample_offsets; i++)
01275 {
01276 PUT_INT64(atrack->sample_offsets[i]);
01277 }
01278
01279
01280 mpeg3_index_t *index = file->indexes[j];
01281 if(index->index_data)
01282 {
01283 PUT_INT32(index->index_size);
01284 PUT_INT32(index->index_zoom);
01285 for(k = 0; k < atrack->channels; k++)
01286 {
01287 fwrite(index->index_data[k],
01288 sizeof(float) * 2,
01289 index->index_size,
01290 file->toc_fd);
01291 }
01292 }
01293 else
01294 {
01295 PUT_INT32(0);
01296 PUT_INT32(1);
01297 }
01298 }
01299
01300
01301
01302
01303
01304 PUT_INT32(VTRACK_COUNT);
01305 PUT_INT32(file->total_vstreams);
01306
01307
01308 for(j = 0; j < file->total_vstreams; j++)
01309 {
01310 mpeg3_vtrack_t *vtrack = file->vtrack[j];
01311 PUT_INT64(vtrack->video_eof);
01312 PUT_INT32(vtrack->total_frame_offsets);
01313 for(i = 0; i < vtrack->total_frame_offsets; i++)
01314 {
01315 PUT_INT64(vtrack->frame_offsets[i]);
01316 }
01317
01318 PUT_INT32(vtrack->total_keyframe_numbers);
01319 for(i = 0; i < vtrack->total_keyframe_numbers; i++)
01320 {
01321 PUT_INT64(vtrack->keyframe_numbers[i]);
01322 }
01323 }
01324
01325
01326
01327
01328 PUT_INT32(STRACK_COUNT);
01329 PUT_INT32(file->total_sstreams);
01330
01331
01332 for(i = 0; i < file->total_sstreams; i++)
01333 {
01334 mpeg3_strack_t *strack = file->strack[i];
01335 PUT_INT32(strack->id);
01336 PUT_INT32(strack->total_offsets);
01337 for(j = 0; j < strack->total_offsets; j++)
01338 {
01339 PUT_INT64(strack->offsets[j]);
01340 }
01341 }
01342
01343
01344 PUT_INT32(IFO_PALETTE);
01345 for(i = 0; i < 16 * 4; i++)
01346 {
01347 fputc(file->palette[i], file->toc_fd);
01348 }
01349
01350
01351 fclose(file->toc_fd);
01352
01353
01354 mpeg3_delete(file);
01355 }
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365 int mpeg3_index_tracks(mpeg3_t *file)
01366 {
01367 return file->total_indexes;
01368 }
01369
01370 int mpeg3_index_channels(mpeg3_t *file, int track)
01371 {
01372 if(!file->total_indexes) return 0;
01373 return file->indexes[track]->index_channels;
01374 }
01375
01376 int mpeg3_index_zoom(mpeg3_t *file)
01377 {
01378 if(!file->total_indexes) return 0;
01379
01380 return file->indexes[0]->index_zoom;
01381 }
01382
01383 int mpeg3_index_size(mpeg3_t *file, int track)
01384 {
01385 if(!file->total_indexes) return 0;
01386 return file->indexes[track]->index_size;
01387 }
01388
01389 float* mpeg3_index_data(mpeg3_t *file, int track, int channel)
01390 {
01391 if(!file->total_indexes) return 0;
01392 return file->indexes[track]->index_data[channel];
01393 }
01394
01395
01396 int mpeg3_has_toc(mpeg3_t *file)
01397 {
01398 if(file->frame_offsets || file->sample_offsets) return 1;
01399 return 0;
01400 }
01401
01402 char* mpeg3_title_path(mpeg3_t *file, int number)
01403 {
01404 if(number < file->demuxer->total_titles)
01405 {
01406 return file->demuxer->titles[number]->fs->path;
01407 }
01408 return 0;
01409 }
01410
01411 int64_t mpeg3_get_source_date(mpeg3_t *file)
01412 {
01413 return file->source_date;
01414 }
01415
01416 int64_t mpeg3_calculate_source_date(char *path)
01417 {
01418 struct stat64 ostat;
01419 bzero(&ostat, sizeof(struct stat64));
01420 stat64(path, &ostat);
01421 return ostat.st_mtime;
01422 }