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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "demuxeraudio.h"
28 #define HDRBYTE2MASK 0xe0
35 PacketBuffer(Stream *as,UCHAR strtype) {
36 log=Log::getInstance();
41 //just handle the data (do not deal with headers)
42 int putInternal(UCHAR* buf,int len,unsigned int &packetnum);
46 framelen=DemuxerAudio::PACKET_SIZE;
56 return (partPacket>=framelen);
58 //can we write a new packet?
62 //only set this, if buffer empty
64 bool setFramelen(int len) {
65 if (! bufferEmpty() ) return false;
66 if (len > (int)DemuxerAudio::PACKET_SIZE) return false;
70 //how much bytes do we need to fill the packet?
72 return framelen-partPacket;
77 void setSkipFactor(int factor) {
82 void packetWritten() {
84 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written packet %ld l=%d, bytes %ld",numpackets,framelen,numbytes);
89 UCHAR store[DemuxerAudio::PACKET_SIZE]; // Storage for partial packets
90 int partPacket; // Length of partial packet stored from previous put()
91 int bytesWritten; //if they are !=0 and != framelength the stream is full...
104 DemuxerAudio::DemuxerAudio(int p_vID, int p_aID)
108 log=Log::getInstance();
110 streamtype=Audio::MP3;
111 buffer=new PacketBuffer(&audiostream,streamtype);
112 // buffer=new PacketBuffer(&teststream,streamtype);
113 globalBytesWritten=0;
121 DemuxerAudio::~DemuxerAudio() {
123 if(info) delete info;
128 void DemuxerAudio::flush()
130 Demuxer::flushAudio();
135 void DemuxerAudio::reset() {
141 globalBytesWritten=0;
144 if (info) delete info;
153 hdrSamplingRate=44100;
159 int DemuxerAudio::scan(UCHAR *buf, int len)
161 //no differend pids here
165 void DemuxerAudio::setVID(int p_vID)
169 void DemuxerAudio::setAID(int p_aID,int type)
173 static const char * id3_1_genre[] = {
258 static int bitrateTable[16][5]={
259 /* L1,L2,L3,2L1,2L2 */
260 /*0000*/ {-1,-1,-1,-1,-1},
261 /*0001*/ {32,32,32,32,8},
262 /*0010*/ {64,48,40,48,16},
263 /*0011*/ {96,56,48,56,24},
264 /*0100*/ {128,64,56,64,32},
265 /*0101*/ {160,80,64,80,40},
266 /*0110*/ {192,96,80,96,48},
267 /*0111*/ {224,112,96,112,56},
268 /*1000*/ {256,128,112,128,64},
269 /*1001*/ {288,160,128,144,80},
270 /*1010*/ {320,192,160,160,96},
271 /*1011*/ {352,224,192,176,112},
272 /*1100*/ {384,256,224,192,128},
273 /*1101*/ {416,320,256,224,144},
274 /*1110*/ {448,384,320,256,160},
275 /*1111*/ {-1,-1,-1,-1,-1} };
277 static int samplingRateTable[4][3]={
278 /*00*/ {44100,22050,11025},
279 /*01*/ {48000,24000,12000},
280 /*10*/ {32000,16000,8000},
284 static const char * mpegString(UCHAR code) {
298 static const char * layerString(UCHAR code) {
301 return "Layer reserved";
309 return "Layer UNKNOWN";
312 * parse an id3 Header
313 * provided by Brian Walton
314 * @returns -1 of nothing found
317 int DemuxerAudio::id3_2_3_FrameParse(unsigned char buf[], id3_frame *frame)
319 if (buf[0] < 0x20 || buf[1] < 0x20 || buf [2] < 0x20 ) return -1;
320 frame->size = (buf[4] & 0x7F) << 21 | (buf[5] & 0x7F) << 14 | (buf[6] & 0x7F) << 7 | (buf[7] & 0x7F);
321 if (frame->size == 0) return -1;
322 //TODO. clearify flags against:
323 //http://id3.org/id3v2.3.0#head-697d09c50ed7fa96fb66c6b0a9d93585e2652b0b
324 frame->flags.tagAlterPreserv = (buf[8] & 0x80) >> 7;
325 frame->flags.filelterPreserv = (buf[8] & 0x40) >> 6;
326 frame->flags.readOnly = (buf[8] & 0x20) >> 5;
327 frame->flags.groupId = (buf[9] & 0x20) >> 5;
328 frame->flags.compression = (buf[9] & 0x80) >> 7;
329 frame->flags.encryption = (buf[9] & 0x40) >> 6;
330 frame->flags.unsync = 0;
331 frame->flags.dataLen = 0;
336 * parse an id3 Header
337 * provided by Brian Walton
338 * @returns -1 of nothing found
341 int DemuxerAudio::id3_2_2_FrameParse(unsigned char buf[], id3_frame *frame)
343 if (buf[0] < 0x20 || buf[1] < 0x20 || buf[2] < 0x20) return -1;
344 frame->size = (buf[3] & 0x7F) << 14 | (buf[4] & 0x7F) << 7 | (buf[5] & 0x7F);
345 if (frame->size == 0) return -1;
350 //fill an id3tag from a frame payload
351 //http://id3.org/id3v2.3.0#head-697d09c50ed7fa96fb66c6b0a9d93585e2652b0b
352 //http://id3.org/id3v2-00
353 static struct tagid {
364 {"TCOM",7}, //composer
365 {"COMM",8}, //comment
368 //Short content descrip. <text string according to encoding> $00 (00)
369 //The actual text <full text string according to encoding>
374 {"TCO",3 }, //(genreNumber)
380 #define NUMKNOWN (sizeof(knownFrames)/sizeof(knownFrames[0]))
383 from an ID3 V2.x, V2.3 frame into the tags structure
384 frameData must point to the header
385 framelen is the len without header (10 Bytes for V23, 6 Bytes for v2x)
388 #define MAXLEN(tagtype) ((UINT)frameLen<sizeof(tag->tagtype)-1?(UINT)frameLen:sizeof(tag->tagtype)-1)
389 bool DemuxerAudio::fillId3Tag(id3_tag * tag,UCHAR * frameData, int frameLen, int dataOffset, bool v23) {
392 if (tag == NULL) return false;
393 if (frameLen < 2) return false;
394 for (UINT i=0;i< NUMKNOWN;i++) {
395 if(strncmp((char *)frameData,knownFrames[i].bytes,tl) == 0) {
396 tagIndex=knownFrames[i].index;
400 if (tagIndex < 0) return false;
401 UCHAR encoding=*(frameData+dataOffset);
405 log->log("DemuxerAudio",Log::DEBUG,"unknown encoding for tag %d, tagid %s",encoding,
406 knownFrames[tagIndex].bytes);
411 strncpy(tag->title,(char*)(frameData+dataOffset),MAXLEN(title));
412 tag->title[MAXLEN(title)]=0;
415 strncpy(tag->artist,(char*)(frameData+dataOffset),MAXLEN(artist));
416 tag->artist[MAXLEN(artist)]=0;
420 UCHAR * st=frameData+dataOffset;
423 genre=atoi((const char *)(st+1)) && 31;
424 st=(UCHAR *)id3_1_genre[genre];
426 strncpy(tag->genre,(char*)st,MAXLEN(genre));
427 tag->genre[MAXLEN(genre)]=0;
431 strncpy(tag->year,(char *)(frameData+dataOffset),MAXLEN(year));
432 tag->year[MAXLEN(year)]=0;
435 strncpy(tag->album,(char *)(frameData+dataOffset),MAXLEN(album));
436 tag->album[MAXLEN(album)]=0;
439 strncpy(tag->track,(char *)(frameData+dataOffset),MAXLEN(track));
440 tag->track[MAXLEN(track)]=0;
443 strncpy(tag->composer,(char *)(frameData+dataOffset),MAXLEN(composer));
444 tag->composer[MAXLEN(composer)]=0;
447 strncpy(tag->comment,(char *)(frameData+dataOffset),MAXLEN(comment));
448 tag->comment[MAXLEN(comment)]=0;
458 * parse an id3 Header
459 * based on code provided by Brian Walton
460 * @returns -1 of nothing found
461 * otherwise the id3 info is filled
464 int DemuxerAudio::parseID3V2(UCHAR *data, int len) {
467 id3_header id3header;
469 id3_tag * id3tag=NULL;
470 //len = read(fd, data, 10);
476 if(data[0]=='I' && data[1]=='D' && data[2]=='3')
478 id3tag=new id3_tag();
479 id3header.major = data[3];
480 id3header.minor = data[4];
481 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"ID3 V2.%d.%d found\n", id3header.major, id3header.minor);
482 id3header.flags.unsynchronisation = (data[5] & 0x80)>>7;
483 id3header.flags.extended_header = (data[5] & 0x40)>>6;
484 id3header.flags.experimental = (data[5] & 0x20)>>5;
485 id3header.flags.footer = (data[5] & 0x10)>>4;
486 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Unsynchronisation flag: %d\n", id3header.flags.unsynchronisation);
487 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Extended header flag: %d\n", id3header.flags.extended_header);
488 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Experimental indicator flag: %d\n", id3header.flags.experimental);
489 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Footer present flag: %d\n", id3header.flags.footer);
490 id3header.size = (data[6] & 0x7F) << 21 | (data[7] & 0x7F) << 14 | (data[8] & 0x7F) << 7 | (data[9] & 0x7F);
491 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"ID3 Size: %d\n", id3header.size);
493 if (len <= id3header.size) {
494 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"header size to big %d, only %d bytes available\n",id3header.size,len);
498 if (id3header.flags.extended_header)
500 int extended_hdr_hdr=4; //still to be discussed (id3.org...)
501 //read extended header size
502 if (len < extended_hdr_hdr) {
503 if (debug) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"extended header found but cannot read\n");
507 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"remaining %d chars after extended hdr hdr\n", len);
508 id3header.extended_header.size = (data[0] & 0x7F) << 21 | (data[1] & 0x7F) << 14 | (data[2] & 0x7F) << 7 | (data[3] & 0x7F);
509 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Extended header size: %d\n", id3header.extended_header.size);
510 if (len <= id3header.extended_header.size+extended_hdr_hdr) {
511 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"extended Header to big, only %d bytes available\n",len);
515 //lseek(fd, id3header.extended_header.size - 6, SEEK_CUR);
516 data+=id3header.extended_header.size+extended_hdr_hdr;
517 len-=id3header.extended_header.size+extended_hdr_hdr;
519 //set the end of the header
520 UCHAR * eob=start+id3header.size+10;
522 while (data < eob && readNext)
524 //skip over some padding - found this in lame MCDI tag...
530 switch(id3header.major)
533 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));
538 if (id3_2_2_FrameParse(data, &id3frame) < 0)
542 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"frame size: %d\n", id3frame.size);
543 fillId3Tag(id3tag,data,id3frame.size,6,false);
544 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"frame payload: %s\n", data + 6 +1);
545 data+=6+id3frame.size;
550 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"version 2.3 frame, %d : %c %c %c %c\n", data-start,
551 *data,*(data+1),*(data+2),*(data+3));
552 if (data + 10 >= eob)
556 if (id3_2_3_FrameParse(data, &id3frame) <0)
560 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame size: %d\n", id3frame.size);
562 if (id3frame.flags.groupId)
565 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame group: %d\n", data[dataOffset]);
567 if (id3frame.flags.compression)
569 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame compressed: %d\n", id3frame.flags.compression);
571 if (id3frame.flags.encryption)
574 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame encryption method: %d\n", data[dataOffset]);
576 fillId3Tag(id3tag,data,id3frame.size-dataOffset+10,dataOffset,true);
577 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"frame payload: %s\n", data + dataOffset +1);
578 data+=10+id3frame.size;
583 //don't support this version
590 //store the found tag
599 * parse an id3v1 Header
600 * based on code provided by Brian Walton
601 * @returns -1 of nothing found
602 * otherwise the id3 info is filled
604 #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;}
606 int DemuxerAudio::parseID3V1(UCHAR *data, int len) {
608 if (len < 128) return -1;
609 if(data[0]=='T' && data[1]=='A' && data[2]=='G')
611 id3_tag * tag=new id3_tag();
612 if (debug != 0)log->log("DemuxerAudio::parseID3V1",Log::DEBUG,"ID3 V1 tag found\n");
614 MEMCPY(artist,30,33);
617 if (data[125]==0 && data[126]!=0)
619 if (debug != 0)log->log("DemuxerAudio::parseID3V1",Log::DEBUG,"ID3 V1.1 tag\n");
620 MEMCPY(comment,29,97);
621 sprintf(tag->track, "%d", data[126]);
623 if (debug != 0)log->log("DemuxerAudio::parseID3V1",Log::DEBUG,"ID3 V1.0 tag\n");
624 MEMCPY(comment,30,97);
626 if (data[127] < sizeof(id3_1_genre)/sizeof(id3_1_genre[0]))
628 sprintf(tag->genre, id3_1_genre[data[127]]);
637 //infos from http://www.multiweb.cz/twoinches/MP3inside.htm
638 int DemuxerAudio::parseVBR(UCHAR *data, int len) {
639 UCHAR *hdr=findHeader(data,len);
640 //we expect the header exactly here
641 if (hdr != data) return -1;
642 const static char * VBRHDR="Xing";
644 UCHAR mpgtype=(data[1] & 0x18)>>3;
645 UCHAR chmode=(data[2] & 0xc0) >> 6;
646 UCHAR layer=(data[2] & 0x06) >>1;
647 if ( mpgtype == 3 && chmode == 11) vbridpos=21;
648 if ( mpgtype != 3 && chmode != 11) vbridpos=21;
649 if ( mpgtype != 3 && chmode == 11) vbridpos=13;
650 //check for the header ID
651 if (vbridpos+(int)strlen(VBRHDR)+4 >= len) {
652 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"frame to short for VBR header %d",len);
655 for (int i=4;i<vbridpos;i++) {
657 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"garbage when searching VBR header at pos %d",i);
661 if ( strncmp((char *)&data[vbridpos],VBRHDR,strlen(VBRHDR)) != 0) {
662 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"no VBR header at pos %d",vbridpos);
665 int framedata=vbridpos+strlen(VBRHDR);
667 //OK we should now have a valid vbr header
668 bool hasFramenum=data[framedata+3] & 1;
669 bool hasBytes=data[framedata+3] & 0x2;
670 bool hasTOC=data[framedata+3] & 0x4;
672 if (hasTOC) expectedLen+=100;
673 if (framedata+expectedLen > len) {
674 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"frame to short for VBR header data %d, expected %d",
675 len,framedata+expectedLen);
678 if (!hasFramenum || ! hasBytes || ! hasTOC) {
679 //not usefull for us..
680 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"not all parts in VBR header - ignore");
686 vbr->numFrames=data[framedata] << 24 | data[framedata+1]<<16|
687 data[framedata+2]<<8 |data[framedata+3];
689 vbr->numBytes=data[framedata] << 24 | data[framedata+1]<<16|
690 data[framedata+2]<<8 |data[framedata+3];
692 for (int ti=0;ti<100;ti++) {
693 vbr->table[ti]=data[framedata+ti];
695 //compute file size in seconds
696 //should be (#of frames -1) *samplesPerFrame / sampleRate
697 //TODO: difference for Mono?
698 ULONG samplesPerFrame=384; //layer1
699 if (layer != 3) samplesPerFrame=1152;
700 vbr->fileSeconds=(vbr->numFrames-1)*samplesPerFrame/hdrSamplingRate;
701 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"successfully read VBR %ldbytes, %ld frames, %ldsec",
702 vbr->numBytes,vbr->numFrames,vbr->fileSeconds);
712 UCHAR * DemuxerAudio::findHeader(UCHAR *buf, int len, bool writeInfo) {
713 while (len >= 3) //assume hdr+crc
717 if (pattern != HDRBYTE1 ) continue;
718 if ((*buf & HDRBYTE2MASK) != HDRBYTE2) continue;
719 if (readHeader((buf-1),4,writeInfo) != 0) continue;
727 int DemuxerAudio::readHeader(UCHAR * hbuf,int len,bool writeInfo) {
730 int curSamplingRate=0;
731 if (*hbuf != HDRBYTE1) return -1;
733 if ((*hbuf & HDRBYTE2MASK) != HDRBYTE2) return -1;
734 UCHAR mpgtype=(*hbuf & 0x18)>>3;
736 log->log("DemuxerAudio",Log::DEBUG,"header invalid mpgtype %s %i %i %i",
737 mpegString(mpgtype),*hbuf,*(hbuf+1),*(hbuf+2));
740 UCHAR layer=(*hbuf & 0x06) >>1;
741 //bool hasCRC=!(*hbuf & 1);
743 UCHAR bitrateCode=(*hbuf & 0xf0) >>4;
744 UCHAR samplingCode=(*hbuf & 0x0c) >> 2;
745 bool padding=*hbuf & 0x02;
747 //0 Stereo, 1 JointStereo, 2 Dual, 3 Mono
748 UCHAR chmode=(*hbuf & 0xc0) >> 6;
749 //UCHAR extension=(*hbuf & 0x30) >> 4;
751 //layercode: 1-L3, 2-L2, 3-L1
752 //columns 0,1,2 for MPEG1
753 UCHAR bitrateColumn=3-layer;
754 if (bitrateColumn > 2) {
755 log->log("DemuxerAudio",Log::DEBUG,"header invalid layer %s %i %i %i",
756 layerString(layer),*(hbuf-2),*(hbuf-1),*hbuf);
759 if (mpgtype != 3) bitrateColumn+=3;
760 if (bitrateColumn>4) bitrateColumn=4;
761 curBitrate=1000*bitrateTable[bitrateCode][bitrateColumn];
762 UCHAR sampleRateColumn=0;
763 if (mpgtype == 10) sampleRateColumn=1;
764 if (mpgtype == 0) sampleRateColumn=2;
765 curSamplingRate=samplingRateTable[samplingCode][sampleRateColumn];
766 if (curSamplingRate < 0 || curBitrate < 0) {
767 log->log("DemuxerAudio",Log::DEBUG,"header invalid rates br=%d sr=%d %i %i %i",
768 curBitrate,curSamplingRate,*(hbuf-2),*(hbuf-1),*hbuf);
773 if (layer == 3) padbytes=4;
778 //FrameLengthInBytes = (12 * BitRate / SampleRate + Padding) * 4
779 curFramelen=(12*curBitrate/curSamplingRate+padbytes) * 4;
783 //FrameLengthInBytes = 144 * BitRate / SampleRate + Padding
784 curFramelen=144*curBitrate/curSamplingRate+padbytes;
787 if (curFramelen < 32) {
788 log->log("DemuxerAudio",Log::DEBUG,"read header %ld mpgv=%s lc=%s br=%d sr=%d, fl=%d-invalid %i %i %i",
789 readHeaders,mpegString(mpgtype),layerString(layer),
790 curBitrate,curSamplingRate,curFramelen,*(hbuf-2),*(hbuf-1),*hbuf);
793 if (writeInfo || isStarting){
794 log->log("DemuxerAudio",Log::DEBUG,"read header %ld mpgv=%s lc=%s br=%d sr=%d, fl=%d %i %i %i",
795 readHeaders,mpegString(mpgtype),layerString(layer),
796 curBitrate,curSamplingRate,curFramelen,*(hbuf-2),*(hbuf-1),*hbuf);
797 if (info) delete info;
799 strcpy(info->mpegVersion,mpegString(mpgtype));
800 info->mpegLayer=4-layer;
801 info->bitRate=curBitrate;
802 info->avrBitrate=curBitrate;
803 info->sampleRate=curSamplingRate;
804 const char *chmodStr=tr("Stereo");
806 case 1: chmodStr=tr("JointStereo");break;
807 case 2: chmodStr=tr("Dual");break;
808 case 3: chmodStr=tr("Mono");break;
810 SNPRINTF(info->info,sizeof(info->info)-1,"%s",chmodStr);
812 if (isStarting) avrBitrate=curBitrate;
815 //moving average F=0.005
816 avrBitrate=avrBitrate+((5*(curBitrate-avrBitrate))/1024);
817 hdrBitrate=curBitrate;
818 hdrFramelen=curFramelen;
819 hdrSamplingRate=curSamplingRate;
824 int DemuxerAudio::findPTS(UCHAR* buf, int len, ULLONG* dest)
826 //we have no PTS number ...
828 return (findHeader(buf,len) != NULL)?1:0;
831 bool PacketBuffer::doSkip() {
832 if (!bufferFull()) return false;
833 if (skipfactor == 0) return false;
835 if (numskip >= skipfactor) {
836 //sent at least always 2 packets
837 if (numskip > skipfactor) numskip=0;
844 // just handle the real stream without dealing with the header
845 int PacketBuffer::putInternal(UCHAR * wbuf, int len,unsigned int &packetnum)
847 /* Important, the type passed to stream must be a mediapacket type as defined in
848 Draintarget.h and not the device setting of the mvp, so we have to translate it here,
849 in order to get it working on windows
852 switch (streamtype) {
853 case Audio::MPEG1_PES: //?
854 case Audio::MPEG2_PES: //Important, this must be a PES !
855 mptype=MPTYPE_MPEG_AUDIO; break;
857 case Audio::MP3: //this can be any Mpeg1 Audio not only layer 3 not packed into PES
858 mptype=MPTYPE_MPEG_AUDIO_LAYER3;break;
862 if (doSkip()) return 0;//NoSkip on Windows
864 //we are still full - so try to write
865 int sent=audio->put(store+bytesWritten,framelen-bytesWritten,/*streamtype*/mptype,packetnum);packetnum++;
866 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream (still full) pp=%d, framelen=%d, written=%d",sent,partPacket,framelen, bytesWritten );
867 if (sent < (framelen - bytesWritten)) {
868 //packet still not written
873 //let the demuxer come back with the rest - need to check header first
876 if (partPacket+len >= framelen) {
877 //now we have at least a complete packet
878 int bytesConsumed=framelen-partPacket;
879 memcpy(store+partPacket,wbuf,bytesConsumed);
881 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"stored packet %ld, length %d (last %d) for stream %p",numpackets,framelen,bytesConsumed,audio );
882 #ifndef WIN32 //No Skip on Windows
883 if (doSkip()) return bytesConsumed;
885 int sent=audio->put(store,framelen,mptype,packetnum);packetnum++;
887 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream",sent );
888 if (bytesWritten < framelen) {
889 //still not completely written
890 return bytesConsumed;
893 //let the player come back...
894 return bytesConsumed;
896 //OK packet still not complete
897 if (len == 0) return 0;
898 int bytesConsumed=len;
899 memcpy(store+partPacket,wbuf,bytesConsumed);
900 partPacket+=bytesConsumed;
901 return bytesConsumed;
905 major entry for data from a player
906 the demuxer is either in the state headerSearch (packet written or
907 just at the beginning), writing garbage (inSync=false) or
908 handling data (none set)
909 A header is expected at the first byte after the previous packet -
910 otherwise we switch to garbage where we always search for a header
911 (but anyway provide the data to the underlying device - it's probably
912 more intelligent then we are...
913 We only loose a correct position display.
915 int DemuxerAudio::put(UCHAR* wbuf, int len)
917 //return audiostream.put(wbuf,len,streamtype);
918 int framelen=PACKET_SIZE;
922 if (tmpFill != 0 || (buffer->bufferEmpty() && len < HDRLEN)) {
923 //OK we have to copy everything to the tmp buffer
924 int cp=(UINT)len<(PACKET_SIZE-tmpFill)?(UINT)len:(PACKET_SIZE-tmpFill);
925 memcpy(&tmpBuffer[tmpFill],wbuf,cp);
930 //if there is no header here and our buffer
931 //is empty - just wait for the next header
932 if (len < HDRLEN && buffer->bufferEmpty()) {
933 log->log("DemuxerAudio",Log::DEBUG,"len to small for header %d at bytes %ld",len,globalBytesWritten);
937 while (bytesConsumed < len ) {
938 if (buffer->bufferFull()) {
939 //if this is the first part of the loop, try to write to the stream
940 if (bytesConsumed == 0) buffer->putInternal(wbuf,0,packetnum);
941 //if the buffer is full, no need to continue
942 if (buffer->bufferFull()) break;
944 //either we are in a packet (buffer != full && buffer != empty)
945 //or we are searching a header
946 if (buffer->bufferEmpty()) {
947 if (len-bytesConsumed < HDRLEN) {
948 // we cannot still search
950 //we are already working at the buffer
953 memcpy(tmpBuffer,wbuf,len-bytesConsumed);
954 tmpFill=len-bytesConsumed;
955 log->log("DemuxerAudio",Log::DEBUG,"len to small for header %d at bytes %ld",len,globalBytesWritten);
959 int lastFramelen=hdrFramelen;
960 //if the header has been valid before and we are searching
962 int maxsearch=((len-bytesConsumed) < (int)PACKET_SIZE)?len-bytesConsumed:(int)PACKET_SIZE;
963 hdr=findHeader(wbuf,maxsearch);
965 //log->log("DemuxerAudio",Log::DEBUG,"header found at offset %d",hdr-wbuf);
967 //hdr now points to the new header
969 //still at least bytes before the header
972 int garbageBytes=(hdr!=NULL)?(hdr-wbuf):maxsearch;
973 //we consider the garbage now as an own packet
974 //we can consume at most our buffer
975 //basically the buffer should be empty here (we are
976 //in header search - and we fill up each garbage
978 int nframesize=garbageBytes;
979 if (nframesize > (int)PACKET_SIZE) {
980 nframesize=(int)PACKET_SIZE;
982 if (! buffer->bufferEmpty()) {
983 log->log("DemuxerAudio",Log::WARN,"buffer not empty when having garbage to store");
984 //at the end no big problem, we only write the remaining bytes that we have...
987 buffer->setFramelen(nframesize);
989 log->log("DemuxerAudio",Log::DEBUG,"garbage found at packet %ld (bytes %ld) of length %d, "
990 "framelen set to %d (last fl=%d)",
991 readHeaders,globalBytesWritten,garbageBytes,buffer->getFramelen(),lastFramelen);
993 //hmm - we assume that he low level driver is more intelligent
994 //and give him the data "as is"
995 int written=buffer->putInternal(wbuf,garbageBytes,packetnum);
996 globalBytesWritten+=written;
997 bytesConsumed+=written;
998 if (written != garbageBytes || hdr == NULL ) {
1001 #else //DS is not intelligent
1002 globalBytesWritten+=garbageBytes;
1003 bytesConsumed+=garbageBytes;
1005 //OK either all the "garbage" is written or
1006 //we found the next header as expected
1007 //continue with the next package
1010 //we have to wait now until the buffer is
1011 //free for the next package
1012 if ( ! buffer->bufferEmpty()) return bytesConsumed;
1013 //this is the place where we start a new packet
1014 framelen=hdrFramelen;
1015 if ( !buffer->setFramelen(framelen) ) {
1016 log->log("DemuxerAudio",Log::DEBUG,"unable to set framelen should=%d, current=%d",
1017 framelen,buffer->getFramelen());
1021 //now we are surely within a packet
1022 int written=buffer->putInternal(wbuf,len-bytesConsumed,packetnum);
1024 globalBytesWritten+=written;
1026 bytesConsumed+=written;
1031 //OK - handle the rest
1033 if (bytesConsumed >= oldBytes) {
1034 //if we consumed more than the old bytes - OK the buffer
1035 //can be thrown away
1037 return bytesConsumed-oldBytes;
1040 //only consumed bytes from the buffer
1041 if (bytesConsumed == 0) {
1042 //restore the buffer
1046 //shift bytes in buffer
1047 for (int i=0;i<oldBytes-bytesConsumed;i++) {
1048 tmpBuffer[i]=tmpBuffer[i+bytesConsumed];
1050 tmpFill=oldBytes-bytesConsumed;
1056 const id3_tag * DemuxerAudio::getId3Tag() {
1060 const DemuxerAudio::mpegInfo * DemuxerAudio::getMpegInfo() {
1061 if (! hasHdrInfo) return NULL;
1062 info->avrBitrate=avrBitrate;
1063 info->bitRate=hdrBitrate;
1067 const DemuxerAudio::vbrInfo * DemuxerAudio::getVBRINfo() {
1071 int DemuxerAudio::checkStart(UCHAR *b, int len) {
1073 int id3len=parseID3V2(b,len);
1075 char * str=id3->toString();
1076 log->log("DemuxerAudio",Log::DEBUG,"parseID3V2 %d bytes of %d",id3len,len);
1077 log->log("DemuxerAudio",Log::DEBUG,"parseID3V2 found:%s",str);
1082 int vbrlen=parseVBR(b,len);
1088 UCHAR * hdr=findHeader(b,len,true);
1089 if (hdr == NULL) return -1;
1093 int DemuxerAudio::checkID3(UCHAR *b, int len) {
1094 if (len != 128) return -1;
1095 int rt=parseID3V1(b,len);
1097 char * str=id3->toString();
1098 log->log("DemuxerAudio",Log::DEBUG,"parseID3V1 found:%s",str);
1104 bool DemuxerAudio::isSync() {
1108 UINT DemuxerAudio::getSyncErrors() {
1112 ULONG DemuxerAudio::getBytesPerSecond()
1114 ULONG bps=hdrBitrate;
1115 if (! hasHdrInfo) return 0;
1116 if (hdrBitrate != avrBitrate) {
1117 //we seem to have vbr
1131 ULONG DemuxerAudio::getSecondsFromLen(ULONG len) {
1132 if (! hasHdrInfo) return 0;
1134 //first find the index where we are between
1135 //rough starting point:
1136 ULONG idx=100*len/vbr->numBytes;
1137 if (idx >= 100) idx=99;
1138 ULONG idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1139 ULONG pbefore=idxPos;
1140 ULONG pafter=idxPos;
1141 //OK now we know whether we have to go up or down
1144 while (idxPos > len && idx > 0) {
1147 idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1150 //OK we are now before our postion
1154 while (idxPos < len && idx < 100 ) {
1157 idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1160 //after our position
1161 if (idx > 0) idx --;
1163 //idx is now the index before our position
1164 //approximate between the 2 points
1165 ULONG idxTime=idx * vbr->fileSeconds/100;
1166 if (pafter == pbefore) return idxTime;
1167 ULONG rt=idxTime+ (len-pbefore)* vbr->fileSeconds/(100 * (pafter-pbefore)) ;
1168 if (rt > vbr -> fileSeconds) return vbr->fileSeconds;
1169 if (rt < idxTime) return idxTime;
1173 ULONG bps=getBytesPerSecond();
1174 if (bps == 0) return 0;
1179 ULONG DemuxerAudio::positionFromSeconds(ULONG seconds) {
1180 if (! hasHdrInfo) return 0;
1182 ULONG idx=seconds*100/vbr->fileSeconds;
1183 if (idx > 99) idx=99;
1184 ULONG idxPos=vbr->table[idx] * vbr->numBytes/256;
1186 if (idx < 99) idx2++;
1187 ULONG nextPos=vbr->table[idx] * vbr->numBytes/256;
1188 ULONG rt=idxPos+(nextPos-idxPos) * (seconds - idx * vbr->fileSeconds /256);
1189 if (rt < idxPos) return idxPos;
1190 if ( rt > vbr->numBytes) return vbr->numBytes;
1194 ULONG bps=getBytesPerSecond();
1199 int id3_tag::stringlen(bool withTitle) const {
1201 return strlen(artist)+strlen(genre)+strlen(year)+strlen(album)+
1202 strlen(track)+strlen(composer)+strlen(comment)+8+3+
1203 90; //30 chars for each name...
1205 return strlen(title)+strlen(artist)+strlen(genre)+strlen(year)+strlen(album)+
1206 strlen(track)+strlen(composer)+strlen(comment)+8+3+
1207 120; //30 chars for each name...
1209 //create a string out of the id3 tag info
1210 //delete this string afterwards if you did not provide the buffer
1211 char * id3_tag::toString(char *b, int len, bool withTitle) const {
1212 const char *ta=tr("Artist");
1213 //char *tg=tr("Genre");
1214 //char *ty=tr("Year");
1215 const char *tx=tr("Album");
1216 //char *to=tr("Composer");
1217 //char *tc=tr("Comment");
1218 const char *tn=tr("Track");
1226 len=stringlen(withTitle);
1229 const char * del=" - ";
1230 if (strlen(year) == 0) del="";
1232 const char *tt=tr("Title");
1233 SNPRINTF(b,len-1,"%s: %s\n%s: %s\n%s: %s%s%s\n%s: %s",
1234 tt,title,ta,artist,tx,year,del,album,tn,track);
1237 SNPRINTF(b,len-1,"%s: %s\n%s: %s%s%s\n%s: %s",
1238 ta,artist,tx,year,del,album,tn,track);
1244 void DemuxerAudio::setSkipFactor(int factor) {
1245 Log::getInstance()->log("DemuxerAudio",Log::DEBUG,"set skipfactor %d\n",factor);
1246 buffer->setSkipFactor(factor);