1 /*******************************************************************************
2 * Goggles Audio Player Library *
3 ********************************************************************************
4 * Copyright (C) 2010-2015 by Sander Jansen. All Rights Reserved *
5 * --- *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see http://www.gnu.org/licenses. *
18 ********************************************************************************/
19 #include "ap_defs.h"
20 #include "ap_packet.h"
21 #include "ap_reader_plugin.h"
22 #include "ap_input_plugin.h"
23
24 #include "ap_vorbis.h"
25 #include "ap_opus.h"
26
27 enum {
28 EBML = 0x1a45dfa3,
29 EBML_VERSION = 0x4286,
30 EBML_READ_VERSION = 0x42f7,
31 EBML_MAX_ID_LENGTH = 0x42f2,
32 EBML_MAX_SIZE_LENGTH = 0x42f3,
33 EBML_DOC_TYPE = 0x4282,
34 EBML_DOC_TYPE_VERSION = 0x4287,
35 EBML_DOC_TYPE_READ_VERSION = 0x4285,
36 SEGMENT = 0x18538067,
37 SEEK_HEAD = 0x114d9b74,
38 SEEK = 0x4dbb,
39 SEEK_ID = 0x53ab,
40 SEEK_POSITION = 0x53ac,
41 TRACK = 0x1654ae6b,
42 TRACK_ENTRY = 0xae,
43 TRACK_TYPE = 0x83,
44 TRACK_NUMBER = 0xd7,
45 CODEC_ID = 0x86,
46 CODEC_PRIVATE = 0x63a2,
47 AUDIO = 0xe1,
48 AUDIO_SAMPLE_RATE = 0xb5,
49 AUDIO_CHANNELS = 0x9f,
50 AUDIO_BITDEPTH = 0x6264,
51 CLUSTER = 0x1f43b675,
52 CLUSTER_PREVSIZE = 0xab,
53 CLUSTER_POSITION = 0xa7,
54 BLOCKGROUP = 0xa0,
55 BLOCK = 0xa1,
56 REFERENCE_BLOCK = 0xfb,
57 SIMPLEBLOCK = 0xa3,
58 TIMECODE = 0xe7,
59 SEGMENT_INFO = 0x1549a966,
60 SEGMENT_INFO_TIMECODE_SCALE = 0x2ad7b1,
61 SEGMENT_INFO_DURATION = 0x4489,
62 VOID = 0xec,
63 CUES = 0x1c53bb6b,
64 CUE_POINT = 0xbb,
65 CUE_TIME = 0xb3,
66 CUE_TRACK_POSITIONS = 0xb7,
67 CUE_TRACK = 0xf7,
68 CUE_CLUSTER_POSITION = 0xf1,
69 CUE_RELATIVE_POSITION = 0xf0,
70 };
71
72
73 namespace ap {
74
75 #ifdef HAVE_FAAD
76 extern FXbool ap_parse_aac_specific_config(const FXuchar * data, FXuint length, FXushort & samples_per_frame,FXbool & upsampled, AudioFormat & af);
77 #endif
78
79 namespace matroska {
80
81 struct Element {
82 FXuint type = 0;
83 FXlong size = 0;
84 FXlong offset = 0;
85
Elementap::matroska::Element86 Element(){}
Elementap::matroska::Element87 Element(FXlong sz) : size(sz) {}
88
resetap::matroska::Element89 void reset() { type=0; size=0; offset=0; }
90
debugap::matroska::Element91 void debug(const FXchar * section) const { fxmessage("%s: 0x%x (%ld bytes)\n",section,type,size); }
92 };
93
94 struct Block {
95 FXlong position;
96 FXuint frames[16]={0};
97 FXuint nframes = 0;
nextap::matroska::Block98 inline FXuint next() {
99 return frames[--nframes];
100 }
resetap::matroska::Block101 void reset() { nframes=0; }
102 };
103
104
105 class Track {
106 public:
107
108
109 struct cue_entry {
110 FXlong position;
111 FXlong cluster;
112 };
113
114
115 public:
116 AudioFormat af;
117 DecoderConfig * dc = nullptr;
118 FXuchar codec = Codec::Invalid;
119 FXulong number = 0;
120 FXushort samples_per_frame = 0;
121 FXArray<cue_entry> cues;
122 FXint ncues=0;
123
add_cue_entry(FXlong pos,FXlong cluster)124 void add_cue_entry(FXlong pos,FXlong cluster) {
125 if (cues.no()>=ncues) {
126 cues.no(cues.no()+256);
127 }
128 cues[ncues].position = pos;
129 cues[ncues].cluster = cluster;
130 ncues++;
131 }
132
~Track()133 ~Track() {
134 delete dc;
135 }
136 };
137
138 /* Layout
139
140 Clusters -> Block -> Frame
141
142
143
144 */
145
146
147 class MatroskaReader : public ReaderPlugin {
148 protected:
149 FXPtrListOf<Track> tracks;
150 Track* track=nullptr;
151 protected:
152 Block block; // current block
153 Element cluster; // current cluster
154 Element group; // current group
155 protected:
156 FXbool is_webm = false;
157 FXlong stream_position = 0;
158 FXulong timecode_scale = 1000000;
159 FXulong duration = 0;
160 FXlong first_cluster = 0;
161 FXlong cluster_size = 0;
162 FXuint frame_size = 0;
163 protected:
164 ReadStatus parse();
165
166 FXuchar parse_ebml_uint64(FXlong & value);
167 FXbool parse_element_uint64(Element & container,FXlong & element);
168 FXbool parse_element_int64(Element & container,FXlong & element);
169 FXbool parse_element_id(Element & container,Element & element);
170
171 FXbool parse_element(Element & element);
172 FXbool parse_element(Element & parent,Element & element,FXbool allow_unknown_size=false);
173
174 FXbool parse_ebml(Element&);
175 FXbool parse_segment(Element &);
176 FXbool parse_segment_info(Element &);
177 FXbool parse_seekhead(Element&);
178 FXbool parse_seek(Element&);
179 FXbool parse_track(Element&);
180 FXbool parse_track_entry(Element&);
181 FXbool parse_track_audio(Element&);
182 FXbool parse_track_codec(Element&);
183
184
185 FXbool parse_uint8(FXuchar & value,const FXlong size);
186 FXbool parse_uint64(FXulong & value,const FXlong size);
187 FXbool parse_unsigned_int(FXulong & value,const FXlong size);
188 FXbool parse_float_as_uint32(FXuint & value,const FXlong size);
189
190
191 FXbool parse_xiph_lace(Element &, FXuint & framesize);
192 FXbool get_next_frame(FXuint & framesize);
193 FXbool parse_block_group(Element&);
194 FXbool parse_simpleblock(Element&);
195
196
197 FXbool parse_cues(Element&);
198 FXbool parse_cue_point(Element&);
199 FXbool parse_cue_track(Element&,FXulong & track,FXulong & cluster);
200
201 protected:
202 void clear_tracks();
203 public:
204 enum {
205 OGG_WROTE_HEADER = 0x2,
206 };
207 public:
208 MatroskaReader(InputContext*);
209
210 // Format
format() const211 FXuchar format() const { return Format::Matroska; };
212
213 // Init
214 FXbool init(InputPlugin*);
215
216 // Seekable
217 FXbool can_seek() const;
218
219 // Seek
220 FXbool seek(FXlong );
221
222 // Process Packet
223 ReadStatus process(Packet*);
224
225 // Destroy
226 ~MatroskaReader();
227 };
228
229
MatroskaReader(InputContext * ctx)230 MatroskaReader::MatroskaReader(InputContext * ctx) : ReaderPlugin(ctx) {
231 }
232
~MatroskaReader()233 MatroskaReader::~MatroskaReader(){
234 clear_tracks();
235 }
236
237
clear_tracks()238 void MatroskaReader::clear_tracks(){
239 for (int i=0;i<tracks.no();i++)
240 if (tracks[i]!=track)
241 delete tracks[i];
242 tracks.clear();
243 delete track;
244 track = nullptr;
245 }
246
247
init(InputPlugin * plugin)248 FXbool MatroskaReader::init(InputPlugin*plugin) {
249 ReaderPlugin::init(plugin);
250 flags&=~FLAG_PARSED;
251 clear_tracks();
252
253 timecode_scale = 1000000;
254 first_cluster = 0;
255 frame_size = 0;
256 stream_position = 0;
257 duration = 0;
258 cluster.reset();
259 block.reset();
260 group.reset();
261 return true;
262 }
263
can_seek() const264 FXbool MatroskaReader::can_seek() const {
265 return true;
266 }
267
seek(FXlong offset)268 FXbool MatroskaReader::seek(FXlong offset){
269 if (track->codec==Codec::Opus)
270 offset = FXMAX(0,offset-3840);
271
272 FXulong target = (offset * NANOSECONDS_PER_SECOND) / af.rate;
273 FXlong lastpos = 0;
274 FXlong timestamp = 0;
275 for (FXint i=0;i<track->ncues;i++) {
276 if (target<track->cues[i].position*timecode_scale) {
277 lastpos = track->cues[i].cluster;
278 timestamp = track->cues[i].position*timecode_scale;
279 continue;
280 }
281 break;
282 }
283 input->position(first_cluster+lastpos,FXIO::Begin);
284 stream_position = (timestamp * track->af.rate) / NANOSECONDS_PER_SECOND;
285
286 frame_size=0;
287 cluster.reset();
288 block.reset();
289 group.reset();
290 return true;
291 }
292
process(Packet * packet)293 ReadStatus MatroskaReader::process(Packet*packet) {
294
295 if (!(flags&FLAG_PARSED)) {
296 packet->unref();
297 return parse();
298 }
299
300 packet->stream_length=stream_length;
301 packet->af=af;
302
303 while(packet->space()) {
304
305 if (frame_size) {
306
307 switch(track->codec) {
308 case Codec::MPEG:
309 {
310 if(frame_size > packet->space())
311 break;
312 if (input->read(packet->ptr(),frame_size)!=frame_size)
313 return ReadError;
314 packet->wroteBytes(frame_size);
315 frame_size-=frame_size;
316 break;
317 }
318 case Codec::PCM:
319 {
320 FXuint n = FXMIN(frame_size,(FXuint)(packet->availableFrames()*af.framesize()));
321 if (input->read(packet->ptr(),n)!=n)
322 return ReadError;
323 packet->wroteBytes(n);
324 frame_size-=n;
325 break;
326 }
327 case Codec::AAC:
328 {
329 if(frame_size+4 > packet->space())
330 break;
331 packet->append(&frame_size,4);
332 if (input->read(packet->ptr(),frame_size)!=frame_size)
333 return ReadError;
334 packet->wroteBytes(frame_size);
335 frame_size-=frame_size;
336 break;
337 }
338 case Codec::Vorbis:
339 case Codec::Opus:
340 {
341 if ( ((frame_size+4)<=packet->space()) ||
342 ((packet->space()>=4) && ((frame_size+4)>packet->capacity()))) {
343
344 if (0==(flags&OGG_WROTE_HEADER)) {
345 packet->append(&frame_size,4);
346 flags|=OGG_WROTE_HEADER;
347 }
348
349 FXint n = FXMIN(frame_size,packet->space());
350 if (input->read(packet->ptr(),n)!=n)
351 return ReadError;
352 packet->wroteBytes(n);
353 frame_size-=n;
354 }
355 break;
356 }
357 default:
358 {
359 FXint n = FXMIN(frame_size,packet->space());
360 if (input->read(packet->ptr(),n)!=n)
361 return ReadError;
362 packet->wroteBytes(n);
363 frame_size-=n;
364 break;
365 }
366 }
367
368 // Still bytes left so pass packet to decoder
369 if (frame_size) {
370 context->post_packet(packet);
371 return ReadOk;
372 }
373 }
374
375 FXASSERT(frame_size==0);
376
377 if (!get_next_frame(frame_size)) {
378 return ReadError;
379 }
380
381 flags&=~OGG_WROTE_HEADER;
382
383 if (frame_size==0) {
384 packet->flags|=FLAG_EOS;
385 context->post_packet(packet);
386 return ReadDone;
387 }
388 }
389 return ReadOk;
390 }
391
392
393 enum {
394 AAC_FLAG_CONFIG = 0x2,
395 AAC_FLAG_FRAME = 0x4
396 };
397
398
parse()399 ReadStatus MatroskaReader::parse() {
400 Element element;
401
402 // Get first element
403 if (!parse_element(element))
404 return ReadError;
405
406 // Make sure it is a matroska file
407 if (element.type!=EBML || !parse_ebml(element)) {
408 return ReadError;
409 }
410
411 // Find First Segment
412 while(parse_element(element)) {
413 if (element.type==SEGMENT) {
414 if (!parse_segment(element)) {
415 return ReadError;
416 }
417 break;
418 }
419 input->position(element.size,FXIO::Current);
420 }
421
422 if (tracks.no()) {
423 track=nullptr;
424
425 for (FXint i=0;i<tracks.no();i++) {
426 if (tracks[i]->codec) {
427 if (track==nullptr) track=tracks[i];
428 }
429 }
430
431 if (track) {
432 GM_DEBUG_PRINT("[matroska] select track with codec %s\n",Codec::name(track->codec));
433
434 track->af.debug();
435 af=track->af;
436 ConfigureEvent * cfg = new ConfigureEvent(track->af,track->codec);
437 cfg->dc = track->dc;
438 track->dc = nullptr;
439 stream_length = (duration * timecode_scale * track->af.rate ) / NANOSECONDS_PER_SECOND;
440 GM_DEBUG_STREAM_LENGTH("matroska",stream_length,track->af.rate);
441 cfg->stream_length = stream_length;
442 context->post_configuration(cfg);
443 flags|=FLAG_PARSED;
444 input->position(first_cluster,FXIO::Begin);
445 return ReadOk;
446 }
447 }
448 GM_DEBUG_PRINT("[matroska] no supported tracks found\n");
449 return ReadError;
450 }
451
452
453
454
parse_block_group(Element & parent)455 FXbool MatroskaReader::parse_block_group(Element & parent) {
456 Element element;
457 while(parse_element(parent,element)) {
458 switch(element.type) {
459 case REFERENCE_BLOCK:
460 {
461 input->position(element.size,FXIO::Current);
462 break;
463 }
464 case BLOCK:
465 {
466 if (!parse_simpleblock(element))
467 return false;
468
469 if (block.nframes)
470 return true;
471
472 } break;
473 default :
474 element.debug("Cluster.BlockGroup");
475 input->position(element.size,FXIO::Current);
476 break;
477 }
478 }
479 return true;
480 }
481
482
483
parse_simpleblock(Element & element)484 FXbool MatroskaReader::parse_simpleblock(Element & element) {
485 FXshort timecode;
486 FXuchar flags;
487 FXlong tracknumber;
488
489 if (!parse_element_uint64(element,tracknumber)) {
490 return false;
491 }
492
493 if (track->number != (FXulong)tracknumber) {
494 block.nframes=0;
495 input->position(element.size,FXIO::Current);
496 return true;
497 }
498
499 if (!input->read_int16_be(timecode)){
500 return false;
501 }
502
503 block.position += timecode;
504
505 if (input->read(&flags,1)!=1){
506 return false;
507 }
508
509 switch((flags>>1)&0x3) {
510
511 case 0: // No lacing
512 {
513 block.nframes = 1;
514 block.frames[0] = element.size-3;
515 break;
516 }
517
518 case 1:
519 {
520 FXuint total=0;
521
522 // total frames - 1
523 if (input->read(&block.nframes,1)!=1)
524 return false;
525
526 // Adjust frame count
527 block.nframes+=1;
528
529 // Read frame sizes
530 for (FXint i=block.nframes-1;i>0;i--) {
531 if (!parse_xiph_lace(element,block.frames[i]))
532 return false;
533 total+=block.frames[i];
534 }
535 block.frames[0] = element.size - total - 4;
536 break;
537 }
538
539 case 2: // fixed
540 {
541 // total frames - 1
542 if (input->read(&block.nframes,1)!=1)
543 return false;
544
545 // Adjust frame count
546 block.nframes+=1;
547
548 // size per frame
549 const FXuint size = (element.size-4) / block.nframes;
550 for (FXint i=block.nframes-1;i>=0;i--) {
551 block.frames[i] = size;
552 }
553 block.frames[0] += ((element.size-4) % size);
554 break;
555 }
556
557 case 3: // ebml
558 {
559 // total frames - 1
560 if (input->read(&block.nframes,1)!=1)
561 return false;
562
563 // Adjust frame count
564 block.nframes+=1;
565
566 FXlong size,total=0;
567
568 // first frame size
569 if (!parse_element_uint64(element,size)) {
570 return false;
571 }
572
573 // read remaining
574 block.frames[block.nframes-1] = total = size;
575 for (FXint i=block.nframes-2;i>0;i--) {
576 if (!parse_element_int64(element,size))
577 return false;
578 block.frames[i]=block.frames[i+1] + size;
579 total+=block.frames[i];
580 }
581 block.frames[0] = (element.size-4) - total;
582 break;
583 }
584 default: return false; break;
585 }
586 /*
587 fxmessage("simpleblock\n");
588 for(FXint i=block.nframes-1;i>=0;i--) {
589 fxmessage("frame[%d]=%u\n",block.nframes-i-1,block.frames[i]);
590 }
591 */
592 return true;
593 }
594
get_next_frame(FXuint & framesize)595 FXbool MatroskaReader::get_next_frame(FXuint & framesize) {
596
597 framesize = 0;
598
599 // First check for any frames left in current block
600 if (block.nframes) {
601 framesize = block.next();
602 return true;
603 }
604
605 // Get next block from Block Group [if any]
606 if (group.size) {
607
608 if (!parse_block_group(group))
609 return false;
610
611 if (block.nframes) {
612 framesize = block.next();
613 return true;
614 }
615 }
616
617 // Get next block from cluster
618 do {
619
620 Element element;
621
622 // Get next block or simple block
623 while(parse_element(cluster,element)) {
624
625 switch(element.type) {
626 case CLUSTER_PREVSIZE:
627 case CLUSTER_POSITION:
628 {
629 input->position(element.size,FXIO::Current);
630 break;
631 }
632 case TIMECODE:
633 {
634 FXulong timecode=0;
635 if (!parse_unsigned_int(timecode,element.size)) return false;
636 block.position = (timecode*timecode_scale*track->af.rate) / NANOSECONDS_PER_SECOND;
637 break;
638 }
639 case SIMPLEBLOCK:
640 {
641
642 if (!parse_simpleblock(element))
643 return false;
644
645 if (block.nframes) {
646 framesize = block.next();
647 return true;
648 }
649
650 } break;
651
652 case BLOCKGROUP:
653 {
654 group=element; // store for next iteration
655
656 if (!parse_block_group(group))
657 return false;
658
659 if (block.nframes) {
660 framesize = block.next();
661 return true;
662 }
663
664 } break;
665 default:
666 element.debug("Cluster");
667 input->position(element.size,FXIO::Current);
668 break;
669 }
670 }
671
672 // Get the next cluster
673 while(parse_element(cluster)) {
674
675 if (cluster.type==CLUSTER) {
676 break;
677 }
678 else if (cluster.type==SEGMENT) {
679 return true;
680 }
681 input->position(cluster.size,FXIO::Current);
682 }
683
684 if (cluster.size<=0) {
685 return true;
686 }
687
688 }
689 while(1);
690 return true;
691 }
692
693
694
parse_track_audio(Element & container)695 FXbool MatroskaReader::parse_track_audio(Element & container) {
696 FXASSERT(track);
697 Element element;
698 while(parse_element(container,element)) {
699 switch(element.type) {
700
701 case AUDIO_CHANNELS :
702 {
703 FXuchar channels;
704 if (!parse_uint8(channels,element.size))
705 return false;
706 track->af.setChannels(channels);
707 } break;
708
709 case AUDIO_BITDEPTH :
710 {
711 FXuchar bitdepth;
712 if (!parse_uint8(bitdepth,element.size))
713 return false;
714 track->af.setBits(bitdepth);
715 } break;
716
717 case AUDIO_SAMPLE_RATE:
718 {
719 if (!parse_float_as_uint32(track->af.rate,element.size))
720 return false;
721 } break;
722
723 default:
724 {
725 element.debug("Track.Audio");
726 input->position(element.size,FXIO::Current);
727 break;
728 }
729 }
730 }
731 return true;
732 }
733
734
parse_xiph_lace(Element & container,FXuint & value)735 FXbool MatroskaReader::parse_xiph_lace(Element & container,FXuint & value) {
736 FXuchar byte;
737 value=0;
738 do {
739 if (input->read(&byte,1)!=1)
740 return false;
741 value+=byte;
742 container.size-=1;
743 if (byte<255)
744 return true;
745 }
746 while(1);
747 }
748
749
750
parse_track_codec(Element & element)751 FXbool MatroskaReader::parse_track_codec(Element & element) {
752
753 switch(track->codec) {
754
755 case Codec::Opus:
756 {
757 if (element.size<19)
758 return false;
759
760 OpusConfig * oc = new OpusConfig();
761
762 oc->info_bytes = element.size;
763 allocElms(oc->info,oc->info_bytes);
764 if (input->read(oc->info,oc->info_bytes)!=oc->info_bytes) {
765 delete oc;
766 return false;
767 }
768
769 track->dc = oc;
770 break;
771 }
772
773 case Codec::Vorbis:
774 {
775 FXuchar npackets=0;
776 FXuint frames[3];
777
778 if (input->read(&npackets,1)!=1)
779 return false;
780
781 if ((npackets+1)!=3)
782 return false;
783
784 if (!parse_xiph_lace(element,frames[0]))
785 return false;
786
787 if (!parse_xiph_lace(element,frames[1]))
788 return false;
789
790 frames[2]=element.size - frames[0] - frames[1] - 1;
791
792
793 VorbisConfig * vc = new VorbisConfig();
794
795 vc->info_bytes = frames[0];
796 allocElms(vc->info,vc->info_bytes);
797 if (input->read(vc->info,vc->info_bytes)!=vc->info_bytes) {
798 delete vc;
799 return false;
800 }
801
802 input->position(frames[1],FXIO::Current);
803
804 vc->setup_bytes = frames[2];
805 allocElms(vc->setup,vc->setup_bytes);
806 if (input->read(vc->setup,vc->setup_bytes)!=vc->setup_bytes){
807 delete vc;
808 return false;
809 }
810
811 track->dc = vc;
812 break;
813 }
814 #ifdef HAVE_FAAD
815 case Codec::AAC:
816 {
817 DecoderSpecificConfig * ac = new DecoderSpecificConfig();
818 ac->config_bytes = element.size;
819 allocElms(ac->config,ac->config_bytes);
820 if (input->read(ac->config,ac->config_bytes)!=element.size) {
821 delete ac;
822 return false;
823 }
824 track->dc = ac;
825 FXbool upsampled=false; //fixme
826 if (!ap_parse_aac_specific_config(ac->config,ac->config_bytes,track->samples_per_frame,upsampled,track->af))
827 return false;
828 break;
829 }
830 #endif
831 case Codec::Invalid:
832 {
833 input->position(element.size,FXIO::Current);
834 break;
835 }
836 default:
837 {
838 element.debug("Track.Codec");
839 input->position(element.size,FXIO::Current);
840 break;
841 }
842 }
843 return true;
844 }
845
parse_track_entry(Element & container)846 FXbool MatroskaReader::parse_track_entry(Element & container) {
847 Element element;
848
849 track = new Track();
850
851 while(parse_element(container,element)) {
852
853 switch(element.type) {
854
855 case TRACK_NUMBER:
856 {
857
858 if (!parse_uint64(track->number,element.size)){
859 delete track;
860 track=nullptr;
861 return false;
862 }
863
864 // Ignore invalid tracks
865 if (track->number==0) {
866 delete track;
867 track=nullptr;
868 return true;
869 }
870
871 break;
872 }
873
874 case TRACK_TYPE :
875 {
876 FXuchar track_type=0;
877
878 if (input->read(&track_type,1)!=1) {
879 delete track;
880 track=nullptr;
881 return false;
882 }
883
884 // Skip rest of container if this is a non audio track
885 if (track_type!=2) {
886 input->position(container.size,FXIO::Current);
887 delete track;
888 track=nullptr;
889 return true;
890 }
891 break;
892 }
893
894 case CODEC_ID :
895 {
896 FXString codec;
897 codec.length(element.size);
898 input->read(codec.text(),element.size);
899
900 GM_DEBUG_PRINT("found codec: '%s'\n",codec.text());
901
902 #ifdef HAVE_OGG
903
904 #if defined(HAVE_VORBIS) || defined(HAVE_TREMOR)
905 if (comparecase(codec,"A_VORBIS")==0) {
906 track->codec = Codec::Vorbis;
907 break;
908 }
909 #endif
910
911 #ifdef HAVE_OPUS
912 if (comparecase(codec,"A_OPUS")==0) {
913 track->codec = Codec::Opus;
914 track->af.format |= (Format::Float|Format::Little);
915 track->af.setBits(32);
916 break;
917 }
918 #endif
919
920 #endif
921 if (!is_webm) {
922
923
924 if (comparecase(codec,"A_PCM/INT/LIT")==0) {
925 track->codec = Codec::PCM;
926 track->af.format |= (Format::Signed|Format::Little);
927 break;
928 }
929
930 if (comparecase(codec,"A_PCM/INT/BIG")==0) {
931 track->codec = Codec::PCM;
932 track->af.format |= (Format::Signed|Format::Big);
933 break;
934 }
935
936 if (comparecase(codec,"A_PCM/FLOAT/IEEE")==0) {
937 track->codec = Codec::PCM;
938 track->af.format |= (Format::Float|Format::Little);
939 break;
940 }
941
942 if (comparecase(codec,"A_DTS")==0) {
943 track->codec = Codec::DCA;
944 track->af.format |= (Format::Float|Format::Little);
945 track->af.setBits(32);
946 break;
947 }
948
949 if (comparecase(codec,"A_AC3")==0) {
950 track->codec = Codec::A52;
951 track->af.format |= (Format::Float|Format::Little);
952 track->af.setBits(32);
953 break;
954 }
955
956 #ifdef HAVE_MAD
957 if (comparecase(codec,"A_MPEG/L3")==0) {
958 track->codec = Codec::MPEG;
959 track->af.format |= (Format::Signed|Format::Little);
960 track->af.setBits(16);
961 break;
962 }
963 #endif
964
965 #ifdef HAVE_FLAC
966 if (comparecase(codec,"A_FLAC")==0) {
967 track->codec = Codec::FLAC;
968 track->af.format |= (Format::Signed|Format::Little);
969 break;
970 }
971 #endif
972
973 #ifdef HAVE_FAAD
974 if (comparecase(codec,"A_AAC")==0) {
975 track->codec = Codec::AAC;
976 track->af.format |= (Format::Signed|Format::Little);
977 track->af.setBits(16);
978 break;
979 }
980 #endif
981 }
982 break;
983 }
984 case CODEC_PRIVATE:
985 {
986 if (!parse_track_codec(element)) {
987 delete track;
988 track=nullptr;
989 return false;
990 }
991 break;
992 }
993 case AUDIO:
994 {
995 if (!parse_track_audio(element)){
996 delete track;
997 track=nullptr;
998 return false;
999 }
1000 } break;
1001 default:
1002 {
1003 element.debug("Track");
1004 input->position(element.size,FXIO::Current);
1005 break;
1006 }
1007 }
1008 }
1009
1010 // Fixup channel maps
1011 if (track->codec == Codec::DCA) {
1012 if (track->af.channels==6)
1013 track->af.channelmap = AP_CMAP6(Channel::FrontCenter,Channel::FrontLeft,Channel::FrontRight,Channel::BackLeft,Channel::BackRight,Channel::LFE);
1014 }
1015 else if (track->codec == Codec::A52) {
1016 if (track->af.channels==6)
1017 track->af.channelmap = AP_CMAP6(Channel::LFE,Channel::FrontLeft,Channel::FrontCenter,Channel::FrontRight,Channel::BackLeft,Channel::BackRight);
1018 }
1019 else if (track->codec == Codec::Opus){
1020 track->af.rate = 48000;
1021 }
1022 tracks.append(track);
1023 return true;
1024 }
1025
1026
parse_track(Element & container)1027 FXbool MatroskaReader::parse_track(Element & container) {
1028 Element element;
1029 while(parse_element(container,element)) {
1030 switch(element.type) {
1031 case TRACK_ENTRY:
1032 {
1033 if (!parse_track_entry(element))
1034 return false;
1035 break;
1036 }
1037 default:
1038 {
1039 element.debug("TrackList");
1040 input->position(element.size,FXIO::Current);
1041 break;
1042 }
1043 }
1044 }
1045 return true;
1046 }
1047
1048
parse_cue_track(Element & container,FXulong & cue_track,FXulong & cluster_position)1049 FXbool MatroskaReader::parse_cue_track(Element & container,FXulong & cue_track,FXulong & cluster_position) {
1050 cue_track=0;
1051 cluster_position=0;
1052 Element element;
1053 while(parse_element(container,element)) {
1054 switch(element.type) {
1055 case CUE_TRACK:
1056 {
1057 if (!parse_uint64(cue_track,element.size))
1058 return false;
1059 break;
1060 }
1061 case CUE_CLUSTER_POSITION:
1062 {
1063 if (!parse_uint64(cluster_position,element.size))
1064 return false;
1065 } break;
1066 case CUE_RELATIVE_POSITION:
1067 {
1068 input->position(element.size,FXIO::Current);
1069 break;
1070 }
1071
1072 // {
1073 // if (!parse_uint64(relative_position,element.size))
1074 // return false;
1075 // } break;
1076 default:
1077 {
1078 element.debug("Cues.CuePoint.Track");
1079 input->position(element.size,FXIO::Current);
1080 break;
1081 }
1082 }
1083 }
1084 return true;
1085 }
1086
1087
parse_cue_point(Element & container)1088 FXbool MatroskaReader::parse_cue_point(Element & container) {
1089 FXulong cuetime = 0;
1090 FXulong cluster_position = 0;
1091 FXulong cuetrack = 0;
1092
1093 FXbool has_cuetime=false;
1094 FXbool has_cuetrack=false;
1095
1096 Element element;
1097 while(parse_element(container,element)) {
1098 switch(element.type) {
1099 case CUE_TIME:
1100 {
1101 if (!parse_uint64(cuetime,element.size))
1102 return false;
1103
1104 has_cuetime=true;
1105 break;
1106 }
1107 case CUE_TRACK_POSITIONS:
1108 {
1109 if (!parse_cue_track(element,cuetrack,cluster_position))
1110 return false;
1111
1112 has_cuetrack=true;
1113 } break;
1114 default:
1115 {
1116 element.debug("Cues.CuePoint");
1117 input->position(element.size,FXIO::Current);
1118 break;
1119 }
1120 }
1121 }
1122
1123 if (has_cuetrack && has_cuetime) {
1124 for (FXint i=0;i<tracks.no();i++) {
1125 if (tracks[i]->number==cuetrack) {
1126 tracks[i]->add_cue_entry(cuetime,cluster_position);
1127 break;
1128 }
1129 }
1130 }
1131 return true;
1132 }
1133
1134
parse_cues(Element & container)1135 FXbool MatroskaReader::parse_cues(Element & container) {
1136 Element element;
1137 while(parse_element(container,element)) {
1138 switch(element.type) {
1139 case CUE_POINT:
1140 {
1141 if (!parse_cue_point(element))
1142 return false;
1143 break;
1144 }
1145 default:
1146 {
1147 element.debug("Cues");
1148 input->position(element.size,FXIO::Current);
1149 break;
1150 }
1151 }
1152 }
1153 return true;
1154 }
1155
parse_segment_info(Element & container)1156 FXbool MatroskaReader::parse_segment_info(Element & container) {
1157 Element element;
1158 while(parse_element(container,element)) {
1159 switch(element.type) {
1160
1161 case SEGMENT_INFO_DURATION:
1162 {
1163 if (element.size==4) {
1164 FXfloat value;
1165 input->read_float_be(value);
1166 duration=lrintf(value);
1167 }
1168 else if (element.size==8) {
1169 FXdouble value;
1170 input->read_double_be(value);
1171 duration=lrint(value);
1172 }
1173
1174 GM_DEBUG_PRINT("[matroska] duration %ld\n",duration);
1175 break;
1176 }
1177
1178 case SEGMENT_INFO_TIMECODE_SCALE:
1179 {
1180
1181 if (!parse_unsigned_int(timecode_scale,element.size))
1182 return false;
1183
1184 GM_DEBUG_PRINT("[matroska] timecode scale %ld\n",timecode_scale);
1185 break;
1186 }
1187 default:
1188 {
1189 element.debug("Segment.Info");
1190 input->position(element.size,FXIO::Current);
1191 break;
1192 }
1193 }
1194 }
1195 return true;
1196 }
1197
1198
parse_segment(Element & container)1199 FXbool MatroskaReader::parse_segment(Element & container) {
1200 Element element;
1201
1202 while(parse_element(container,element,true)) {
1203 switch(element.type) {
1204
1205 case SEGMENT_INFO:
1206 {
1207 if (!parse_segment_info(element))
1208 return false;
1209 break;
1210 }
1211
1212 case SEEK_HEAD:
1213 {
1214 if (!parse_seekhead(element))
1215 return false;
1216 break;
1217 }
1218
1219 case TRACK :
1220 {
1221
1222 if (!parse_track(element))
1223 return false;
1224
1225 if (tracks.no()==0)
1226 return true;
1227
1228 } break;
1229
1230 case CLUSTER :
1231 {
1232
1233 if (first_cluster==0)
1234 first_cluster=element.offset;
1235
1236 if (input->serial())
1237 return true;
1238
1239 input->position(element.size,FXIO::Current);
1240
1241 } break;
1242
1243 case CUES:
1244 {
1245 if (!parse_cues(element))
1246 return false;
1247
1248 break;
1249 }
1250 default :
1251 element.debug("Segment");
1252 input->position(element.size,FXIO::Current);
1253 break;
1254 }
1255 }
1256 return true;
1257 }
1258
1259
parse_seekhead(Element & container)1260 FXbool MatroskaReader::parse_seekhead(Element & container) {
1261 Element element;
1262 while(parse_element(container,element)) {
1263 switch(element.type) {
1264 case SEEK :
1265 parse_seek(element);
1266 break;
1267 default :
1268 element.debug("Seek");
1269 input->position(element.size,FXIO::Current);
1270 break;
1271 }
1272 }
1273 return true;
1274 }
1275
parse_seek(Element & container)1276 FXbool MatroskaReader::parse_seek(Element & container) {
1277 Element element;
1278 while(parse_element(container,element)) {
1279 switch(element.type) {
1280 case SEEK_ID:
1281 input->position(element.size,FXIO::Current);
1282 break;
1283 case SEEK_POSITION:
1284 input->position(element.size,FXIO::Current);
1285 break;
1286 default:
1287 element.debug("Seek.Entry");
1288 input->position(element.size,FXIO::Current);
1289 break;
1290 }
1291 }
1292 return true;
1293 }
1294
1295
1296
1297
1298
1299
1300
1301
parse_element(Element & element)1302 FXbool MatroskaReader::parse_element(Element & element) {
1303 Element container(12);
1304
1305 element.offset = input->position();
1306 element.size = 0;
1307
1308 if (!parse_element_id(container,element))
1309 return false;
1310
1311 if (!parse_element_uint64(container,element.size))
1312 return false;
1313
1314 return true;
1315 }
1316
parse_element(Element & container,Element & element,FXbool allow_unknown_size)1317 FXbool MatroskaReader::parse_element(Element & container,Element & element,FXbool allow_unknown_size) {
1318 if (container.size > 2) {
1319
1320 element.offset = input->position();
1321 element.size = 0;
1322
1323 if (!parse_element_id(container,element))
1324 return false;
1325
1326 if (!parse_element_uint64(container,element.size))
1327 return false;
1328
1329 if (element.size>0)
1330 container.size-=element.size;
1331
1332 return true;
1333 }
1334 else if (container.size == -1 && allow_unknown_size) {
1335 return parse_element(element);
1336 }
1337 return false;
1338 }
1339
1340
parse_ebml(Element & container)1341 FXbool MatroskaReader::parse_ebml(Element & container) {
1342 Element element;
1343 FXString doctype;
1344
1345 while(parse_element(container,element)) {
1346
1347 switch(element.type) {
1348 case EBML_DOC_TYPE:
1349 doctype.length(element.size);
1350 input->read(doctype.text(),element.size);
1351 break;
1352
1353 case EBML_VERSION:
1354 case EBML_READ_VERSION:
1355 case EBML_MAX_ID_LENGTH:
1356 case EBML_MAX_SIZE_LENGTH:
1357 case EBML_DOC_TYPE_VERSION:
1358 case EBML_DOC_TYPE_READ_VERSION:
1359 input->position(element.size,FXIO::Current);
1360 break;
1361 default:
1362 element.debug("ebml");
1363 input->position(element.size,FXIO::Current);
1364 break;
1365 }
1366 }
1367
1368 if (doctype=="webm") {
1369 is_webm = true;
1370 return true;
1371 }
1372
1373 if (doctype=="matroska"){
1374 is_webm = false;
1375 return true;
1376 }
1377
1378 GM_DEBUG_PRINT("[matroska] unknown doctype \"%s\"\n",doctype.text());
1379 return false;
1380 }
1381
1382
1383
1384
1385
1386
parse_element_id(Element & container,Element & element)1387 FXbool MatroskaReader::parse_element_id(Element & container,Element & element) {
1388 FXuchar buffer[3]={0};
1389 FXuchar size;
1390
1391
1392 // Read first byte
1393 if (input->read(buffer,1)!=1 || (buffer[0]<=0x7)) {
1394 return false;
1395 }
1396
1397 element.type=buffer[0];
1398
1399 // Get size of id
1400 size=clz32(element.type)-24;
1401
1402 // Read remaining bytes
1403 if (size) {
1404
1405 if (input->read(buffer,size)!=size) {
1406 return false;
1407 }
1408
1409 for (FXint i=0;i<size;i++) {
1410 element.type=(element.type<<8)|static_cast<FXuint>(buffer[i]);
1411 }
1412 }
1413 container.size-=(size+1);
1414 return true;
1415 }
1416
parse_element_uint64(Element & container,FXlong & value)1417 FXbool MatroskaReader::parse_element_uint64(Element & container,FXlong & value) {
1418 FXuchar n = parse_ebml_uint64(value);
1419 if (n==0) return false;
1420 container.size-=n;
1421 return true;
1422 }
1423
parse_element_int64(Element & container,FXlong & value)1424 FXbool MatroskaReader::parse_element_int64(Element & container,FXlong & value) {
1425 FXuchar n = parse_ebml_uint64(value);
1426 if (n==0) return false;
1427 value = value - ((FXULONG(1)<<((7*n)-1))-1);
1428 container.size-=n;
1429 return true;
1430 }
1431
1432
1433
1434
parse_ebml_uint64(FXlong & value)1435 FXuchar MatroskaReader::parse_ebml_uint64(FXlong & value) {
1436 FXuchar buffer[7];
1437 FXuchar n;
1438
1439 // Read first byte
1440 if (input->read(buffer,1)!=1 || (buffer[0]==0)) {
1441 return 0;
1442 }
1443
1444 // Store first byte value
1445 value=buffer[0];
1446
1447 // Get size of id
1448 n=clz32(value)-24;
1449
1450 // Apply mask
1451 value=value&((1<<(7-n))-1);
1452
1453 // Read remaining bytes
1454 if (n) {
1455
1456 if (input->read(buffer,n)!=n) {
1457 return 0;
1458 }
1459
1460 for (FXint i=0;i<n;i++) {
1461 value=(value<<8)|static_cast<FXlong>(buffer[i]);
1462 }
1463 }
1464
1465 // Check for unknown sizes
1466 if ((FXulong)value == ((FXULONG(1)<<((7-n)+(n*8)))-1)) {
1467 fxwarning("matroska: unknown element size not supported");
1468 value=-1;
1469 }
1470 return (n+1);
1471 }
1472
1473
1474
1475
1476
parse_uint8(FXuchar & value,const FXlong size)1477 FXbool MatroskaReader::parse_uint8(FXuchar & value,const FXlong size) {
1478 if (size==1 && input->read(&value,1)==1)
1479 return true;
1480 else
1481 return false;
1482 }
1483
parse_uint64(FXulong & value,const FXlong size)1484 FXbool MatroskaReader::parse_uint64(FXulong & value,const FXlong size) {
1485 FXuchar byte;
1486 value = 0;
1487 for (FXlong i=0;i<size;i++) {
1488 if (input->read(&byte,1)!=1) return false;
1489 value = value<<8 | static_cast<FXulong>(byte);
1490 }
1491 return true;
1492 }
1493
1494
1495
parse_unsigned_int(FXulong & value,const FXlong size)1496 FXbool MatroskaReader::parse_unsigned_int(FXulong & value,const FXlong size) {
1497 FXuchar byte;
1498 value = 0;
1499 for (FXlong i=0;i<size;i++) {
1500 if (input->read(&byte,1)!=1) return false;
1501 value = value<<8 | static_cast<FXulong>(byte);
1502 }
1503 return true;
1504 }
1505
parse_float_as_uint32(FXuint & value,const FXlong size)1506 FXbool MatroskaReader::parse_float_as_uint32(FXuint & value,const FXlong size) {
1507 if (size==4) {
1508 FXfloat val;
1509 if (!input->read_float_be(val)) return false;
1510 value = lrintf(val);
1511 }
1512 else if (size==8) {
1513 FXdouble val;
1514 if (!input->read_double_be(val)) return false;
1515 value = rintf(val);
1516 }
1517 else {
1518 return false;
1519 }
1520 return true;
1521 }
1522
1523 }
1524
1525
ap_matroska_reader(InputContext * ctx)1526 ReaderPlugin * ap_matroska_reader(InputContext * ctx) {
1527 return new matroska::MatroskaReader(ctx);
1528 }
1529
1530 }
1531
1532
1533
1534