summaryrefslogtreecommitdiffstats
path: root/mpeglib/lib/decoder
diff options
context:
space:
mode:
Diffstat (limited to 'mpeglib/lib/decoder')
-rw-r--r--mpeglib/lib/decoder/Makefile.am39
-rw-r--r--mpeglib/lib/decoder/cddaPlugin.cpp150
-rw-r--r--mpeglib/lib/decoder/cddaPlugin.h49
-rw-r--r--mpeglib/lib/decoder/command.cpp85
-rw-r--r--mpeglib/lib/decoder/command.h52
-rw-r--r--mpeglib/lib/decoder/commandPipe.cpp163
-rw-r--r--mpeglib/lib/decoder/commandPipe.h78
-rw-r--r--mpeglib/lib/decoder/decoderPlugin.cpp428
-rw-r--r--mpeglib/lib/decoder/decoderPlugin.h201
-rw-r--r--mpeglib/lib/decoder/mpegPlugin.cpp160
-rw-r--r--mpeglib/lib/decoder/mpegPlugin.h47
-rw-r--r--mpeglib/lib/decoder/mpgPlugin.cpp260
-rw-r--r--mpeglib/lib/decoder/mpgPlugin.h62
-rw-r--r--mpeglib/lib/decoder/nukePlugin.cpp62
-rw-r--r--mpeglib/lib/decoder/nukePlugin.h34
-rw-r--r--mpeglib/lib/decoder/splayPlugin.cpp308
-rw-r--r--mpeglib/lib/decoder/splayPlugin.h67
-rw-r--r--mpeglib/lib/decoder/tplayPlugin.cpp264
-rw-r--r--mpeglib/lib/decoder/tplayPlugin.h47
-rw-r--r--mpeglib/lib/decoder/vorbisPlugin.cpp305
-rw-r--r--mpeglib/lib/decoder/vorbisPlugin.h87
21 files changed, 2948 insertions, 0 deletions
diff --git a/mpeglib/lib/decoder/Makefile.am b/mpeglib/lib/decoder/Makefile.am
new file mode 100644
index 00000000..9362e851
--- /dev/null
+++ b/mpeglib/lib/decoder/Makefile.am
@@ -0,0 +1,39 @@
+# libplayerplugin - Makefile.am
+
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libdecoder.la
+
+kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/decoder
+
+kmpginclude_HEADERS = decoderPlugin.h command.h \
+ commandPipe.h nukePlugin.h \
+ vorbisPlugin.h cddaPlugin.h \
+ splayPlugin.h mpegPlugin.h \
+ mpgPlugin.h tplayPlugin.h
+
+libdecoder_la_SOURCES = decoderPlugin.cpp command.cpp \
+ commandPipe.cpp nukePlugin.cpp \
+ vorbisPlugin.cpp cddaPlugin.cpp \
+ splayPlugin.cpp mpegPlugin.cpp \
+ mpgPlugin.cpp tplayPlugin.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mpeglib/lib/decoder/cddaPlugin.cpp b/mpeglib/lib/decoder/cddaPlugin.cpp
new file mode 100644
index 00000000..fe84986b
--- /dev/null
+++ b/mpeglib/lib/decoder/cddaPlugin.cpp
@@ -0,0 +1,150 @@
+/*
+ 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 "cddaPlugin.h"
+
+#ifdef CDDA_PARANOIA
+
+#include <sys/types.h>
+
+#include <iostream>
+
+using namespace std;
+
+typedef int16_t size16;
+typedef int32_t size32;
+
+extern "C" {
+#include <cdda_interface.h>
+#include <cdda_paranoia.h>
+}
+
+
+CDDAPlugin::CDDAPlugin() {
+}
+
+
+CDDAPlugin::~CDDAPlugin() {
+}
+
+
+// here we can config our decoder with special flags
+void CDDAPlugin::config(const char* key,const char* value,void* user_data) {
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+
+void CDDAPlugin::decoder_loop() {
+
+ if (input == NULL) {
+ cout << "CDDAPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "CDDAPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+ // init decoder
+ output->audioInit();
+ TimeStamp* stamp;
+ char buf[CD_FRAMESIZE_RAW*4];
+ int len=0;
+ // start decoding
+ while(runCheck()) {
+
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ output->audioSetup(44100,1,0,0,16);
+ output->audioOpen();
+ setStreamState(_STREAM_STATE_PLAY);
+ len=getTotalLength();
+ pluginInfo->setLength(len);
+ output->writeInfo(pluginInfo);
+ break;
+ case _STREAM_STATE_INIT :
+ setStreamState(_STREAM_STATE_PLAY);
+ break;
+ case _STREAM_STATE_PLAY : {
+ // decode
+ int read=input->read(buf,2*CD_FRAMESIZE_RAW);
+ int pos=input->getBytePosition();
+ stamp=input->getTimeStamp(pos);
+ output->audioPlay(stamp,stamp,buf,read);
+ break;
+ }
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+ // remove decoder
+
+ output->audioFlush();
+}
+
+// splay can seek in streams
+int CDDAPlugin::seek_impl(int second) {
+ int bytes_per_second;
+ int seconds;
+ int back;
+ float frequence=44100;
+ int bits=16;
+ int channels=2;
+
+ bytes_per_second = (int)(frequence * channels * (bits / 8));
+
+
+
+ seconds = bytes_per_second * second;
+ cout << "seek to :"<<seconds<<endl;
+ back=input->seek(seconds);
+
+ return true;
+}
+
+
+int CDDAPlugin::getTotalLength() {
+ shutdownLock();
+ float wavfilesize;
+ int back=0;
+ float frequence=44100;
+ if (input == NULL) {
+ shutdownUnlock();
+ return 0;
+ }
+ wavfilesize = input->getByteLength();
+ int bits=16;
+ int channels=2;
+ if (bits == 16) {
+ wavfilesize=wavfilesize/2;
+ }
+ if (channels==2) {
+ wavfilesize=wavfilesize/2;
+ }
+ if (frequence != 0) {
+ back=(int)(wavfilesize/frequence);
+ }
+ shutdownUnlock();
+ return back;
+}
+
+
+
+
+#endif
+//CDDA_PARANOIA
+
diff --git a/mpeglib/lib/decoder/cddaPlugin.h b/mpeglib/lib/decoder/cddaPlugin.h
new file mode 100644
index 00000000..c0adf5e2
--- /dev/null
+++ b/mpeglib/lib/decoder/cddaPlugin.h
@@ -0,0 +1,49 @@
+/*
+ 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
+
+ */
+
+
+#ifndef __CDDAPLUGIN_H
+#define __CDDAPLUGIN_H
+
+#include "nukePlugin.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef CDDA_PARANOIA
+class CDDAPlugin : public NukePlugin {
+};
+#else
+
+
+
+class CDDAPlugin : public DecoderPlugin {
+
+ public:
+ CDDAPlugin();
+ ~CDDAPlugin();
+
+ void decoder_loop();
+ int seek_impl(int second);
+ void config(const char* key,const char* value,void* user_data);
+
+ protected:
+ int getTotalLength();
+
+
+};
+
+#endif
+//CDDA_PARANOIA
+
+#endif
diff --git a/mpeglib/lib/decoder/command.cpp b/mpeglib/lib/decoder/command.cpp
new file mode 100644
index 00000000..8b29efe6
--- /dev/null
+++ b/mpeglib/lib/decoder/command.cpp
@@ -0,0 +1,85 @@
+/*
+ describes a command
+ Copyright (C) 2000 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 "command.h"
+
+#include <iostream>
+
+using namespace std;
+
+Command::Command(int id) {
+ this->id=id;
+ this->intArg=0;
+}
+
+Command::Command(int id,int arg) {
+ this->id=id;
+ this->intArg=arg;
+}
+
+
+Command::~Command() {
+}
+
+
+int Command::getID() {
+ return id;
+}
+
+
+int Command::getIntArg() {
+ return intArg;
+}
+
+
+void Command::copyTo(Command* dest) {
+ dest->id=this->id;
+ dest->intArg=this->intArg;
+}
+
+void Command::print(const char* text) {
+ cout << "COMMAND:"<<text<<endl;
+ switch(id) {
+ case _COMMAND_NONE:
+ cout << "_COMMAND_NONE";
+ break;
+ case _COMMAND_PING:
+ cout << "_COMMAND_PING";
+ break;
+ case _COMMAND_PAUSE:
+ cout << "_COMMAND_PAUSE";
+ break;
+ case _COMMAND_PLAY:
+ cout << "_COMMAND_PLAY";
+ break;
+ case _COMMAND_SEEK:
+ cout << "_COMMAND_SEEK";
+ cout << " intArg:"<<intArg;
+ break;
+ case _COMMAND_CLOSE:
+ cout << "_COMMAND_CLOSE";
+ break;
+ case _COMMAND_START:
+ cout << "_COMMAND_START";
+ break;
+ case _COMMAND_RESYNC_START:
+ cout << "_COMMAND_RESYNC_START";
+ break;
+ case _COMMAND_RESYNC_END:
+ cout << "_COMMAND_RESYNC_END";
+ break;
+
+ default:
+ cout << "unknown command id in Command::print"<<endl;
+ }
+ cout << endl;
+}
diff --git a/mpeglib/lib/decoder/command.h b/mpeglib/lib/decoder/command.h
new file mode 100644
index 00000000..fc96fd73
--- /dev/null
+++ b/mpeglib/lib/decoder/command.h
@@ -0,0 +1,52 @@
+/*
+ describes a command
+ Copyright (C) 2000 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
+
+ */
+
+
+
+
+#ifndef __COMMAND_H
+#define __COMMAND_H
+
+#include "../util/abstract/abs_thread.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define _COMMAND_NONE 0
+#define _COMMAND_PLAY 1
+#define _COMMAND_PAUSE 2
+#define _COMMAND_SEEK 3
+#define _COMMAND_CLOSE 4
+#define _COMMAND_START 5
+#define _COMMAND_RESYNC_START 6
+#define _COMMAND_RESYNC_END 7
+#define _COMMAND_PING 8
+
+
+
+class Command {
+
+ int id;
+ int intArg;
+
+ public:
+ Command(int id);
+ Command(int id,int arg);
+ ~Command();
+
+ int getID();
+ int getIntArg();
+ void copyTo(Command* dest);
+ void print(const char* text);
+};
+
+#endif
diff --git a/mpeglib/lib/decoder/commandPipe.cpp b/mpeglib/lib/decoder/commandPipe.cpp
new file mode 100644
index 00000000..05991ca5
--- /dev/null
+++ b/mpeglib/lib/decoder/commandPipe.cpp
@@ -0,0 +1,163 @@
+/*
+ thread safe fifo queue for commands
+ Copyright (C) 2000 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 "commandPipe.h"
+
+#define _COMMAND_ARRAY_SIZE 100
+
+CommandPipe::CommandPipe() {
+ abs_thread_cond_init(&spaceCond);
+ abs_thread_cond_init(&emptyCond);
+ abs_thread_cond_init(&dataCond);
+ abs_thread_mutex_init(&pipeMut);
+
+ entries=0;
+ readPos=0;
+ writePos=0;
+
+
+ int i;
+
+ commandArray=new Command*[_COMMAND_ARRAY_SIZE];
+
+
+ for(i=0;i<_COMMAND_ARRAY_SIZE;i++) {
+ commandArray[i]=new Command(_COMMAND_NONE,0);
+ }
+}
+
+
+CommandPipe::~CommandPipe() {
+ abs_thread_cond_destroy(&spaceCond);
+ abs_thread_cond_destroy(&emptyCond);
+ abs_thread_cond_destroy(&dataCond);
+ abs_thread_mutex_destroy(&pipeMut);
+
+
+ int i;
+
+ for(i=0;i<_COMMAND_ARRAY_SIZE;i++) {
+ delete commandArray[i];
+ }
+ delete [] commandArray;
+}
+
+void CommandPipe::sendCommand(Command& cmd) {
+ sendCommand(cmd,true);
+}
+
+void CommandPipe::sendCommandNoWait(Command& cmd) {
+ sendCommand(cmd,false);
+}
+
+
+void CommandPipe::sendCommand(Command& cmd,int lWait) {
+ lockCommandPipe();
+ if (entries==_COMMAND_ARRAY_SIZE) {
+ waitForSpace();
+ }
+ cmd.copyTo(commandArray[writePos]);
+ writePos++;
+ if (writePos==_COMMAND_ARRAY_SIZE) {
+ writePos=0;
+ }
+ entries++;
+ // low water signal
+ if (entries==1) {
+ signalData();
+ }
+ unlockCommandPipe();
+ if (lWait) {
+ waitForEmptyQueue();
+ }
+}
+
+
+int CommandPipe::hasCommand(Command* dest) {
+ lockCommandPipe();
+ if (entries==0) {
+ unlockCommandPipe();
+ return false;
+ }
+
+ commandArray[readPos]->copyTo(dest);
+ readPos++;
+ if (readPos==_COMMAND_ARRAY_SIZE) {
+ readPos=0;
+ }
+ entries--;
+ // low water
+ if (entries==0) {
+ signalEmpty();
+ unlockCommandPipe();
+ return true;
+ }
+ // if we are on highwater, signal space
+ if (entries==_COMMAND_ARRAY_SIZE-1) {
+ signalSpace();
+ }
+ unlockCommandPipe();
+ return true;
+}
+
+
+void CommandPipe::waitForEmptyQueue() {
+ lockCommandPipe();
+ while (entries > 0) {
+ waitForEmpty();
+ }
+ unlockCommandPipe();
+}
+
+void CommandPipe::waitForCommand() {
+ lockCommandPipe();
+ while (entries == 0) {
+ waitForData();
+ }
+ unlockCommandPipe();
+}
+
+
+void CommandPipe::lockCommandPipe() {
+ abs_thread_mutex_lock(&pipeMut);
+}
+
+
+void CommandPipe::unlockCommandPipe() {
+ abs_thread_mutex_unlock(&pipeMut);
+}
+
+void CommandPipe::waitForSpace() {
+ abs_thread_cond_wait(&spaceCond,&pipeMut);
+}
+
+void CommandPipe::waitForEmpty() {
+ abs_thread_cond_wait(&emptyCond,&pipeMut);
+}
+
+void CommandPipe::waitForData() {
+ abs_thread_cond_wait(&dataCond,&pipeMut);
+}
+
+
+void CommandPipe::signalSpace() {
+ abs_thread_cond_signal(&spaceCond);
+}
+
+void CommandPipe::signalEmpty() {
+ abs_thread_cond_signal(&emptyCond);
+}
+
+void CommandPipe::signalData() {
+ abs_thread_cond_signal(&dataCond);
+}
diff --git a/mpeglib/lib/decoder/commandPipe.h b/mpeglib/lib/decoder/commandPipe.h
new file mode 100644
index 00000000..4ecf84eb
--- /dev/null
+++ b/mpeglib/lib/decoder/commandPipe.h
@@ -0,0 +1,78 @@
+/*
+ thread safe fifo queue for commands
+ Copyright (C) 2000 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
+
+ */
+
+
+#ifndef __COMMAND_PIPE_H
+#define __COMMAND_PIPE_H
+
+
+
+#include "command.h"
+
+/**
+ This queue deals with the ugly deadlock problem.
+ We insert all commands in a queue and the thread
+ polls this queue for next commands.
+*/
+
+class CommandPipe {
+
+ Command** commandArray;
+ int entries;
+ int readPos;
+ int writePos;
+
+ abs_thread_mutex_t pipeMut;
+ abs_thread_cond_t spaceCond;
+ abs_thread_cond_t emptyCond;
+ abs_thread_cond_t dataCond;
+
+ public:
+ CommandPipe();
+ ~CommandPipe();
+
+ // writer thread:
+ void sendCommand(Command& cmd);
+ void sendCommandNoWait(Command& cmd);
+
+ void waitForEmptyQueue();
+
+ // reader thread
+ int hasCommand(Command* dest);
+ void waitForCommand();
+
+
+
+
+ private:
+ void sendCommand(Command& cmd,int lWait);
+
+ void lockCommandPipe();
+ void unlockCommandPipe();
+
+
+ // writer thread wait here
+ void waitForSpace();
+ void waitForEmpty();
+ void waitForData();
+
+ // reader thread signals this
+ void signalSpace();
+ void signalEmpty();
+ void signalData();
+
+
+
+
+};
+
+#endif
diff --git a/mpeglib/lib/decoder/decoderPlugin.cpp b/mpeglib/lib/decoder/decoderPlugin.cpp
new file mode 100644
index 00000000..0a45bb42
--- /dev/null
+++ b/mpeglib/lib/decoder/decoderPlugin.cpp
@@ -0,0 +1,428 @@
+/*
+ base class for the 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 "decoderPlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+static void *playerThread(void *arg){
+ ((DecoderPlugin*)arg)->idleThread();
+ return NULL;
+}
+
+static int instanceCnt=0;
+
+DecoderPlugin::DecoderPlugin(){
+ input=NULL;
+ output=NULL;
+ commandPipe=new CommandPipe();
+ threadCommand=new Command(_COMMAND_NONE);
+ abs_thread_cond_init(&streamStateCond);
+ abs_thread_mutex_init(&streamStateMut);
+ abs_thread_mutex_init(&shutdownMut);
+
+ lCreatorLoop=true;
+ lDecoderLoop=false;
+ linDecoderLoop=false;
+ streamState=_STREAM_STATE_EOF;
+ lDecode=false;
+ lhasLength=false;
+ // this default is necessary. if you have a blocking
+ // device and we start automatic the thread
+ // may block on it and all commands (including play)
+ // blocks everything
+ // *you should not use autoplay*
+ lAutoPlay=false;
+
+ pluginInfo=new PluginInfo();
+ runCheck_Counter=0;
+ decode_loopCounter=0;
+ instance=instanceCnt;
+ instanceCnt++;
+ abs_thread_create(&tr,playerThread,this);
+
+ // we send a ping. because this signal is synchron
+ // we block until the thread is started and
+ // has read the ping singnal
+ Command cmd(_COMMAND_PING);
+ insertSyncCommand(&cmd);
+
+
+}
+
+
+DecoderPlugin::~DecoderPlugin(){
+ void* ret;
+ lCreatorLoop=false;
+ Command cmd(_COMMAND_CLOSE);
+ insertAsyncCommand(&cmd);
+
+ abs_thread_join(tr,&ret);
+
+ abs_thread_cond_destroy(&streamStateCond);
+ abs_thread_mutex_destroy(&streamStateMut);
+ abs_thread_mutex_destroy(&shutdownMut);
+
+ delete commandPipe;
+ delete threadCommand;
+ delete pluginInfo;
+}
+
+
+void DecoderPlugin::close(){
+ // from here we can only walk to init or eof
+ // in both cases we sometimes catch out decoderMut :-)
+ Command cmd(_COMMAND_CLOSE);
+ insertAsyncCommand(&cmd);
+ shutdownLock();
+ if (input != NULL) {
+ input->close();
+ }
+ shutdownUnlock();
+ insertSyncCommand(&cmd);
+ waitForStreamState(_STREAM_STATE_EOF);
+ input=NULL;
+}
+
+
+void DecoderPlugin::pause() {
+ Command cmd(_COMMAND_PAUSE);
+ insertSyncCommand(&cmd);
+}
+
+
+
+
+int DecoderPlugin::play() {
+ Command cmd(_COMMAND_PLAY);
+ insertSyncCommand(&cmd);
+
+ return true;
+}
+
+int DecoderPlugin::seek(int second) {
+ Command cmd(_COMMAND_SEEK,second);
+ insertSyncCommand(&cmd);
+
+ return true;
+}
+
+void DecoderPlugin::insertAsyncCommand(Command* cmd) {
+ commandPipe->sendCommandNoWait(*cmd);
+}
+
+void DecoderPlugin::insertSyncCommand(Command* cmd) {
+ commandPipe->sendCommand(*cmd);
+}
+
+
+void DecoderPlugin::shutdownLock() {
+ abs_thread_mutex_lock(&shutdownMut);
+}
+
+
+void DecoderPlugin::shutdownUnlock() {
+ abs_thread_mutex_unlock(&shutdownMut);
+}
+
+int DecoderPlugin::getTime(int lCurrent) {
+ int secLen=getTotalLength();
+
+ if (lCurrent==false) {
+ return secLen;
+ }
+ shutdownLock();
+ int byteLen=1;
+ int pos=1;
+ if (input != NULL) {
+ pos=input->getBytePosition()+1;
+ byteLen=input->getByteLength()+1;
+ }
+ int back=(int)(((double)pos/(double)byteLen) * (double)secLen);
+ shutdownUnlock();
+ return back;
+
+}
+
+int DecoderPlugin::getTotalLength() {
+ cout << "plugin does not support total playtime reporting"<<endl;
+ return 0;
+}
+
+int DecoderPlugin::seek_impl(int) {
+ cout << "plugin does not support seek"<<endl;
+ return false;
+}
+
+
+
+
+void DecoderPlugin::setOutputPlugin(OutputStream* output) {
+ this->output=output;
+}
+
+
+int DecoderPlugin::setInputPlugin(InputStream* input) {
+ this->input=input;
+
+ if (!input) {
+ cout << "input is NULL"<<endl;
+ exit(0);
+ }
+ pluginInfo->setUrl(input->getUrl());
+
+
+ // the command is synchron we block until the
+ // thread has read it
+ Command cmd(_COMMAND_START);
+ insertSyncCommand(&cmd);
+
+
+ // now that we know he has read it, we send another
+ // command, this is only read if the thread is in the
+ // decode_loop, and we then know that the streamState
+ // is FIRST_INIT
+ Command ping(_COMMAND_PING);
+ insertSyncCommand(&ping);
+
+
+ if (lAutoPlay) {
+ play();
+ }
+ return true;
+}
+
+
+void DecoderPlugin::config(const char* key,const char* value,void* ){
+ if (strcmp(key,"-y")==0) {
+ if (strcmp(value,"on")==0) {
+ lAutoPlay=true;
+ } else {
+ lAutoPlay=false;
+ }
+ }
+
+}
+
+/**
+ during shutdown the streamState is undefined until
+ the thread has left the decode_loop().
+ Make sure we wait for this.
+*/
+int DecoderPlugin::getStreamState() {
+ shutdownLock();
+ int back=streamState;
+ shutdownUnlock();
+ return back;
+}
+
+
+int DecoderPlugin::waitForStreamState(int state) {
+ int back;
+ abs_thread_mutex_lock(&streamStateMut);
+ while ((streamState & state) == false) {
+ abs_thread_cond_wait(&streamStateCond,&streamStateMut);
+ }
+ back=streamState;
+ abs_thread_mutex_unlock(&streamStateMut);
+ return back;
+}
+
+
+void DecoderPlugin::setStreamState(int streamState) {
+ abs_thread_mutex_lock(&streamStateMut);
+ this->streamState=streamState;
+ abs_thread_cond_signal(&streamStateCond);
+ abs_thread_mutex_unlock(&streamStateMut);
+}
+
+
+void DecoderPlugin::decoder_loop() {
+ cout << "direct call decoder loop->plugin not found ???"<<endl;
+ TimeWrapper::usleep(100000);
+}
+
+
+void* DecoderPlugin::idleThread() {
+
+ while(lCreatorLoop) {
+ linDecoderLoop=true;
+ commandPipe->waitForCommand();
+ commandPipe->hasCommand(threadCommand);
+ int id=threadCommand->getID();
+ switch(id) {
+ case _COMMAND_START:
+ lDecoderLoop=true;
+ break;
+ case _COMMAND_PING:
+ break;
+ /*
+ default:
+ threadCommand->print("ignoring non START command in idleThread");
+ */
+ }
+
+
+ if (lDecoderLoop) {
+ setStreamState(_STREAM_STATE_FIRST_INIT);
+ linDecoderLoop=false;
+ decode_loopCounter++;
+ runCheck_Counter=0;
+ shutdownLock();
+ decoder_loop();
+ lDecode=false;
+ lDecoderLoop=false;
+ lhasLength=false;
+ setStreamState(_STREAM_STATE_EOF);
+ shutdownUnlock();
+ }
+ }
+ return NULL;
+}
+
+
+PluginInfo* DecoderPlugin::getPluginInfo() {
+ return pluginInfo;
+}
+
+
+int DecoderPlugin::runCheck() {
+ if (runCheck_Counter==0) {
+ shutdownUnlock();
+ }
+ runCheck_Counter++;
+ while (lDecoderLoop && lCreatorLoop) {
+
+ // if we have an eof this always leads to
+ // a shutdown of the decode_loop thread
+ // it has more priority than the resyn request
+ if (input->eof()) {
+ setStreamState(_STREAM_STATE_WAIT_FOR_END);
+ }
+ //
+ // if we are in _STREAM_STATE_RESYNC_COMMIT
+ // we only leave it if command is _COMMAND_RESYNC_END
+ // (or close)
+
+ //
+ // check user commands
+ //
+ if (lDecode==false) {
+ commandPipe->waitForCommand();
+ commandPipe->hasCommand(threadCommand);
+ } else {
+ if (commandPipe->hasCommand(threadCommand)==false) {
+ // no commands and lDecode=true
+ return true;
+ }
+ }
+
+ // here we forward the command to a special
+ // method who can handle everything
+ // (the default method should work fine);
+ int nextCheck= processThreadCommand(threadCommand);
+ switch(nextCheck) {
+ case _RUN_CHECK_CONTINUE:
+ break;
+ case _RUN_CHECK_FALSE:
+ shutdownLock();
+ return false;
+ case _RUN_CHECK_TRUE:
+ return true;
+ default:
+ cout << "unknown runCheck return command"<<endl;
+ exit(0);
+ }
+
+
+ }
+
+ shutdownLock();
+ return false;
+}
+
+int DecoderPlugin::processThreadCommand(Command* command) {
+
+
+ int id=command->getID();
+ int intArg;
+
+ //
+ // if we are in _STREAM_STATE_RESYNC_COMMIT
+ // we only leave it if command is _COMMAND_RESYNC_END
+ //
+ if (streamState==_STREAM_STATE_RESYNC_COMMIT) {
+ switch(id) {
+ case _COMMAND_RESYNC_END:
+ setStreamState(_STREAM_STATE_INIT);
+ input->clear();
+ break;
+ case _COMMAND_CLOSE:
+ //
+ // we return false so that the plugin clears
+ // all its allocated classes
+ // its a _must_ !!
+ // in the next call we exit immediately
+ return _RUN_CHECK_FALSE;
+
+ /*
+ default:
+ command->print("ignore command in _STREAM_STATE_RESYNC_COMMIT");
+ */
+ }
+ return _RUN_CHECK_CONTINUE;
+ }
+
+
+ switch(id) {
+ case _COMMAND_NONE:
+ break;
+ case _COMMAND_PING:
+ break;
+ case _COMMAND_PAUSE:
+ lDecode=false;
+ break;
+ case _COMMAND_PLAY:
+ lDecode=true;
+ break;
+ case _COMMAND_SEEK: {
+ if (streamState==_STREAM_STATE_FIRST_INIT) {
+ command->print("ignore command seek in _STREAM_STATE_FIRST_INIT");
+ } else {
+ intArg=command->getIntArg();
+ seek_impl(intArg);
+ }
+ break;
+ }
+ case _COMMAND_CLOSE:
+ //
+ // we return false so that the plugin clears
+ // all its allocated classes
+ // its a _must_ !!
+ // in the next call we exit immediately
+ return _RUN_CHECK_FALSE;
+ case _COMMAND_RESYNC_START:
+ setStreamState(_STREAM_STATE_RESYNC_COMMIT);
+ input->clear();
+ break;
+ /*
+ default:
+ cout << "unknown command id in Command::print"<<endl;
+ */
+ }
+ return _RUN_CHECK_CONTINUE;
+}
+
+
diff --git a/mpeglib/lib/decoder/decoderPlugin.h b/mpeglib/lib/decoder/decoderPlugin.h
new file mode 100644
index 00000000..b616ed51
--- /dev/null
+++ b/mpeglib/lib/decoder/decoderPlugin.h
@@ -0,0 +1,201 @@
+/*
+ base class for the 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
+
+ */
+
+
+
+
+
+#ifndef __DECODERPLUGIN_H
+#define __DECODERPLUGIN_H
+
+
+
+
+
+#include "commandPipe.h"
+#include "../input/inputPlugin.h"
+#include "../output/outPlugin.h"
+#include "../util/timeWrapper.h"
+
+#include <kdemacros.h>
+
+/**
+ Note: streamstate can be "or'ed" for the waitStreamState call
+*/
+
+#define _STREAM_STATE_EOF 1
+#define _STREAM_STATE_FIRST_INIT 4
+#define _STREAM_STATE_INIT 8
+#define _STREAM_STATE_PLAY 16
+#define _STREAM_STATE_WAIT_FOR_END 32
+#define _STREAM_STATE_RESYNC_COMMIT 64
+#define _STREAM_STATE_ALL 1+4+8+16+32+64
+
+
+#define _RUN_CHECK_FALSE 0
+#define _RUN_CHECK_TRUE 1
+#define _RUN_CHECK_CONTINUE 2
+
+
+
+/**
+ Here is the base class for the player plugin.
+ we can set the output of the player, and the input.
+ <p>
+ This class offer you a thread which you have to use
+ in derived class for the decoding work.
+ <p>
+ All calls to your decoder goes through this class
+ which must make sure that there are no races.
+ <p>
+ The life of the decoder thread:
+ ------------------------------
+
+ We start every time a thread if you make an instance of this class.
+ The thread then goes to the idleThread() method and waits
+ until we wake him up.
+ If we wake him um he graps the decoderMut and enters the
+ decode_loop() This method must be used for your plugin.
+ Then this thread "polls" during decoding the decoderChangeMut
+ (see runCheck())
+ if he can get the decoderChangeMut,the thread is authenticated for another
+ decode round if not, he waits until we wake him up again.
+ If the stream ends or the user stops decoding we leave the decoder_loop
+ and go back to the idleThread().
+ If you delete this class the thread is joined.
+
+*/
+
+class KDE_EXPORT DecoderPlugin {
+
+ public:
+
+ DecoderPlugin();
+ virtual ~DecoderPlugin();
+
+ //
+ // you can submit the following commands to the decode_loop thread
+ //
+ virtual void close();
+ virtual void pause();
+ virtual int play();
+ virtual int seek(int second);
+ void insertAsyncCommand(Command* cmd);
+ void insertSyncCommand(Command* cmd);
+
+ // returns total length (lCurrent==false) or current time (true)
+ // Note: you should not call this too often because
+ // it locks the decoder thread.
+ // Should be called only after the initialisation of the stream
+ // no need to override this, overide getTotalLength()
+ int getTime(int lCurrent);
+
+
+
+ virtual void setOutputPlugin(OutputStream* output);
+
+ // This method can only be called _once_ after a "close"
+ virtual int setInputPlugin(InputStream* input);
+ virtual void config(const char* key,const char* value,void* user_data);
+ virtual int getStreamState();
+
+ /**
+ Use this method to wait for a stream signal.
+ For example: after setInputPlugin the thread starts with
+ the state _EOF then the state changes between:
+
+ After setInput you can wait for (INIT | DECODE | WAIT_FOR_END | EOF) this
+ make sure the first init is passed. (successful or not)
+ return value is current streamState, which had a succesfull match.
+ Note: after return the state may already have changed (nature of threads)
+
+ */
+ int waitForStreamState(int state);
+ PluginInfo* getPluginInfo();
+
+ // Needed for Video Embedding
+ int x11WindowId() { return output->x11WindowId(); }
+
+ // never use this!
+ void* idleThread();
+
+ // Note: can only be called by the decode_loop thread !!!
+ void setStreamState(int streamState);
+
+ protected:
+
+ // override this if you have the total length in second
+ virtual int getTotalLength();
+ // implement this if your plugin supports seek
+ // (called by decoder_loop thread
+ virtual int seek_impl(int second);
+
+
+ /**
+ should be called from decoder_loop
+ checks some mutex variables if user want decoder to pause/quit
+ returns:
+ false : quit decoding
+ true : continue decoding
+
+ Note: method blocks if user "pauses" the stream
+ */
+ int runCheck();
+
+ // this mut is set from the start of decoder_loop()
+ // its _not_ set if the thread runs in the while() loop
+ // it it set if the thread leaves the while loop (runCheck->false)
+ // (its used internally to make the getTime() call safe
+ void shutdownLock();
+ void shutdownUnlock();
+
+
+ // this is the method to override in your decoder
+ virtual void decoder_loop();
+
+ // this method handles the commands for the decode_loop thread
+ virtual int processThreadCommand(Command* command);
+
+ OutputStream* output;
+ InputStream* input;
+
+ abs_thread_t tr;
+ abs_thread_mutex_t shutdownMut;
+ abs_thread_mutex_t streamStateMut;
+ abs_thread_cond_t streamStateCond;
+
+
+
+
+ int lDecoderLoop;
+ int lCreatorLoop;
+ int linDecoderLoop;
+ int lDecode;
+ int streamState;
+ int lhasLength;
+ int lAutoPlay;
+ int decode_loopCounter; // count how much we started decode_loop
+ int runCheck_Counter; // count how much we called runCheck
+ int instance;
+ PluginInfo* pluginInfo;
+
+ private:
+
+ CommandPipe* commandPipe;
+ Command* threadCommand;
+
+
+
+};
+
+#endif
+
diff --git a/mpeglib/lib/decoder/mpegPlugin.cpp b/mpeglib/lib/decoder/mpegPlugin.cpp
new file mode 100644
index 00000000..e230adb5
--- /dev/null
+++ b/mpeglib/lib/decoder/mpegPlugin.cpp
@@ -0,0 +1,160 @@
+/*
+ mpeg 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 "mpegPlugin.h"
+
+#include "../mpegplay/mpegVideoStream.h"
+#include "../mpegplay/proto.h"
+#include "../mpegplay/mpegVideoHeader.h"
+
+using namespace std;
+
+
+MpegPlugin::MpegPlugin() {
+ init();
+}
+
+
+MpegPlugin::~MpegPlugin() {
+}
+
+
+void MpegPlugin::init() {
+ lCalcLength=false;
+ mpegVideoHeader=NULL;
+ mpegVideoStream=NULL;
+}
+
+
+void MpegPlugin::decoder_loop() {
+
+
+ VideoDecoder* video=NULL;
+ if (input == NULL) {
+ cout << "MpegPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "MpegPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+
+ mpegVideoHeader=new MpegVideoHeader();
+ mpegVideoStream=new MpegVideoStream(input);
+
+ PictureArray* pictureArray;
+ YUVPicture* pic;
+ int skipMode=_SYNC_TO_NONE;
+ // decode loop
+
+ while(runCheck()) {
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ if (mpegVideoStream->firstInitialize(mpegVideoHeader)==false) {
+
+ } else {
+ pluginInfo->setLength(getSongLength());
+
+ // now create pictureArray from the sequence
+ int width=mpegVideoHeader->getMB_Width()*16;
+ int height=mpegVideoHeader->getMB_Height()*16;
+
+ output->openWindow(width,height,(char*)"kmpg");
+ video=new VideoDecoder(mpegVideoStream,mpegVideoHeader);
+ setStreamState(_STREAM_STATE_INIT);
+ }
+ break;
+ case _STREAM_STATE_INIT :
+ // cout << "mpeg _STREAM_STATE_INI"<<endl;
+ if (skipMode==_SYNC_TO_GOP) {
+ if (mpegVideoStream->nextGOP()==false) {
+ continue;
+ }
+ video->resyncToI_Frame();
+ }
+ if (skipMode==_SYNC_TO_PIC) {
+ if (mpegVideoStream->nextPIC()==false) {
+ continue;
+ }
+ }
+ skipMode=_SYNC_TO_NONE;
+ setStreamState(_STREAM_STATE_PLAY);
+ break;
+ case _STREAM_STATE_PLAY :
+ pictureArray=output->lockPictureArray();
+ skipMode=video->mpegVidRsrc(pictureArray);
+
+ if (skipMode != _SYNC_TO_NONE) {
+ setStreamState(_STREAM_STATE_INIT);
+ }
+ pic=pictureArray->getYUVPictureCallback();
+ if (pic == NULL) {
+ // nothin to display
+ break;
+ }
+
+ output->unlockPictureArray(pictureArray);
+ pictureArray->setYUVPictureCallback(NULL);
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+
+ output->flushWindow();
+ // copy sequence back if needed
+ if (video != NULL) {
+ delete video;
+ }
+ delete mpegVideoStream;
+ delete mpegVideoHeader;
+ mpegVideoStream=NULL;
+ mpegVideoHeader=NULL;
+}
+
+
+
+
+
+// here we can config our decoder with special flags
+void MpegPlugin::config(const char* key,const char* value,void* user_data) {
+ if (strcmp(key,"-c")==0) {
+ lCalcLength=false;
+ }
+
+ if (strcmp(key,"decode")==0) {
+ if (strcmp(value,"true")==0) {
+ lDecode=true;
+ } else {
+ lDecode=false;
+ }
+ }
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+
+int MpegPlugin::getSongLength() {
+ int back=0;
+ return back;
+}
+
+
+
+
+
+
diff --git a/mpeglib/lib/decoder/mpegPlugin.h b/mpeglib/lib/decoder/mpegPlugin.h
new file mode 100644
index 00000000..ff236f9b
--- /dev/null
+++ b/mpeglib/lib/decoder/mpegPlugin.h
@@ -0,0 +1,47 @@
+/*
+ mpeg 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
+
+ */
+
+
+#ifndef __MPEGPLUGIN_H
+#define __MPEGPLUGIN_H
+
+#include "../decoder/decoderPlugin.h"
+
+
+class MpegVideoHeader;
+class MpegVideoStream;
+
+
+class MpegPlugin : public DecoderPlugin {
+
+ int lCalcLength;
+
+ MpegVideoHeader* mpegVideoHeader;
+ MpegVideoStream* mpegVideoStream;
+
+ public:
+ MpegPlugin();
+ ~MpegPlugin();
+
+ void decoder_loop();
+ void config(const char* key,const char* value,void* user_data);
+
+
+ private:
+ void init();
+
+ int getSongLength();
+
+
+};
+#endif
+
diff --git a/mpeglib/lib/decoder/mpgPlugin.cpp b/mpeglib/lib/decoder/mpgPlugin.cpp
new file mode 100644
index 00000000..fd7170c8
--- /dev/null
+++ b/mpeglib/lib/decoder/mpgPlugin.cpp
@@ -0,0 +1,260 @@
+/*
+ mpg I video/audio 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 "mpgPlugin.h"
+
+#include "../mpegplay/mpegSystemStream.h"
+#include "../mpgplayer/mpegStreamPlayer.h"
+#include "../mpegplay/mpegVideoLength.h"
+
+#include "splayPlugin.h"
+#include "mpegPlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+
+MpgPlugin::MpgPlugin() {
+
+ mpegSystemHeader=NULL;
+ mpegSystemStream=NULL;
+ mpegStreamPlayer=NULL;
+ mpegVideoLength=NULL;
+
+ // make runtime config easier, no NULL check necessary
+ mpegSystemHeader=new MpegSystemHeader();
+ timeStamp=new TimeStamp();
+ lMono=false;
+ lDown=false;
+ lWriteStreams=false;
+ lDoLength=true;
+}
+
+
+MpgPlugin::~MpgPlugin() {
+ delete mpegSystemHeader;
+ delete timeStamp;
+}
+
+
+
+void MpgPlugin::decoder_loop() {
+
+ if (input == NULL) {
+ cout << "MPGPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "MPGPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+
+ // decoder
+ SplayPlugin* splayPlugin=new SplayPlugin();
+ splayPlugin->config("-c","true",NULL);
+ if (lMono) {
+ splayPlugin->config("-m","true",NULL);
+ }
+ if (lDown) {
+ splayPlugin->config("-2","true",NULL);
+ }
+
+ MpegPlugin* mpegplayPlugin=new MpegPlugin();
+
+ mpegSystemStream=new MpegSystemStream(input);
+ mpegStreamPlayer=new MpegStreamPlayer(input,output,
+ splayPlugin,mpegplayPlugin);
+ mpegStreamPlayer->setWriteToDisk(lWriteStreams);
+ mpegVideoLength=new MpegVideoLength(input);
+
+
+ int lSysLayer=false;
+ int lHasLength=false;
+
+ while(runCheck()) {
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ if ((lHasLength==false) && (lDoLength)) {
+ if (mpegVideoLength->firstInitialize()==false) {
+ continue;
+ }
+ lHasLength=true;
+ }
+ if (mpegSystemStream->firstInitialize(mpegSystemHeader)==false) {
+ //cout << "still initializing system stream"<<endl;
+ } else {
+ // if we have found a raw stream,
+ // make sure we pass as first argument a SEQ_START_CODE
+ if (mpegSystemHeader->getLayer() == _PACKET_SYSLAYER) {
+ lSysLayer=true;
+ mpegStreamPlayer->processSystemHeader(mpegSystemHeader);
+ } else {
+ //output->config("-s","false");
+ unsigned int startCodeRaw=htonl(_SEQ_START_CODE);
+ mpegStreamPlayer->
+ insertVideoDataRaw((unsigned char*)&startCodeRaw,4,timeStamp);
+ }
+ pluginInfo->setLength(mpegVideoLength->getLength());
+ output->writeInfo(pluginInfo);
+ setStreamState(_STREAM_STATE_INIT);
+
+ if (mpegSystemHeader->getMPEG2()==true) {
+ cout << "this plugin does not support MPEG2/VOB/DVD"<<endl;
+ lDecoderLoop=false;
+ if (lWriteStreams == true) {
+ cout << "demux is supported"<<endl;
+ lDecoderLoop=true;
+
+ }
+ break;
+ }
+
+ }
+ break;
+ case _STREAM_STATE_INIT :
+ setStreamState(_STREAM_STATE_PLAY);
+ break;
+ case _STREAM_STATE_PLAY :
+ // syslayer
+
+ if (mpegSystemStream->nextPacket(mpegSystemHeader) == false) {
+
+ break;
+ }
+
+ if (mpegStreamPlayer->processSystemHeader(mpegSystemHeader) == false) {
+ mpegSystemStream->reset();
+ setStreamState(_STREAM_STATE_INIT);
+ }
+
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ if (mpegStreamPlayer->hasEnd()==true) {
+ // exit while loop
+ lDecoderLoop=false;
+ }
+ TimeWrapper::usleep(100000);
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+
+ delete mpegStreamPlayer;
+ delete mpegSystemStream;
+ delete mpegVideoLength;
+ delete mpegplayPlugin;
+ delete splayPlugin;
+
+ mpegSystemStream=NULL;
+ mpegStreamPlayer=NULL;
+ mpegVideoLength=NULL;
+
+
+ output->audioFlush();
+ output->flushWindow();
+
+}
+
+
+
+// here we can config our decoder with special flags
+void MpgPlugin::config(const char* key,const char* value,void* user_data) {
+ if(strcmp("VideoLayer", key) == 0) {
+ int videoLayerSelect=atoi(value);
+ mpegSystemHeader->setVideoLayerSelect(videoLayerSelect);
+ }
+
+ if(strcmp("AudioLayer", key) == 0) {
+ int audioLayerSelect=atoi(value);
+ mpegSystemHeader->setAudioLayerSelect(audioLayerSelect);
+ }
+ if (strcmp(key,"-2")==0) {
+ lDown=true;
+ }
+ if (strcmp(key,"-m")==0) {
+ lMono=true;
+ }
+ if (strcmp(key,"-c")==0) {
+ lDoLength=false;
+ }
+ if (strcmp(key,"-w")==0) {
+ if (strcmp(value,"true")==0) {
+ lWriteStreams=true;
+ } else {
+ lWriteStreams=true;
+ }
+ }
+ // now try to set it if stream is running:
+ shutdownLock();
+ if (mpegStreamPlayer != NULL) {
+ mpegStreamPlayer->setWriteToDisk(lWriteStreams);
+ }
+ shutdownUnlock();
+
+
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+
+
+int MpgPlugin::getTotalLength() {
+ shutdownLock();
+ int back=0;
+ if (mpegVideoLength != NULL) {
+ back=mpegVideoLength->getLength();
+ } else {
+ cout << "cannot report total length, plugin not initialized"<<endl;
+ }
+ shutdownUnlock();
+
+ return back;
+}
+
+
+
+
+
+int MpgPlugin::processThreadCommand(Command* command) {
+
+ int id=command->getID();
+ int arg;
+ switch(id) {
+ case _COMMAND_SEEK: {
+ //
+ // mapping from second to bytePosition
+ //
+ if (mpegStreamPlayer->isInit()==false) {
+ command->print("MPGPLUGIN:ignore command in _STREAM_STATE_FIRST_INIT");
+ } else {
+ arg=command->getIntArg();
+ int pos=mpegVideoLength->getSeekPos(arg);
+ Command seek(_COMMAND_SEEK,pos);
+ // insert correct values
+ mpegStreamPlayer->processThreadCommand(&seek);
+ }
+ return _RUN_CHECK_CONTINUE;
+ }
+
+ default:
+ // we forward the command to the mpegStreamPlayer
+ mpegStreamPlayer->processThreadCommand(command);
+ }
+
+ // use default
+ return (DecoderPlugin::processThreadCommand(command));
+}
+
+
diff --git a/mpeglib/lib/decoder/mpgPlugin.h b/mpeglib/lib/decoder/mpgPlugin.h
new file mode 100644
index 00000000..79d986cc
--- /dev/null
+++ b/mpeglib/lib/decoder/mpgPlugin.h
@@ -0,0 +1,62 @@
+/*
+ mpg I video/audio 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
+
+ */
+
+
+
+#ifndef __MPGPLUGIN_H
+#define __MPGPLUGIN_H
+
+#include "../decoder/decoderPlugin.h"
+#include <kdemacros.h>
+
+#define _INSERT_NO 0
+#define _INSERT_VIDEO 1
+#define _INSERT_AUDIO 2
+#define _INSERT_ALL 3
+
+class MpegSystemHeader;
+class MpegSystemStream;
+class MpegStreamPlayer;
+class MpegVideoLength;
+
+class KDE_EXPORT MpgPlugin : public DecoderPlugin {
+
+ MpegSystemHeader* mpegSystemHeader;
+ MpegSystemStream* mpegSystemStream;
+ MpegStreamPlayer* mpegStreamPlayer;
+ MpegVideoLength* mpegVideoLength;
+ TimeStamp* timeStamp;
+ int lMono;
+ int lDown;
+ int lWriteStreams;
+ int lDoLength;
+
+ public:
+ MpgPlugin();
+ ~MpgPlugin();
+
+ void decoder_loop();
+ int getTime(int lCurrent);
+
+ void config(const char* key,const char* value,void* user_data);
+
+ int processThreadCommand(Command* command);
+
+
+
+ protected:
+ int getTotalLength();
+
+
+};
+#endif
+
diff --git a/mpeglib/lib/decoder/nukePlugin.cpp b/mpeglib/lib/decoder/nukePlugin.cpp
new file mode 100644
index 00000000..08c8ce89
--- /dev/null
+++ b/mpeglib/lib/decoder/nukePlugin.cpp
@@ -0,0 +1,62 @@
+/*
+ this plugin nukes the input data.
+ Copyright (C) 2000 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 "nukePlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+NukePlugin::NukePlugin() {
+}
+
+
+NukePlugin::~NukePlugin() {
+}
+
+
+
+void NukePlugin::decoder_loop() {
+ if (input == NULL) {
+ cout << "NukePlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "NukePlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+ char nukeBuffer[8192];
+
+ while(runCheck()) {
+
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ case _STREAM_STATE_INIT :
+ case _STREAM_STATE_PLAY :
+ input->read(nukeBuffer,8192);
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ cout << "nukePlugin _STREAM_STATE_WAIT_FOR_END"<<endl;
+ lDecoderLoop=false;
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+}
+
+
+void NukePlugin::config(const char* key,const char* value,void* user_data) {
+ DecoderPlugin::config(key,value,user_data);
+}
diff --git a/mpeglib/lib/decoder/nukePlugin.h b/mpeglib/lib/decoder/nukePlugin.h
new file mode 100644
index 00000000..8a9aa9a3
--- /dev/null
+++ b/mpeglib/lib/decoder/nukePlugin.h
@@ -0,0 +1,34 @@
+/*
+ this plugin nukes the input data.
+ Copyright (C) 2000 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
+
+ */
+
+
+#ifndef __NUKEPLUGIN_H
+#define __NUKEPLUGIN_H
+
+
+#include "../decoder/decoderPlugin.h"
+#include <kdemacros.h>
+
+class KDE_EXPORT NukePlugin : public DecoderPlugin {
+
+ public:
+
+ NukePlugin();
+ ~NukePlugin();
+
+ void decoder_loop();
+ void config(const char* key,const char* value,void* user_data);
+
+ private:
+
+};
+#endif
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;
+}
+
+
+
+
+
diff --git a/mpeglib/lib/decoder/splayPlugin.h b/mpeglib/lib/decoder/splayPlugin.h
new file mode 100644
index 00000000..34a9751b
--- /dev/null
+++ b/mpeglib/lib/decoder/splayPlugin.h
@@ -0,0 +1,67 @@
+/*
+ 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
+
+ */
+
+
+#ifndef __SPLAYPLUGIN_H
+#define __SPLAYPLUGIN_H
+
+#include "../decoder/decoderPlugin.h"
+#include <kdemacros.h>
+
+class SplayDecoder;
+class MpegAudioFrame;
+class AudioFrame;
+class FloatFrame;
+class PCMFrame;
+class FileAccessWrapper;
+class MpegAudioInfo;
+
+class KDE_EXPORT SplayPlugin : public DecoderPlugin {
+
+ int lnoLength;
+ int lfirst;
+ int lOutput;
+ /*
+ * directly writes decoded data as float, instead of converting it to
+ * short int samples first. float->int conversions are _very_
+ * time intensiv!
+ */
+ bool doFloat;
+
+ SplayDecoder* splay;
+ MpegAudioFrame* framer;
+ FloatFrame* floatFrame;
+ PCMFrame* pcmFrame;
+ unsigned char* inputbuffer;
+ int lenghtInSec;
+ MpegAudioInfo* info;
+ FileAccessWrapper* fileAccess;
+ int resyncCounter;
+ AudioFrame* audioFrame;
+
+
+ public:
+ SplayPlugin();
+ ~SplayPlugin();
+
+ void decoder_loop();
+ int seek_impl(int second);
+ void config(const char* key,const char* value,void* user_data);
+
+ protected:
+ int getTotalLength();
+ void processStreamState(TimeStamp* stamp,AudioFrame* audioFrame);
+ void audioSetup(AudioFrame* setupFrame);
+ int doFrameFind();
+
+};
+#endif
diff --git a/mpeglib/lib/decoder/tplayPlugin.cpp b/mpeglib/lib/decoder/tplayPlugin.cpp
new file mode 100644
index 00000000..01c44cbc
--- /dev/null
+++ b/mpeglib/lib/decoder/tplayPlugin.cpp
@@ -0,0 +1,264 @@
+/*
+ tplay 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 "tplayPlugin.h"
+
+#include "../tplay/tplayfunctions.h"
+
+#include <iostream>
+
+using namespace std;
+
+TplayPlugin::TplayPlugin() {
+ info=new info_struct();
+
+ info->progname = NULL;
+ info->loop = FALSE;
+ info->in_seconds = FALSE;
+ info->speed = DEFAULT_SPEED;
+ info->bits = DEFAULT_BITS;
+ info->channels = DEFAULT_CHANNELS;
+ info->buffer_size = BUFFER_SIZE;
+ info->show_usage = FALSE;
+ info->swap = FALSE;
+ info->forceraw = FALSE;
+ info->force = FALSE;
+ info->device = NULL;
+ info->verbose = FALSE;
+ info->optind = 0;
+ info->buffer = NULL;
+ info->firstblock = NULL;
+ info->number_of_blocks = 0;
+ info->readblock = 0;
+ info->writeblock = 0;
+ info->readcount = 0;
+ info->writecount = 0;
+ info->alldone = FALSE;
+ info->overflow = FALSE;
+ info->underflow = FALSE;
+ info->audioset = FALSE;
+ info->headerskip = 0;
+ info->blocksize = 4096;
+ info->bytes_on_last_block = 0;
+
+ startStamp=new TimeStamp();
+ endStamp=new TimeStamp();
+}
+
+
+TplayPlugin::~TplayPlugin() {
+ delete startStamp;
+ delete endStamp;
+ delete info;
+}
+
+
+
+void TplayPlugin::decoder_loop() {
+ int bytesread, count, stereo;
+ char *p, *bufferp;
+
+ if (input == NULL) {
+ cout << "TplayPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "TplayPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+
+ TimeStamp* stamp;
+ long pos;
+
+ info->buffer = (char*) malloc(info->buffer_size * sizeof(char));
+
+ while(runCheck()) {
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT : {
+ read_header();
+
+ if (info->channels == 1)
+ stereo = FALSE;
+ else
+ stereo = TRUE;
+
+ info->number_of_blocks = 0;
+ bufferp = info->buffer;
+ pluginInfo->setLength(getTotalLength());
+ output->writeInfo(pluginInfo);
+ lhasLength=true;
+
+ setStreamState(_STREAM_STATE_INIT);
+ break;
+ }
+ case _STREAM_STATE_INIT :
+ setStreamState(_STREAM_STATE_PLAY);
+ cout << "audioSetup call"<<endl;
+ output->audioOpen();
+ output->audioSetup(info->speed, stereo, 1, 0, info->bits);
+ break;
+ case _STREAM_STATE_PLAY :
+ bytesread = 0;
+ count = 0;
+ p = bufferp;
+ while ((bytesread < info->blocksize) && (count != -1) &&
+ ((count = input->read(p,info->blocksize-bytesread))!=0)){
+ p += count;
+ bytesread += count;
+ }
+ if (info->swap) {
+ swap_block(bufferp, bytesread);
+ }
+
+ if (bytesread > 0) {
+ pos=input->getBytePosition();
+ stamp=input->getTimeStamp(pos-bytesread);
+ output->audioPlay(stamp,endStamp,(char *) bufferp, bytesread);
+ }
+
+ if (bytesread < info->blocksize) {
+ info->alldone = TRUE;
+
+ }
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ break;
+ default:
+ cout << "unknown stream state:"<<streamState<<endl;
+ }
+ }
+ cout << "tplay exit"<<endl;
+ free(info->buffer);
+ info->buffer = NULL;
+ output->audioFlush();
+}
+
+
+int TplayPlugin::seek_impl(int second) {
+ int bytes_per_second;
+ int seconds;
+ int back;
+
+
+ bytes_per_second = info->speed * info->channels * (info->bits / 8);
+
+
+
+ seconds = bytes_per_second * second;
+ back=input->seek(seconds);
+
+ return back;
+}
+
+
+void TplayPlugin::config(const char* key,const char* value,void* user_data) {
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+void TplayPlugin::swap_block(char * buffer, int blocksize) {
+ register int i;
+ char c, *p;
+
+ p = buffer;
+ for (i = 0; i < (blocksize / 2); i++) {
+ c = *p;
+ *p = *(p + 1);
+ *++p = c;
+ p++;
+ }
+}
+
+
+void TplayPlugin::read_header() {
+ int bytesread, count;
+ char *p, *bufferp;
+
+ info->firstblock = (char*) malloc(info->blocksize * sizeof(char));
+ bufferp = info->firstblock;
+ if (!info->forceraw) {
+ bytesread = 0;
+ count = 0;
+ p = bufferp;
+ while ((bytesread < info->blocksize) && (count != -1) &&
+ ((count=input->read(p,info->blocksize-bytesread)) != 0)){
+ p += count;
+ bytesread += count;
+ }
+
+ if (bytesread < SUN_HDRSIZE)
+ cout << "Sample size is too small"<<endl;
+
+ if (read_au(info,info->firstblock) && read_wav(info,info->firstblock)) {
+ if (info->verbose)
+ printf("Playing raw data: %ld samples/s, %d bits, %d channels.\n",
+ info->speed, info->bits, info->channels);
+ }
+
+ if (info->swap)
+ swap_block(bufferp, bytesread);
+
+ if (bytesread < info->blocksize) {
+ info->alldone = TRUE;
+ info->bytes_on_last_block = bytesread;
+ return;
+ }
+
+ if (info->headerskip) {
+ count = 0;
+ bytesread = info->blocksize - info->headerskip;
+ p = info->firstblock + (info->blocksize - info->headerskip);
+ while ((bytesread < info->blocksize) && (count != -1) &&
+ ((count = input->read(p,info->blocksize - bytesread)) != 0)) {
+ p += count;
+ bytesread += count;
+ }
+ }
+
+ info->writeblock++;
+ info->writecount++;
+ }
+ else {
+ if (info->verbose)
+ printf("Playing raw data: %ld samples/s, %d bits, %d channels\n",
+ info->speed, info->bits, info->channels);
+ }
+}
+
+/**
+ Nobody is perfect I'm too tired to fix this race
+*/
+
+int TplayPlugin::getTotalLength() {
+ float wavfilesize = input->getByteLength();
+ int back=0;
+
+
+ float frequence=info->speed;
+
+ int bits=info->bits;
+
+
+ if (bits == 16) {
+ wavfilesize=wavfilesize/2;
+ }
+ if (info->channels==2) {
+ wavfilesize=wavfilesize/2;
+ }
+ if (frequence != 0) {
+ back=(int)(wavfilesize/frequence);
+ }
+ return back;
+}
diff --git a/mpeglib/lib/decoder/tplayPlugin.h b/mpeglib/lib/decoder/tplayPlugin.h
new file mode 100644
index 00000000..daa0de74
--- /dev/null
+++ b/mpeglib/lib/decoder/tplayPlugin.h
@@ -0,0 +1,47 @@
+/*
+ tplay 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
+
+ */
+
+
+#ifndef __TPLAYPLUGIN_H
+#define __TPLAYPLUGIN_H
+
+#include "../decoder/decoderPlugin.h"
+#include <kdemacros.h>
+/**
+ The tplayPlugin is ugly and needs a rewrite.
+ Im not sure if you can make mutiple instances of it
+*/
+
+class KDE_EXPORT TplayPlugin : public DecoderPlugin {
+
+ struct info_struct* info;
+ class TimeStamp* startStamp;
+ class TimeStamp* endStamp;
+
+ public:
+ TplayPlugin();
+ ~TplayPlugin();
+
+ void decoder_loop();
+ int seek_impl(int second);
+ void config(const char* key,const char* value,void* user_data);
+
+ protected:
+ int getTotalLength();
+
+ private:
+ void swap_block(char* buffer, int blocksize);
+ void read_header();
+
+
+};
+#endif
diff --git a/mpeglib/lib/decoder/vorbisPlugin.cpp b/mpeglib/lib/decoder/vorbisPlugin.cpp
new file mode 100644
index 00000000..b32ba93f
--- /dev/null
+++ b/mpeglib/lib/decoder/vorbisPlugin.cpp
@@ -0,0 +1,305 @@
+/*
+ vorbis player plugin
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "vorbisPlugin.h"
+
+#include <iostream>
+
+using namespace std;
+
+#ifdef OGG_VORBIS
+
+size_t fread_func(void *ptr, size_t size, size_t nmemb, void *stream) {
+ InputStream* input=((VorbisPlugin*)stream)->getInputStream();
+ int bytes=input->read((char*)ptr,size*nmemb);
+ // workaround for RC3, report success during seek
+ /*
+ if (((VorbisPlugin*)stream)->vorbis_seek_bug_active == true) {
+ errno=0;
+ return 0;
+ }
+ */
+ // error on read and no "seek workaround"
+ if (bytes == 0) {
+ //
+ // If different thread close the input we signal
+ // a read error to vorbis
+ //
+ if (input->isOpen() == false) {
+ // note: errno is in this thread another variable, than in
+ // the thread which closed the file.
+ // here we "fake" the errno var.
+ errno=EBADF;
+ return 0;
+ }
+ }
+ // successful read
+ return bytes;
+}
+
+
+int fseek_func(void *stream, ogg_int64_t offset, int whence) {
+ int ret=-1;
+ InputStream* input=((VorbisPlugin*)stream)->getInputStream();
+
+ switch(whence) {
+ case SEEK_SET:
+ ret=input->seek(offset);
+ break;
+ case SEEK_CUR:
+ ret=input->seek(input->getBytePosition()+offset);
+ break;
+ case SEEK_END:
+ ret=input->seek(input->getByteLength());
+ break;
+ default:
+ cout << "fseek_func VorbisPlugn strange call"<<endl;
+ }
+
+ if (ret == false) {
+ // vorbis does not handle errors in seek at all
+ // and if they are handled vorbis segfaults. (RC3)
+ // here we always "success" but set an seek_error_mark
+ //
+ ret=-1;
+ }
+
+ return ret;
+
+}
+
+
+int fclose_func (void *) {
+ //InputStream* input=(InputStream*) stream;
+
+ // its handled different in kmpg
+ // we close the stream if the decoder signals eof.
+ return true;
+
+}
+
+
+long ftell_func (void *stream) {
+ InputStream* input=((VorbisPlugin*)stream)->getInputStream();
+ return input->getBytePosition();
+}
+
+
+VorbisPlugin::VorbisPlugin() {
+
+
+ memset(&vf, 0, sizeof(vf));
+ timeDummy=new TimeStamp();
+ pcmout=new char[4096];
+ lnoLength=false;
+ lshutdown=true;
+
+}
+
+
+VorbisPlugin::~VorbisPlugin() {
+ delete timeDummy;
+ delete pcmout;
+}
+
+
+// here we can config our decoder with special flags
+void VorbisPlugin::config(const char* key,const char* value,void* user_data) {
+
+ if (strcmp(key,"-c")==0) {
+ lnoLength=true;
+ }
+ DecoderPlugin::config(key,value,user_data);
+}
+
+
+int VorbisPlugin::init() {
+ ov_callbacks callbacks;
+
+ callbacks.read_func = fread_func;
+ callbacks.seek_func = fseek_func;
+ callbacks.close_func = fclose_func;
+ callbacks.tell_func = ftell_func;
+
+ // here is the hack to pass the pointer to
+ // our streaming interface.
+
+ if(ov_open_callbacks(this, &vf, NULL, 0, callbacks) < 0) {
+ return false;
+ }
+
+ return true;
+}
+
+
+// called by decoder thread
+int VorbisPlugin::processVorbis(vorbis_info* vi,vorbis_comment* comment) {
+
+ // decode
+ int ret;
+ int current_section=-1; /* A vorbis physical bitstream may
+ consist of many logical sections
+ (information for each of which may be
+ fetched from the vf structure). This
+ value is filled in by ov_read to alert
+ us what section we're currently
+ decoding in case we need to change
+ playback settings at a section
+ boundary */
+ ret=ov_read(&vf,pcmout,4096,0,2,1,&current_section);
+ switch(ret){
+ case 0:
+ /* EOF */
+ lDecoderLoop=false;
+ break;
+ case -1:
+ /* error in the stream. Not a problem, just reporting it in
+ case we (the app) cares. In this case, we don't. */
+ cout << "error found"<<endl;
+ break;
+ default:
+ if(current_section!=last_section){
+ vi=ov_info(&vf,-1); /* The info struct is different in each
+ section. vf holds them all for the
+ given bitstream. This requests the
+ current one */
+
+ double timeoffset=ov_time_tell(&vf);
+
+ comment = ov_comment(&vf, -1);
+ if(comment) {
+ cout << "we have a comment:"<<timeoffset<<endl;
+ }
+ }
+ last_section=current_section;
+ output->audioPlay(timeDummy,timeDummy,pcmout,ret);
+ break;
+ }
+ return true;
+}
+
+
+void VorbisPlugin::decoder_loop() {
+ vorbis_info *vi=NULL;
+ vorbis_comment *comment=NULL;
+ last_section=0;
+ current_section=0;
+
+
+
+ if (input == NULL) {
+ cout << "VorbisPlugin::decoder_loop input is NULL"<<endl;
+ exit(0);
+ }
+ if (output == NULL) {
+ cout << "VorbisPlugin::decoder_loop output is NULL"<<endl;
+ exit(0);
+ }
+ // init audio stream
+ output->audioInit();
+
+ /********** Decode setup ************/
+ // start decoding
+ lshutdown=false;
+ /**
+ Vorbis RC3 introducted a new bug:
+ seek on a closed stream segfaults vorbis.
+ The bugfix in vorbis is (RC3) around line 1190 should be:
+ seek_error:
+ // the caller of this goto may not set a return code
+ ret=OV_ENOSEEK;
+ The workaround is to check if we are in a seek operation
+ and always "fake" successful reads.
+ */
+ vorbis_seek_bug_active=false;
+
+
+ while(runCheck()) {
+
+ switch(streamState) {
+ case _STREAM_STATE_FIRST_INIT :
+ if (init()== false) {
+ // total failure. exit decoding
+ lDecoderLoop=false;
+ break;
+ }
+ // now init stream
+ vi=ov_info(&vf,-1);
+ if (lnoLength==false) {
+ pluginInfo->setLength(getTotalLength());
+ output->writeInfo(pluginInfo);
+ }
+ output->audioOpen();
+ output->audioSetup(vi->rate,vi->channels-1,1,0,16);
+
+
+ lhasLength=true;
+ setStreamState(_STREAM_STATE_PLAY);
+ break;
+ case _STREAM_STATE_INIT :
+ case _STREAM_STATE_PLAY :
+ processVorbis(vi,comment);
+ break;
+ case _STREAM_STATE_WAIT_FOR_END:
+ // exit while loop
+ lDecoderLoop=false;
+ usleep(2000000);
+ break;
+ default:
+ cout << "unknown stream state vorbis decoder:"<<streamState<<endl;
+ }
+
+ }
+
+ lshutdown=true;
+ ov_clear(&vf); /* ov_clear closes the stream if its open. Safe to
+ call on an uninitialized structure as long as
+ we've zeroed it */
+ memset(&vf, 0, sizeof(vf));
+
+ output->audioFlush();
+}
+
+// vorbis can seek in streams
+int VorbisPlugin::seek_impl(int second) {
+ vorbis_seek_bug_active=true;
+ ov_time_seek(&vf,(double) second);
+ vorbis_seek_bug_active=false;
+ return true;
+}
+
+
+
+int VorbisPlugin::getTotalLength() {
+ int back=0;
+ int byteLen=input->getByteLength();
+ if (byteLen == 0) {
+ return 0;
+ }
+ /* Retrieve the length in second*/
+ shutdownLock();
+ if (lshutdown==false) {
+ back = (int) ov_time_total(&vf, -1);
+ }
+ shutdownUnlock();
+
+ return back;
+}
+
+
+
+
+#endif
+//OGG_VORBIS
+
+
diff --git a/mpeglib/lib/decoder/vorbisPlugin.h b/mpeglib/lib/decoder/vorbisPlugin.h
new file mode 100644
index 00000000..b680ed69
--- /dev/null
+++ b/mpeglib/lib/decoder/vorbisPlugin.h
@@ -0,0 +1,87 @@
+/*
+ vorbis player plugin
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#ifndef __VORBISPLUGIN_H
+#define __VORBISPLUGIN_H
+
+#include "nukePlugin.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+
+#ifndef OGG_VORBIS
+class VorbisPlugin : public NukePlugin {
+};
+#else
+
+
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+
+/**
+ callbacks from vorbisfile
+*/
+extern "C" {
+
+extern size_t fread_func (void *ptr,size_t size,size_t nmemb, void *stream);
+extern int fseek_func (void *stream, ogg_int64_t offset, int whence);
+extern int fclose_func (void *stream);
+extern long ftell_func (void *stream);
+
+}
+
+
+class VorbisPlugin : public DecoderPlugin {
+
+ OggVorbis_File vf;
+
+
+ // END vorbis setup
+
+
+ int lnoLength;
+ int lAutoPlay;
+ TimeStamp* timeDummy;
+ char* pcmout; // temporay pcm buffer
+ int last_section;
+ int current_section;
+ int lshutdown;
+
+ public:
+ VorbisPlugin();
+ ~VorbisPlugin();
+
+ void decoder_loop();
+ int seek_impl(int second);
+ void config(const char* key,const char* value,void* user_data);
+
+ // vorbis bug workaround [START]
+ int vorbis_seek_bug_active;
+ ::InputStream* getInputStream() { return input; }
+ // vorbis bug workaround [END]
+
+ private:
+ int processVorbis(vorbis_info* vi,vorbis_comment* comment);
+ int getTotalLength();
+ int init();
+
+};
+
+#endif
+//OGG_VORBIS
+
+#endif