9 static uint8_t def_palette[] = { /* better than nothing */
10 0x00, 0x80, 0x80, 0x00, /* black #000000 */
11 0xff, 0x80, 0x80, 0x00, /* white #ffffff */
12 0x4c, 0x54, 0xff, 0x00, /* red #ff0000 */
13 0x96, 0x2b, 0x15, 0x00, /* green #00ff00 */
14 0x1d, 0xff, 0x6b, 0x00, /* blue #0000ff */
15 0xe2, 0x00, 0x94, 0x00, /* yellow #ffff00 */
16 0x69, 0xd4, 0xea, 0x00, /* purple #ff00ff */
17 0xb3, 0xab, 0x00, 0x00, /* cyan #00ffff */
18 0x80, 0x80, 0x80, 0x00, /* grey #808080 */
19 0xa6, 0x6a, 0xbf, 0x00, /* pink #ff8080 */
20 0xcb, 0x55, 0x4a, 0x00, /* lime #80ff80 */
21 0x8e, 0xbf, 0x75, 0x00, /* lavndr #8080ff */
22 0xd9, 0x95, 0x40, 0x00, /* brt cyan #80ffff */
23 0xb4, 0xaa, 0xb5, 0x00, /* brt purple #ff80ff */
24 0xf1, 0x40, 0x8a, 0x00, /* brt yellow #ffff80 */
25 0xff, 0x80, 0x80, 0x00, /* white #ffffff */
29 init(const char *title_path)
34 interleave = angle = 0;
35 total_interleaves = 1;
36 bitfont_t::init_fonts();
37 demuxer = new demuxer_t(this, 0, 0, -1);
38 seekable = 1; log_errs = getenv("LOG_ERRS") ? 1 : 0;
39 memcpy(&palette[0], &def_palette[0], sizeof(def_palette));
40 char *cp = getenv("PTS_PADDING");
41 pts_padding = cp ? atoi(cp) : 1;
42 index_bytes = 0x300000;
45 iopened = fs->is_open;
46 int ret = !iopened ? fs->open_file() : 0;
48 int toc_atracks = INT_MAX;
49 int toc_vtracks = INT_MAX;
50 ret = get_file_type(&toc_atracks, &toc_vtracks, title_path);
52 /* Start from scratch */
53 if( !demuxer->total_titles )
54 demuxer->create_title();
56 if( is_transport_stream() || is_program_stream() ) {
58 /* Create video tracks */
59 for( i=n=0; i<MAX_STREAMZ && total_vtracks<toc_vtracks; ++i ) {
60 if( demuxer->vstream_table[i] ) {
61 vtrack[total_vtracks] = new_vtrack_t(i, demuxer, n++);
62 if( vtrack[total_vtracks] ) ++total_vtracks;
65 /* Create audio tracks */
66 for( i=n=0; i<MAX_STREAMZ && total_atracks<toc_atracks; ++i ) {
67 int format = demuxer->astream_table[i];
69 atrack[total_atracks] = new_atrack_t(i, format, demuxer, n++);
70 if( atrack[total_atracks] ) ++total_atracks;
73 /* Create subtile tracks */
74 for( i=0; i<MAX_STREAMZ; ++i ) {
75 if( demuxer->sstream_table[i] ) {
76 strack[total_stracks] = new strack_t(i);
77 if( strack[total_stracks] ) ++total_stracks;
81 else if( is_video_stream() ) {
82 /* Create video tracks */
83 vtrack[0] = new_vtrack_t(-1, demuxer, 0);
84 if( vtrack[0] ) ++total_vtracks;
86 else if( is_audio_stream() ) {
87 /* Create audio tracks */
88 atrack[0] = new_atrack_t(-1, afmt_UNKNOWN, demuxer, 0);
89 if( atrack[0] ) ++total_atracks;
92 if( (fs->access() & ZIO_SEQUENTIAL) != 0 )
94 demuxer->seek_byte(0);
99 allocate_slice_decoders();
108 for( i=0; i<total_vtracks; ++i ) {
109 vtrack_t *vtrk = vtrack[i];
110 if( vtrk && vtrk->video ) {
111 vtrk->current_position = 0;
113 vtrk->frame_cache->clear();
114 vtrk->video->rewind_video(0);
118 for( i=0; i<total_atracks; ++i ) {
119 atrack_t *atrk = atrack[i];
120 if( atrk && atrk->audio ) {
121 atrk->current_position = 0;
123 atrk->audio->output_size = 0;
124 atrk->audio->output_position = 0;
125 atrk->audio->rewind_audio();
133 zmpeg3_t(const char *path)
138 fs = new fs_t(this, path);
139 cpus = 1; log_errs = getenv("LOG_ERRS") ? 1 : 0;
140 demuxer = new demuxer_t(this, 0, 0, -1);
141 // for toc generation
143 memcpy(&palette[0], &def_palette[0], sizeof(def_palette));
144 char *cp = getenv("PTS_PADDING");
145 pts_padding = cp ? atoi(cp) : 1;
146 index_bytes = 0x300000;
152 zmpeg3_t(const char *path, int &ret, int atype, const char *title_path)
157 fs = new fs_t(this, path, atype);
158 ret = init(title_path);
162 zmpeg3_t(int fd, int &ret, int atype)
167 fs = new fs_t(this, fd, atype);
172 zmpeg3_t(FILE *fp, int &ret, int atype)
177 fs = new fs_t(this, fp, atype);
187 if( debug ) zmsg("0\n");
189 delete_slice_decoders();
191 if( debug ) zmsg("1\n");
192 for( i=0; i<total_stracks; ++i )
195 if( debug ) zmsg("2\n");
196 for( i=0; i<total_atracks; ++i )
199 if( debug ) zmsg("3\n");
200 for( i=0; i<total_vtracks; ++i )
203 if( debug ) zmsg("4\n");
206 if( playinfo ) delete playinfo;
208 if( debug ) zmsg("5\n");
209 if( frame_offsets ) {
210 for( i=0; i<total_vtracks; ++i ) {
211 delete [] frame_offsets[i];
212 delete [] keyframe_numbers[i];
215 if( debug ) zmsg("6\n");
216 delete [] frame_offsets;
217 delete [] keyframe_numbers;
218 delete [] total_frame_offsets;
219 delete [] total_keyframe_numbers;
223 if( debug ) zmsg("7\n");
224 if( sample_offsets ) {
225 for( i=0; i<total_atracks; ++i )
226 delete [] sample_offsets[i];
228 delete [] sample_offsets;
229 delete [] total_sample_offsets;
232 if( debug ) zmsg("8\n");
233 delete [] channel_counts;
235 delete [] total_samples;
238 if( debug ) zmsg("9\n");
240 for( i=0; i<total_indexes; ++i )
243 if( debug ) zmsg("10\n");
246 bitfont_t::destroy_fonts();
259 for( int i=0;i<index_channels; ++i )
260 delete [] index_data[i];
261 delete [] index_data;
264 // Return number of tracks in the table of contents
268 return total_indexes;
271 // Return number of channels in track
273 index_channels(int track)
275 if( track<0 || track>=total_indexes ) return 0;
276 return indexes[track]->index_channels;
279 // Return zoom factor of index
283 return !total_indexes ? 0 : indexes[0]->index_zoom;
286 // Number of high/low pairs in a channel of the track
288 index_size(int track)
290 if( track<0 || track>=total_indexes ) return 0;
291 int size = indexes[track]->index_size;
292 if( track < total_atracks && atrack[track]->nudge > 0 )
293 size -= atrack[track]->nudge / indexes[0]->index_zoom;
297 // Get data for one index channel
299 index_data(int track, int channel)
301 if( track<0 || track>=total_indexes ) return 0;
302 float *data = indexes[track]->index_data[channel];
303 if( track < total_atracks && atrack[track]->nudge > 0 )
304 data += (atrack[track]->nudge / indexes[0]->index_zoom) * 2;
308 zstrack_t* zmpeg3_t::
309 get_strack_id(int id, video_t *vid)
311 for( int i=0; i<total_stracks; ++i ) {
312 strack_t *strk = strack[i];
313 if( strk->video && strk->video != vid ) continue;
314 if( strk->id == id ) return strack[i];
319 zstrack_t* zmpeg3_t::
320 get_strack(int number)
322 if( number >= total_stracks || number < 0 ) return 0;
323 return strack[number];
326 zstrack_t* zmpeg3_t::
327 create_strack(int id, zvideo_t *vid)
332 if( !(strk=get_strack_id(id, vid)) ) {
333 strk = new strack_t(id, vid);
334 for( i=0; i<total_stracks; ++i ) {
335 /* Search for first ID > current id */
336 if( strack[i]->id > id ) {
338 for( j=total_stracks; --j>=i; )
339 strack[j+1] = strack[j];
353 show_subtitle(int stream, int strk)
356 if( stream>=0 && stream<total_vtracks ) {
357 vtrack_t *vtrk = vtrack[stream];
358 if( vtrk && vtrk->video )
359 result = vtrk->video->show_subtitle(strk);
364 static inline int is_toc_(uint32_t bits)
366 return (bits == zmpeg3_t::TOC_PREFIX);
370 static inline int is_ifo_(uint32_t bits)
372 return (bits == zmpeg3_t::IFO_PREFIX);
375 static inline int is_transport_(uint32_t bits)
377 return (((bits >> 24) & 0xff) == zmpeg3_t::SYNC_BYTE);
380 static inline int is_bd_(uint32_t bits1, uint32_t bits2, char *ext)
382 return (((bits2 >> 24) & 0xff) == zmpeg3_t::SYNC_BYTE) &&
384 (!strncasecmp(ext, ".m2ts", 5) ||
385 !strncasecmp(ext, ".mts", 4))) );
388 static inline int is_program_(uint32_t bits)
390 return (bits == zmpeg3_t::PACK_START_CODE);
393 static inline int is_mpeg_audio_(uint32_t bits)
395 return (bits & 0xfff00000) == 0xfff00000 ||
396 (bits & 0xffff0000) == 0xffe30000 ||
397 ((bits >> 8) == zmpeg3_t::ID3_PREFIX) ||
398 (bits == zmpeg3_t::RIFF_CODE);
401 static inline int is_mpeg_video_(uint32_t bits)
403 return (bits == zmpeg3_t::SEQUENCE_START_CODE ||
404 bits == zmpeg3_t::PICTURE_START_CODE);
407 static inline int is_ac3_(uint32_t bits)
409 return (((bits & 0xffff0000) >> 16) == zmpeg3_t::AC3_START_CODE);
413 check_sig(char *path)
416 fs_t *fs = new fs_t(0, path);
418 if( !fs->open_file() ) { /* File found */
419 char *ext = strrchr(path, '.');
420 uint32_t bits = fs->read_uint32();
421 // uint32_t bits2 = fs->read_uint32();
423 /* pre-approved suffixes */
424 if( ext && !strncasecmp(ext, ".mp3", 4) ) {
428 else if( bits == TOC_PREFIX ) {
431 /* don't use, does not work well at all */
432 // /* Blu-Ray or AVC-HD*/
433 // else if( is_bd_(bits, bits2, ext) ) {
436 else if( (((bits >> 24) & 0xff) == zmpeg3_t::SYNC_BYTE ) ||
437 (bits == zmpeg3_t::PACK_START_CODE) ||
438 ((bits & 0xfff00000) == 0xfff00000) ||
439 ((bits & 0xffff0000) == 0xffe30000) ||
440 (bits == zmpeg3_t::SEQUENCE_START_CODE) ||
441 (bits == zmpeg3_t::PICTURE_START_CODE) ||
442 (((bits & 0xffff0000) >> 16) == zmpeg3_t::AC3_START_CODE) ||
443 ((bits >> 8) == zmpeg3_t::ID3_PREFIX) ||
444 (bits == zmpeg3_t::RIFF_CODE) ||
445 (bits == zmpeg3_t::IFO_PREFIX)) {
448 /* Test file extension. */
450 if( strcasecmp(ext, "ifo") &&
451 strcasecmp(ext, "mp2") &&
452 strcasecmp(ext, "mp3") &&
453 strcasecmp(ext, "m1v") &&
454 strcasecmp(ext, "m2v") &&
455 strcasecmp(ext, "m2s") &&
456 strcasecmp(ext, "mpg") &&
457 strcasecmp(ext, "vob") &&
458 strcasecmp(ext, "ts") &&
459 strcasecmp(ext, "vts") &&
460 strcasecmp(ext, "mpeg") &&
461 strcasecmp(ext, "m2t") &&
462 strcasecmp(ext, "ac3") )
474 calculate_packet_size()
476 if( is_transport_stream() )
477 return is_bd() ? BD_PACKET_SIZE : TS_PACKET_SIZE;
478 if( is_program_stream() )
480 if( is_audio_stream() || is_video_stream() )
481 return DVD_PACKET_SIZE;
482 zerr("undefined stream type.\n");
487 get_file_type(int *toc_atracks, int *toc_vtracks, const char *title_path)
491 uint32_t bits = fs->read_uint32();
492 uint32_t bits2 = fs->read_uint32();
495 if( is_toc_(bits) ) {
496 /* Table of contents for another title set */
497 result = toc_atracks && toc_vtracks ?
498 read_toc(toc_atracks, toc_vtracks, title_path) : 1;
499 if( result ) fs->close_file();
501 else if( is_ifo_(bits) ) {
504 file_type = FT_PROGRAM_STREAM | FT_IFO_FILE;
507 else if( is_bd_(bits,bits2,0) ) {
508 file_type = FT_TRANSPORT_STREAM | FT_BD_FILE;
510 /* Transport stream */
511 else if( is_transport_(bits) ) {
512 file_type = FT_TRANSPORT_STREAM;
515 /* Determine packet size empirically */
516 else if( is_program_(bits) ) {
517 file_type = FT_PROGRAM_STREAM;
519 /* MPEG Audio only */
520 else if( is_mpeg_audio_(bits) ) {
521 file_type = FT_AUDIO_STREAM;
524 else if( is_mpeg_video_(bits) ) {
525 file_type = FT_VIDEO_STREAM;
528 else if( is_ac3_(bits) ) {
529 file_type = FT_AUDIO_STREAM;
532 const char *ext = strrchr(fs->path, '.');
534 if( !strncasecmp(ext, ".mp3", 4) ) {
535 file_type = FT_AUDIO_STREAM;
539 //zmsgs("2 %x\n", file_type);
541 zerr("not a readable stream.\n");
542 if( !result ) result = ERR_UNDEFINED_ERROR;
545 packet_size = calculate_packet_size();
550 set_pts_padding(int v)
552 int ret = pts_padding;
554 if( pts_padding >= 0 ) {
555 for( int vtk=0; vtk<total_vtracks; ++vtk )
556 vtrack[vtk]->pts_starttime = -1.;
557 for( int atk=0; atk<total_atracks; ++atk )
558 atrack[atk]->pts_starttime = -1.;
561 for( int vtk=0; vtk<total_vtracks; ++vtk )
562 vtrack[vtk]->pts_starttime = vtrack[vtk]->pts_offset = 0.;
563 for( int atk=0; atk<total_atracks; ++atk )
564 atrack[atk]->pts_starttime = atrack[atk]->pts_offset = 0.;
574 for( i=0; i<total_vtracks; ++i )
575 vtrack[i]->video->set_cpus(cpus);
582 return total_atracks > 0;
588 return total_atracks;
592 audio_channels(int stream)
594 return stream>=0 && stream<total_atracks ?
595 atrack[stream]->channels : -1;
599 sample_rate(int stream)
601 return stream>=0 && stream<total_atracks ?
602 (double)atrack[stream]->sample_rate : -1.;
606 get_sample(int stream)
608 return stream>=0 && stream<total_atracks ?
609 atrack[stream]->current_position : -1;
613 set_sample(long sample, int stream)
616 if( stream>=0 && stream<total_atracks ) {
617 atrack_t *atrk = atrack[stream];
618 if( atrk && atrk->audio ) {
619 //zmsgs("1 %d %ld\n", atrk->current_position, sample);
620 if( atrk->current_position != sample ) {
621 atrk->current_position = sample;
622 atrk->audio->seek_sample(sample);
631 audio_nudge(int stream)
634 if( stream>=0 && stream<total_atracks ) {
635 atrack_t *atrk = atrack[stream];
636 if( atrk ) result = atrk->nudge;
642 audio_samples(int stream)
645 if( stream>=0 && stream<total_atracks ) {
646 atrack_t *atrk = atrack[stream];
647 if( atrk ) result = atrk->total_samples;
652 const char* zmpeg3_t::
653 audio_format(int stream)
655 const char *result = 0;
656 if( stream>=0 && stream<total_atracks ) {
657 switch( atrack[stream]->format ) {
658 case afmt_IGNORE: result = "Ignore"; break;
659 case afmt_UNKNOWN: result = "Unknown"; break;
660 case afmt_MPEG: result = "MPEG"; break;
661 case afmt_AC3: result = "AC3"; break;
662 case afmt_PCM: result = "PCM"; break;
663 case afmt_AAC: result = "AAC"; break;
664 case afmt_JESUS: result = "Vorbis"; break;
665 default: result = "Undef"; break;
674 return total_vtracks > 0;
680 return total_vtracks;
684 video_width(int stream)
687 if( stream>=0 && stream<total_vtracks ) {
688 vtrack_t *vtrk = vtrack[stream];
689 if( vtrk ) result = vtrk->width;
695 video_height(int stream)
698 if( stream>=0 && stream<total_vtracks ) {
699 vtrack_t *vtrk = vtrack[stream];
700 if( vtrk ) result = vtrk->height;
706 coded_width(int stream)
709 if( stream>=0 && stream<total_vtracks ) {
710 vtrack_t *vtrk = vtrack[stream];
712 result = vtrk->video->coded_picture_width;
718 coded_height(int stream)
721 if( stream>=0 && stream<total_vtracks ) {
722 vtrack_t *vtrk = vtrack[stream];
724 result = vtrk->video->coded_picture_height;
730 video_pid(int stream)
733 if( stream>=0 && stream<total_vtracks ) {
734 vtrack_t *vtrk = vtrack[stream];
735 if( vtrk ) result = vtrk->pid;
741 aspect_ratio(int stream)
744 if( stream>=0 && stream<total_vtracks ) {
745 vtrack_t *vtrk = vtrack[stream];
746 if( vtrk ) result = vtrk->aspect_ratio;
752 frame_rate(int stream)
754 double result = -1.0;
755 if( stream>=0 && stream<total_vtracks ) {
756 vtrack_t *vtrk = vtrack[stream];
757 if( vtrk ) result = vtrk->frame_rate;
763 video_frames(int stream)
766 if( stream>=0 && stream<total_vtracks ) {
767 vtrack_t *vtrk = vtrack[stream];
768 if( vtrk ) result = vtrk->total_frames;
774 get_frame(int stream)
777 if( stream>=0 && stream<total_vtracks ) {
778 vtrack_t *vtrk = vtrack[stream];
779 if( vtrk ) result = vtrk->current_position;
785 set_frame(long frame, int stream)
788 if( stream>=0 && stream<total_vtracks ) {
789 vtrack_t *vtrk = vtrack[stream];
790 if( vtrk && vtrk->video ) {
791 if( vtrk->current_position != frame ) {
792 vtrk->current_position = frame;
793 vtrk->video->seek_frame(frame);
802 seek_byte(int64_t byte)
806 for( i=0; i<total_vtracks; ++i ) {
807 vtrack_t *vtrk = vtrack[i];
808 if( vtrk && vtrk->video ) {
809 vtrk->current_position = 0;
811 vtrk->video->seek_byte(byte);
813 vtrk->video->rewind_video();
817 for( i=0; i<total_atracks; ++i ) {
818 atrack_t *atrk = atrack[i];
819 if( atrk && atrk->audio ) {
820 atrk->current_position = 0;
821 atrk->audio->seek_byte(byte);
829 previous_frame(int stream)
833 if( stream>=0 && stream<total_vtracks ) {
834 vtrack_t *vtrk = vtrack[stream];
835 if( vtrk && vtrk->video ) {
837 last_stream_read = stream;
838 result = vtrk->video->previous_frame();
848 if( last_type_read == 1 )
849 result = atrack[last_stream_read]->demuxer->tell_byte();
850 else if( last_type_read == 2 )
851 result =vtrack[last_stream_read]->demuxer->tell_byte();
858 return demuxer->movie_size();
862 get_audio_time(int stream)
865 if( stream >= 0 && stream < total_atracks ) {
866 double samplerate = sample_rate(stream);
867 if( samplerate > 0. ) {
868 int64_t sample = get_sample(stream);
869 if( !pts_padding || is_audio_stream() || is_video_stream() ) {
870 atime = sample / samplerate;
873 atime = atrack[stream]->audio_time +
874 (sample - atrack[stream]->pts_position) / samplerate;
882 get_video_time(int stream)
885 if( stream >= 0 && stream < total_vtracks ) {
886 double framerate = frame_rate(stream);
887 if( !pts_padding || is_audio_stream() || is_video_stream() ) {
889 vtime = (double)get_frame(stream) / framerate;
892 vtime = vtrack[stream]->video_time;
893 if( vtime >= 0. && framerate > 0. )
894 vtime += (get_frame(stream) - vtrack[stream]->pts_position) / framerate;
900 /* pts timecode available only in transport stream */
905 if( last_type_read == 1 )
906 time = get_audio_time(last_stream_read);
907 else if( last_type_read == 2 )
908 time = get_video_time(last_stream_read);
913 get_total_vts_titles()
915 return total_vts_titles;
919 set_vts_title(int title)
921 int result = vts_title;
928 get_total_interleaves()
930 return total_interleaves;
934 set_interleave(int inlv)
936 int result = interleave;
954 int result = set_vts_title()*100 + set_angle()*10 + set_interleave();
956 set_vts_title(no / 100);
957 set_angle((no/10) % 10);
958 set_interleave(no % 10);
964 get_cell_time(int no, double &time)
966 int result = 1, i = 0;
969 result = demuxer->get_cell(i, cell);
970 if( result < 0 ) return result;
971 if( result > 0 ) i = cell->cell_no;
974 time = cell->cell_time;
979 end_of_audio(int stream)
982 if( stream>=0 && stream<total_atracks ) {
983 atrack_t *atrk = atrack[stream];
984 if( atrk && atrk->demuxer )
985 result = atrk->demuxer->eof();
991 end_of_video(int stream)
994 if( stream>=0 && stream<total_vtracks ) {
995 vtrack_t *vtrk = vtrack[stream];
996 if( vtrk && vtrk->demuxer )
997 result = vtrk->demuxer->eof();
1003 drop_frames(long frames, int stream)
1006 if( stream>=0 && stream<total_vtracks ) {
1007 vtrack_t *vtrk = vtrack[stream];
1008 if( vtrk && vtrk->video ) {
1009 result = vtrk->video->drop_frames(frames, 0);
1011 vtrk->current_position += frames;
1013 last_stream_read = stream;
1020 colormodel(int stream)
1023 if( stream>=0 && stream<total_vtracks ) {
1024 vtrack_t *vtrk = vtrack[stream];
1025 if( vtrk && vtrk->video )
1026 result = vtrk->video->colormodel();
1032 set_rowspan(int bytes, int stream)
1035 if( stream>=0 && stream<total_vtracks ) {
1036 vtrack_t *vtrk = vtrack[stream];
1037 if( vtrk && vtrk->video ) {
1038 vtrk->video->row_span = bytes;
1047 read_frame(uint8_t **output_rows,
1048 int in_x, int in_y, int in_w, int in_h,
1049 int out_w, int out_h, int color_model, int stream)
1052 //zmsgs("1 %d\n", vtrack[stream]->current_position);
1053 if( stream>=0 && stream<total_vtracks ) {
1054 vtrack_t *vtrk = vtrack[stream];
1055 if( vtrk && vtrk->video ) {
1056 result = vtrk->video->read_frame(output_rows,
1057 in_x, in_y, in_w, in_h, out_w, out_h, color_model);
1060 last_stream_read = stream;
1061 vtrk->current_position++;
1064 //zmsgs("2 %d\n", vtrack[stream]->current_position);
1069 read_yuvframe(char *y_output, char *u_output, char *v_output,
1070 int in_x, int in_y, int in_w, int in_h, int stream)
1074 if( stream>=0 && stream<total_vtracks ) {
1075 vtrack_t *vtrk = vtrack[stream];
1076 if( vtrk && vtrk->video ) {
1077 result = vtrk->video->read_yuvframe(y_output, u_output, v_output,
1078 in_x, in_y, in_w, in_h);
1080 last_stream_read = stream;
1081 vtrk->current_position++;
1089 read_yuvframe_ptr(char **y_output, char **u_output, char **v_output,
1093 if( stream>=0 && stream<total_vtracks ) {
1094 vtrack_t *vtrk = vtrack[stream];
1095 if( vtrk && vtrk->video ) {
1096 result = vtrk->video->read_yuvframe_ptr(y_output, u_output, v_output);
1098 last_stream_read = stream;
1099 vtrk->current_position++;
1106 read_audio(void *output, int type, int channel, long samples, int stream)
1109 if( stream>=0 && stream<total_atracks ) {
1110 atrack_t *atrk = atrack[stream];
1111 if( atrk && atrk->audio ) {
1112 atrk->audio->update_audio_history();
1113 result = atrk->audio->decode_audio(output, type, channel, samples);
1115 last_stream_read = stream;
1116 atrk->current_position += samples;
1123 read_audio(double *output_d, int channel, long samples, int stream)
1125 return read_audio((void *)output_d, atyp_DOUBLE, channel, samples, stream);
1129 read_audio(float *output_f, int channel, long samples, int stream)
1131 return read_audio((void *)output_f, atyp_FLOAT, channel, samples, stream);
1135 read_audio(int *output_i, int channel, long samples, int stream)
1137 return read_audio((void *)output_i, atyp_INT, channel, samples, stream);
1141 read_audio(short *output_s, int channel, long samples, int stream)
1143 return read_audio((void *)output_s, atyp_SHORT, channel, samples, stream);
1147 reread_audio(void *output, int atyp, int channel, long samples, int stream)
1150 if( stream>=0 && stream<total_atracks ) {
1151 atrack_t *atrk = atrack[stream];
1152 if( atrk && atrk->audio ) {
1153 set_sample( atrk->current_position-samples, stream);
1154 result = atrk->audio->decode_audio(output, atyp, channel, samples);
1156 last_stream_read = stream;
1157 atrk->current_position += samples;
1164 reread_audio(double *output_d, int channel, long samples, int stream)
1166 return reread_audio((void *)output_d, atyp_DOUBLE, channel, samples, stream);
1170 reread_audio(float *output_f, int channel, long samples, int stream)
1172 return reread_audio((void *)output_f, atyp_FLOAT, channel, samples, stream);
1176 reread_audio(int *output_i, int channel, long samples, int stream)
1178 return reread_audio((void *)output_i, atyp_INT, channel, samples, stream);
1182 reread_audio(short *output_s, int channel, long samples, int stream)
1184 return reread_audio((void *)output_s, atyp_SHORT, channel, samples, stream);
1189 read_audio_chunk(uint8_t *output, long *size, long max_size, int stream)
1192 if( stream>=0 && stream<total_atracks ) {
1193 atrack_t *atrk = atrack[stream];
1194 if( atrk && atrk->audio ) {
1195 result = atrk->audio->read_raw(output, size, max_size);
1197 last_stream_read = stream;
1204 read_video_chunk( uint8_t *output, long *size, long max_size, int stream)
1207 if( stream>=0 && stream<total_vtracks ) {
1208 vtrack_t *vtrk = vtrack[stream];
1209 if( vtrk && vtrk->video ) {
1210 result = vtrk->video->read_raw(output, size, max_size);
1212 last_stream_read = stream;
1222 for( int i=0; i<total_vtracks; ++i )
1223 if( vtrack[i]->frame_cache )
1224 result += vtrack[i]->frame_cache->memory_usage();
1229 start_record(int fd, int bsz)
1231 if( recd_fd >= 0 ) return 1;
1233 memset(&st, 0, sizeof(st));
1234 if( fstat64(fd, &st) < 0 ) return 1;
1236 recd_pos = st.st_size;
1237 if (fs->start_record(bsz)) return recd_fd = -1;
1243 if( fs->stop_record() ) return 1;
1249 write_record(uint8_t *data, int len)
1251 if( recd_fd < 0 ) return;
1252 if( write(recd_fd, data, len) < 0 ) {
1253 zmsgs("write err: %s\n",strerror(errno));
1262 return fs->pause_reader(v);
1266 get_thumbnail(int trk, int64_t &frn, uint8_t *&t, int &w, int &h)
1269 if( trk>=0 && trk<total_vtracks ) {
1270 vtrack_t *vtrk = vtrack[trk];
1272 video_t *vid = vtrk->video;
1273 frn = vid->framenum;
1275 w = 2*vid->mb_width;
1276 h = 2*vid->mb_height;
1284 set_thumbnail_callback(int trk, int skim, int thumb,
1285 zthumbnail_cb fn, void *p)
1288 // all tracks, toc build
1291 // one track, commercials verify
1292 else if( trk >= 0 && trk<total_vtracks ) {
1293 vtrack_t *vtrk = vtrack[trk];
1295 video_t *vid = vtrk->video;
1296 if( !(result=vid->seek_video()) ) {
1312 set_cc_text_callback(int trk, zcc_text_cb fn)
1315 if( trk>=0 && trk<total_vtracks ) {
1316 vtrack_t *vtrk = vtrack[trk];
1318 video_t *vid = vtrk->video;
1319 vid->get_cc()->text_cb = fn;
1327 calculate_source_date(char *path)
1329 struct stat64 ostat;
1330 memset(&ostat,0,sizeof(struct stat64));
1331 return stat64(path, &ostat) < 0 ? 0 : ostat.st_mtime;
1335 calculate_source_date(int fd)
1337 struct stat64 ostat;
1338 memset(&ostat,0,sizeof(struct stat64));
1339 return fstat64(fd, &ostat) < 0 ? 0 : ostat.st_mtime;