r706: French translation update by Jean-Luc Coulon.
[cinelerra_cv.git] / libmpeg3 / mpeg3tocutil.c
blob6161433379231cc1f89a6261aa498ca8a1f365cf
1 #include "libmpeg3.h"
2 #include "mpeg3protos.h"
4 #include <errno.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
10 static uint32_t read_int32(unsigned char *buffer, int *position)
12 uint32_t temp;
14 if(MPEG3_LITTLE_ENDIAN)
16 ((unsigned char*)&temp)[3] = buffer[(*position)++];
17 ((unsigned char*)&temp)[2] = buffer[(*position)++];
18 ((unsigned char*)&temp)[1] = buffer[(*position)++];
19 ((unsigned char*)&temp)[0] = buffer[(*position)++];
21 else
23 ((unsigned char*)&temp)[0] = buffer[(*position)++];
24 ((unsigned char*)&temp)[1] = buffer[(*position)++];
25 ((unsigned char*)&temp)[2] = buffer[(*position)++];
26 ((unsigned char*)&temp)[3] = buffer[(*position)++];
29 return temp;
32 static uint64_t read_int64(unsigned char *buffer, int *position)
34 uint64_t temp;
36 if(MPEG3_LITTLE_ENDIAN)
38 ((unsigned char*)&temp)[7] = buffer[(*position)++];
39 ((unsigned char*)&temp)[6] = buffer[(*position)++];
40 ((unsigned char*)&temp)[5] = buffer[(*position)++];
41 ((unsigned char*)&temp)[4] = buffer[(*position)++];
42 ((unsigned char*)&temp)[3] = buffer[(*position)++];
43 ((unsigned char*)&temp)[2] = buffer[(*position)++];
44 ((unsigned char*)&temp)[1] = buffer[(*position)++];
45 ((unsigned char*)&temp)[0] = buffer[(*position)++];
47 else
49 ((unsigned char*)&temp)[0] = buffer[(*position)++];
50 ((unsigned char*)&temp)[1] = buffer[(*position)++];
51 ((unsigned char*)&temp)[2] = buffer[(*position)++];
52 ((unsigned char*)&temp)[3] = buffer[(*position)++];
53 ((unsigned char*)&temp)[4] = buffer[(*position)++];
54 ((unsigned char*)&temp)[5] = buffer[(*position)++];
55 ((unsigned char*)&temp)[6] = buffer[(*position)++];
56 ((unsigned char*)&temp)[7] = buffer[(*position)++];
59 return temp;
62 static int read_data(unsigned char *buffer,
63 int *position,
64 unsigned char *output,
65 int bytes)
67 memcpy(output, buffer + *position, bytes);
68 *position += bytes;
71 int mpeg3_read_toc(mpeg3_t *file, int *atracks_return, int *vtracks_return)
73 unsigned char *buffer;
74 int file_type;
75 int position = 4;
76 int stream_type;
77 int i, j;
78 int is_vfs = 0;
79 int vfs_len = strlen(RENDERFARM_FS_PREFIX);
80 int toc_version;
81 int64_t current_byte = 0;
83 //printf("read_toc 1\n");
84 // Fix title paths for Cinelerra VFS
85 if(!strncmp(file->fs->path, RENDERFARM_FS_PREFIX, vfs_len))
86 is_vfs = 1;
88 buffer = malloc(mpeg3io_total_bytes(file->fs));
89 mpeg3io_seek(file->fs, 0);
90 mpeg3io_read_data(buffer, mpeg3io_total_bytes(file->fs), file->fs);
92 // Test version
93 if((toc_version = buffer[position++]) != MPEG3_TOC_VERSION)
95 fprintf(stderr,
96 "read_toc: invalid TOC version %x\n",
97 toc_version);
98 return 1;
101 //printf("read_toc %lld\n", mpeg3io_total_bytes(file->fs));
103 // File type
104 file_type = buffer[position++];
105 switch(file_type)
107 case FILE_TYPE_PROGRAM:
108 file->is_program_stream = 1;
109 break;
110 case FILE_TYPE_TRANSPORT:
111 file->is_transport_stream = 1;
112 break;
113 case FILE_TYPE_AUDIO:
114 file->is_audio_stream = 1;
115 break;
116 case FILE_TYPE_VIDEO:
117 file->is_video_stream = 1;
118 break;
121 //printf("read_toc 10\n");
123 // Stream ID's
124 while((stream_type = buffer[position]) != TITLE_PATH)
126 int offset;
127 int stream_id;
129 //printf("read_toc %d %x\n", position, buffer[position]);
130 position++;
131 offset = read_int32(buffer, &position);
132 stream_id = read_int32(buffer, &position);
134 if(stream_type == STREAM_AUDIO)
136 file->demuxer->astream_table[offset] = stream_id;
139 if(stream_type == STREAM_VIDEO)
141 file->demuxer->vstream_table[offset] = stream_id;
147 //printf("read_toc 10\n");
150 // Titles
151 while(buffer[position] == TITLE_PATH)
153 char string[MPEG3_STRLEN];
154 int string_len = 0;
155 mpeg3_title_t *title;
156 FILE *test_fd;
158 // Construct title path from VFS prefix and path.
159 position++;
160 if(is_vfs)
162 strcpy(string, RENDERFARM_FS_PREFIX);
163 string_len = vfs_len;
165 while(buffer[position] != 0) string[string_len++] = buffer[position++];
166 string[string_len++] = 0;
167 position++;
169 // Test title availability
170 test_fd = fopen(string, "r");
171 if(test_fd)
173 fclose(test_fd);
175 else
177 // Try concatenating title and toc directory if title is not absolute and
178 // toc path has a directory section.
179 if((!is_vfs && string[0] != '/') ||
180 (is_vfs && string[vfs_len] != '/'))
182 // Get toc filename without path
183 char *ptr = strrchr(file->fs->path, '/');
184 if(ptr)
186 char string2[MPEG3_STRLEN];
188 // Stack filename on toc path
189 strcpy(string2, file->fs->path);
190 if(!is_vfs)
191 strcpy(&string2[ptr - file->fs->path + 1], string);
192 else
193 strcpy(&string2[ptr - file->fs->path + 1], string + vfs_len);
195 test_fd = fopen(string2, "r");
196 if(test_fd)
198 fclose(test_fd);
199 strcpy(string, string2);
201 else
203 fprintf(stderr,
204 "read_toc: failed to open %s or %s\n",
205 string,
206 string2);
207 return 1;
210 else
212 fprintf(stderr,
213 "read_toc: failed to open %s\n",
214 string);
215 return 1;
218 else
220 fprintf(stderr,
221 "read_toc: failed to open %s\n",
222 string);
223 return 1;
227 title =
228 file->demuxer->titles[file->demuxer->total_titles++] =
229 mpeg3_new_title(file, string);
231 title->total_bytes = read_int64(buffer, &position);
232 title->start_byte = current_byte;
233 title->end_byte = title->start_byte + title->total_bytes;
234 current_byte = title->end_byte;
236 // Cells
237 title->cell_table_size =
238 title->cell_table_allocation =
239 read_int32(buffer, &position);
240 title->cell_table = calloc(title->cell_table_size, sizeof(mpeg3_cell_t));
241 for(i = 0; i < title->cell_table_size; i++)
243 mpeg3_cell_t *cell = &title->cell_table[i];
244 cell->title_start = read_int64(buffer, &position);
245 cell->title_end = read_int64(buffer, &position);
246 cell->program_start = read_int64(buffer, &position);
247 cell->program_end = read_int64(buffer, &position);
248 cell->program = read_int32(buffer, &position);
251 //printf("read_toc 10\n");
255 // Audio streams
256 // Skip ATRACK_COUNT
257 position++;
258 *atracks_return = read_int32(buffer, &position);
259 //printf("read_toc 1 %d\n", *atracks_return);
261 // Skip VTRACK_COUNT
262 position++;
263 *vtracks_return = read_int32(buffer, &position);
264 //printf("read_toc 2 %d\n", *vtracks_return);
267 if(*atracks_return)
269 file->channel_counts = calloc(sizeof(int), *atracks_return);
270 file->sample_offsets = calloc(sizeof(int64_t*), *atracks_return);
271 file->total_sample_offsets = calloc(sizeof(int*), *atracks_return);
272 file->audio_eof = calloc(sizeof(int64_t), *atracks_return);
274 for(i = 0; i < *atracks_return; i++)
276 file->audio_eof[i] = read_int64(buffer, &position);
277 file->channel_counts[i] = read_int32(buffer, &position);
278 file->total_sample_offsets[i] = read_int32(buffer, &position);
279 file->sample_offsets[i] = malloc(file->total_sample_offsets[i] * sizeof(int64_t));
280 for(j = 0; j < file->total_sample_offsets[i]; j++)
282 file->sample_offsets[i][j] = read_int64(buffer, &position);
284 //printf("samples %d %x %llx\n", i, file->sample_offsets[i][0]);
287 //printf("read_toc 10\n");
289 if(*vtracks_return)
291 file->frame_offsets = calloc(sizeof(int64_t*), *vtracks_return);
292 file->total_frame_offsets = calloc(sizeof(int*), *vtracks_return);
293 file->keyframe_numbers = calloc(sizeof(int64_t*), *vtracks_return);
294 file->total_keyframe_numbers = calloc(sizeof(int*), *vtracks_return);
295 file->video_eof = calloc(sizeof(int64_t), *vtracks_return);
297 for(i = 0; i < *vtracks_return; i++)
299 file->video_eof[i] = read_int64(buffer, &position);
300 file->total_frame_offsets[i] = read_int32(buffer, &position);
301 file->frame_offsets[i] = malloc(file->total_frame_offsets[i] * sizeof(int64_t));
302 for(j = 0; j < file->total_frame_offsets[i]; j++)
304 file->frame_offsets[i][j] = read_int64(buffer, &position);
305 //printf("frame %llx\n", file->frame_offsets[i][j]);
309 file->total_keyframe_numbers[i] = read_int32(buffer, &position);
310 file->keyframe_numbers[i] = malloc(file->total_keyframe_numbers[i] * sizeof(int64_t));
311 for(j = 0; j < file->total_keyframe_numbers[i]; j++)
313 file->keyframe_numbers[i][j] = read_int64(buffer, &position);
320 // Indexes. ATracks aren't created yet so we need to put the indexes somewhere
321 // else.
322 file->indexes = calloc(sizeof(mpeg3_index_t*), *atracks_return);
323 file->total_indexes = *atracks_return;
324 for(i = 0; i < *atracks_return; i++)
326 mpeg3_index_t *index = file->indexes[i] = mpeg3_new_index();
328 index->index_size = read_int32(buffer, &position);
329 index->index_zoom = read_int32(buffer, &position);
330 //printf("mpeg3_read_toc %d %d %d\n", i, index->index_size, index->index_zoom);
331 int channels = index->index_channels = file->channel_counts[i];
332 if(channels)
334 index->index_data = calloc(sizeof(float*), channels);
335 for(j = 0; j < channels; j++)
337 index->index_data[j] = calloc(sizeof(float),
338 index->index_size * 2);
339 read_data(buffer,
340 &position,
341 (unsigned char*)index->index_data[j],
342 sizeof(float) * index->index_size * 2);
351 free(buffer);
352 //printf("read_toc 10\n");
356 //printf("read_toc 1\n");
357 mpeg3demux_open_title(file->demuxer, 0);
358 //printf("read_toc 10\n");
360 return 0;
364 mpeg3_t* mpeg3_start_toc(char *path, char *toc_path, int64_t *total_bytes)
366 *total_bytes = 0;
367 mpeg3_t *file = mpeg3_new(path);
369 file->toc_fd = fopen(toc_path, "w");
370 if(!file->toc_fd)
372 printf("mpeg3_start_toc: can't open \"%s\". %s\n",
373 toc_path,
374 strerror(errno));
375 mpeg3_delete(file);
376 return 0;
381 file->seekable = 0;
383 /* Authenticate encryption before reading a single byte */
384 if(mpeg3io_open_file(file->fs))
386 mpeg3_delete(file);
387 return 0;
390 // Determine file type
391 int toc_atracks = 0, toc_vtracks = 0;
392 if(mpeg3_get_file_type(file, 0, 0, 0)) return 0;
396 // Create title without scanning for tracks
397 if(!file->demuxer->total_titles)
399 mpeg3_title_t *title;
400 title = file->demuxer->titles[0] = mpeg3_new_title(file, file->fs->path);
401 file->demuxer->total_titles = 1;
402 mpeg3demux_open_title(file->demuxer, 0);
403 title->total_bytes = mpeg3io_total_bytes(title->fs);
404 title->start_byte = 0;
405 title->end_byte = title->total_bytes;
406 mpeg3_new_cell(title,
408 title->end_byte,
410 title->end_byte,
414 // mpeg3demux_seek_byte(file->demuxer, 0x1734e4800LL);
415 mpeg3demux_seek_byte(file->demuxer, 0);
416 file->demuxer->read_all = 1;
417 *total_bytes = mpeg3demux_movie_size(file->demuxer);
419 return file;
422 void mpeg3_set_index_bytes(mpeg3_t *file, int64_t bytes)
424 file->index_bytes = bytes;
431 static void divide_index(mpeg3_t *file, int track_number)
433 if(file->total_indexes <= track_number) return;
436 int i, j;
437 mpeg3_atrack_t *atrack = file->atrack[track_number];
438 mpeg3_index_t *index = file->indexes[track_number];
441 index->index_size /= 2;
442 index->index_zoom *= 2;
443 for(i = 0; i < index->index_channels; i++)
445 float *current_channel = index->index_data[i];
446 float *out = current_channel;
447 float *in = current_channel;
449 for(j = 0; j < index->index_size; j++)
451 float max = MAX(in[0], in[2]);
452 float min = MIN(in[1], in[3]);
453 *out++ = max;
454 *out++ = min;
455 in += 4;
464 int mpeg3_update_index(mpeg3_t *file,
465 int track_number,
466 int flush)
468 int i, j, k;
469 mpeg3_atrack_t *atrack = file->atrack[track_number];
470 mpeg3_index_t *index = file->indexes[track_number];
473 while((flush && atrack->audio->output_size) ||
474 (!flush && atrack->audio->output_size > MPEG3_AUDIO_CHUNKSIZE))
476 int fragment = MPEG3_AUDIO_CHUNKSIZE;
477 if(atrack->audio->output_size < fragment)
478 fragment = atrack->audio->output_size;
480 int index_fragments = fragment /
481 index->index_zoom;
482 if(flush) index_fragments++;
484 int new_index_samples;
485 new_index_samples = index_fragments +
486 index->index_size;
488 // Update number of channels
489 if(index->index_allocated &&
490 index->index_channels < atrack->channels)
492 float **new_index_data = calloc(sizeof(float*), atrack->channels);
493 for(i = 0; i < index->index_channels; i++)
495 new_index_data[i] = index->index_data[i];
497 for(i = index->index_channels; i < atrack->channels; i++)
499 new_index_data[i] = calloc(sizeof(float),
500 index->index_allocated * 2);
502 index->index_channels = atrack->channels;
503 free(index->index_data);
504 index->index_data = new_index_data;
507 // Allocate index buffer
508 if(new_index_samples > index->index_allocated)
510 // Double current number of samples
511 index->index_allocated = new_index_samples * 2;
512 if(!index->index_data)
514 index->index_data = calloc(sizeof(float*), atrack->channels);
517 // Allocate new size in high and low pairs
518 for(i = 0; i < atrack->channels; i++)
519 index->index_data[i] = realloc(index->index_data[i],
520 index->index_allocated * sizeof(float) * 2);
521 index->index_channels = atrack->channels;
526 // Calculate new index chunk
527 for(i = 0; i < atrack->channels; i++)
529 float *in_channel = atrack->audio->output[i];
530 float *out_channel = index->index_data[i] +
531 index->index_size * 2;
532 float min = 0;
533 float max = 0;
535 // Calculate index frames
536 for(j = 0; j < index_fragments; j++)
538 int remaining_fragment = fragment - j * index->index_zoom;
539 // Incomplete index frame
540 if(remaining_fragment < index->index_zoom)
542 for(k = 0; k < remaining_fragment; k++)
544 if(k == 0)
546 min = max = *in_channel++;
548 else
550 if(*in_channel > max) max = *in_channel;
551 else
552 if(*in_channel < min) min = *in_channel;
553 in_channel++;
557 else
559 min = max = *in_channel++;
560 for(k = 1; k < index->index_zoom; k++)
562 if(*in_channel > max) max = *in_channel;
563 else
564 if(*in_channel < min) min = *in_channel;
565 in_channel++;
568 *out_channel++ = max;
569 *out_channel++ = min;
573 index->index_size = new_index_samples;
575 // Shift audio buffer
576 mpeg3_shift_audio(atrack->audio, fragment);
579 // Create new toc entry
580 mpeg3_append_samples(atrack, atrack->prev_offset);
583 atrack->current_position += fragment;
586 // Divide index by 2 and increase zoom
587 if(index->index_size * atrack->channels * sizeof(float) * 2 >
588 file->index_bytes &&
589 !(index->index_size % 2))
591 divide_index(file, track_number);
597 int mpeg3_toc_audio(mpeg3_t *file,
598 int track_number)
600 int i, j, k;
601 mpeg3_atrack_t *atrack = file->atrack[track_number];
603 // Assume last packet of stream
604 atrack->audio_eof = mpeg3demux_tell_byte(file->demuxer);
606 // Append demuxed data to track buffer
607 mpeg3demux_append_data(atrack->demuxer,
608 file->demuxer->audio_buffer,
609 file->demuxer->audio_size);
612 // Decode samples
613 mpeg3audio_decode_audio(atrack->audio,
617 MPEG3_AUDIO_HISTORY);
619 // When a chunk is available,
620 // add downsampled samples to the index buffer and create toc entry.
621 mpeg3_update_index(file, track_number, 0);
623 return 0;
626 int mpeg3_toc_video(mpeg3_t *file,
627 mpeg3_vtrack_t *vtrack)
629 mpeg3video_t *video = vtrack->video;
632 * static FILE *test = 0;
633 * if(!test) test = fopen("test.m2v", "w");
634 * fwrite(file->demuxer->data_buffer, 1, file->demuxer->data_size, test);
635 * static int counter = 0;
636 * printf("%x %d\n", vtrack->pid, counter++);
638 // Assume last packet of stream
639 vtrack->video_eof = mpeg3demux_tell_byte(file->demuxer);
641 // Append demuxed data to track buffer
642 mpeg3demux_append_data(vtrack->demuxer,
643 file->demuxer->video_buffer,
644 file->demuxer->video_size);
647 if(vtrack->demuxer->data_size - vtrack->demuxer->data_position <
648 MPEG3_VIDEO_STREAM_SIZE) return 0;
650 // Scan for a start code a certain number of bytes from the end of the
651 // buffer. Then scan the header using the video decoder to get the
652 // repeat count.
653 unsigned char *ptr = &vtrack->demuxer->data_buffer[
654 vtrack->demuxer->data_position];
655 uint32_t code = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
656 ptr += 4;
657 while(vtrack->demuxer->data_size - vtrack->demuxer->data_position >
658 MPEG3_VIDEO_STREAM_SIZE)
660 if(code == MPEG3_SEQUENCE_START_CODE ||
661 code == MPEG3_GOP_START_CODE ||
662 code == MPEG3_PICTURE_START_CODE)
665 // Use video decoder to get repeat count and field type. Should never hit EOF in here.
666 // This rereads up to the current ptr since data_position isn't updated by
667 // mpeg3_toc_video.
668 if(!mpeg3video_get_header(video, 0))
670 if(video->pict_struct == BOTTOM_FIELD ||
671 video->pict_struct == FRAME_PICTURE ||
672 !video->pict_struct)
674 int is_keyframe = (video->pict_type == I_TYPE);
676 // Add entry for every repeat count.
677 mpeg3_append_frame(vtrack, vtrack->prev_offset, is_keyframe);
678 video->current_repeat += 100;
679 while(video->repeat_count - video->current_repeat >= 100)
681 mpeg3_append_frame(vtrack, vtrack->prev_offset, is_keyframe);
682 video->current_repeat += 100;
685 ptr = &vtrack->demuxer->data_buffer[
686 vtrack->demuxer->data_position];
687 code = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
688 ptr += 4;
690 // Shift out data from before frame
691 mpeg3demux_shift_data(vtrack->demuxer, vtrack->demuxer->data_position);
694 else
696 // Try this offset again with more data
697 break;
700 else
702 vtrack->demuxer->data_position++;
703 code <<= 8;
704 code |= *ptr++;
707 vtrack->demuxer->data_position -= 4;
710 return 0;
713 int mpeg3_do_toc(mpeg3_t *file, int64_t *bytes_processed)
715 int i, j, k;
716 // Starting byte before our packet read
717 int64_t start_byte;
719 start_byte = mpeg3demux_tell_byte(file->demuxer);
721 int result = mpeg3_read_next_packet(file->demuxer);
723 // Determine program and stream id for current packet. Should be only one.
724 int program = mpeg3demux_tell_program(file->demuxer);
728 * if(start_byte > 0x1b0000 &&
729 * start_byte < 0x1c0000)
730 * printf("mpeg3_do_toc 1 start_byte=%llx custum_id=%x got_audio=%d got_video=%d audio_size=%d video_size=%d data_size=%d\n",
731 * start_byte,
732 * file->demuxer->custom_id,
733 * file->demuxer->got_audio,
734 * file->demuxer->got_video,
735 * file->demuxer->audio_size,
736 * file->demuxer->video_size,
737 * file->demuxer->data_size);
740 // Only handle program 0
741 if(program == 0)
743 // Find current PID in tracks.
744 int custom_id = file->demuxer->custom_id;
745 int got_it = 0;
748 // In a transport stream the PID's are unique for all audio and video but in
749 // other streams the PID's are shared.
750 if(file->demuxer->got_audio ||
751 file->is_transport_stream ||
752 file->is_audio_stream)
754 for(i = 0; i < file->total_astreams && !got_it; i++)
756 mpeg3_atrack_t *atrack = file->atrack[i];
757 if(custom_id == atrack->pid)
759 //printf("mpeg3_do_toc 2 %x\n", atrack->pid);
760 // Update an audio track
761 mpeg3_toc_audio(file, i);
762 atrack->prev_offset = start_byte;
763 got_it = 1;
764 break;
768 if(!got_it && ((file->demuxer->got_audio &&
769 file->demuxer->astream_table[custom_id]) ||
770 file->is_audio_stream))
772 mpeg3_atrack_t *atrack =
773 file->atrack[file->total_astreams] =
774 mpeg3_new_atrack(file,
775 custom_id,
776 file->demuxer->astream_table[custom_id],
777 file->demuxer,
778 file->total_astreams);
780 if(atrack)
782 // Create index table
783 file->total_indexes++;
784 file->indexes = realloc(file->indexes,
785 file->total_indexes * sizeof(mpeg3_index_t*));
786 file->indexes[file->total_indexes - 1] =
787 mpeg3_new_index();
790 file->total_astreams++;
791 // Make the first offset correspond to the start of the first packet.
792 mpeg3_append_samples(atrack, start_byte);
793 mpeg3_toc_audio(file, file->total_astreams - 1);
794 atrack->prev_offset = start_byte;
801 if(file->demuxer->got_video ||
802 file->is_transport_stream ||
803 file->is_video_stream)
805 got_it = 0;
806 for(i = 0; i < file->total_vstreams && !got_it; i++)
808 mpeg3_vtrack_t *vtrack = file->vtrack[i];
809 if(vtrack->pid == custom_id)
811 // Update a video track
812 mpeg3_toc_video(file, vtrack);
813 vtrack->prev_offset = start_byte;
814 got_it = 1;
815 break;
821 if(!got_it && ((file->demuxer->got_video &&
822 file->demuxer->vstream_table[custom_id]) ||
823 file->is_video_stream))
825 mpeg3_vtrack_t *vtrack =
826 file->vtrack[file->total_vstreams] =
827 mpeg3_new_vtrack(file,
828 custom_id,
829 file->demuxer,
830 file->total_vstreams);
832 // Make the first offset correspond to the start of the first packet.
833 if(vtrack)
835 file->total_vstreams++;
836 // Create table entry for frame 0
837 mpeg3_append_frame(vtrack, start_byte, 1);
838 mpeg3_toc_video(file, vtrack);
839 vtrack->prev_offset = start_byte;
846 // Make user value independant of data type in packet
847 *bytes_processed = mpeg3demux_tell_byte(file->demuxer);
848 //printf("mpeg3_do_toc 1000 %llx\n", *bytes_processed);
855 #define PUT_INT32(x) \
857 if(MPEG3_LITTLE_ENDIAN) \
859 fputc(((unsigned char*)&x)[3], file->toc_fd); \
860 fputc(((unsigned char*)&x)[2], file->toc_fd); \
861 fputc(((unsigned char*)&x)[1], file->toc_fd); \
862 fputc(((unsigned char*)&x)[0], file->toc_fd); \
864 else \
866 fputc(((unsigned char*)&x)[0], file->toc_fd); \
867 fputc(((unsigned char*)&x)[1], file->toc_fd); \
868 fputc(((unsigned char*)&x)[2], file->toc_fd); \
869 fputc(((unsigned char*)&x)[3], file->toc_fd); \
876 #define PUT_INT64(x) \
878 if(MPEG3_LITTLE_ENDIAN) \
880 fputc(((unsigned char*)&x)[7], file->toc_fd); \
881 fputc(((unsigned char*)&x)[6], file->toc_fd); \
882 fputc(((unsigned char*)&x)[5], file->toc_fd); \
883 fputc(((unsigned char*)&x)[4], file->toc_fd); \
884 fputc(((unsigned char*)&x)[3], file->toc_fd); \
885 fputc(((unsigned char*)&x)[2], file->toc_fd); \
886 fputc(((unsigned char*)&x)[1], file->toc_fd); \
887 fputc(((unsigned char*)&x)[0], file->toc_fd); \
889 else \
891 fwrite(&x, 1, 8, file->toc_fd); \
899 void mpeg3_stop_toc(mpeg3_t *file)
901 // Create final chunk for audio tracks to count the last samples.
902 int i, j;
903 for(i = 0; i < file->total_astreams; i++)
905 mpeg3_atrack_t *atrack = file->atrack[i];
906 mpeg3_append_samples(atrack, atrack->prev_offset);
909 // Flush audio indexes
910 for(i = 0; i < file->total_astreams; i++)
911 mpeg3_update_index(file, i, 1);
913 // Make all indexes the same scale
914 int max_scale = 1;
915 for(i = 0; i < file->total_astreams; i++)
917 mpeg3_atrack_t *atrack = file->atrack[i];
918 mpeg3_index_t *index = file->indexes[i];
919 if(index->index_data && index->index_zoom > max_scale)
920 max_scale = index->index_zoom;
923 for(i = 0; i < file->total_astreams; i++)
925 mpeg3_atrack_t *atrack = file->atrack[i];
926 mpeg3_index_t *index = file->indexes[i];
927 if(index->index_data && index->index_zoom < max_scale)
929 while(index->index_zoom < max_scale)
930 divide_index(file, i);
937 // Sort tracks by PID
938 int done = 0;
939 while(!done)
941 done = 1;
942 for(i = 0; i < file->total_astreams - 1; i++)
944 mpeg3_atrack_t *atrack1 = file->atrack[i];
945 mpeg3_atrack_t *atrack2 = file->atrack[i + 1];
946 if(atrack1->pid > atrack2->pid)
948 done = 0;
949 file->atrack[i + 1] = atrack1;
950 file->atrack[i] = atrack2;
951 mpeg3_index_t *index1 = file->indexes[i];
952 mpeg3_index_t *index2 = file->indexes[i + 1];
953 file->indexes[i] = index2;
954 file->indexes[i + 1] = index1;
960 done = 0;
961 while(!done)
963 done = 1;
964 for(i = 0; i < file->total_vstreams - 1; i++)
966 mpeg3_vtrack_t *vtrack1 = file->vtrack[i];
967 mpeg3_vtrack_t *vtrack2 = file->vtrack[i + 1];
968 if(vtrack1->pid > vtrack2->pid)
970 done = 0;
971 file->vtrack[i + 1] = vtrack1;
972 file->vtrack[i] = vtrack2;
979 // Output toc to file
980 // Write file type
981 fputc('T', file->toc_fd);
982 fputc('O', file->toc_fd);
983 fputc('C', file->toc_fd);
984 fputc(' ', file->toc_fd);
986 // Write version
987 fputc(MPEG3_TOC_VERSION, file->toc_fd);
989 // Write stream type
990 if(file->is_program_stream)
992 fputc(FILE_TYPE_PROGRAM, file->toc_fd);
994 else
995 if(file->is_transport_stream)
997 fputc(FILE_TYPE_TRANSPORT, file->toc_fd);
999 else
1000 if(file->is_audio_stream)
1002 fputc(FILE_TYPE_AUDIO, file->toc_fd);
1004 else
1005 if(file->is_video_stream)
1007 fputc(FILE_TYPE_VIDEO, file->toc_fd);
1010 // Write stream ID's
1011 // Only program and transport streams have these
1012 for(i = 0; i < MPEG3_MAX_STREAMS; i++)
1014 if(file->demuxer->astream_table[i])
1016 fputc(STREAM_AUDIO, file->toc_fd);
1017 PUT_INT32(i);
1018 PUT_INT32(file->demuxer->astream_table[i]);
1021 if(file->demuxer->vstream_table[i])
1023 fputc(STREAM_VIDEO, file->toc_fd);
1024 PUT_INT32(i);
1025 PUT_INT32(file->demuxer->vstream_table[i]);
1029 // Write titles
1030 for(i = 0; i < file->demuxer->total_titles; i++)
1032 mpeg3_title_t *title = file->demuxer->titles[i];
1033 // Path
1034 fputc(TITLE_PATH, file->toc_fd);
1035 fprintf(file->toc_fd, title->fs->path);
1036 fputc(0, file->toc_fd);
1037 // Total bytes
1038 PUT_INT64(title->total_bytes);
1039 // Byte offsets of cells
1040 PUT_INT32(file->demuxer->titles[i]->cell_table_size);
1041 for(j = 0; j < title->cell_table_size; j++)
1043 mpeg3_cell_t *cell = &title->cell_table[j];
1044 PUT_INT64(cell->title_start);
1045 PUT_INT64(cell->title_end);
1046 PUT_INT64(cell->program_start);
1047 PUT_INT64(cell->program_end);
1048 PUT_INT32(cell->program);
1054 fputc(ATRACK_COUNT, file->toc_fd);
1055 PUT_INT32(file->total_astreams);
1057 fputc(VTRACK_COUNT, file->toc_fd);
1058 PUT_INT32(file->total_vstreams);
1060 // Audio streams
1061 for(j = 0; j < file->total_astreams; j++)
1063 mpeg3_atrack_t *atrack = file->atrack[j];
1064 PUT_INT64(atrack->audio_eof);
1065 PUT_INT32(atrack->channels);
1066 PUT_INT32(atrack->total_sample_offsets);
1067 for(i = 0; i < atrack->total_sample_offsets; i++)
1069 PUT_INT64(atrack->sample_offsets[i]);
1077 // Video streams
1078 for(j = 0; j < file->total_vstreams; j++)
1080 mpeg3_vtrack_t *vtrack = file->vtrack[j];
1081 PUT_INT64(vtrack->video_eof);
1082 PUT_INT32(vtrack->total_frame_offsets);
1083 for(i = 0; i < vtrack->total_frame_offsets; i++)
1085 PUT_INT64(vtrack->frame_offsets[i]);
1088 PUT_INT32(vtrack->total_keyframe_numbers);
1089 for(i = 0; i < vtrack->total_keyframe_numbers; i++)
1091 PUT_INT64(vtrack->keyframe_numbers[i]);
1096 // Audio indexes
1097 // Write indexes
1098 for(i = 0; i < file->total_astreams; i++)
1100 mpeg3_atrack_t *atrack = file->atrack[i];
1101 mpeg3_index_t *index = file->indexes[i];
1102 if(index->index_data)
1104 PUT_INT32(index->index_size);
1105 PUT_INT32(index->index_zoom);
1106 for(j = 0; j < atrack->channels; j++)
1108 fwrite(index->index_data[j],
1109 sizeof(float) * 2,
1110 index->index_size,
1111 file->toc_fd);
1119 fclose(file->toc_fd);
1122 mpeg3_delete(file);
1133 int mpeg3_index_tracks(mpeg3_t *file)
1135 return file->total_indexes;
1138 int mpeg3_index_channels(mpeg3_t *file, int track)
1140 if(!file->total_indexes) return 0;
1141 return file->indexes[track]->index_channels;
1144 int mpeg3_index_zoom(mpeg3_t *file)
1146 if(!file->total_indexes) return 0;
1148 return file->indexes[0]->index_zoom;
1151 int mpeg3_index_size(mpeg3_t *file, int track)
1153 if(!file->total_indexes) return 0;
1154 return file->indexes[track]->index_size;
1157 float* mpeg3_index_data(mpeg3_t *file, int track, int channel)
1159 if(!file->total_indexes) return 0;
1160 return file->indexes[track]->index_data[channel];
1164 int mpeg3_has_toc(mpeg3_t *file)
1166 if(file->frame_offsets || file->sample_offsets) return 1;
1167 return 0;