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)
845 if (doSkip()) return 0;
846 //we are still full - so try to write
847 int sent=audio->put(store+bytesWritten,framelen-bytesWritten,streamtype);
848 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream (still full) pp=%d, framelen=%d, written=%d",sent,partPacket,framelen, bytesWritten );
849 if (sent < (framelen - bytesWritten)) {
850 //packet still not written
855 //let the demuxer come back with the rest - need to check header first
858 if (partPacket+len >= framelen) {
859 //now we have at least a complete packet
860 int bytesConsumed=framelen-partPacket;
861 memcpy(store+partPacket,wbuf,bytesConsumed);
863 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"stored packet %ld, length %d (last %d) for stream %p",numpackets,framelen,bytesConsumed,audio );
864 if (doSkip()) return bytesConsumed;
865 int sent=audio->put(store,framelen,streamtype);
867 //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream",sent );
868 if (bytesWritten < framelen) {
869 //still not completely written
870 return bytesConsumed;
873 //let the player come back...
874 return bytesConsumed;
876 //OK packet still not complete
877 if (len == 0) return 0;
878 int bytesConsumed=len;
879 memcpy(store+partPacket,wbuf,bytesConsumed);
880 partPacket+=bytesConsumed;
881 return bytesConsumed;
885 major entry for data from a player
886 the demuxer is either in the state headerSearch (packet written or
887 just at the beginning), writing garbage (inSync=false) or
888 handling data (none set)
889 A header is expected at the first byte after the previous packet -
890 otherwise we switch to garbage where we always search for a header
891 (but anyway provide the data to the underlying device - it's probably
892 more intelligent then we are...
893 We only loose a correct position display.
895 int DemuxerAudio::put(UCHAR* wbuf, int len)
897 //return audiostream.put(wbuf,len,streamtype);
898 int framelen=PACKET_SIZE;
902 if (tmpFill != 0 || (buffer->bufferEmpty() && len < HDRLEN)) {
903 //OK we have to copy everything to the tmp buffer
904 int cp=(UINT)len<(PACKET_SIZE-tmpFill)?(UINT)len:(PACKET_SIZE-tmpFill);
905 memcpy(&tmpBuffer[tmpFill],wbuf,cp);
910 //if there is no header here and our buffer
911 //is empty - just wait for the next header
912 if (len < HDRLEN && buffer->bufferEmpty()) {
913 log->log("DemuxerAudio",Log::DEBUG,"len to small for header %d at bytes %ld",len,globalBytesWritten);
917 while (bytesConsumed < len ) {
918 if (buffer->bufferFull()) {
919 //if this is the first part of the loop, try to write to the stream
920 if (bytesConsumed == 0) buffer->putInternal(wbuf,0);
921 //if the buffer is full, no need to continue
922 if (buffer->bufferFull()) break;
924 //either we are in a packet (buffer != full && buffer != empty)
925 //or we are searching a header
926 if (buffer->bufferEmpty()) {
927 if (len-bytesConsumed < HDRLEN) {
928 // we cannot still search
930 //we are already working at the buffer
933 memcpy(tmpBuffer,wbuf,len-bytesConsumed);
934 tmpFill=len-bytesConsumed;
935 log->log("DemuxerAudio",Log::DEBUG,"len to small for header %d at bytes %ld",len,globalBytesWritten);
939 int lastFramelen=hdrFramelen;
940 //if the header has been valid before and we are searching
942 int maxsearch=((len-bytesConsumed) < (int)PACKET_SIZE)?len-bytesConsumed:(int)PACKET_SIZE;
943 hdr=findHeader(wbuf,maxsearch);
945 //log->log("DemuxerAudio",Log::DEBUG,"header found at offset %d",hdr-wbuf);
947 //hdr now points to the new header
949 //still at least bytes before the header
952 int garbageBytes=(hdr!=NULL)?(hdr-wbuf):maxsearch;
953 //we consider the garbage now as an own packet
954 //we can consume at most our buffer
955 //basically the buffer should be empty here (we are
956 //in header search - and we fill up each garbage
958 int nframesize=garbageBytes;
959 if (nframesize > (int)PACKET_SIZE) {
960 nframesize=(int)PACKET_SIZE;
962 if (! buffer->bufferEmpty()) {
963 log->log("DemuxerAudio",Log::WARN,"buffer not empty when having garbage to store");
964 //at the end no big problem, we only write the remaining bytes that we have...
967 buffer->setFramelen(nframesize);
969 log->log("DemuxerAudio",Log::DEBUG,"garbage found at packet %ld (bytes %ld) of length %d, "
970 "framelen set to %d (last fl=%d)",
971 readHeaders,globalBytesWritten,garbageBytes,buffer->getFramelen(),lastFramelen);
972 //hmm - we assume that he low level driver is more intelligent
973 //and give him the data "as is"
974 int written=buffer->putInternal(wbuf,garbageBytes);
975 globalBytesWritten+=written;
976 bytesConsumed+=written;
977 if (written != garbageBytes || hdr == NULL ) {
980 //OK either all the "garbage" is written or
981 //we found the next header as expected
982 //continue with the next package
985 //we have to wait now until the buffer is
986 //free for the next package
987 if ( ! buffer->bufferEmpty()) return bytesConsumed;
988 //this is the place where we start a new packet
989 framelen=hdrFramelen;
990 if ( !buffer->setFramelen(framelen) ) {
991 log->log("DemuxerAudio",Log::DEBUG,"unable to set framelen should=%d, current=%d",
992 framelen,buffer->getFramelen());
996 //now we are surely within a packet
997 int written=buffer->putInternal(wbuf,len-bytesConsumed);
999 globalBytesWritten+=written;
1001 bytesConsumed+=written;
1006 //OK - handle the rest
1008 if (bytesConsumed >= oldBytes) {
1009 //if we consumed more than the old bytes - OK the buffer
1010 //can be thrown away
1012 return bytesConsumed-oldBytes;
1015 //only consumed bytes from the buffer
1016 if (bytesConsumed == 0) {
1017 //restore the buffer
1021 //shift bytes in buffer
1022 for (int i=0;i<oldBytes-bytesConsumed;i++) {
1023 tmpBuffer[i]=tmpBuffer[i+bytesConsumed];
1025 tmpFill=oldBytes-bytesConsumed;
1031 const id3_tag * DemuxerAudio::getId3Tag() {
1035 const DemuxerAudio::mpegInfo * DemuxerAudio::getMpegInfo() {
1036 if (! hasHdrInfo) return NULL;
1037 info->avrBitrate=avrBitrate;
1038 info->bitRate=hdrBitrate;
1042 const DemuxerAudio::vbrInfo * DemuxerAudio::getVBRINfo() {
1046 int DemuxerAudio::checkStart(UCHAR *b, int len) {
1048 int id3len=parseID3V2(b,len);
1050 char * str=id3->toString();
1051 log->log("DemuxerAudio",Log::DEBUG,"parseID3V2 %d bytes of %d",id3len,len);
1052 log->log("DemuxerAudio",Log::DEBUG,"parseID3V2 found:%s",str);
1057 int vbrlen=parseVBR(b,len);
1063 UCHAR * hdr=findHeader(b,len,true);
1064 if (hdr == NULL) return -1;
1068 int DemuxerAudio::checkID3(UCHAR *b, int len) {
1069 if (len != 128) return -1;
1070 int rt=parseID3V1(b,len);
1072 char * str=id3->toString();
1073 log->log("DemuxerAudio",Log::DEBUG,"parseID3V1 found:%s",str);
1079 bool DemuxerAudio::isSync() {
1083 UINT DemuxerAudio::getSyncErrors() {
1087 ULONG DemuxerAudio::getBytesPerSecond()
1089 ULONG bps=hdrBitrate;
1090 if (! hasHdrInfo) return 0;
1091 if (hdrBitrate != avrBitrate) {
1092 //we seem to have vbr
1106 ULONG DemuxerAudio::getSecondsFromLen(ULONG len) {
1107 if (! hasHdrInfo) return 0;
1109 //first find the index where we are between
1110 //rough starting point:
1111 ULONG idx=100*len/vbr->numBytes;
1112 if (idx >= 100) idx=99;
1113 ULONG idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1114 ULONG pbefore=idxPos;
1115 ULONG pafter=idxPos;
1116 //OK now we know whether we have to go up or down
1119 while (idxPos > len && idx > 0) {
1122 idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1125 //OK we are now before our postion
1129 while (idxPos < len && idx < 100 ) {
1132 idxPos=(vbr->table[idx]) * vbr->numBytes/256;
1135 //after our position
1136 if (idx > 0) idx --;
1138 //idx is now the index before our position
1139 //approximate between the 2 points
1140 ULONG idxTime=idx * vbr->fileSeconds/100;
1141 if (pafter == pbefore) return idxTime;
1142 ULONG rt=idxTime+ (len-pbefore)* vbr->fileSeconds/(100 * (pafter-pbefore)) ;
1143 if (rt > vbr -> fileSeconds) return vbr->fileSeconds;
1144 if (rt < idxTime) return idxTime;
1148 ULONG bps=getBytesPerSecond();
1149 if (bps == 0) return 0;
1154 ULONG DemuxerAudio::positionFromSeconds(ULONG seconds) {
1155 if (! hasHdrInfo) return 0;
1157 ULONG idx=seconds*100/vbr->fileSeconds;
1158 if (idx > 99) idx=99;
1159 ULONG idxPos=vbr->table[idx] * vbr->numBytes/256;
1161 if (idx < 99) idx2++;
1162 ULONG nextPos=vbr->table[idx] * vbr->numBytes/256;
1163 ULONG rt=idxPos+(nextPos-idxPos) * (seconds - idx * vbr->fileSeconds /256);
1164 if (rt < idxPos) return idxPos;
1165 if ( rt > vbr->numBytes) return vbr->numBytes;
1169 ULONG bps=getBytesPerSecond();
1174 int id3_tag::stringlen(bool withTitle) const {
1176 return strlen(artist)+strlen(genre)+strlen(year)+strlen(album)+
1177 strlen(track)+strlen(composer)+strlen(comment)+8+3+
1178 90; //30 chars for each name...
1180 return strlen(title)+strlen(artist)+strlen(genre)+strlen(year)+strlen(album)+
1181 strlen(track)+strlen(composer)+strlen(comment)+8+3+
1182 120; //30 chars for each name...
1184 //create a string out of the id3 tag info
1185 //delete this string afterwards if you did not provide the buffer
1186 char * id3_tag::toString(char *b, int len, bool withTitle) const {
1187 char *ta=tr("Artist");
1188 //char *tg=tr("Genre");
1189 //char *ty=tr("Year");
1190 char *tx=tr("Album");
1191 //char *to=tr("Composer");
1192 //char *tc=tr("Comment");
1193 char *tn=tr("Track");
1201 len=stringlen(withTitle);
1204 const char * del=" - ";
1205 if (strlen(year) == 0) del="";
1207 char *tt=tr("Title");
1208 snprintf(b,len-1,"%s: %s\n%s: %s\n%s: %s%s%s\n%s: %s",
1209 tt,title,ta,artist,tx,year,del,album,tn,track);
1212 snprintf(b,len-1,"%s: %s\n%s: %s%s%s\n%s: %s",
1213 ta,artist,tx,year,del,album,tn,track);
1219 void DemuxerAudio::setSkipFactor(int factor) {
1220 Log::getInstance()->log("DemuxerAudio",Log::DEBUG,"set skipfactor %d\n",factor);
1221 buffer->setSkipFactor(factor);