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"
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);
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;
120 DemuxerAudio::~DemuxerAudio() {
122 if(info) delete info;
127 void DemuxerAudio::flush()
129 Demuxer::flushAudio();
134 void DemuxerAudio::reset() {
139 globalBytesWritten=0;
142 if (info) delete info;
151 hdrSamplingRate=44100;
157 int DemuxerAudio::scan(UCHAR *buf, int len)
159 //no differend pids here
163 void DemuxerAudio::setVID(int p_vID)
167 void DemuxerAudio::setAID(int p_aID)
171 static char * id3_1_genre[] = {
256 static int bitrateTable[16][5]={
257 /* L1,L2,L3,2L1,2L2 */
258 /*0000*/ {-1,-1,-1,-1,-1},
259 /*0001*/ {32,32,32,32,8},
260 /*0010*/ {64,48,40,48,16},
261 /*0011*/ {96,56,48,56,24},
262 /*0100*/ {128,64,56,64,32},
263 /*0101*/ {160,80,64,80,40},
264 /*0110*/ {192,96,80,96,48},
265 /*0111*/ {224,112,96,112,56},
266 /*1000*/ {256,128,112,128,64},
267 /*1001*/ {288,160,128,144,80},
268 /*1010*/ {320,192,160,160,96},
269 /*1011*/ {352,224,192,176,112},
270 /*1100*/ {384,256,224,192,128},
271 /*1101*/ {416,320,256,224,144},
272 /*1110*/ {448,384,320,256,160},
273 /*1111*/ {-1,-1,-1,-1,-1} };
275 static int samplingRateTable[4][3]={
276 /*00*/ {44100,22050,11025},
277 /*01*/ {48000,24000,12000},
278 /*10*/ {32000,16000,8000},
282 static const char * mpegString(UCHAR code) {
296 static const char * layerString(UCHAR code) {
299 return "Layer reserved";
307 return "Layer UNKNOWN";
310 * parse an id3 Header
311 * provided by Brian Walton
312 * @returns -1 of nothing found
315 int DemuxerAudio::id3_2_3_FrameParse(unsigned char buf[], id3_frame *frame)
317 if (buf[0] < 0x20 || buf[1] < 0x20 || buf [2] < 0x20 ) return -1;
318 frame->size = (buf[4] & 0x7F) << 21 | (buf[5] & 0x7F) << 14 | (buf[6] & 0x7F) << 7 | (buf[7] & 0x7F);
319 if (frame->size == 0) return -1;
320 //TODO. clearify flags against:
321 //http://id3.org/id3v2.3.0#head-697d09c50ed7fa96fb66c6b0a9d93585e2652b0b
322 frame->flags.tagAlterPreserv = (buf[8] & 0x80) >> 7;
323 frame->flags.filelterPreserv = (buf[8] & 0x40) >> 6;
324 frame->flags.readOnly = (buf[8] & 0x20) >> 5;
325 frame->flags.groupId = (buf[9] & 0x20) >> 5;
326 frame->flags.compression = (buf[9] & 0x80) >> 7;
327 frame->flags.encryption = (buf[9] & 0x40) >> 6;
328 frame->flags.unsync = 0;
329 frame->flags.dataLen = 0;
334 * parse an id3 Header
335 * provided by Brian Walton
336 * @returns -1 of nothing found
339 int DemuxerAudio::id3_2_2_FrameParse(unsigned char buf[], id3_frame *frame)
341 if (buf[0] < 0x20 || buf[1] < 0x20 || buf[2] < 0x20) return -1;
342 frame->size = (buf[3] & 0x7F) << 14 | (buf[4] & 0x7F) << 7 | (buf[5] & 0x7F);
343 if (frame->size == 0) return -1;
348 //fill an id3tag from a frame payload
349 //http://id3.org/id3v2.3.0#head-697d09c50ed7fa96fb66c6b0a9d93585e2652b0b
350 //http://id3.org/id3v2-00
351 static struct tagid {
362 {"TCOM",7}, //composer
363 {"COMM",8}, //comment
366 //Short content descrip. <text string according to encoding> $00 (00)
367 //The actual text <full text string according to encoding>
372 {"TCO",3 }, //(genreNumber)
378 #define NUMKNOWN (sizeof(knownFrames)/sizeof(knownFrames[0]))
381 from an ID3 V2.x, V2.3 frame into the tags structure
382 frameData must point to the header
383 framelen is the len without header (10 Bytes for V23, 6 Bytes for v2x)
386 #define MAXLEN(tagtype) ((UINT)frameLen<sizeof(tag->tagtype)-1?(UINT)frameLen:sizeof(tag->tagtype)-1)
387 bool DemuxerAudio::fillId3Tag(id3_tag * tag,UCHAR * frameData, int frameLen, int dataOffset, bool v23) {
390 if (tag == NULL) return false;
391 if (frameLen < 2) return false;
392 for (UINT i=0;i< NUMKNOWN;i++) {
393 if(strncmp((char *)frameData,knownFrames[i].bytes,tl) == 0) {
394 tagIndex=knownFrames[i].index;
398 if (tagIndex < 0) return false;
399 UCHAR encoding=*(frameData+dataOffset);
403 log->log("DemuxerAudio",Log::DEBUG,"unknown encoding for tag %d, tagid %s",encoding,
404 knownFrames[tagIndex].bytes);
409 strncpy(tag->title,(char*)(frameData+dataOffset),MAXLEN(title));
410 tag->title[MAXLEN(title)]=0;
413 strncpy(tag->artist,(char*)(frameData+dataOffset),MAXLEN(artist));
414 tag->artist[MAXLEN(artist)]=0;
418 UCHAR * st=frameData+dataOffset;
421 genre=atoi((const char *)(st+1)) && 31;
422 st=(UCHAR *)id3_1_genre[genre];
424 strncpy(tag->genre,(char*)st,MAXLEN(genre));
425 tag->genre[MAXLEN(genre)]=0;
429 strncpy(tag->year,(char *)(frameData+dataOffset),MAXLEN(year));
430 tag->year[MAXLEN(year)]=0;
433 strncpy(tag->album,(char *)(frameData+dataOffset),MAXLEN(album));
434 tag->album[MAXLEN(album)]=0;
437 strncpy(tag->track,(char *)(frameData+dataOffset),MAXLEN(track));
438 tag->track[MAXLEN(track)]=0;
441 strncpy(tag->composer,(char *)(frameData+dataOffset),MAXLEN(composer));
442 tag->composer[MAXLEN(composer)]=0;
445 strncpy(tag->comment,(char *)(frameData+dataOffset),MAXLEN(comment));
446 tag->comment[MAXLEN(comment)]=0;
456 * parse an id3 Header
457 * based on code provided by Brian Walton
458 * @returns -1 of nothing found
459 * otherwise the id3 info is filled
462 int DemuxerAudio::parseID3V2(UCHAR *data, int len) {
465 id3_header id3header;
467 id3_tag * id3tag=NULL;
468 //len = read(fd, data, 10);
474 if(data[0]=='I' && data[1]=='D' && data[2]=='3')
476 id3tag=new id3_tag();
477 id3header.major = data[3];
478 id3header.minor = data[4];
479 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"ID3 V2.%d.%d found\n", id3header.major, id3header.minor);
480 id3header.flags.unsynchronisation = (data[5] & 0x80)>>7;
481 id3header.flags.extended_header = (data[5] & 0x40)>>6;
482 id3header.flags.experimental = (data[5] & 0x20)>>5;
483 id3header.flags.footer = (data[5] & 0x10)>>4;
484 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Unsynchronisation flag: %d\n", id3header.flags.unsynchronisation);
485 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Extended header flag: %d\n", id3header.flags.extended_header);
486 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Experimental indicator flag: %d\n", id3header.flags.experimental);
487 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Footer present flag: %d\n", id3header.flags.footer);
488 id3header.size = (data[6] & 0x7F) << 21 | (data[7] & 0x7F) << 14 | (data[8] & 0x7F) << 7 | (data[9] & 0x7F);
489 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"ID3 Size: %d\n", id3header.size);
491 if (len <= id3header.size) {
492 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"header size to big %d, only %d bytes available\n",id3header.size,len);
496 if (id3header.flags.extended_header)
498 int extended_hdr_hdr=4; //still to be discussed (id3.org...)
499 //read extended header size
500 if (len < extended_hdr_hdr) {
501 if (debug) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"extended header found but cannot read\n");
505 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"remaining %d chars after extended hdr hdr\n", len);
506 id3header.extended_header.size = (data[0] & 0x7F) << 21 | (data[1] & 0x7F) << 14 | (data[2] & 0x7F) << 7 | (data[3] & 0x7F);
507 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Extended header size: %d\n", id3header.extended_header.size);
508 if (len <= id3header.extended_header.size+extended_hdr_hdr) {
509 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"extended Header to big, only %d bytes available\n",len);
513 //lseek(fd, id3header.extended_header.size - 6, SEEK_CUR);
514 data+=id3header.extended_header.size+extended_hdr_hdr;
515 len-=id3header.extended_header.size+extended_hdr_hdr;
517 //set the end of the header
518 UCHAR * eob=start+id3header.size+10;
520 while (data < eob && readNext)
522 //skip over some padding - found this in lame MCDI tag...
528 switch(id3header.major)
531 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));
536 if (id3_2_2_FrameParse(data, &id3frame) < 0)
540 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"frame size: %d\n", id3frame.size);
541 fillId3Tag(id3tag,data,id3frame.size,6,false);
542 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"frame payload: %s\n", data + 6 +1);
543 data+=6+id3frame.size;
548 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"version 2.3 frame, %d : %c %c %c %c\n", data-start,
549 *data,*(data+1),*(data+2),*(data+3));
550 if (data + 10 >= eob)
554 if (id3_2_3_FrameParse(data, &id3frame) <0)
558 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame size: %d\n", id3frame.size);
560 if (id3frame.flags.groupId)
563 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame group: %d\n", data[dataOffset]);
565 if (id3frame.flags.compression)
567 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame compressed: %d\n", id3frame.flags.compression);
569 if (id3frame.flags.encryption)
572 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"Frame encryption method: %d\n", data[dataOffset]);
574 fillId3Tag(id3tag,data,id3frame.size-dataOffset+10,dataOffset,true);
575 if (debug != 0) log->log("DemuxerAudio::parseID3V2",Log::DEBUG,"frame payload: %s\n", data + dataOffset +1);
576 data+=10+id3frame.size;
581 //don't support this version
588 //store the found tag
597 * parse an id3v1 Header
598 * based on code provided by Brian Walton
599 * @returns -1 of nothing found
600 * otherwise the id3 info is filled
602 #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;}
604 int DemuxerAudio::parseID3V1(UCHAR *data, int len) {
606 if (len < 128) return -1;
607 if(data[0]=='T' && data[1]=='A' && data[2]=='G')
609 id3_tag * tag=new id3_tag();
610 if (debug != 0)log->log("DemuxerAudio::parseID3V1",Log::DEBUG,"ID3 V1 tag found\n");
612 MEMCPY(artist,30,33);
615 if (data[125]==0 && data[126]!=0)
617 if (debug != 0)log->log("DemuxerAudio::parseID3V1",Log::DEBUG,"ID3 V1.1 tag\n");
618 MEMCPY(comment,29,97);
619 sprintf(tag->track, "%d", data[126]);
621 if (debug != 0)log->log("DemuxerAudio::parseID3V1",Log::DEBUG,"ID3 V1.0 tag\n");
622 MEMCPY(comment,30,97);
624 if (data[127] < sizeof(id3_1_genre)/sizeof(id3_1_genre[0]))
626 sprintf(tag->genre, id3_1_genre[data[127]]);
635 //infos from http://www.multiweb.cz/twoinches/MP3inside.htm
636 int DemuxerAudio::parseVBR(UCHAR *data, int len) {
637 UCHAR *hdr=findHeader(data,len);
638 //we expect the header exactly here
639 if (hdr != data) return -1;
640 const static char * VBRHDR="Xing";
642 UCHAR mpgtype=(data[1] & 0x18)>>3;
643 UCHAR chmode=(data[2] & 0xc0) >> 6;
644 UCHAR layer=(data[2] & 0x06) >>1;
645 if ( mpgtype == 3 && chmode == 11) vbridpos=21;
646 if ( mpgtype != 3 && chmode != 11) vbridpos=21;
647 if ( mpgtype != 3 && chmode == 11) vbridpos=13;
648 //check for the header ID
649 if (vbridpos+(int)strlen(VBRHDR)+4 >= len) {
650 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"frame to short for VBR header %d",len);
653 for (int i=4;i<vbridpos;i++) {
655 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"garbage when searching VBR header at pos %d",i);
659 if ( strncmp((char *)&data[vbridpos],VBRHDR,strlen(VBRHDR)) != 0) {
660 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"no VBR header at pos %d",vbridpos);
663 int framedata=vbridpos+strlen(VBRHDR);
665 //OK we should now have a valid vbr header
666 bool hasFramenum=data[framedata+3] & 1;
667 bool hasBytes=data[framedata+3] & 0x2;
668 bool hasTOC=data[framedata+3] & 0x4;
670 if (hasTOC) expectedLen+=100;
671 if (framedata+expectedLen > len) {
672 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"frame to short for VBR header data %d, expected %d",
673 len,framedata+expectedLen);
676 if (!hasFramenum || ! hasBytes || ! hasTOC) {
677 //not usefull for us..
678 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"not all parts in VBR header - ignore");
684 vbr->numFrames=data[framedata] << 24 | data[framedata+1]<<16|
685 data[framedata+2]<<8 |data[framedata+3];
687 vbr->numBytes=data[framedata] << 24 | data[framedata+1]<<16|
688 data[framedata+2]<<8 |data[framedata+3];
690 for (int ti=0;ti<100;ti++) {
691 vbr->table[ti]=data[framedata+ti];
693 //compute file size in seconds
694 //should be (#of frames -1) *samplesPerFrame / sampleRate
695 //TODO: difference for Mono?
696 ULONG samplesPerFrame=384; //layer1
697 if (layer != 3) samplesPerFrame=1152;
698 vbr->fileSeconds=(vbr->numFrames-1)*samplesPerFrame/hdrSamplingRate;
699 Log::getInstance()->log("DemuxerAudio::parseVBR",Log::DEBUG,"successfully read VBR %ldbytes, %ld frames, %ldsec",
700 vbr->numBytes,vbr->numFrames,vbr->fileSeconds);
710 UCHAR * DemuxerAudio::findHeader(UCHAR *buf, int len, bool writeInfo) {
711 while (len >= 3) //assume hdr+crc
715 if (pattern != HDRBYTE1 ) continue;
716 if ((*buf & HDRBYTE2MASK) != HDRBYTE2) continue;
717 if (readHeader((buf-1),4,writeInfo) != 0) continue;
725 int DemuxerAudio::readHeader(UCHAR * hbuf,int len,bool writeInfo) {
728 int curSamplingRate=0;
729 if (*hbuf != HDRBYTE1) return -1;
731 if ((*hbuf & HDRBYTE2MASK) != HDRBYTE2) return -1;
732 UCHAR mpgtype=(*hbuf & 0x18)>>3;
734 log->log("DemuxerAudio",Log::DEBUG,"header invalid mpgtype %s %i %i %i",
735 mpegString(mpgtype),*hbuf,*(hbuf+1),*(hbuf+2));
738 UCHAR layer=(*hbuf & 0x06) >>1;
739 //bool hasCRC=!(*hbuf & 1);
741 UCHAR bitrateCode=(*hbuf & 0xf0) >>4;
742 UCHAR samplingCode=(*hbuf & 0x0c) >> 2;
743 bool padding=*hbuf & 0x02;
745 //0 Stereo, 1 JointStereo, 2 Dual, 3 Mono
746 UCHAR chmode=(*hbuf & 0xc0) >> 6;
747 //UCHAR extension=(*hbuf & 0x30) >> 4;
749 //layercode: 1-L3, 2-L2, 3-L1
750 //columns 0,1,2 for MPEG1
751 UCHAR bitrateColumn=3-layer;
752 if (bitrateColumn > 2) {
753 log->log("DemuxerAudio",Log::DEBUG,"header invalid layer %s %i %i %i",
754 layerString(layer),*(hbuf-2),*(hbuf-1),*hbuf);
757 if (mpgtype != 3) bitrateColumn+=3;
758 if (bitrateColumn>4) bitrateColumn=4;
759 curBitrate=1000*bitrateTable[bitrateCode][bitrateColumn];
760 UCHAR sampleRateColumn=0;
761 if (mpgtype == 10) sampleRateColumn=1;
762 if (mpgtype == 0) sampleRateColumn=2;
763 curSamplingRate=samplingRateTable[samplingCode][sampleRateColumn];
764 if (curSamplingRate < 0 || curBitrate < 0) {
765 log->log("DemuxerAudio",Log::DEBUG,"header invalid rates br=%d sr=%d %i %i %i",
766 curBitrate,curSamplingRate,*(hbuf-2),*(hbuf-1),*hbuf);
771 if (layer == 3) padbytes=4;
776 //FrameLengthInBytes = (12 * BitRate / SampleRate + Padding) * 4
777 curFramelen=(12*curBitrate/curSamplingRate+padbytes) * 4;
781 //FrameLengthInBytes = 144 * BitRate / SampleRate + Padding
782 curFramelen=144*curBitrate/curSamplingRate+padbytes;
785 if (curFramelen < 32) {
786 log->log("DemuxerAudio",Log::DEBUG,"read header %ld mpgv=%s lc=%s br=%d sr=%d, fl=%d-invalid %i %i %i",
787 readHeaders,mpegString(mpgtype),layerString(layer),
788 curBitrate,curSamplingRate,curFramelen,*(hbuf-2),*(hbuf-1),*hbuf);
791 if (writeInfo || isStarting){
792 log->log("DemuxerAudio",Log::DEBUG,"read header %ld mpgv=%s lc=%s br=%d sr=%d, fl=%d %i %i %i",
793 readHeaders,mpegString(mpgtype),layerString(layer),
794 curBitrate,curSamplingRate,curFramelen,*(hbuf-2),*(hbuf-1),*hbuf);
795 if (info) delete info;
797 strcpy(info->mpegVersion,mpegString(mpgtype));
798 info->mpegLayer=4-layer;
799 info->bitRate=curBitrate;
800 info->avrBitrate=curBitrate;
801 info->sampleRate=curSamplingRate;
802 const char *chmodStr=tr("Stereo");
804 case 1: chmodStr=tr("JointStereo");break;
805 case 2: chmodStr=tr("Dual");break;
806 case 3: chmodStr=tr("Mono");break;
808 SNPRINTF(info->info,sizeof(info->info)-1,"%s",chmodStr);
810 if (isStarting) avrBitrate=curBitrate;
813 //moving average F=0.005
814 avrBitrate=avrBitrate+((5*(curBitrate-avrBitrate))/1024);
815 hdrBitrate=curBitrate;
816 hdrFramelen=curFramelen;
817 hdrSamplingRate=curSamplingRate;
822 int DemuxerAudio::findPTS(UCHAR* buf, int len, ULLONG* dest)
824 //we have no PTS number ...
826 return (findHeader(buf,len) != NULL)?1:0;
829 bool PacketBuffer::doSkip() {
830 if (!bufferFull()) return false;
831 if (skipfactor == 0) return false;
833 if (numskip >= skipfactor) {
834 //sent at least always 2 packets
835 if (numskip > skipfactor) numskip=0;
842 // just handle the real stream without dealing with the header
843 int PacketBuffer::putInternal(UCHAR * wbuf, int len)
845 /* Important, the type passed to stream must be a mediapacket type as defined in
846 Draintarget.h and not the device setting of the mvp, so we have to translate it here,
847 in order to get it working on windows
850 switch (streamtype) {
851 case Audio::MPEG1_PES: //?
852 case Audio::MPEG2_PES: //Important, this must be a PES !
853 mptype=MPTYPE_MPEG_AUDIO; break;
855 case Audio::MP3: //this can be any Mpeg1 Audio not only layer 3 not packed into PES
856 mptype=MPTYPE_MPEG_AUDIO_LAYER3;break;
860 if (doSkip()) return 0;//NoSkip on Windows
862 //we are still full - so try to write
863 int sent=audio->put(store+bytesWritten,framelen-bytesWritten,/*streamtype*/mptype);
864 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream (still full) pp=%d, framelen=%d, written=%d",sent,partPacket,framelen, bytesWritten );
865 if (sent < (framelen - bytesWritten)) {
866 //packet still not written
871 //let the demuxer come back with the rest - need to check header first
874 if (partPacket+len >= framelen) {
875 //now we have at least a complete packet
876 int bytesConsumed=framelen-partPacket;
877 memcpy(store+partPacket,wbuf,bytesConsumed);
879 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"stored packet %ld, length %d (last %d) for stream %p",numpackets,framelen,bytesConsumed,audio );
880 #ifndef WIN32 //No Skip on Windows
881 if (doSkip()) return bytesConsumed;
883 int sent=audio->put(store,framelen,mptype);
885 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream",sent );
886 if (bytesWritten < framelen) {
887 //still not completely written
888 return bytesConsumed;
891 //let the player come back...
892 return bytesConsumed;
894 //OK packet still not complete
895 if (len == 0) return 0;
896 int bytesConsumed=len;
897 memcpy(store+partPacket,wbuf,bytesConsumed);
898 partPacket+=bytesConsumed;
899 return bytesConsumed;
903 major entry for data from a player
904 the demuxer is either in the state headerSearch (packet written or
905 just at the beginning), writing garbage (inSync=false) or
906 handling data (none set)
907 A header is expected at the first byte after the previous packet -
908 otherwise we switch to garbage where we always search for a header
909 (but anyway provide the data to the underlying device - it's probably
910 more intelligent then we are...
911 We only loose a correct position display.
913 int DemuxerAudio::put(UCHAR* wbuf, int len)
915 //return audiostream.put(wbuf,len,streamtype);
916 int framelen=PACKET_SIZE;
920 if (tmpFill != 0 || (buffer->bufferEmpty() && len < HDRLEN)) {
921 //OK we have to copy everything to the tmp buffer
922 int cp=(UINT)len<(PACKET_SIZE-tmpFill)?(UINT)len:(PACKET_SIZE-tmpFill);
923 memcpy(&tmpBuffer[tmpFill],wbuf,cp);
928 //if there is no header here and our buffer
929 //is empty - just wait for the next header
930 if (len < HDRLEN && buffer->bufferEmpty()) {
931 log->log("DemuxerAudio",Log::DEBUG,"len to small for header %d at bytes %ld",len,globalBytesWritten);
935 while (bytesConsumed < len ) {
936 if (buffer->bufferFull()) {
937 //if this is the first part of the loop, try to write to the stream
938 if (bytesConsumed == 0) buffer->putInternal(wbuf,0);
939 //if the buffer is full, no need to continue
940 if (buffer->bufferFull()) break;
942 //either we are in a packet (buffer != full && buffer != empty)
943 //or we are searching a header
944 if (buffer->bufferEmpty()) {
945 if (len-bytesConsumed < HDRLEN) {
946 // we cannot still search
948 //we are already working at the buffer
951 memcpy(tmpBuffer,wbuf,len-bytesConsumed);
952 tmpFill=len-bytesConsumed;
953 log->log("DemuxerAudio",Log::DEBUG,"len to small for header %d at bytes %ld",len,globalBytesWritten);
957 int lastFramelen=hdrFramelen;
958 //if the header has been valid before and we are searching
960 int maxsearch=((len-bytesConsumed) < (int)PACKET_SIZE)?len-bytesConsumed:(int)PACKET_SIZE;
961 hdr=findHeader(wbuf,maxsearch);
963 //log->log("DemuxerAudio",Log::DEBUG,"header found at offset %d",hdr-wbuf);
965 //hdr now points to the new header
967 //still at least bytes before the header
970 int garbageBytes=(hdr!=NULL)?(hdr-wbuf):maxsearch;
971 //we consider the garbage now as an own packet
972 //we can consume at most our buffer
973 //basically the buffer should be empty here (we are
974 //in header search - and we fill up each garbage
976 int nframesize=garbageBytes;
977 if (nframesize > (int)PACKET_SIZE) {
978 nframesize=(int)PACKET_SIZE;
980 if (! buffer->bufferEmpty()) {
981 log->log("DemuxerAudio",Log::WARN,"buffer not empty when having garbage to store");
982 //at the end no big problem, we only write the remaining bytes that we have...
985 buffer->setFramelen(nframesize);
987 log->log("DemuxerAudio",Log::DEBUG,"garbage found at packet %ld (bytes %ld) of length %d, "
988 "framelen set to %d (last fl=%d)",
989 readHeaders,globalBytesWritten,garbageBytes,buffer->getFramelen(),lastFramelen);
991 //hmm - we assume that he low level driver is more intelligent
992 //and give him the data "as is"
993 int written=buffer->putInternal(wbuf,garbageBytes);
994 globalBytesWritten+=written;
995 bytesConsumed+=written;
996 if (written != garbageBytes || hdr == NULL ) {
999 #else //DS is not intelligent
1000 globalBytesWritten+=garbageBytes;
1001 bytesConsumed+=garbageBytes;
1003 //OK either all the "garbage" is written or
1004 //we found the next header as expected
1005 //continue with the next package
1008 //we have to wait now until the buffer is
1009 //free for the next package
1010 if ( ! buffer->bufferEmpty()) return bytesConsumed;
1011 //this is the place where we start a new packet
1012 framelen=hdrFramelen;
1013 if ( !buffer->setFramelen(framelen) ) {
1014 log->log("DemuxerAudio",Log::DEBUG,"unable to set framelen should=%d, current=%d",
1015 framelen,buffer->getFramelen());
1019 //now we are surely within a packet
1020 int written=buffer->putInternal(wbuf,len-bytesConsumed);
1022 globalBytesWritten+=written;
1024 bytesConsumed+=written;
1029 //OK - handle the rest
1031 if (bytesConsumed >= oldBytes) {
1032 //if we consumed more than the old bytes - OK the buffer
1033 //can be thrown away
1035 return bytesConsumed-oldBytes;
1038 //only consumed bytes from the buffer
1039 if (bytesConsumed == 0) {
1040 //restore the buffer
1044 //shift bytes in buffer
1045 for (int i=0;i<oldBytes-bytesConsumed;i++) {
1046 tmpBuffer[i]=tmpBuffer[i+bytesConsumed];
1048 tmpFill=oldBytes-bytesConsumed;
1054 const id3_tag * DemuxerAudio::getId3Tag() {
1058 const DemuxerAudio::mpegInfo * DemuxerAudio::getMpegInfo() {
1059 if (! hasHdrInfo) return NULL;
1060 info->avrBitrate=avrBitrate;
1061 info->bitRate=hdrBitrate;
1065 const DemuxerAudio::vbrInfo * DemuxerAudio::getVBRINfo() {
1069 int DemuxerAudio::checkStart(UCHAR *b, int len) {
1071 int id3len=parseID3V2(b,len);
1073 char * str=id3->toString();
1074 log->log("DemuxerAudio",Log::DEBUG,"parseID3V2 %d bytes of %d",id3len,len);
1075 log->log("DemuxerAudio",Log::DEBUG,"parseID3V2 found:%s",str);
1080 int vbrlen=parseVBR(b,len);
1086 UCHAR * hdr=findHeader(b,len,true);
1087 if (hdr == NULL) return -1;
1091 int DemuxerAudio::checkID3(UCHAR *b, int len) {
1092 if (len != 128) return -1;
1093 int rt=parseID3V1(b,len);
1095 char * str=id3->toString();
1096 log->log("DemuxerAudio",Log::DEBUG,"parseID3V1 found:%s",str);
1102 bool DemuxerAudio::isSync() {
1106 UINT DemuxerAudio::getSyncErrors() {
1110 ULONG DemuxerAudio::getBytesPerSecond()
1112 ULONG bps=hdrBitrate;
1113 if (! hasHdrInfo) return 0;
1114 if (hdrBitrate != avrBitrate) {
1115 //we seem to have vbr
1129 ULONG DemuxerAudio::getSecondsFromLen(ULONG len) {
1130 if (! hasHdrInfo) return 0;
1132 //first find the index where we are between
1133 //rough starting point:
1134 ULONG idx=100*len/vbr->numBytes;
1135 if (idx >= 100) idx=99;
1136 ULONG idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1137 ULONG pbefore=idxPos;
1138 ULONG pafter=idxPos;
1139 //OK now we know whether we have to go up or down
1142 while (idxPos > len && idx > 0) {
1145 idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1148 //OK we are now before our postion
1152 while (idxPos < len && idx < 100 ) {
1155 idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1158 //after our position
1159 if (idx > 0) idx --;
1161 //idx is now the index before our position
1162 //approximate between the 2 points
1163 ULONG idxTime=idx * vbr->fileSeconds/100;
1164 if (pafter == pbefore) return idxTime;
1165 ULONG rt=idxTime+ (len-pbefore)* vbr->fileSeconds/(100 * (pafter-pbefore)) ;
1166 if (rt > vbr -> fileSeconds) return vbr->fileSeconds;
1167 if (rt < idxTime) return idxTime;
1171 ULONG bps=getBytesPerSecond();
1172 if (bps == 0) return 0;
1177 ULONG DemuxerAudio::positionFromSeconds(ULONG seconds) {
1178 if (! hasHdrInfo) return 0;
1180 ULONG idx=seconds*100/vbr->fileSeconds;
1181 if (idx > 99) idx=99;
1182 ULONG idxPos=vbr->table[idx] * vbr->numBytes/256;
1184 if (idx < 99) idx2++;
1185 ULONG nextPos=vbr->table[idx] * vbr->numBytes/256;
1186 ULONG rt=idxPos+(nextPos-idxPos) * (seconds - idx * vbr->fileSeconds /256);
1187 if (rt < idxPos) return idxPos;
1188 if ( rt > vbr->numBytes) return vbr->numBytes;
1192 ULONG bps=getBytesPerSecond();
1197 int id3_tag::stringlen(bool withTitle) const {
1199 return strlen(artist)+strlen(genre)+strlen(year)+strlen(album)+
1200 strlen(track)+strlen(composer)+strlen(comment)+8+3+
1201 90; //30 chars for each name...
1203 return strlen(title)+strlen(artist)+strlen(genre)+strlen(year)+strlen(album)+
1204 strlen(track)+strlen(composer)+strlen(comment)+8+3+
1205 120; //30 chars for each name...
1207 //create a string out of the id3 tag info
1208 //delete this string afterwards if you did not provide the buffer
1209 char * id3_tag::toString(char *b, int len, bool withTitle) const {
1210 const char *ta=tr("Artist");
1211 //char *tg=tr("Genre");
1212 //char *ty=tr("Year");
1213 const char *tx=tr("Album");
1214 //char *to=tr("Composer");
1215 //char *tc=tr("Comment");
1216 const char *tn=tr("Track");
1224 len=stringlen(withTitle);
1227 const char * del=" - ";
1228 if (strlen(year) == 0) del="";
1230 const char *tt=tr("Title");
1231 SNPRINTF(b,len-1,"%s: %s\n%s: %s\n%s: %s%s%s\n%s: %s",
1232 tt,title,ta,artist,tx,year,del,album,tn,track);
1235 SNPRINTF(b,len-1,"%s: %s\n%s: %s%s%s\n%s: %s",
1236 ta,artist,tx,year,del,album,tn,track);
1242 void DemuxerAudio::setSkipFactor(int factor) {
1243 Log::getInstance()->log("DemuxerAudio",Log::DEBUG,"set skipfactor %d\n",factor);
1244 buffer->setSkipFactor(factor);