3 #define PUT_INT32(x) do { \
4 uint32_t be = htobe32(x); \
5 fwrite((uint8_t*)&be,1,sizeof(be),toc_fp); \
8 #define PUT_INT64(x) do { \
9 uint64_t be = htobe64(x); \
10 fwrite((uint8_t*)&be,1,sizeof(be),toc_fp); \
17 static FILE **video_fp = 0;
18 static FILE **audio_fp = 0;
21 static inline void read_data(uint8_t *bfr, int &pos, uint8_t *out, int len)
23 memcpy(out, bfr + pos, len);
27 /* Concatenate title and toc directory if title is not absolute and */
28 /* toc path has a directory section. */
29 static inline void concat_path(char *full_path, char *toc_path, char *path)
31 if( path[0] != '/' ) {
32 char *ptr = strrchr(toc_path, '/');
34 strcpy(full_path, toc_path);
35 strcpy(&full_path[ptr - toc_path + 1], path);
39 strcpy(full_path, path);
43 read_toc(int *atracks_return, int *vtracks_return, const char *title_path)
46 int64_t current_byte = 0;
48 /* Fix title paths for Cinelerra VFS */
49 int vfs_len = strlen(ZRENDERFARM_FS_PREFIX);
50 int is_vfs = !strncmp(fs->path,ZRENDERFARM_FS_PREFIX, vfs_len) ? 1 : 0;
54 uint32_t toc_version = fs->read_uint32();
55 if( toc_version != TOC_VERSION ) {
56 zerrs("invalid TOC version %08x (should be %08x)\n",
57 toc_version, TOC_VERSION);
58 return ERR_INVALID_TOC_VERSION;
62 /* Get section type */
63 int section_type = fs->read_uint32();
64 //zmsgs("section_type=%d position=%jx\n", section_type, fs->tell());
65 switch( section_type ) {
66 case toc_FILE_TYPE_PROGRAM:
67 file_type = FT_PROGRAM_STREAM;
69 case toc_FILE_TYPE_TRANSPORT:
70 file_type = FT_TRANSPORT_STREAM;
72 case toc_FILE_TYPE_AUDIO:
73 file_type = FT_AUDIO_STREAM;
75 case toc_FILE_TYPE_VIDEO:
76 file_type = FT_VIDEO_STREAM;
82 fs->read_data((uint8_t*)&string[0],STRLEN);
84 strcpy(string2, title_path);
86 concat_path(string2, fs->path, string);
87 source_date = fs->read_uint64();
88 int64_t current_date = calculate_source_date(string2);
89 //zmsgs("zsrc=%s source_date=%jd current_date=%jd\n",
90 // string2, source_date, current_date);
91 if( current_date != source_date ) {
92 zerrs("date mismatch %jx (should be %jx)\n",
93 current_date, source_date);
94 return ERR_TOC_DATE_MISMATCH;
98 case toc_STREAM_AUDIO: {
99 int n = fs->read_uint32();
100 demuxer->astream_table[n] = fs->read_uint32();
103 case toc_STREAM_VIDEO: {
104 int n = fs->read_uint32();
105 demuxer->vstream_table[n] = fs->read_uint32();
109 case toc_ATRACK_COUNT: {
110 int atracks = fs->read_uint32();
111 *atracks_return = atracks;
112 channel_counts = znew(int,atracks);
113 nudging = znew(int,atracks);
114 sample_offsets = znew(int64_t*,atracks);
115 total_sample_offsets = znew(int,atracks);
116 audio_eof = znew(int64_t,atracks);
117 total_samples = znew(int64_t,atracks);
118 indexes = znew(index_t*,atracks);
119 total_indexes = atracks;
120 for( i=0; i < atracks; ++i ) {
121 audio_eof[i] = fs->read_uint64();
122 channel_counts[i] = fs->read_uint32();
123 nudging[i] = fs->read_uint32();
124 total_sample_offsets[i] = fs->read_uint32();
125 total_samples[i] = fs->read_uint64();
127 if(total_samples[i] < 1) total_samples[i] = 1;
128 sample_offsets[i] = znew(int64_t,total_sample_offsets[i]);
129 for( j=0; j < total_sample_offsets[i]; ++j ) {
130 sample_offsets[i][j] = fs->read_uint64();
133 index_t *index = indexes[i] = new index_t();
134 index->index_size = fs->read_uint32();
135 index->index_zoom = fs->read_uint32();
136 //zmsgs("%d %d %d\n", i, index->index_size, index->index_zoom);
137 int channels = index->index_channels = channel_counts[i];
139 index->index_data = znew(float*,channels);
140 for( j=0; j < channels; ++j ) {
141 index->index_data[j] = znew(float,index->index_size*2);
142 fs->read_data((uint8_t*)index->index_data[j],
143 sizeof(float) * index->index_size * 2);
149 case toc_VTRACK_COUNT: {
150 int vtracks = fs->read_uint32();
151 *vtracks_return = vtracks;
152 frame_offsets = znew(int64_t*,vtracks);
153 total_frame_offsets = znew(int,vtracks);
154 keyframe_numbers = znew(int*,vtracks);
155 total_keyframe_numbers = znew(int,vtracks);
156 video_eof = znew(int64_t,vtracks);
157 for( i=0; i < vtracks; ++i ) {
158 video_eof[i] = fs->read_uint64();
159 total_frame_offsets[i] = fs->read_uint32();
160 frame_offsets[i] = new int64_t[total_frame_offsets[i]];
161 if( debug ) zmsgs("62 %d %jx %jx\n",
162 total_frame_offsets[i], fs->tell(), fs->ztotal_bytes());
163 for( j=0; j < total_frame_offsets[i]; ++j ) {
164 frame_offsets[i][j] = fs->read_uint64();
165 //zmsgs("frame %llx\n", frame_offsets[i][j]);
167 if(debug) zmsg("64\n");
168 total_keyframe_numbers[i] = fs->read_uint32();
169 keyframe_numbers[i] = new int[total_keyframe_numbers[i]];
170 for( j=0; j < total_keyframe_numbers[i]; ++j ) {
171 keyframe_numbers[i][j] = fs->read_uint32();
176 case toc_STRACK_COUNT: {
177 total_stracks = fs->read_uint32();
178 for( i=0; i < total_stracks; ++i ) {
179 int id = fs->read_uint32();
180 strack_t *strk = new strack_t(id);
182 strk->total_offsets = fs->read_uint32();
183 strk->offsets = znew(int64_t,strk->total_offsets);
184 strk->allocated_offsets = strk->total_offsets;
185 for( j=0; j < strk->total_offsets; ++j ) {
186 strk->offsets[j] = fs->read_uint64();
191 case toc_TITLE_PATH: {
192 if(debug) zmsg("11\n");
194 fs->read_data((uint8_t*)string, STRLEN);
196 if( debug ) printf("11 position=%jx\n", fs->tell());
197 char *ext = strrchr(string, '.');
199 if( !strncasecmp(ext, ".m2ts", 5) ||
200 !strncasecmp(ext, ".mts", 4) ) file_type |= FT_BD_FILE;
202 if(debug) printf("12\n");
203 // if title_path concatenate dirname title_path and basename path
205 char string2[STRLEN], *bp = string2, *cp = string2;
206 for( const char *tp=title_path; (*cp++=*tp) != 0; ++tp )
207 if( *tp == '/' ) bp = cp;
208 for( char *sp=cp=string; *sp != 0; ++sp )
209 if( *sp == '/' ) cp = sp+1;
210 while( (*bp++=*cp++)!=0 );
211 strcpy(string, string2);
213 // Test title availability
214 if( access(string,R_OK) ) {
215 /* Concatenate title and toc directory if title is not absolute and */
216 /* toc path has a directory section. */
217 if( (!is_vfs && string[0] != '/') ||
218 (is_vfs && string[vfs_len] != '/') ) {
219 /* Get toc filename without path */
220 char *ptr = strrchr(fs->path, '/');
222 char string2[STRLEN];
223 /* Stack filename on toc path */
224 strcpy(string2, fs->path);
226 strcpy(&string2[ptr - fs->path + 1], string);
228 strcpy(&string2[ptr - fs->path + 1], string + vfs_len);
229 if( access(string2,R_OK) ) {
230 zerrs("failed to open %s or %s\n", string, string2);
233 strcpy(string, string2);
236 zerrs("failed to open %s\n", string);
241 zerrs("failed to open %s\n", string);
246 if(debug) zmsg("30\n");
247 demuxer_t::title_t *title = new demuxer_t::title_t(this, string);
248 demuxer->titles[demuxer->total_titles++] = title;
249 title->total_bytes = fs->read_uint64();
250 title->start_byte = current_byte;
251 title->end_byte = title->start_byte + title->total_bytes;
252 current_byte = title->end_byte;
254 title->cell_table_allocation = fs->read_uint32();
255 title->cell_table_size = title->cell_table_allocation;
256 //zmsgs("40 %llx %d\n", title->total_bytes, title->cell_table_size);
258 new demuxer_t::title_t::cell_t[title->cell_table_size];
259 for( i=0; i < title->cell_table_size; ++i ) {
260 demuxer_t::title_t::cell_t *cell = &title->cell_table[i];
261 cell->title_start = fs->read_uint64();
262 cell->title_end = fs->read_uint64();
263 cell->program_start = fs->read_uint64();
264 cell->program_end = fs->read_uint64();
265 union { double d; uint64_t u; } cell_time;
266 cell_time.u = fs->read_uint64();
267 cell->cell_time = cell_time.d;
268 cell->cell_no = fs->read_uint32();
269 cell->discontinuity = fs->read_uint32();
270 //zmsgs("50 %jx-%jx %jx-%jx %d %d\n",
271 // cell->title_start, cell->title_end, cell->program_start,
272 // cell->program_end, cell->cell_no, cell->discontinuity);
276 case toc_IFO_PALETTE:
277 for(i = 0; i < 16; i++) {
279 palette[k + 0] = fs->read_char();
280 palette[k + 1] = fs->read_char();
281 palette[k + 2] = fs->read_char();
282 palette[k + 3] = fs->read_char();
283 //zmsgs("color %02d: 0x%02x 0x%02x 0x%02x 0x%02x\n",
284 // i, palette[k+0], palette[k+1], palette[k+2], palette[k+3]);
288 case toc_IFO_PLAYINFO: {
289 int ncells = fs->read_uint32();
290 icell_table_t *cells = new icell_table_t();
291 if( playinfo ) delete playinfo;
293 while( --ncells >= 0 ) {
294 icell_t *cell = cells->append_cell();
295 cell->start_byte = fs->read_uint64();
296 cell->end_byte = fs->read_uint64();
297 cell->vob_id = fs->read_uint32();
298 cell->cell_id = fs->read_uint32();
299 cell->inlv = fs->read_uint32();
300 cell->discon = fs->read_uint32();
304 case toc_SRC_PROGRAM: {
305 vts_title = fs->read_uint32();
306 total_vts_titles = fs->read_uint32();
307 int inlv = fs->read_uint32();
308 angle = inlv / 10; interleave = inlv % 10;
309 total_interleaves = fs->read_uint32();
314 if(debug) zmsg("90\n");
315 demuxer->open_title(0);
316 if(debug) zmsg("100\n");
323 start_toc(const char *path, const char *toc_path,
324 int program, int64_t *total_bytes)
326 if( total_bytes ) *total_bytes = 0;
327 zmpeg3_t *zsrc = new zmpeg3_t(path);
328 zsrc->toc_fp = fopen(toc_path, "w");
330 perrs("%s",toc_path);
335 zsrc->set_vts_title(program / 100);
336 zsrc->set_angle((program / 10) % 10);
337 zsrc->set_interleave(program % 10);
338 zsrc->last_cell_no = 0;
341 zsrc->fs->sequential();
342 zsrc->file_type = FT_TRANSPORT_STREAM;
343 zsrc->packet_size = zsrc->calculate_packet_size();
346 /* Authenticate encryption before reading a single byte */
347 /* and Determine file type */
348 int toc_atracks = 0, toc_vtracks = 0;
349 if( zsrc->fs->open_file() ||
351 zsrc->get_file_type(&toc_atracks, &toc_vtracks, 0) ) ) {
352 fclose(zsrc->toc_fp); zsrc->toc_fp = 0;
357 demuxer_t *demux = zsrc->demuxer;
358 /* Create title without scanning for tracks */
359 if( !demux->total_titles ) {
360 demuxer_t::title_t *title = new demuxer_t::title_t(zsrc);
361 demux->titles[0] = title;
362 demux->total_titles = 1;
363 demux->open_title(0);
364 title->total_bytes = title->fs->ztotal_bytes();
365 title->start_byte = 0;
366 title->end_byte = title->total_bytes;
367 title->new_cell(title->end_byte);
370 /* mpeg3demux_seek_byte(zsrc->demuxer, 0x1734e4800LL); */
372 demux->read_all = -1;
373 int64_t bytes = demux->movie_size();
374 if( total_bytes ) *total_bytes = bytes;
376 //*total_bytes = 500000000;
377 zsrc->allocate_slice_decoders();
382 divide_index(int track_number)
384 if( total_indexes <= track_number ) return;
385 index_t *idx = indexes[track_number];
386 idx->index_size /= 2;
387 idx->index_zoom *= 2;
388 for( int i=0; i < idx->index_channels; ++i ) {
389 float *current_channel = idx->index_data[i];
390 float *out = current_channel;
391 float *in = current_channel;
392 for( int j=0; j < idx->index_size; ++j ) {
393 float max = ZMAX(in[0], in[2]);
394 float min = ZMIN(in[1], in[3]);
403 update_index(int track_number, int flush)
407 atrack_t *atrk = atrack[track_number];
408 if( track_number >= total_indexes ) {
409 /* Create index table */
410 int new_allocation = track_number + 1;
411 index_t **new_indexes = new index_t*[new_allocation];
412 for( i=0; i<total_indexes; ++i )
413 new_indexes[i] = indexes[i];
414 while( i < new_allocation )
415 new_indexes[i++] = new index_t();
417 indexes = new_indexes;
418 total_indexes = new_allocation;
420 index_t *idx = indexes[track_number];
421 audio_t *aud = atrk->audio;
422 //zmsgs("%d atrk->audio->output_size=%d\n", __LINE__, aud->output_size);
423 while( ( flush && aud->output_size) ||
424 (!flush && aud->output_size > AUDIO_CHUNKSIZE) ) {
425 int fragment = AUDIO_CHUNKSIZE;
426 if( aud->output_size < fragment ) fragment = aud->output_size;
427 int index_fragments = fragment / idx->index_zoom;
428 if( flush ) ++index_fragments;
429 int new_index_samples = index_fragments + idx->index_size;
430 /* Update number of channels */
431 if( idx->index_allocated && idx->index_channels < atrk->channels ) {
432 float **new_index_data = znew(float*,atrk->channels);
433 for( i=0; i < idx->index_channels; ++i )
434 new_index_data[i] = idx->index_data[i];
435 for( i=idx->index_channels; i < atrk->channels; ++i )
436 new_index_data[i] = znew(float,idx->index_allocated*2);
437 idx->index_channels = atrk->channels;
438 delete [] idx->index_data;
439 idx->index_data = new_index_data;
442 /* Allocate index buffer */
443 if( new_index_samples > idx->index_allocated ) {
444 /* Double current number of samples */
445 idx->index_allocated = new_index_samples * 2;
446 if( !idx->index_data ) {
447 idx->index_data = znew(float*,atrk->channels);
449 /* Allocate new size in high and low pairs */
450 k = idx->index_allocated * sizeof(float*) * 2;
451 for( i=0; i < atrk->channels; ++i ) {
452 float *old_data = idx->index_data[i];
453 float *new_data = new float[k];
454 n = idx->index_size*2;
455 for( j=0; j<n; ++j ) new_data[j] = old_data[j];
456 while( j < k ) new_data[j++] = 0.;
457 delete [] idx->index_data[i];
458 idx->index_data[i] = new_data;
460 idx->index_channels = atrk->channels;
463 /* Calculate new index chunk */
464 for( i=0; i<atrk->channels; ++i ) {
465 float *in_channel = i < aud->output_channels ? aud->output[i] : 0;
466 float *out_channel = idx->index_data[i] + idx->index_size*2;
467 /* Calculate index frames */
468 for( j=0; j < index_fragments; ++j ) {
471 int remaining_fragment = fragment - j*idx->index_zoom;
472 int len = remaining_fragment < idx->index_zoom ?
473 remaining_fragment : idx->index_zoom;
474 if( in_channel && len > 0 ) {
475 min = max = *in_channel++;
476 for( k=1; k < len; ++k ) {
477 if( *in_channel > max ) max = *in_channel;
478 else if( *in_channel < min ) min = *in_channel;
482 *out_channel++ = max;
483 *out_channel++ = min;
487 idx->index_size = new_index_samples;
488 /* Shift audio buffer */
489 aud->shift_audio(fragment);
490 /* Create new toc entry */
491 atrk->append_samples(atrk->prev_offset);
492 atrk->current_position += fragment;
495 /* Divide index by 2 and increase zoom */
496 k = idx->index_size * atrk->channels * sizeof(float) * 2;
497 if( k > index_bytes && !(idx->index_size % 2) )
498 divide_index(track_number);
504 handle_audio_data(int track_number)
506 zmpeg3_t *zsrc = audio->src;
508 while( !audio->decode_audio(0, atyp_NONE, 0, AUDIO_HISTORY) ) {
509 /* add downsampled samples to the index buffer and create toc entry. */
510 if( !zsrc->update_index(track_number, 0) ) break;
511 prev_offset = curr_offset;
517 handle_audio(int track_number)
521 audio_fp = new FILE*[65536];
522 memset(audio_fp,0,65536*sizeof(FILE*));
524 if( !audio_fp[pid] ) {
526 sprintf(fn,"/tmp/dat/a%04x.mpg",pid);
527 audio_fp[pid] = fopen(fn,"w");
529 if( audio_fp[pid] ) {
530 zmpeg3_t *zsrc = audio->src;
531 demuxer_t *demux = zsrc->demuxer;
532 if( demux->zaudio.size )
533 fwrite(demux->zaudio.buffer, demux->zaudio.size, 1, audio_fp[pid]);
534 else if( demux->zdata.size )
535 fwrite(demux->zdata.buffer, demux->zdata.size, 1, audio_fp[pid]);
540 if( format != afmt_IGNORE ) {
541 zmpeg3_t *zsrc = audio->src;
542 demuxer_t *demux = zsrc->demuxer;
543 /* Assume last packet of stream */
544 audio_eof = demux->tell_byte();
545 /* Append demuxed data to track buffer */
546 if( demux->zaudio.size )
547 demuxer->append_data(demux->zaudio.buffer,demux->zaudio.size);
548 else if( demux->zdata.size )
549 demuxer->append_data(demux->zdata.buffer,demux->zdata.size);
550 if( demux->pes_audio_pid == pid && demux->pes_audio_time >= 0 ) {
551 demuxer->pes_audio_time = demux->pes_audio_time;
552 demux->pes_audio_time = -1.;
555 /* check for audio starting past first cell */
556 if( zsrc->pts_padding > 0 && zsrc->cell_time >= 0. ) {
557 audio_time = zsrc->cell_time;
559 if( pts_starttime < 0. ) {
560 pts_offset = zsrc->cell_time;
565 //zmsgs("%d pid=%p zaudio.size=%d zdata.size=%d\n", __LINE__,
566 // demux->pid, demux->zaudio.size, demux->zdata.size);
568 if( pid == 0x1100 ) {
569 static FILE *test = 0;
570 if( !test ) test = fopen("/hmov/test.ac3", "w");
571 fwrite(demux->zaudio.buffer,
572 demux->zaudio.size, 1, test);
575 result = handle_audio_data(track_number);
576 demuxer->shift_data();
582 handle_video_data(int track_number, int prev_data_size)
584 zmpeg3_t *zsrc = video->src;
585 /* Scan for a start code a certain number of bytes from the end of the */
586 /* buffer. Then scan the header using the video decoder to get the */
588 while( demuxer->zdata.length() >= VIDEO_STREAM_SIZE ) {
589 if( !demuxer->last_code ) {
590 if( video->thumb && video->pict_type == video_t::pic_type_I ) {
591 if( tcode >= SLICE_MIN_START && tcode <= SLICE_MAX_START ) {
593 slice = video->get_slice_buffer();
594 //int vtrk, sbfr = slice - &video->slice_buffers[0];
595 //for( vtrk=0; vtrk<zsrc->total_vtracks && video!=zsrc->vtrack[vtrk]->video; ++vtrk );
596 //printf("get_slice_buffer %p vtrk=%d, sbfr=%d\n",slice,vtrk,sbfr);
598 for( int i=32; i>0; ) *sbp++ = (tcode>>(i-=8));
599 sb_size = slice->buffer_allocation-4-4;
606 if( (uint8_t)tcode != 0 ) {
607 tcode = (tcode<<8) | demuxer->read_char();
608 tcode = (tcode<<8) | demuxer->read_char();
610 tcode = (tcode<<8) | demuxer->read_char();
611 if( (tcode&0xffffff) == PACKET_START_CODE_PREFIX ) break;
612 if( demuxer->zdata.length() < VIDEO_STREAM_SIZE ) return 0;
614 tcode = (tcode<<8) | demuxer->read_char();
619 sbp = slice->expand_buffer(sbp - slice->data);
620 sb_size = slice->buffer_size;
622 if( (uint8_t)tcode != 0 ) {
624 tcode = (tcode<<8) | (*sbp++ = demuxer->read_char());
625 tcode = (tcode<<8) | (*sbp++ = demuxer->read_char());
629 tcode = (tcode<<8) | (*sbp++ = demuxer->read_char());
630 if( (tcode&0xffffff) == PACKET_START_CODE_PREFIX ) break;
631 if( demuxer->zdata.length() < VIDEO_STREAM_SIZE ) return 0;
633 tcode = (tcode<<8) | (*sbp++ = demuxer->read_char());
635 slice->buffer_size = sbp - slice->data;
637 //#define MULTI_THREADED
638 #ifdef MULTI_THREADED
639 // this is actually slower than single threaded
640 zsrc->decode_slice(slice);
642 slice_decoder_t *decoder = &zsrc->slice_decoders[0];
643 decoder->slice_buffer = slice;
644 decoder->video = video;
645 decoder->decode_slice();
646 video->put_slice_buffer(slice);
650 //zmsgs("trk=%d, pos=0x%04x,size=0x%04x,length=0x%04x, cur_pos 0x%012lx/0x%012lx, tcode=0x%08x\n",
651 // track_number, demuxer->zdata.position, demuxer->zdata.size, demuxer->zdata.length(),
652 // prev_offset, curr_offset, tcode);
655 case PICTURE_START_CODE:
656 if( !video->found_seqhdr ) continue;
657 /* else fall through */
658 case SEQUENCE_START_CODE:
659 /* save start of packet, data before prev_data_size from prev_offset */
660 if( prev_frame_offset == -1 )
661 prev_frame_offset = demuxer->zdata.position < prev_data_size ?
662 prev_offset : curr_offset;
663 video->vstream->reset(tcode);
669 /* Wait for decoders to finish */
670 if( video->slice_active_locked ) {
671 video->slice_active.lock();
672 video->slice_active.unlock();
675 if( total_frame_offsets-1 > video->framenum ) {
676 video->framenum = total_frame_offsets-1;
678 if( video->framenum >= 0 ) {
679 int64_t last_frame_offset = frame_offsets[video->framenum];
680 while( video->video_pts_padding() ) {
681 append_frame(last_frame_offset, 0);
682 video->framenum = total_frame_offsets-1;
685 if( video->video_pts_skipping() )
689 /* if last frame was P-Frame after I-Frame show thumbnail */
690 if( video->thumb && video->decoder_initted ) {
691 switch( video->pict_type ) {
692 case video_t::pic_type_P:
693 if( !video->ithumb ) break;
695 zsrc->thumbnail_fn(zsrc->thumbnail_priv, track_number);
697 case video_t::pic_type_I:
704 /* Use video decoder to get repeat count and field type. */
705 /* Should never hit EOF in here. This rereads up to the current ptr */
706 /* since zdata.position isn't updated by handle_video. */
707 /* if get_header fails, try this offset again with more data */
708 int data_position = demuxer->zdata.position;
709 int have_seqhdr = video->found_seqhdr;
710 int32_t repeat_data = video->repeat_data;
711 if( video->get_header() ) {
712 if( video->found_seqhdr ) {
713 /* try again with more data */
714 demuxer->last_code = tcode;
715 demuxer->zdata.position = data_position;
717 video->found_seqhdr = have_seqhdr;
718 video->repeat_data = repeat_data;
722 if( !video->decoder_initted ) {
723 video->init_decoder();
724 width = video->horizontal_size;
725 height = video->vertical_size;
726 frame_rate = video->frame_rate;
729 /* check for video starting past first cell */
730 if( !have_seqhdr && zsrc->pts_padding > 0 &&
731 video_time < 0 && zsrc->cell_time >= 0. ) {
732 video_time = zsrc->cell_time;
734 if( pts_starttime < 0. ) {
735 pts_offset = zsrc->cell_time;
740 video->secondfield = 0;
741 if( video->pict_struct != video_t::pics_FRAME_PICTURE ) {
742 if( video->got_top || video->got_bottom )
743 video->secondfield = 1;
746 int field = video->secondfield ? 2 : 1;
747 if( video->pict_struct == video_t::pics_TOP_FIELD )
748 video->got_top = field;
749 else if( video->pict_struct == video_t::pics_BOTTOM_FIELD )
750 video->got_bottom = field;
752 if( video->pict_struct == video_t::pics_FRAME_PICTURE ||
753 video->secondfield || !video->pict_struct ) {
754 //zmsgs("video pid %02x framenum %d video_time %12.5f %c 0x%012lx rep %d\n",
755 // pid, video->framenum, get_video_time(), "XIPBD"[video->pict_type],
756 // prev_frame_offset, video->repeat_fields-2);
757 if( video->pict_type == video_t::pic_type_I )
759 append_frame(prev_frame_offset, got_keyframe);
760 /* Add entry for every repeat count. */
761 video->current_field += 2;
762 while( video->repeat_fields-video->current_field >= 2 ) {
763 append_frame(prev_frame_offset, 0);
764 video->current_field += 2;
766 if( (video->repeat_fields-=video->current_field) < 0 )
767 video->repeat_fields = 0;
768 /* Shift out data from before frame */
769 prev_frame_offset = -1;
773 // This was a TOP/BOTTOM FIELD and was not secondfield
774 // Shift out data from this field
775 if( video->pict_type == video_t::pic_type_I )
777 video->current_field += 2;
779 tcode = video->vstream->show_bits(32);
780 if( !video->repeat_fields ) video->current_field = 0;
781 demuxer->last_code = 0;
787 handle_video(int track_number)
789 zmpeg3_t *zsrc = video->src;
790 demuxer_t *demux = zsrc->demuxer;
791 /* Assume last packet of stream */
792 video_eof = demux->tell_byte();
793 int prev_data_size = demuxer->zdata.size;
794 //zmsgs("%d %d %02x %02x %02x %02x %02x %02x %02x %02x\n",
795 // demux->zvideo.size, demux->zdata.size,
796 // demux->zvideo.buffer[0], demux->zvideo.buffer[1],
797 // demux->zvideo.buffer[2], demux->zvideo.buffer[3],
798 // demux->zvideo.buffer[4], demux->zvideo.buffer[5],
799 // demux->zvideo.buffer[6], demux->zvideo.buffer[7]);
803 video_fp = new FILE*[65536];
804 memset(video_fp,0,65536*sizeof(FILE*));
806 if( !video_fp[pid] ) {
808 sprintf(fn,"/tmp/dat/v%04x.mpg",pid);
809 video_fp[pid] = fopen(fn,"w");
811 if( video_fp[pid] ) {
812 if( demux->zvideo.size )
813 fwrite(demux->zvideo.buffer, demux->zvideo.size, 1, video_fp[pid]);
814 else if( demux->zdata.size )
815 fwrite(demux->zdata.buffer, demux->zdata.size, 1, video_fp[pid]);
819 /* Append demuxed data to track buffer */
820 if( demux->zvideo.size )
821 demuxer->append_data(demux->zvideo.buffer, demux->zvideo.size);
822 else if( demux->zdata.size )
823 demuxer->append_data(demux->zdata.buffer, demux->zdata.size);
824 if( demux->pes_video_pid == pid && demux->pes_video_time >= 0 ) {
825 demuxer->pes_video_time = demux->pes_video_time;
826 demux->pes_video_time = -1.;
829 if( !test_file ) test_file = fopen("/tmp/test.m2v", "w");
830 if( demuxer->zdata.position > 0 ) fwrite(demuxer->zdata.buffer,
831 demuxer->zdata.position, 1, test_file);
834 handle_video_data(track_number, prev_data_size);
835 demuxer->shift_data();
842 for( int i=0; i<total_stracks; ++i ) {
843 strack_t *strk = get_strack(i);
844 while( strk->total_subtitles ) {
845 subtitle_t *subtitle = strk->subtitles[0];
846 strk->append_subtitle_offset(subtitle->offset);
847 strk->del_subtitle(subtitle);
853 handle_cell(int cell_no)
858 //zmsgs("cell %d\n", cell_no);
859 for( idx=0; idx<total_vtracks; ++idx ) {
860 zvtrack_t *vtrk = vtrack[idx];
861 zvideo_t *vid = vtrk->video;
863 double pts = vtrk->get_video_time();
864 //zmsgs(" vtrack %d = %f\n", idx, pts);
865 if( cell_time < pts ) cell_time = pts;
867 for( idx=0; idx<total_atracks; ++idx ) {
868 zatrack_t *atrk = atrack[idx];
869 zaudio_t *aud = atrk->audio;
871 double pts = atrk->get_audio_time();
872 //zmsgs(" atrack %d = %f\n", idx, pts);
873 if( cell_time < pts ) cell_time = pts;
877 if( !demuxer->get_cell(cell_no, cell) )
878 cell->cell_time = cell_time;
879 if( pts_padding <= 0 ) return;
881 int discon = cell ? cell->discontinuity : 0;
882 //zmsgs("cell %d cell_time=%f pos=%jx discon %d\n",
883 // cell_no, cell_time, !cell? -1 : cell->program_start, discon);
884 if( !discon ) return;
886 for( idx=0; idx<total_vtracks; ++idx ) {
887 zvtrack_t *vtrk = vtrack[idx];
888 zvideo_t *vid = vtrk->video;
890 if( !vtrk->total_frame_offsets ) continue;
891 vtrk->video_time = cell_time;
892 vid->framenum = vtrk->pts_position = vtrk->total_frame_offsets-1;
893 if( vid->framenum >= 0 ) {
894 int64_t prev_frame_offset = vtrk->frame_offsets[vid->framenum];
895 while( vid->video_pts_padding() ) {
896 vtrk->append_frame(prev_frame_offset, 0);
897 vid->framenum = vtrk->total_frame_offsets-1;
902 vtrk->pts_offset = cell_time;
903 if( discon < 0 ) vtrk->pts_starttime = 0.;
907 for( idx=0; idx<total_atracks; ++idx ) {
908 zatrack_t *atrk = atrack[idx];
909 zaudio_t *aud = atrk->audio;
911 atrk->audio_time = cell_time;
912 atrk->pts_position = aud->audio_position();
913 while( aud->audio_pts_padding() ) {
914 if( update_index(idx, 0) )
915 atrk->prev_offset = atrk->curr_offset;
919 atrk->pts_offset = cell_time;
920 if( discon < 0 ) atrk->pts_starttime = 0.;
928 int i, n, atrk, vtrk;
930 for( i=0; i<total_atracks; ++i )
931 atrack[i]->nudge = 0;
933 int total_channels = dvb.channel_count();
935 // lines up first apts/vpts
936 for( n=0; n<total_channels; ++n ) {
937 int astreams, vstreams;
938 dvb.total_vstreams(n, vstreams);
939 double apts = -1., vpts = -1.;
940 for( i=0; i<vstreams; ++i ) {
941 dvb.vstream_number(n, i, vtrk);
942 if( vtrack[vtrk]->pts_origin > vpts )
943 vpts = vtrack[vtrk]->pts_origin;
945 dvb.total_astreams(n, astreams);
946 for( i=0; i<astreams; ++i ) {
947 dvb.astream_number(n, i, atrk);
948 double samplerate = sample_rate(atrk);
949 if( samplerate < 0. ) samplerate = 0.;
950 apts = atrack[atrk]->pts_origin;
951 if( apts >= 0. && vpts >= 0. ) {
952 atrack[atrk]->nudge = (long)((vpts - apts) * samplerate);
958 // lines up nearest apts/vpts
961 elem_t *next; int vtrk, atrk;
962 double apts, vpts, pts_nudge;
963 uint64_t apos, vpos, pts_dist;
964 elem_t(elem_t *p, int vtrk, int atrk)
965 : next(p), vtrk(vtrk), atrk(atrk) {
966 apos = vpos = 0; apts = vpts = 0.;
967 pts_dist = ~0; pts_nudge = 0;
970 // collect all vtrk[0]-atrk[i] associations
971 for( n=0; n<total_channels; ++n ) {
972 int astreams, vstreams;
973 dvb.total_vstreams(n, vstreams);
974 if( vstreams <= 0 ) continue;
975 dvb.vstream_number(n, 0, vtrk);
976 if( vtrk < 0 || vtrk >= total_vtracks ) continue;
977 dvb.total_astreams(n, astreams);
978 for( i=0; i<astreams; ++i ) {
979 dvb.astream_number(n, i, atrk);
980 if( atrk < 0 || atrk >= total_atracks ) continue;
981 elems = new elem_t(elems, vtrk, atrk);
985 demuxer->pes_audio_time = -1.;
986 demuxer->pes_video_time = -1.;
987 demuxer->seek_byte(START_BYTE);
989 // probe for atrk/vtrk pts nearest to each other in file
990 while( !demuxer->titles[0]->fs->eof() ) {
991 int64_t pos = demuxer->absolute_position();
992 if( pos > START_BYTE + MAX_TS_PROBE ) break;
993 if( demuxer->read_next_packet() ) break;
995 if( demuxer->pes_audio_time >= 0 ) {
996 for( ep=elems; ep && atrack[ep->atrk]->pid!=demuxer->pid; ep=ep->next );
997 if( ep ) { ep->apos = pos; ep->apts = demuxer->pes_audio_time; }
998 demuxer->pes_audio_time = -1.;
1000 if( demuxer->pes_video_time >= 0 ) {
1001 for( ep=elems; ep && vtrack[ep->vtrk]->pid!=demuxer->pid; ep=ep->next );
1002 if( ep ) { ep->vpos = pos; ep->vpts = demuxer->pes_video_time; }
1003 demuxer->pes_video_time = -1.;
1005 if( !ep || !ep->apos || !ep->vpos ) continue;
1006 int64_t dist = ep->apos - ep->vpos;
1007 if( dist < 0 ) dist = -dist;
1008 if( (uint64_t)dist < ep->pts_dist ) {
1009 ep->pts_dist = dist;
1010 ep->pts_nudge = ep->vpts - ep->apts;
1014 // nudge audio to align timestamps
1016 ep = elems; elems = elems->next;
1017 //zmsgs("v/atrk %d/%d, dist %jd\n", ep->vtrk, ep->atrk, ep->pts_dist);
1018 //zmsgs(" v/apts %f/%f, nudge %f\n", ep->vpts, ep->apts, ep->pts_nudge);
1019 //zmsgs(" v/aorg %f/%f, nudge %f\n",
1020 // vtrack[ep->vtrk]->pts_origin, atrack[ep->atrk]->pts_origin,
1021 // vtrack[ep->vtrk]->pts_origin-atrack[ep->atrk]->pts_origin);
1022 double samplerate = sample_rate(ep->atrk);
1023 if( samplerate < 0. ) samplerate = 0.;
1024 if( ep->apts >= 0. && ep->vpts >= 0. ) {
1025 atrack[ep->atrk]->nudge = (long)(ep->pts_nudge * samplerate);
1035 do_toc(int64_t *bytes_processed)
1037 /* Starting byte before our packet read */
1038 int64_t start_byte = demuxer->tell_byte();
1039 //zmsgs("%d offset=%llx file_type=%x\n", __LINE__,
1040 // start_byte, file_type);
1041 int result = demuxer->seek_phys();
1043 int cell_no = demuxer->current_cell_no();
1044 if( last_cell_no != cell_no )
1045 handle_cell(last_cell_no=cell_no);
1046 result = demuxer->read_next_packet();
1048 //zmsgs("%d %d %llx\n", __LINE__, result, demuxer->tell_byte());
1049 /* if(start_byte > 0x1b0000 && start_byte < 0x1c0000) */
1050 //zmsgs("1 start_byte=%llx custum_id=%x got_audio=%d got_video=%d"
1051 // " zaudio.size=%d zvideo.size=%d zdata.size=%d\n", start_byte,
1052 // demuxer->custom_id, demuxer->got_audio, demuxer->got_video,
1053 // demuxer->zaudio.size, demuxer->zvideo.size, demuxer->zdata.size);
1056 /* Find current PID in tracks. */
1058 if( demuxer->got_subtitle )
1060 if( is_transport_stream() )
1061 dvb.atsc_tables(demuxer, demuxer->custom_id);
1062 /* In a transport stream the audio or video is determined by the PID. */
1063 /* In other streams the data type is determined by stream ID. */
1064 if( demuxer->got_audio >= 0 || is_transport_stream() || is_audio_stream() ) {
1065 int audio_pid = is_transport_stream() ? demuxer->custom_id : demuxer->got_audio;
1067 for( idx=0; idx < total_atracks; ++idx ) {
1068 if( atrack[idx]->pid == audio_pid ) { /* Update an audio track */
1074 if( is_audio_stream() ||
1075 (audio_pid >= 0 && demuxer->astream_table[audio_pid]) ) {
1076 int format = demuxer->astream_table[audio_pid];
1077 atrk = new_atrack_t(audio_pid, format, demuxer, total_atracks);
1079 atrack[idx=total_atracks++] = atrk;
1080 atrk->prev_offset = start_byte;
1085 atrk->curr_offset = start_byte;
1086 atrk->handle_audio(idx);
1089 if( demuxer->got_video >= 0 || is_transport_stream() || is_video_stream() ) {
1090 int video_pid = is_transport_stream() ? demuxer->custom_id : demuxer->got_video;
1092 for( idx=0; idx < total_vtracks; ++idx ) {
1093 if( vtrack[idx]->pid == video_pid ) { /* Update a video track */
1099 if( is_video_stream() ||
1100 (video_pid >= 0 && demuxer->vstream_table[video_pid]) ) {
1101 vtrk = new_vtrack_t(video_pid, demuxer, total_vtracks);
1102 /* Make the first offset correspond to the */
1103 /* start of the first packet. */
1105 vtrack[total_vtracks++] = vtrk;
1107 vtrk->prev_frame_offset = -1;
1108 vtrk->curr_offset = start_byte;
1110 vtrk->video->thumb = vtrk->video->skim = 1;
1115 vtrk->prev_offset = vtrk->curr_offset;
1116 vtrk->curr_offset = start_byte;
1117 vtrk->handle_video(idx);
1121 /* Make user value independant of data type in packet */
1122 *bytes_processed = demuxer->tell_byte();
1123 //zmsgs("1000 %jx\n", *bytes_processed);
1130 delete_slice_decoders();
1131 if( !is_ifo_file() ) {
1132 int64_t total_bytes = demuxer->tell_byte();
1133 demuxer->end_title(total_bytes);
1135 /* Create final chunk for audio tracks to count the last samples. */
1139 /* Flush audio indexes */
1140 for( i=0; i < total_atracks; ++i )
1142 for( i=0; i < total_atracks; ++i ) {
1144 atrk->append_samples(atrk->curr_offset);
1147 /* Make all indexes the same scale */
1149 for( i=0; i < total_atracks; ++i ) {
1152 if( idx->index_data && idx->index_zoom > max_scale )
1153 max_scale = idx->index_zoom;
1155 for( i=0; i < total_atracks; ++i ) {
1158 if( idx->index_data && idx->index_zoom < max_scale ) {
1159 while( idx->index_zoom < max_scale )
1163 /* delete vtracks with no frames */
1164 for( i=0; i < total_vtracks; ) {
1165 if( !vtrack[i]->total_frame_offsets ) {
1166 demuxer->vstream_table[vtrack[i]->pid] = 0;
1169 for( j=i; j < total_vtracks; ++j )
1170 vtrack[j] = vtrack[j+1];
1175 for( i=0; i < MAX_STREAMZ; ++i ) {
1176 if( demuxer->vstream_table[i] ) {
1177 for( j=total_vtracks; --j>=0; )
1178 if( vtrack[j]->pid == i ) break;
1180 demuxer->vstream_table[i] = 0;
1183 /* delete atracks with no samples */
1184 for( i=0; i < total_atracks; ) {
1185 if( !atrack[i]->total_sample_offsets || atrack[i]->format == afmt_IGNORE ) {
1186 demuxer->astream_table[atrack[i]->pid] = 0;
1187 delete atrack[i]; delete indexes[i];
1188 --total_atracks; --total_indexes;
1189 for( j=i; j < total_atracks; ++j ) {
1190 indexes[j] = indexes[j+1];
1191 atrack[j] = atrack[j+1];
1197 for( i=0; i < MAX_STREAMZ; ++i ) {
1198 if( demuxer->astream_table[i] ) {
1199 for( j=total_atracks; --j>=0; )
1200 if( atrack[j]->pid == i ) break;
1202 demuxer->astream_table[i] = 0;
1205 /* Sort tracks by PID */
1209 for( i=1; i < total_atracks; ++i ) {
1210 atrack_t *atrk0 = atrack[i - 0];
1211 atrack_t *atrk1 = atrack[i - 1];
1212 if( atrk1->pid > atrk0->pid ) {
1213 atrack[i - 1] = atrk0;
1214 atrack[i - 0] = atrk1;
1215 index_t *idx0 = indexes[i - 0];
1216 index_t *idx1 = indexes[i - 1];
1217 indexes[i - 1] = idx0;
1218 indexes[i - 0] = idx1;
1223 for( i=0; i < total_atracks; ++i )
1224 atrack[i]->number = i;
1228 for( i=1; i < total_vtracks; ++i ) {
1229 vtrack_t *vtrk0 = vtrack[i - 0];
1230 vtrack_t *vtrk1 = vtrack[i - 1];
1231 if( vtrk1->pid > vtrk0->pid ) {
1232 vtrack[i - 1] = vtrk0;
1233 vtrack[i - 0] = vtrk1;
1238 for( i=0; i < total_vtracks; ++i )
1239 vtrack[i]->number = i;
1241 if( is_transport_stream() )
1244 demuxer->read_all = 0;
1246 /* Output toc to file */
1247 /* Write file type */
1253 PUT_INT32(TOC_VERSION);
1255 PUT_INT32(toc_SRC_PROGRAM);
1256 PUT_INT32(vts_title);
1257 PUT_INT32(total_vts_titles);
1258 PUT_INT32(angle*10 + interleave);
1259 PUT_INT32(total_interleaves);
1260 /* Write stream type */
1261 if( is_program_stream() )
1262 PUT_INT32(toc_FILE_TYPE_PROGRAM);
1263 else if( is_transport_stream() )
1264 PUT_INT32(toc_FILE_TYPE_TRANSPORT);
1265 else if( is_audio_stream() )
1266 PUT_INT32(toc_FILE_TYPE_AUDIO);
1267 else if( is_video_stream() )
1268 PUT_INT32(toc_FILE_TYPE_VIDEO);
1269 /* Store file information */
1270 PUT_INT32(toc_FILE_INFO);
1271 char *path = fs->path;
1272 fprintf(toc_fp, "%s", path);
1273 for( j=strlen(path); j < STRLEN; ++j ) fputc(0, toc_fp);
1274 source_date = calculate_source_date(path);
1275 PUT_INT64(source_date);
1276 /* Write stream ID's */
1277 /* Only program and transport streams have these */
1278 for( i=0; i < MAX_STREAMZ; ++i ) {
1279 if( demuxer->astream_table[i] ) {
1280 PUT_INT32(toc_STREAM_AUDIO);
1282 PUT_INT32(demuxer->astream_table[i]);
1284 if( demuxer->vstream_table[i] ) {
1285 PUT_INT32(toc_STREAM_VIDEO);
1287 PUT_INT32(demuxer->vstream_table[i]);
1291 for( i=0; i < demuxer->total_titles; ++i ) {
1292 demuxer_t::title_t *title = demuxer->titles[i];
1294 PUT_INT32(toc_TITLE_PATH);
1295 path = !is_program_stream() ? path : title->fs->path;
1296 fprintf(toc_fp, "%s", path);
1297 for( j=strlen(path); j < STRLEN; ++j ) fputc(0, toc_fp);
1299 PUT_INT64(title->total_bytes);
1300 /* Total cells in title */
1301 PUT_INT32(demuxer->titles[i]->cell_table_size);
1302 for( j=0; j < title->cell_table_size; ++j ) {
1303 demuxer_t::title_t::cell_t *cell = &title->cell_table[j];
1304 //zmsgs("%x: %llx-%llx %llx-%llx %d %d %d\n",
1305 // ftell(toc_fp), cell->title_start, cell->title_end,
1306 // cell->program_start, cell->program_end, cell->cell_no,
1307 // cell->program, cell->discontinuity);
1308 PUT_INT64(cell->title_start);
1309 PUT_INT64(cell->title_end);
1310 PUT_INT64(cell->program_start);
1311 PUT_INT64(cell->program_end);
1312 union { double d; uint64_t u; } cell_time;
1313 cell_time.d = cell->cell_time;
1314 PUT_INT64(cell_time.u);
1315 PUT_INT32(cell->cell_no);
1316 PUT_INT32(cell->discontinuity);
1319 PUT_INT32(toc_ATRACK_COUNT);
1320 PUT_INT32(total_atracks);
1322 for( j=0; j < total_atracks; ++j ) {
1323 atrack_t *atrk = atrack[j];
1324 PUT_INT64(atrk->audio_eof);
1325 PUT_INT32(atrk->channels);
1326 PUT_INT32(atrk->nudge);
1327 PUT_INT32(atrk->total_sample_offsets);
1329 PUT_INT64(atrk->current_position);
1330 /* Sample offsets */
1331 for( i=0; i < atrk->total_sample_offsets; ++i )
1332 PUT_INT64(atrk->sample_offsets[i]);
1334 index_t *idx = indexes[j];
1335 if( idx->index_data ) {
1336 PUT_INT32(idx->index_size);
1337 PUT_INT32(idx->index_zoom);
1338 for( k=0; k < atrk->channels; ++k ) {
1339 fwrite(idx->index_data[k], 2*sizeof(float),
1340 idx->index_size, toc_fp);
1348 PUT_INT32(toc_VTRACK_COUNT);
1349 PUT_INT32(total_vtracks);
1351 for( j=0; j < total_vtracks; ++j ) {
1352 vtrack_t *vtrk = vtrack[j];
1353 PUT_INT64(vtrk->video_eof);
1354 PUT_INT32(vtrk->total_frame_offsets);
1355 for( i=0; i < vtrk->total_frame_offsets; ++i )
1356 PUT_INT64(vtrk->frame_offsets[i]);
1357 PUT_INT32(vtrk->total_keyframe_numbers);
1358 for( i=0; i < vtrk->total_keyframe_numbers; ++i )
1359 PUT_INT32(vtrk->keyframe_numbers[i]);
1361 PUT_INT32(toc_STRACK_COUNT);
1362 PUT_INT32(total_stracks);
1363 /* Subtitle tracks */
1364 for( i=0; i < total_stracks; ++i ) {
1365 strack_t *strk = strack[i];
1366 PUT_INT32(strk->id);
1367 PUT_INT32(strk->total_offsets);
1368 for(j = 0; j < strk->total_offsets; j++)
1369 PUT_INT64(strk->offsets[j]);
1371 PUT_INT32(toc_IFO_PALETTE);
1372 for( i=0; i < 16*4; ++i )
1373 fputc(palette[i], toc_fp);
1375 PUT_INT32(toc_IFO_PLAYINFO);
1376 PUT_INT32(playinfo->total_cells);
1377 icell_t *cell = &playinfo->cells[0];
1378 for( i=playinfo->total_cells; --i>=0; ++cell ) {
1379 PUT_INT64(cell->start_byte);
1380 PUT_INT64(cell->end_byte);
1381 PUT_INT32(cell->vob_id);
1382 PUT_INT32(cell->cell_id);
1383 PUT_INT32(cell->inlv);
1384 PUT_INT32(cell->discon);
1397 int64_t current_byte = 0;
1401 uint32_t toc_version = fs->read_uint32();
1402 if( toc_version != TOC_VERSION ) {
1403 zmsgs("invalid TOC version %08x (should be %08x)\n",
1404 toc_version, TOC_VERSION);
1405 return ERR_INVALID_TOC_VERSION;
1408 while( !fs->eof() ) {
1409 /* Get section type */
1410 int section_type = fs->read_uint32();
1411 switch( section_type ) {
1412 case toc_FILE_TYPE_PROGRAM:
1413 zmsg("is_program_stream\n");
1416 case toc_FILE_TYPE_TRANSPORT:
1417 zmsg("is_transport_stream\n");
1420 case toc_FILE_TYPE_AUDIO:
1421 zmsg("is_audio_stream\n");
1424 case toc_FILE_TYPE_VIDEO:
1425 zmsg("is_video_stream\n");
1428 case toc_FILE_INFO: {
1429 char string[STRLEN];
1430 char string2[STRLEN];
1431 fs->read_data((uint8_t*)&string[0],STRLEN);
1432 concat_path(string2, fs->path, string);
1433 int64_t sdate = fs->read_uint64();
1434 zmsgs("zsrc=%s source_date=%jd\n", string2, sdate);
1437 case toc_STREAM_AUDIO: {
1438 static const char *afmts[] = {
1439 "unknown", "mpeg", "ac3", "pcm", "aac", "jesus",
1441 int n = fs->read_uint32();
1442 int fmt = fs->read_uint32();
1443 if( fmt < 0 || fmt >= lengthof(afmts) ) fmt = 0;
1444 zmsgs(" audio stream 0x%04x is %s\n", n, afmts[fmt]);
1447 case toc_STREAM_VIDEO: {
1448 int n = fs->read_uint32();
1450 zmsgs(" video stream 0x%04x\n", n);
1454 case toc_ATRACK_COUNT: {
1456 int atracks = fs->read_uint32();
1457 zmsgs("audio tracks = %d\n", atracks);
1458 for( i=0; i < atracks; ++i ) {
1459 int64_t eof = fs->read_uint64();
1460 int channels = fs->read_uint32();
1461 int nudge = fs->read_uint32();
1462 int total_sample_offsets = fs->read_uint32();
1463 int64_t total_samples = fs->read_uint64();
1464 zmsgs(" audio %d, eof=0x%012jx ch=%d, offsets=%d samples=%jd nudge=%d\n",
1465 i, eof, channels, total_sample_offsets, total_samples, nudge);
1466 if( flags & show_toc_SAMPLE_OFFSETS ) {
1467 for( j=0; j < total_sample_offsets; ) {
1468 if( !(j&7) ) zmsgs(" %8d: ",j*AUDIO_CHUNKSIZE);
1469 printf(" %08jx", fs->read_uint64());
1470 if( !(++j&7) ) printf("\n");
1472 if( (j&7) ) printf("\n");
1475 fs->seek_relative(sizeof(int64_t) * total_sample_offsets);
1476 int index_size = fs->read_uint32();
1477 int index_zoom = fs->read_uint32();
1478 zmsgs(" index_size=%d index_zoom=%d\n", index_size, index_zoom);
1479 for( j=0; j < channels; ++j ) {
1480 if( flags & show_toc_AUDIO_INDEX ) {
1481 zmsgs("audio track %d, channel %d\n",i,j);
1482 for( k=0; k<index_size; ) {
1483 union { int i; float f; } min, max;
1484 min.i = bswap_32(fs->read_uint32());
1485 max.i = bswap_32(fs->read_uint32());
1486 if( !(k&3) ) zmsgs(" %08x: ",k*index_zoom);
1487 printf(" %5.3f/%-5.3f",min.f,max.f);
1488 if( !(++k&3) ) printf("\n");
1490 if( (k&3) ) printf("\n");
1493 fs->seek_relative(sizeof(float) * index_size * 2);
1498 case toc_VTRACK_COUNT: {
1500 int vtracks = fs->read_uint32();
1501 zmsgs("video tracks = %d\n", vtracks);
1502 for( i=0; i < vtracks; ++i ) {
1503 int64_t eof = fs->read_uint64();
1504 int total_frame_offsets = fs->read_uint32();
1505 if( flags & show_toc_FRAME_OFFSETS ) {
1506 int64_t *frame_offsets = new int64_t[total_frame_offsets];
1507 for( k=0; k<total_frame_offsets; ++k ) {
1508 frame_offsets[k] = fs->read_uint64();
1510 int total_keyframes = fs->read_uint32();
1511 zmsgs(" video %d, eof=0x%012jx offsets=%d keyframes=%d\n",
1512 i, eof, total_frame_offsets, total_keyframes);
1513 int *keyframe_numbers = new int[total_keyframes];
1514 for( j=0; j<total_keyframes; ++j ) {
1515 keyframe_numbers[j] = fs->read_uint32();
1517 for( j=k=0; k<total_frame_offsets; ) {
1518 if( !(k&7) ) zmsgs(" %8d: ",k);
1519 if( k >= keyframe_numbers[j] ) {
1524 printf("%08jx",frame_offsets[k]);
1525 if( !(++k&7) ) printf("\n");
1527 if( (k&7) ) printf("\n");
1528 delete [] keyframe_numbers;
1529 delete [] frame_offsets;
1532 fs->seek_relative(sizeof(int64_t) * total_frame_offsets);
1533 int total_keyframes = fs->read_uint32();
1534 zmsgs(" video %d, eof=0x%012jx offsets=%d keyframes=%d\n",
1535 i, eof, total_frame_offsets, total_keyframes);
1536 fs->seek_relative(sizeof(int) * total_keyframes);
1541 case toc_STRACK_COUNT: {
1542 total_stracks = fs->read_uint32();
1543 for( i=0; i < total_stracks; ++i ) {
1544 int id = fs->read_uint32();
1545 int total_offsets = fs->read_uint32();
1546 for( j=0; j < total_offsets; ++j ) {
1549 zmsgs(" subtitle %d, id=0x%04x offsets=%d\n",
1550 i, id, total_offsets);
1554 case toc_TITLE_PATH: {
1555 char string[STRLEN];
1556 fs->read_data((uint8_t*)string, STRLEN);
1557 int64_t total_bytes = fs->read_uint64();
1558 int64_t start_byte = current_byte;
1559 int64_t end_byte = start_byte + total_bytes;
1560 current_byte = end_byte;
1561 zmsgs("title %s,\n", &string[0]);
1562 zmsgs(" bytes=0x%012jx, start=0x%012jx, end=0x%012jx\n",
1563 total_bytes, start_byte, end_byte);
1564 int cell_table_size = fs->read_uint32();
1565 for( i=0; i < cell_table_size; ++i ) {
1566 int64_t title_start = fs->read_uint64();
1567 int64_t title_end = fs->read_uint64();
1568 int64_t program_start = fs->read_uint64();
1569 int64_t program_end = fs->read_uint64();
1570 union { double d; uint64_t u; } cell_time;
1571 cell_time.u = fs->read_uint64();
1572 int cell_no = fs->read_uint32();
1573 int discontinuity = fs->read_uint32();
1574 zmsgs(" cell[%2d], title 0x%012jx-0x%012jx, cell_no %2d, cell_time %5.3f\n",
1575 i, title_start, title_end, cell_no, cell_time.d);
1576 zmsgs(" discon %d program 0x%012jx-0x%012jx\n",
1577 discontinuity, program_start, program_end);
1581 case toc_IFO_PALETTE:
1584 for( i=0; i<16/4; ++i ) {
1585 uint32_t rgb0 = fs->read_uint32();
1586 uint32_t rgb1 = fs->read_uint32();
1587 uint32_t rgb2 = fs->read_uint32();
1588 uint32_t rgb3 = fs->read_uint32();
1589 zmsgs(" 0x%08x 0x%08x 0x%08x 0x%08x\n", rgb0, rgb1, rgb2, rgb3);
1593 case toc_IFO_PLAYINFO: {
1595 int ncells = fs->read_uint32();
1596 zmsgs("playcells %d\n", ncells);
1597 for( i=0; i<ncells; ++i) {
1598 int64_t start_byte = fs->read_uint64();
1599 int64_t end_byte = fs->read_uint64();
1600 int vob_id = fs->read_uint32();
1601 int cell_id = fs->read_uint32();
1602 int inlv = fs->read_uint32();
1603 int discon = fs->read_uint32();
1604 zmsgs(" cell[%2d], start=0x%012jx, end=0x%012jx discon %d\n",
1605 i, start_byte, end_byte, discon);
1606 zmsgs(" vob_id %d, cell_id %d, inlv %d\n",
1607 vob_id, cell_id, inlv);
1612 case toc_SRC_PROGRAM: {
1613 int vtitl = fs->read_uint32();
1614 int vtotl = fs->read_uint32();
1615 int inlv = fs->read_uint32();
1616 int tinlv = fs->read_uint32();
1617 zmsgs("vts_title %d\n",vtitl);
1618 zmsgs("total_vts_title %d\n",vtotl);
1619 zmsgs("interleave/angle %d/%d\n",inlv%10,inlv/10);
1620 zmsgs("total_interleaves %d\n",tinlv);