summaryrefslogtreecommitdiffstats
path: root/mpeglib/lib/decoder/splayPlugin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mpeglib/lib/decoder/splayPlugin.cpp')
-rw-r--r--mpeglib/lib/decoder/splayPlugin.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/mpeglib/lib/decoder/splayPlugin.cpp b/mpeglib/lib/decoder/splayPlugin.cpp
new file mode 100644
index 00000000..d0caa077
--- /dev/null
+++ b/mpeglib/lib/decoder/splayPlugin.cpp
@@ -0,0 +1,308 @@
+/*
+ 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 <iostream>
+
+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();
+ lenghtInSec=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"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "SplayPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+ // init decoder
+ output->audioInit();
+
+ // start decoding
+
+ fileAccess=new FileAccessWrapper(input);
+ info= new MpegAudioInfo(fileAccess);
+
+
+
+ framer->reset();
+ lenghtInSec=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"<<endl;
+ exit(0);
+ }
+ return back;
+}
+
+void SplayPlugin::audioSetup(AudioFrame* setupFrame) {
+ setupFrame->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) {
+ lenghtInSec=getTotalLength();
+ pluginInfo->setLength(lenghtInSec);
+ 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:"<<streamState<<endl;
+ }
+}
+
+
+
+// splay can seek in streams
+int SplayPlugin::seek_impl(int second) {
+
+
+ if (info != NULL) {
+ int pos=info->getSeekPosition(second);
+ input->seek(pos);
+ setStreamState(_STREAM_STATE_INIT);
+ } else {
+ cout << "cannot seek, plugin not initialized"<<endl;
+ }
+ return true;
+}
+
+
+int SplayPlugin::getTotalLength() {
+ shutdownLock();
+ int back=0;
+
+ if (info->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;
+}
+
+
+
+
+