/* splay player plugin Copyright (C) 1999 Martin Vogt This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation. For more information look at the file COPYRIGHT in this package */ #include "splayPlugin.h" #include "../splay/mpegsound.h" #include "../splay/splayDecoder.h" #include "../frame/floatFrame.h" #include "../frame/pcmFrame.h" #include "../splay/mpegAudioFrame.h" #include "../splay/mpegAudioInfo.h" #include "../input/fileAccessWrapper.h" #include using namespace std; #define INPUTBUFFER_SIZE 8192 SplayPlugin::SplayPlugin() { pow(6.0,3.0); // fixes bug in __math.h doFloat = false; lnoLength=false; inputbuffer=new unsigned char[INPUTBUFFER_SIZE]; pcmFrame=new PCMFrame(MP3FRAMESIZE); floatFrame=new FloatFrame(MP3FRAMESIZE); audioFrame=new AudioFrame(); framer=new MpegAudioFrame(); splay=new SplayDecoder(); lengthInSec=0; fileAccess=NULL; info=NULL; lOutput=true; } SplayPlugin::~SplayPlugin() { delete [] inputbuffer; delete pcmFrame; delete floatFrame; delete framer; delete splay; delete audioFrame; } // here we can config our decoder with special flags void SplayPlugin::config(const char* key,const char* value,void* user_data) { if (strcmp(key,"dofloat")==0) { doFloat=true; } if (strcmp(key,"-m")==0) { splay->config("m","0",NULL); } if (strcmp(key,"-2")==0) { splay->config("2","1",NULL); } if (strcmp(key,"-c")==0) { lnoLength=true; } if (strcmp(key,"-d")==0) { lOutput=false; } if (strcmp(key,"decode")==0) { if (strcmp(value,"true")==0) { lDecode=true; } else { lDecode=false; } } DecoderPlugin::config(key,value,user_data); } void SplayPlugin::decoder_loop() { if (input == NULL) { cout << "SplayPlugin::decoder_loop input is NULL"<audioInit(); // start decoding fileAccess=new FileAccessWrapper(input); info= new MpegAudioInfo(fileAccess); framer->reset(); lengthInSec=0; resyncCounter=0; AudioFrame* audioFrame=pcmFrame; if (doFloat) { audioFrame=floatFrame; } output->audioInit(); while(runCheck()) { // // check for re-init or for "eof" // switch(streamState) { case _STREAM_STATE_INIT : framer->reset(); resyncCounter=5; setStreamState(_STREAM_STATE_PLAY); continue; case _STREAM_STATE_WAIT_FOR_END: // exit while loop lDecoderLoop=false; continue; } if (doFrameFind() == true) { if (splay->decode(framer->outdata(),framer->len(),audioFrame) == false){ continue; } // send data out: int rest=framer->restBytes(); // we have inserted more data already than the // framer has processed. But framer tells us // how much he still needs to process. long pos=input->getBytePosition(); TimeStamp* stamp=input->getTimeStamp(pos-rest); processStreamState(stamp,audioFrame); // make this stamp invalid for further synchronisation stamp->setPTSFlag(false); } } output->audioFlush(); delete fileAccess; delete info; fileAccess=NULL; info=NULL; } int SplayPlugin::doFrameFind() { // // fine, we can work on the stream: // int back=false; int framerState=framer->getState(); switch(framerState) { case FRAME_NEED: { int bytes=framer->canStore(); int read=input->read((char*)inputbuffer,bytes); if (read <= 0) { // read error. reset framer, drop frames setStreamState(_STREAM_STATE_INIT); break; } framer->store(inputbuffer,read); break; } case FRAME_WORK: back=framer->work(); break; case FRAME_HAS: { break; } default: cout << "unknown state in mpeg audio framing"<copyFormat(audioFrame); output->audioSetup(audioFrame->getFrequenceHZ(), audioFrame->getStereo(), audioFrame->getSigned(), audioFrame->getBigEndian(), audioFrame->getSampleSize()); } void SplayPlugin::processStreamState(TimeStamp* stamp,AudioFrame* playFrame){ // we always have a frame here, with the correct timestamp here. switch(streamState) { case _STREAM_STATE_FIRST_INIT : output->audioOpen(); audioSetup(playFrame); if (lnoLength==false) { lengthInSec=getTotalLength(); pluginInfo->setLength(lengthInSec); output->writeInfo(pluginInfo); } setStreamState(_STREAM_STATE_PLAY); // yes, here is no break. // we want to send the frame to the output. case _STREAM_STATE_PLAY : if (resyncCounter > 0) { resyncCounter--; break; } if (audioFrame->isFormatEqual(playFrame)==false) { audioSetup(playFrame); } if (lOutput == false) { break; } if(doFloat) { FloatFrame* floatFrame=(FloatFrame*)playFrame; output->audioPlay(stamp,stamp, (char*) floatFrame->getData(), playFrame->getLen()*sizeof(float) ); } else { PCMFrame* pcmFrame=(PCMFrame*)playFrame; output->audioPlay(stamp,stamp, (char*)pcmFrame->getData(), playFrame->getLen()*sizeof(short int)); } break; default: cout << "unknown stream state:"<getSeekPosition(second); input->seek(pos); setStreamState(_STREAM_STATE_INIT); } else { cout << "cannot seek, plugin not initialized"<getNeedInit()) { long pos=input->getBytePosition(); if (input->seek(0) == true) { int bytes=1024; // try reading all info, but not more // than 1024 iterations. info->reset(); while(bytes>0) { if (info->initialize()==true) { break; } bytes--; } input->seek(pos); } // wheter successful or not, never touch // the info thing again. info->setNeedInit(false); } back=info->getLength(); shutdownUnlock(); return back; }