2 Copyright 2006 Mark Calderbank, Andreas Vogel
4 This file is part of VOMP.
6 VOMP 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 2 of the License, or
9 (at your option) any later version.
11 VOMP 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.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "demuxeraudio.h"
27 #define HDRBYTE2MASK 0xe0
34 PacketBuffer(Stream *as,UCHAR strtype) {
35 log=Log::getInstance();
40 //just handle the data (do not deal with headers)
41 int putInternal(UCHAR* buf,int len);
45 framelen=DemuxerAudio::PACKET_SIZE;
55 return (partPacket>=framelen);
57 //can we write a new packet?
61 //only set this, if buffer empty
63 bool setFramelen(int len) {
64 if (! bufferEmpty() ) return false;
65 if (len > (int)DemuxerAudio::PACKET_SIZE) return false;
69 //how much bytes do we need to fill the packet?
71 return framelen-partPacket;
76 void setSkipFactor(int factor) {
81 void packetWritten() {
83 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written packet %ld l=%d, bytes %ld",numpackets,framelen,numbytes);
88 UCHAR store[DemuxerAudio::PACKET_SIZE]; // Storage for partial packets
89 int partPacket; // Length of partial packet stored from previous put()
90 int bytesWritten; //if they are !=0 and != framelength the stream is full...
103 DemuxerAudio::DemuxerAudio(int p_vID, int p_aID)
107 log=Log::getInstance();
109 streamtype=Audio::MP3;
110 buffer=new PacketBuffer(&audiostream,streamtype);
111 // buffer=new PacketBuffer(&teststream,streamtype);
112 globalBytesWritten=0;
119 DemuxerAudio::~DemuxerAudio() {
121 if(info) delete info;
126 void DemuxerAudio::flush()
128 Demuxer::flushAudio();
133 void DemuxerAudio::reset() {
138 globalBytesWritten=0;
141 if (info) delete info;
150 hdrSamplingRate=44100;
156 int DemuxerAudio::scan(UCHAR *buf, int len)
158 //no differend pids here
162 void DemuxerAudio::setVID(int p_vID)
166 void DemuxerAudio::setAID(int p_aID)
170 static char * id3_1_genre[] = {
255 static int bitrateTable[16][5]={
256 /* L1,L2,L3,2L1,2L2 */
257 /*0000*/ {-1,-1,-1,-1,-1},
258 /*0001*/ {32,32,32,32,8},
259 /*0010*/ {64,48,40,48,16},
260 /*0011*/ {96,56,48,56,24},
261 /*0100*/ {128,64,56,64,32},
262 /*0101*/ {160,80,64,80,40},
263 /*0110*/ {192,96,80,96,48},
264 /*0111*/ {224,112,96,112,56},
265 /*1000*/ {256,128,112,128,64},
266 /*1001*/ {288,160,128,144,80},
267 /*1010*/ {320,192,160,160,96},
268 /*1011*/ {352,224,192,176,112},
269 /*1100*/ {384,256,224,192,128},
270 /*1101*/ {416,320,256,224,144},
271 /*1110*/ {448,384,320,256,160},
272 /*1111*/ {-1,-1,-1,-1,-1} };
274 static int samplingRateTable[4][3]={
275 /*00*/ {44100,22050,11025},
276 /*01*/ {48000,24000,12000},
277 /*10*/ {32000,16000,8000},
281 static const char * mpegString(UCHAR code) {
295 static const char * layerString(UCHAR code) {
298 return "Layer reserved";
306 return "Layer UNKNOWN";
309 * parse an id3 Header
310 * provided by Brian Walton
311 * @returns -1 of nothing found
314 int DemuxerAudio::id3_2_3_FrameParse(unsigned char buf[], id3_frame *frame)
316 if (buf[0] < 0x20 || buf[1] < 0x20 || buf [2] < 0x20 ) return -1;
317 frame->size = (buf[4] & 0x7F) << 21 | (buf[5] & 0x7F) << 14 | (buf[6] & 0x7F) << 7 | (buf[7] & 0x7F);
318 if (frame->size == 0) return -1;
319 //TODO. clearify flags against:
320 //http://id3.org/id3v2.3.0#head-697d09c50ed7fa96fb66c6b0a9d93585e2652b0b
321 frame->flags.tagAlterPreserv = (buf[8] & 0x80) >> 7;
322 frame->flags.filelterPreserv = (buf[8] & 0x40) >> 6;
323 frame->flags.readOnly = (buf[8] & 0x20) >> 5;
324 frame->flags.groupId = (buf[9] & 0x20) >> 5;
325 frame->flags.compression = (buf[9] & 0x80) >> 7;
326 frame->flags.encryption = (buf[9] & 0x40) >> 6;
327 frame->flags.unsync = 0;
328 frame->flags.dataLen = 0;
333 * parse an id3 Header
334 * provided by Brian Walton
335 * @returns -1 of nothing found
338 int DemuxerAudio::id3_2_2_FrameParse(unsigned char buf[], id3_frame *frame)
340 if (buf[0] < 0x20 || buf[1] < 0x20 || buf[2] < 0x20) return -1;
341 frame->size = (buf[3] & 0x7F) << 14 | (buf[4] & 0x7F) << 7 | (buf[5] & 0x7F);
342 if (frame->size == 0) return -1;
347 //fill an id3tag from a frame payload
348 //http://id3.org/id3v2.3.0#head-697d09c50ed7fa96fb66c6b0a9d93585e2652b0b
349 //http://id3.org/id3v2-00
350 static struct tagid {
361 {"TCOM",7}, //composer
362 {"COMM",8}, //comment
365 //Short content descrip. <text string according to encoding> $00 (00)
366 //The actual text <full text string according to encoding>
371 {"TCO",3 }, //(genreNumber)
377 #define NUMKNOWN (sizeof(knownFrames)/sizeof(knownFrames[0]))
380 from an ID3 V2.x, V2.3 frame into the tags structure
381 frameData must point to the header
382 framelen is the len without header (10 Bytes for V23, 6 Bytes for v2x)
385 #define MAXLEN(tagtype) ((UINT)frameLen<sizeof(tag->tagtype)-1?(UINT)frameLen:sizeof(tag->tagtype)-1)
386 bool DemuxerAudio::fillId3Tag(id3_tag * tag,UCHAR * frameData, int frameLen, int dataOffset, bool v23) {
389 if (tag == NULL) return false;
390 if (frameLen < 2) return false;
391 for (UINT i=0;i< NUMKNOWN;i++) {
392 if(strncmp((char *)frameData,knownFrames[i].bytes,tl) == 0) {
393 tagIndex=knownFrames[i].index;
397 if (tagIndex < 0) return false;
398 UCHAR encoding=*(frameData+dataOffset);
402 log->log("DemuxerAudio",Log::DEBUG,"unknown encoding for tag %d, tagid %s",encoding,
403 knownFrames[tagIndex].bytes);
408 strncpy(tag->title,(char*)(frameData+dataOffset),MAXLEN(title));
409 tag->title[MAXLEN(title)]=0;
412 strncpy(tag->artist,(char*)(frameData+dataOffset),MAXLEN(artist));
413 tag->artist[MAXLEN(artist)]=0;
417 UCHAR * st=frameData+dataOffset;
420 genre=atoi((const char *)(st+1)) && 31;
421 st=(UCHAR *)id3_1_genre[genre];
423 strncpy(tag->genre,(char*)st,MAXLEN(genre));
424 tag->genre[MAXLEN(genre)]=0;
428 strncpy(tag->year,(char *)(frameData+dataOffset),MAXLEN(year));
429 tag->year[MAXLEN(year)]=0;
432 strncpy(tag->album,(char *)(frameData+dataOffset),MAXLEN(album));
433 tag->album[MAXLEN(album)]=0;
436 strncpy(tag->track,(char *)(frameData+dataOffset),MAXLEN(track));
437 tag->track[MAXLEN(track)]=0;
440 strncpy(tag->composer,(char *)(frameData+dataOffset),MAXLEN(composer));
441 tag->composer[MAXLEN(composer)]=0;
444 strncpy(tag->comment,(char *)(frameData+dataOffset),MAXLEN(comment));
445 tag->comment[MAXLEN(comment)]=0;
455 * parse an id3 Header
456 * based on code provided by Brian Walton
457 * @returns -1 of nothing found
458 * otherwise the id3 info is filled
461 int DemuxerAudio::parseID3V2(UCHAR *data, int len) {
464 id3_header id3header;
466 id3_tag * id3tag=NULL;
467 //len = read(fd, data, 10);
473 if(data[0]=='I' && data[1]=='D' && data[2]=='3')
475 id3tag=new id3_tag();
476 id3header.major = data[3];
477 id3header.minor = data[4];
478 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"ID3 V2.%d.%d found\n", id3header.major, id3header.minor);
479 id3header.flags.unsynchronisation = (data[5] & 0x80)>>7;
480 id3header.flags.extended_header = (data[5] & 0x40)>>6;
481 id3header.flags.experimental = (data[5] & 0x20)>>5;
482 id3header.flags.footer = (data[5] & 0x10)>>4;
483 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Unsynchronisation flag: %d\n", id3header.flags.unsynchronisation);
484 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Extended header flag: %d\n", id3header.flags.extended_header);
485 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Experimental indicator flag: %d\n", id3header.flags.experimental);
486 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Footer present flag: %d\n", id3header.flags.footer);
487 id3header.size = (data[6] & 0x7F) << 21 | (data[7] & 0x7F) << 14 | (data[8] & 0x7F) << 7 | (data[9] & 0x7F);
488 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"ID3 Size: %d\n", id3header.size);
490 if (len <= id3header.size) {
491 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"header size to big %d, only %d bytes available\n",id3header.size,len);
495 if (id3header.flags.extended_header)
497 int extended_hdr_hdr=4; //still to be discussed (id3.org...)
498 //read extended header size
499 if (len < extended_hdr_hdr) {
500 if (debug) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"extended header found but cannot read\n");
504 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"remaining %d chars after extended hdr hdr\n", len);
505 id3header.extended_header.size = (data[0] & 0x7F) << 21 | (data[1] & 0x7F) << 14 | (data[2] & 0x7F) << 7 | (data[3] & 0x7F);
506 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Extended header size: %d\n", id3header.extended_header.size);
507 if (len <= id3header.extended_header.size+extended_hdr_hdr) {
508 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"extended Header to big, only %d bytes available\n",len);
512 //lseek(fd, id3header.extended_header.size - 6, SEEK_CUR);
513 data+=id3header.extended_header.size+extended_hdr_hdr;
514 len-=id3header.extended_header.size+extended_hdr_hdr;
516 //set the end of the header
517 UCHAR * eob=start+id3header.size+10;
519 while (data < eob && readNext)
521 //skip over some padding - found this in lame MCDI tag...
527 switch(id3header.major)
530 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"version 2.2 frame, %d : %c %c %c\n", data-start,*data,*(data+1),*(data+2));
535 if (id3_2_2_FrameParse(data, &id3frame) < 0)
539 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"frame size: %d\n", id3frame.size);
540 fillId3Tag(id3tag,data,id3frame.size,6,false);
541 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"frame payload: %s\n", data + 6 +1);
542 data+=6+id3frame.size;
547 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"version 2.3 frame, %d : %c %c %c %c\n", data-start,
548 *data,*(data+1),*(data+2),*(data+3));
549 if (data + 10 >= eob)
553 if (id3_2_3_FrameParse(data, &id3frame) <0)
557 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame size: %d\n", id3frame.size);
559 if (id3frame.flags.groupId)
562 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame group: %d\n", data[dataOffset]);
564 if (id3frame.flags.compression)
566 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame compressed: %d\n", id3frame.flags.compression);
568 if (id3frame.flags.encryption)
571 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame encryption method: %d\n", data[dataOffset]);
573 fillId3Tag(id3tag,data,id3frame.size-dataOffset+10,dataOffset,true);
574 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"frame payload: %s\n", data + dataOffset +1);
575 data+=10+id3frame.size;
580 //don't support this version
587 //store the found tag
596 * parse an id3v1 Header
597 * based on code provided by Brian Walton
598 * @returns -1 of nothing found
599 * otherwise the id3 info is filled
601 #define MEMCPY(type,len,offset) {int type##max=sizeof(tag->type)-1<len?sizeof(tag->type)-1:len;strncpy(tag->type,(char*)&data[offset],type##max);tag->type[type##max]=0;}
603 int DemuxerAudio::parseID3V1(UCHAR *data, int len) {
605 if (len < 128) return -1;
606 if(data[0]=='T' && data[1]=='A' && data[2]=='G')
608 id3_tag * tag=new id3_tag();
609 if (debug != 0)log->log("DemuxerAudio::parseID3V1",Log::DEBUG,"ID3 V1 tag found\n");
611 MEMCPY(artist,30,33);
614 if (data[125]==0 && data[126]!=0)
616 if (debug != 0)log->log("DemuxerAudio::parseID3V1",Log::DEBUG,"ID3 V1.1 tag\n");
617 MEMCPY(comment,29,97);
618 sprintf(tag->track, "%d", data[126]);
620 if (debug != 0)log->log("DemuxerAudio::parseID3V1",Log::DEBUG,"ID3 V1.0 tag\n");
621 MEMCPY(comment,30,97);
623 if (data[127] < sizeof(id3_1_genre)/sizeof(id3_1_genre[0]))
625 sprintf(tag->genre, id3_1_genre[data[127]]);
634 //infos from http://www.multiweb.cz/twoinches/MP3inside.htm
635 int DemuxerAudio::parseVBR(UCHAR *data, int len) {
636 UCHAR *hdr=findHeader(data,len);
637 //we expect the header exactly here
638 if (hdr != data) return -1;
639 const static char * VBRHDR="Xing";
641 UCHAR mpgtype=(data[1] & 0x18)>>3;
642 UCHAR chmode=(data[2] & 0xc0) >> 6;
643 UCHAR layer=(data[2] & 0x06) >>1;
644 if ( mpgtype == 3 && chmode == 11) vbridpos=21;
645 if ( mpgtype != 3 && chmode != 11) vbridpos=21;
646 if ( mpgtype != 3 && chmode == 11) vbridpos=13;
647 //check for the header ID
648 if (vbridpos+(int)strlen(VBRHDR)+4 >= len) {
649 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"frame to short for VBR header %d",len);
652 for (int i=4;i<vbridpos;i++) {
654 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"garbage when searching VBR header at pos %d",i);
658 if ( strncmp((char *)&data[vbridpos],VBRHDR,strlen(VBRHDR)) != 0) {
659 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"no VBR header at pos %d",vbridpos);
662 int framedata=vbridpos+strlen(VBRHDR);
664 //OK we should now have a valid vbr header
665 bool hasFramenum=data[framedata+3] & 1;
666 bool hasBytes=data[framedata+3] & 0x2;
667 bool hasTOC=data[framedata+3] & 0x4;
669 if (hasTOC) expectedLen+=100;
670 if (framedata+expectedLen > len) {
671 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"frame to short for VBR header data %d, expected %d",
672 len,framedata+expectedLen);
675 if (!hasFramenum || ! hasBytes || ! hasTOC) {
676 //not usefull for us..
677 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"not all parts in VBR header - ignore");
683 vbr->numFrames=data[framedata] << 24 | data[framedata+1]<<16|
684 data[framedata+2]<<8 |data[framedata+3];
686 vbr->numBytes=data[framedata] << 24 | data[framedata+1]<<16|
687 data[framedata+2]<<8 |data[framedata+3];
689 for (int ti=0;ti<100;ti++) {
690 vbr->table[ti]=data[framedata+ti];
692 //compute file size in seconds
693 //should be (#of frames -1) *samplesPerFrame / sampleRate
694 //TODO: difference for Mono?
695 ULONG samplesPerFrame=384; //layer1
696 if (layer != 3) samplesPerFrame=1152;
697 vbr->fileSeconds=(vbr->numFrames-1)*samplesPerFrame/hdrSamplingRate;
698 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"successfully read VBR %ldbytes, %ld frames, %ldsec",
699 vbr->numBytes,vbr->numFrames,vbr->fileSeconds);
709 UCHAR * DemuxerAudio::findHeader(UCHAR *buf, int len, bool writeInfo) {
710 while (len >= 3) //assume hdr+crc
714 if (pattern != HDRBYTE1 ) continue;
715 if ((*buf & HDRBYTE2MASK) != HDRBYTE2) continue;
716 if (readHeader((buf-1),4,writeInfo) != 0) continue;
724 int DemuxerAudio::readHeader(UCHAR * hbuf,int len,bool writeInfo) {
727 int curSamplingRate=0;
728 if (*hbuf != HDRBYTE1) return -1;
730 if ((*hbuf & HDRBYTE2MASK) != HDRBYTE2) return -1;
731 UCHAR mpgtype=(*hbuf & 0x18)>>3;
733 log->log("DemuxerAudio",Log::DEBUG,"header invalid mpgtype %s %i %i %i",
734 mpegString(mpgtype),*hbuf,*(hbuf+1),*(hbuf+2));
737 UCHAR layer=(*hbuf & 0x06) >>1;
738 //bool hasCRC=!(*hbuf & 1);
740 UCHAR bitrateCode=(*hbuf & 0xf0) >>4;
741 UCHAR samplingCode=(*hbuf & 0x0c) >> 2;
742 bool padding=*hbuf & 0x02;
744 //0 Stereo, 1 JointStereo, 2 Dual, 3 Mono
745 UCHAR chmode=(*hbuf & 0xc0) >> 6;
746 //UCHAR extension=(*hbuf & 0x30) >> 4;
748 //layercode: 1-L3, 2-L2, 3-L1
749 //columns 0,1,2 for MPEG1
750 UCHAR bitrateColumn=3-layer;
751 if (bitrateColumn > 2) {
752 log->log("DemuxerAudio",Log::DEBUG,"header invalid layer %s %i %i %i",
753 layerString(layer),*(hbuf-2),*(hbuf-1),*hbuf);
756 if (mpgtype != 3) bitrateColumn+=3;
757 if (bitrateColumn>4) bitrateColumn=4;
758 curBitrate=1000*bitrateTable[bitrateCode][bitrateColumn];
759 UCHAR sampleRateColumn=0;
760 if (mpgtype == 10) sampleRateColumn=1;
761 if (mpgtype == 0) sampleRateColumn=2;
762 curSamplingRate=samplingRateTable[samplingCode][sampleRateColumn];
763 if (curSamplingRate < 0 || curBitrate < 0) {
764 log->log("DemuxerAudio",Log::DEBUG,"header invalid rates br=%d sr=%d %i %i %i",
765 curBitrate,curSamplingRate,*(hbuf-2),*(hbuf-1),*hbuf);
770 if (layer == 3) padbytes=4;
775 //FrameLengthInBytes = (12 * BitRate / SampleRate + Padding) * 4
776 curFramelen=(12*curBitrate/curSamplingRate+padbytes) * 4;
780 //FrameLengthInBytes = 144 * BitRate / SampleRate + Padding
781 curFramelen=144*curBitrate/curSamplingRate+padbytes;
784 if (curFramelen < 32) {
785 log->log("DemuxerAudio",Log::DEBUG,"read header %ld mpgv=%s lc=%s br=%d sr=%d, fl=%d-invalid %i %i %i",
786 readHeaders,mpegString(mpgtype),layerString(layer),
787 curBitrate,curSamplingRate,curFramelen,*(hbuf-2),*(hbuf-1),*hbuf);
790 if (writeInfo || isStarting){
791 log->log("DemuxerAudio",Log::DEBUG,"read header %ld mpgv=%s lc=%s br=%d sr=%d, fl=%d %i %i %i",
792 readHeaders,mpegString(mpgtype),layerString(layer),
793 curBitrate,curSamplingRate,curFramelen,*(hbuf-2),*(hbuf-1),*hbuf);
794 if (info) delete info;
796 strcpy(info->mpegVersion,mpegString(mpgtype));
797 info->mpegLayer=4-layer;
798 info->bitRate=curBitrate;
799 info->avrBitrate=curBitrate;
800 info->sampleRate=curSamplingRate;
801 const char *chmodStr=tr("Stereo");
803 case 1: chmodStr=tr("JointStero");break;
804 case 2: chmodStr=tr("Dual");break;
805 case 3: chmodStr=tr("Mono");break;
807 SNPRINTF(info->info,sizeof(info->info)-1,"%s",chmodStr);
809 if (isStarting) avrBitrate=curBitrate;
812 //moving average F=0.005
813 avrBitrate=avrBitrate+((5*(curBitrate-avrBitrate))/1024);
814 hdrBitrate=curBitrate;
815 hdrFramelen=curFramelen;
816 hdrSamplingRate=curSamplingRate;
821 int DemuxerAudio::findPTS(UCHAR* buf, int len, ULLONG* dest)
823 //we have no PTS number ...
825 return (findHeader(buf,len) != NULL)?1:0;
828 bool PacketBuffer::doSkip() {
829 if (!bufferFull()) return false;
830 if (skipfactor == 0) return false;
832 if (numskip >= skipfactor) {
833 //sent at least always 2 packets
834 if (numskip > skipfactor) numskip=0;
841 // just handle the real stream without dealing with the header
842 int PacketBuffer::putInternal(UCHAR * wbuf, int len)
844 /* Important, the type passed to stream must be a mediapacket type as defined in
845 Draintarget.h and not the device setting of the mvp, so we have to translate it here,
846 in order to get it working on windows
849 switch (streamtype) {
850 case Audio::MPEG1_PES: //?
851 case Audio::MPEG2_PES: //Important, this must be a PES !
852 mptype=MPTYPE_MPEG_AUDIO; break;
854 case Audio::MP3: //this can be any Mpeg1 Audio not only layer 3 not packed into PES
855 mptype=MPTYPE_MPEG_AUDIO_LAYER3;break;
859 if (doSkip()) return 0;//NoSkip on Windows
861 //we are still full - so try to write
862 int sent=audio->put(store+bytesWritten,framelen-bytesWritten,/*streamtype*/mptype);
863 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream (still full) pp=%d, framelen=%d, written=%d",sent,partPacket,framelen, bytesWritten );
864 if (sent < (framelen - bytesWritten)) {
865 //packet still not written
870 //let the demuxer come back with the rest - need to check header first
873 if (partPacket+len >= framelen) {
874 //now we have at least a complete packet
875 int bytesConsumed=framelen-partPacket;
876 memcpy(store+partPacket,wbuf,bytesConsumed);
878 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"stored packet %ld, length %d (last %d) for stream %p",numpackets,framelen,bytesConsumed,audio );
879 #ifndef WIN32 //No Skip on Windows
880 if (doSkip()) return bytesConsumed;
882 int sent=audio->put(store,framelen,mptype);
884 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream",sent );
885 if (bytesWritten < framelen) {
886 //still not completely written
887 return bytesConsumed;
890 //let the player come back...
891 return bytesConsumed;
893 //OK packet still not complete
894 if (len == 0) return 0;
895 int bytesConsumed=len;
896 memcpy(store+partPacket,wbuf,bytesConsumed);
897 partPacket+=bytesConsumed;
898 return bytesConsumed;
902 major entry for data from a player
903 the demuxer is either in the state headerSearch (packet written or
904 just at the beginning), writing garbage (inSync=false) or
905 handling data (none set)
906 A header is expected at the first byte after the previous packet -
907 otherwise we switch to garbage where we always search for a header
908 (but anyway provide the data to the underlying device - it's probably
909 more intelligent then we are...
910 We only loose a correct position display.
912 int DemuxerAudio::put(UCHAR* wbuf, int len)
914 //return audiostream.put(wbuf,len,streamtype);
915 int framelen=PACKET_SIZE;
919 if (tmpFill != 0 || (buffer->bufferEmpty() && len < HDRLEN)) {
920 //OK we have to copy everything to the tmp buffer
921 int cp=(UINT)len<(PACKET_SIZE-tmpFill)?(UINT)len:(PACKET_SIZE-tmpFill);
922 memcpy(&tmpBuffer[tmpFill],wbuf,cp);
927 //if there is no header here and our buffer
928 //is empty - just wait for the next header
929 if (len < HDRLEN && buffer->bufferEmpty()) {
930 log->log("DemuxerAudio",Log::DEBUG,"len to small for header %d at bytes %ld",len,globalBytesWritten);
934 while (bytesConsumed < len ) {
935 if (buffer->bufferFull()) {
936 //if this is the first part of the loop, try to write to the stream
937 if (bytesConsumed == 0) buffer->putInternal(wbuf,0);
938 //if the buffer is full, no need to continue
939 if (buffer->bufferFull()) break;
941 //either we are in a packet (buffer != full && buffer != empty)
942 //or we are searching a header
943 if (buffer->bufferEmpty()) {
944 if (len-bytesConsumed < HDRLEN) {
945 // we cannot still search
947 //we are already working at the buffer
950 memcpy(tmpBuffer,wbuf,len-bytesConsumed);
951 tmpFill=len-bytesConsumed;
952 log->log("DemuxerAudio",Log::DEBUG,"len to small for header %d at bytes %ld",len,globalBytesWritten);
956 int lastFramelen=hdrFramelen;
957 //if the header has been valid before and we are searching
959 int maxsearch=((len-bytesConsumed) < (int)PACKET_SIZE)?len-bytesConsumed:(int)PACKET_SIZE;
960 hdr=findHeader(wbuf,maxsearch);
962 //log->log("DemuxerAudio",Log::DEBUG,"header found at offset %d",hdr-wbuf);
964 //hdr now points to the new header
966 //still at least bytes before the header
969 int garbageBytes=(hdr!=NULL)?(hdr-wbuf):maxsearch;
970 //we consider the garbage now as an own packet
971 //we can consume at most our buffer
972 //basically the buffer should be empty here (we are
973 //in header search - and we fill up each garbage
975 int nframesize=garbageBytes;
976 if (nframesize > (int)PACKET_SIZE) {
977 nframesize=(int)PACKET_SIZE;
979 if (! buffer->bufferEmpty()) {
980 log->log("DemuxerAudio",Log::WARN,"buffer not empty when having garbage to store");
981 //at the end no big problem, we only write the remaining bytes that we have...
984 buffer->setFramelen(nframesize);
986 log->log("DemuxerAudio",Log::DEBUG,"garbage found at packet %ld (bytes %ld) of length %d, "
987 "framelen set to %d (last fl=%d)",
988 readHeaders,globalBytesWritten,garbageBytes,buffer->getFramelen(),lastFramelen);
990 //hmm - we assume that he low level driver is more intelligent
991 //and give him the data "as is"
992 int written=buffer->putInternal(wbuf,garbageBytes);
993 globalBytesWritten+=written;
994 bytesConsumed+=written;
995 if (written != garbageBytes || hdr == NULL ) {
998 #else //DS is not intelligent
999 globalBytesWritten+=garbageBytes;
1000 bytesConsumed+=garbageBytes;
1002 //OK either all the "garbage" is written or
1003 //we found the next header as expected
1004 //continue with the next package
1007 //we have to wait now until the buffer is
1008 //free for the next package
1009 if ( ! buffer->bufferEmpty()) return bytesConsumed;
1010 //this is the place where we start a new packet
1011 framelen=hdrFramelen;
1012 if ( !buffer->setFramelen(framelen) ) {
1013 log->log("DemuxerAudio",Log::DEBUG,"unable to set framelen should=%d, current=%d",
1014 framelen,buffer->getFramelen());
1018 //now we are surely within a packet
1019 int written=buffer->putInternal(wbuf,len-bytesConsumed);
1021 globalBytesWritten+=written;
1023 bytesConsumed+=written;
1028 //OK - handle the rest
1030 if (bytesConsumed >= oldBytes) {
1031 //if we consumed more than the old bytes - OK the buffer
1032 //can be thrown away
1034 return bytesConsumed-oldBytes;
1037 //only consumed bytes from the buffer
1038 if (bytesConsumed == 0) {
1039 //restore the buffer
1043 //shift bytes in buffer
1044 for (int i=0;i<oldBytes-bytesConsumed;i++) {
1045 tmpBuffer[i]=tmpBuffer[i+bytesConsumed];
1047 tmpFill=oldBytes-bytesConsumed;
1053 const id3_tag * DemuxerAudio::getId3Tag() {
1057 const DemuxerAudio::mpegInfo * DemuxerAudio::getMpegInfo() {
1058 if (! hasHdrInfo) return NULL;
1059 info->avrBitrate=avrBitrate;
1060 info->bitRate=hdrBitrate;
1064 const DemuxerAudio::vbrInfo * DemuxerAudio::getVBRINfo() {
1068 int DemuxerAudio::checkStart(UCHAR *b, int len) {
1070 int id3len=parseID3V2(b,len);
1072 char * str=id3->toString();
1073 log->log("DemuxerAudio",Log::DEBUG,"parseID3V2 %d bytes of %d",id3len,len);
1074 log->log("DemuxerAudio",Log::DEBUG,"parseID3V2 found:%s",str);
1079 int vbrlen=parseVBR(b,len);
1085 UCHAR * hdr=findHeader(b,len,true);
1086 if (hdr == NULL) return -1;
1090 int DemuxerAudio::checkID3(UCHAR *b, int len) {
1091 if (len != 128) return -1;
1092 int rt=parseID3V1(b,len);
1094 char * str=id3->toString();
1095 log->log("DemuxerAudio",Log::DEBUG,"parseID3V1 found:%s",str);
1101 bool DemuxerAudio::isSync() {
1105 UINT DemuxerAudio::getSyncErrors() {
1109 ULONG DemuxerAudio::getBytesPerSecond()
1111 ULONG bps=hdrBitrate;
1112 if (! hasHdrInfo) return 0;
1113 if (hdrBitrate != avrBitrate) {
1114 //we seem to have vbr
1128 ULONG DemuxerAudio::getSecondsFromLen(ULONG len) {
1129 if (! hasHdrInfo) return 0;
1131 //first find the index where we are between
1132 //rough starting point:
1133 ULONG idx=100*len/vbr->numBytes;
1134 if (idx >= 100) idx=99;
1135 ULONG idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1136 ULONG pbefore=idxPos;
1137 ULONG pafter=idxPos;
1138 //OK now we know whether we have to go up or down
1141 while (idxPos > len && idx > 0) {
1144 idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1147 //OK we are now before our postion
1151 while (idxPos < len && idx < 100 ) {
1154 idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1157 //after our position
1158 if (idx > 0) idx --;
1160 //idx is now the index before our position
1161 //approximate between the 2 points
1162 ULONG idxTime=idx * vbr->fileSeconds/100;
1163 if (pafter == pbefore) return idxTime;
1164 ULONG rt=idxTime+ (len-pbefore)* vbr->fileSeconds/(100 * (pafter-pbefore)) ;
1165 if (rt > vbr -> fileSeconds) return vbr->fileSeconds;
1166 if (rt < idxTime) return idxTime;
1170 ULONG bps=getBytesPerSecond();
1171 if (bps == 0) return 0;
1176 ULONG DemuxerAudio::positionFromSeconds(ULONG seconds) {
1177 if (! hasHdrInfo) return 0;
1179 ULONG idx=seconds*100/vbr->fileSeconds;
1180 if (idx > 99) idx=99;
1181 ULONG idxPos=vbr->table[idx] * vbr->numBytes/256;
1183 if (idx < 99) idx2++;
1184 ULONG nextPos=vbr->table[idx] * vbr->numBytes/256;
1185 ULONG rt=idxPos+(nextPos-idxPos) * (seconds - idx * vbr->fileSeconds /256);
1186 if (rt < idxPos) return idxPos;
1187 if ( rt > vbr->numBytes) return vbr->numBytes;
1191 ULONG bps=getBytesPerSecond();
1196 int id3_tag::stringlen(bool withTitle) const {
1198 return strlen(artist)+strlen(genre)+strlen(year)+strlen(album)+
1199 strlen(track)+strlen(composer)+strlen(comment)+8+3+
1200 90; //30 chars for each name...
1202 return strlen(title)+strlen(artist)+strlen(genre)+strlen(year)+strlen(album)+
1203 strlen(track)+strlen(composer)+strlen(comment)+8+3+
1204 120; //30 chars for each name...
1206 //create a string out of the id3 tag info
1207 //delete this string afterwards if you did not provide the buffer
1208 char * id3_tag::toString(char *b, int len, bool withTitle) const {
1209 const char *ta=tr("Artist");
1210 //char *tg=tr("Genre");
1211 //char *ty=tr("Year");
1212 const char *tx=tr("Album");
1213 //char *to=tr("Composer");
1214 //char *tc=tr("Comment");
1215 const char *tn=tr("Track");
1223 len=stringlen(withTitle);
1226 const char * del=" - ";
1227 if (strlen(year) == 0) del="";
1229 const char *tt=tr("Title");
1230 SNPRINTF(b,len-1,"%s: %s\n%s: %s\n%s: %s%s%s\n%s: %s",
1231 tt,title,ta,artist,tx,year,del,album,tn,track);
1234 SNPRINTF(b,len-1,"%s: %s\n%s: %s%s%s\n%s: %s",
1235 ta,artist,tx,year,del,album,tn,track);
1241 void DemuxerAudio::setSkipFactor(int factor) {
1242 Log::getInstance()->log("DemuxerAudio",Log::DEBUG,"set skipfactor %d\n",factor);
1243 buffer->setSkipFactor(factor);