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