diff options
Diffstat (limited to 'mpeglib/lib/output')
27 files changed, 2943 insertions, 0 deletions
diff --git a/mpeglib/lib/output/Makefile.am b/mpeglib/lib/output/Makefile.am new file mode 100644 index 00000000..e430550e --- /dev/null +++ b/mpeglib/lib/output/Makefile.am @@ -0,0 +1,52 @@ +# liboutplugin - Makefile.am + +INCLUDES = $(all_includes) + + +noinst_LTLIBRARIES = liboutput.la + +noinst_HEADERS = windowOut.h \ + audioData.h audioDataArray.h \ + performance.h yuvDumper.h + +kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/output + +kmpginclude_HEADERS = outputStream.h pluginInfo.h \ + outPlugin.h dspX11OutputStream.h \ + artsOutputStream.h audioTime.h \ + avSyncer.h threadSafeOutputStream.h + + +liboutput_la_SOURCES = outPlugin.cpp outputStream.cpp \ + dspX11OutputStream.cpp \ + windowOut.cpp \ + audioTime.cpp \ + audioData.cpp audioDataArray.cpp \ + avSyncer.cpp performance.cpp \ + artsOutputStream.cpp \ + pluginInfo.cpp yuvDumper.cpp \ + threadSafeOutputStream.cpp + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mpeglib/lib/output/artsOutputStream.cpp b/mpeglib/lib/output/artsOutputStream.cpp new file mode 100644 index 00000000..571dd258 --- /dev/null +++ b/mpeglib/lib/output/artsOutputStream.cpp @@ -0,0 +1,205 @@ +/* + output to arts + 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 "artsOutputStream.h" +#include "windowOut.h" +#include "avSyncer.h" +#include "../util/abstract/threadQueue.h" + + +ArtsOutputStream::ArtsOutputStream(void (*streamStateChangeCallback)(void*)) { + + audioTime=new AudioTime(); + x11Window=new WindowOut(); + privateBufferSize=1024*32; + + // we can dynamically change the buffer size, + // over a config switch in avSyncer + // but for now this should be ok + // Arts must pass the total size of the audiobuffer + // from /dev/dsp + connected nodes + // or arts need a video interface + stream=new BufferInputStream(privateBufferSize,1024*64,"artsLoopback"); + avSyncer=new AVSyncer(privateBufferSize); + + // with the ThreadQueue we protect all calls to the + // x11 output. This is necessary, because arts may call + // in the future "config" entries to switch the video + // mode (full,double,desktop) + threadQueue=new ThreadQueue(); + // we set it, but its never used ! + this->streamStateChangeCallback=streamStateChangeCallback; +} + + +ArtsOutputStream::~ArtsOutputStream() { + delete stream; + delete audioTime; + delete x11Window; + delete avSyncer; + delete threadQueue; +} + + + + +int ArtsOutputStream::audioSetup(int freq,int stereo, + int sign,int big,int sampleSize) { + audioTime->setFormat(stereo,sampleSize,freq,sign,big); + avSyncer->audioSetup(freq,stereo,sign,big,sampleSize); + + OutputStream::audioSetup(freq,stereo,sign,big,sampleSize); + + return true; +} + +AudioTime* ArtsOutputStream::getAudioTime() { + return audioTime; +} + + +void ArtsOutputStream::audioClose() { + audioTime->setTime(0.0); + // if we close this stream the thread is kicked out. + stream->close(); + stream->clear(); + avSyncer->audioClose(); +} + +void ArtsOutputStream::audioFlush() { + OutputStream::audioFlush(); + audioClose(); +} + + +void ArtsOutputStream::audioOpen() { + audioTime->setTime(0.0); + // if we close this stream the thread is kicked out. + stream->open("artsLoopback"); +} + + +int ArtsOutputStream::audioPlay(TimeStamp* startStamp, + TimeStamp* endStamp,char *buffer, int size) { + int write=size; + + + // we call this for stream state handling + OutputStream::audioPlay(startStamp,endStamp,buffer,size); + + // store sync information + avSyncer->audioPlay(startStamp,endStamp,buffer,size); + + + // here we simulate our own blocking audio device + if (stream->isOpen()==false) { + audioTime->sleepWrite(size); + } else { + write=stream->write(buffer,size,startStamp); + } + return write; + +} + + +int ArtsOutputStream::read(char** buffer,int bytes) { + int back=stream->readRemote(buffer,bytes); + return back; +} + + +void ArtsOutputStream::forwardReadPtr(int bytes) { + audioTime->forwardTime(bytes); + stream->forwardReadPtr(bytes); + +} + + + + +int ArtsOutputStream::getPreferredDeliverSize() { + return avSyncer->getPreferredDeliverSize(); +} + + +int ArtsOutputStream::openWindow(int width, int height,const char *title) { + threadQueue->waitForExclusiveAccess(); + int back=x11Window->openWindow(width,height,title); + threadQueue->releaseExclusiveAccess(); + + return back; +} + +int ArtsOutputStream::x11WindowId() { + return x11Window->x11WindowId(); +} + +void ArtsOutputStream::closeWindow() { + threadQueue->waitForExclusiveAccess(); + x11Window->closeWindow(); + threadQueue->releaseExclusiveAccess(); +} + +void ArtsOutputStream::flushWindow() { + threadQueue->waitForExclusiveAccess(); + x11Window->flushWindow(); + threadQueue->releaseExclusiveAccess(); +} + + +PictureArray* ArtsOutputStream::lockPictureArray() { + PictureArray* back; + threadQueue->waitForExclusiveAccess(); + back=x11Window->lockPictureArray(); + threadQueue->releaseExclusiveAccess(); + return back; +} + + +void ArtsOutputStream::unlockPictureArray(PictureArray* pictureArray) { + + + YUVPicture* pic=pictureArray->getYUVPictureCallback(); + if (avSyncer->syncPicture(pic)==false) { + return; + } + threadQueue->waitForExclusiveAccess(); + x11Window->unlockPictureArray(pictureArray); + threadQueue->releaseExclusiveAccess(); + +} + +int ArtsOutputStream::getBufferFillgrade() { + return stream->getFillgrade(); +} + +int ArtsOutputStream::getFrameusec() { + return avSyncer->getFrameusec(); +} + + + +void ArtsOutputStream::setAudioBufferSize(int size) { + avSyncer->setAudioBufferSize(privateBufferSize+size); +} + + +void ArtsOutputStream::config(const char* key,const char* value, + void* user_data) { + + threadQueue->waitForExclusiveAccess(); + avSyncer->config(key,value,user_data); + x11Window->config(key,value,user_data); + threadQueue->releaseExclusiveAccess(); +} diff --git a/mpeglib/lib/output/artsOutputStream.h b/mpeglib/lib/output/artsOutputStream.h new file mode 100644 index 00000000..757022fd --- /dev/null +++ b/mpeglib/lib/output/artsOutputStream.h @@ -0,0 +1,123 @@ +/* + output to arts + 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 __ARTSOUTPUTSTREAM_H +#define __ARTSOUTPUTSTREAM_H + +#include "outputStream.h" +#include "../input/bufferInputStream.h" +#include "audioTime.h" + + +class WindowOut; +class AVSyncer; + + + + +/** + a word about synchronisation: Arts currently has not asynchronous + starting of stream, which means, poll if stream is initialized + or set a callbackfunction. + + mpeglib is threaded and would not have much problems + with a "callback" but currently we only support blocking wait + for initilisation. + + I think, if people realize that smooth mixing of streams + is impossible(because of the blocking start behaviour), + this will become a desired feature :-) + +*/ + + +/** + This class offers a blocking device, its behaviour is similar + to /dev/dsp we use a buffer to store the pcm data, if + we open/close the buffer the stored data is removed + and the blocking thread is "kicked" + + Arts must first wait for an init signal. it has its own + method to check for eof. during seek we close this + device, after seek we reopen it. + + close and open have the same functionality, they simply + clear the buffer. +*/ + + + +class ArtsOutputStream : public OutputStream { + + BufferInputStream* stream; + AudioTime* audioTime; + + void (*streamStateChangeCallback)(void*); + + WindowOut* x11Window; + AVSyncer* avSyncer; + int privateBufferSize; + class ThreadQueue* threadQueue; + + public: + ArtsOutputStream(void (*streamStateChangeCallback)(void*)); + ~ArtsOutputStream(); + + // Audio part + + int audioSetup(int freq,int stereo,int sign,int big,int sampleSize); + void audioClose(); + void audioOpen(); + void audioFlush(); + + int audioPlay(TimeStamp* startStamp, + TimeStamp* endStamp,char *buffer, int size); + + + AudioTime* getAudioTime(); + + int getPreferredDeliverSize(); + + // Video part + + int openWindow(int width, int height,const char *title); + int x11WindowId(); + void closeWindow(); + void flushWindow(); + + PictureArray* lockPictureArray(); + void unlockPictureArray(PictureArray* pictureArray); + + int getFrameusec(); + + void config(const char* key,const char* value,void* user_data); + + // Remote read extension + + int read(char** buffer,int bytes); + void forwardReadPtr(int bytes); + + // buffer control + int getBufferFillgrade(); + + // sync control + void setAudioBufferSize(int size); + + private: + void sendSignal(int state,int value); + void initStream(); + +}; +#endif diff --git a/mpeglib/lib/output/audioData.cpp b/mpeglib/lib/output/audioData.cpp new file mode 100644 index 00000000..d28e74cf --- /dev/null +++ b/mpeglib/lib/output/audioData.cpp @@ -0,0 +1,100 @@ +/* + describes a paket oriented audioData, because Im fed up + 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 "audioData.h" + +#include <iostream> + +using namespace std; + +AudioData::AudioData() { + pcmLen=0; + audioTime=new AudioTime(); + start=new TimeStamp(); + end=new TimeStamp(); + writeStamp=new TimeStamp(); +} + + +AudioData::~AudioData() { + delete audioTime; + delete start; + delete end; + delete writeStamp; +} + + +void AudioData::copyTo(AudioData* dest) { + dest->setAudioTime(getAudioTime()); + dest->setStart(getStart()); + dest->setEnd(getEnd()); + dest->setWrite(getWrite()); + dest->setPCMLen(getPCMLen()); +} + + +int AudioData::getPCMLen(){ + return pcmLen; +} + +void AudioData::setPCMLen(int pcmLen) { + this->pcmLen=pcmLen; +} + +void AudioData::setAudioTime(AudioTime* aTime) { + aTime->copyTo(audioTime); +} + +AudioTime* AudioData::getAudioTime() { + return audioTime; +} + + +void AudioData::setStart(TimeStamp* s) { + s->copyTo(start); +} + + +TimeStamp* AudioData::getStart() { + return start; +} + +void AudioData::setEnd(TimeStamp* e) { + e->copyTo(end); +} + + +TimeStamp* AudioData::getEnd() { + return end; +} + +void AudioData::setWrite(TimeStamp* e) { + e->copyTo(writeStamp); +} + + +TimeStamp* AudioData::getWrite() { + return writeStamp; +} + + + +void AudioData::print() { + cout << "AudioData::print [START]"<<endl; + start->print("audioData start"); + end->print("audioData end"); + cout << "pcmlen:"<<pcmLen<<endl; + cout << "AudioData::print [END]"<<endl; +} diff --git a/mpeglib/lib/output/audioData.h b/mpeglib/lib/output/audioData.h new file mode 100644 index 00000000..ff6c8242 --- /dev/null +++ b/mpeglib/lib/output/audioData.h @@ -0,0 +1,71 @@ +/* + describes a paket oriented audioData, because Im fed up + 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 __AUDIODATA_H +#define __AUDIODATA_H + +#include "../util/timeStamp.h" +#include "audioTime.h" + + +#define _AUDIODATA_MAX_SIZE 8192 + + +/** + My attempt to encapsulate all this stupid things which deals + with timing, synchronisation, length, stamps and everything + unimaginable else. +*/ + + + +class AudioData { + + + AudioTime* audioTime; + TimeStamp* start; + TimeStamp* end; + TimeStamp* writeStamp; + + int pcmLen; + + public: + AudioData(); + ~AudioData(); + + void copyTo(AudioData* dest); + + + int getPCMLen(); + void setPCMLen(int pcmLen); + + void setAudioTime(AudioTime* audioTime); + AudioTime* getAudioTime(); + + void setStart(TimeStamp* start); + TimeStamp* getStart(); + + void setWrite(TimeStamp* writeStamp); + TimeStamp* getWrite(); + + + void setEnd(TimeStamp* end); + TimeStamp* getEnd(); + + void print(); +}; +#endif + + + diff --git a/mpeglib/lib/output/audioDataArray.cpp b/mpeglib/lib/output/audioDataArray.cpp new file mode 100644 index 00000000..a0b91ec1 --- /dev/null +++ b/mpeglib/lib/output/audioDataArray.cpp @@ -0,0 +1,138 @@ +/* + fifo for audioData + 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 "audioDataArray.h" + +#include <iostream> + +using namespace std; + + +AudioDataArray::AudioDataArray(int entries) { + + this->entries=entries; + fillgrade=0; + readPos=0; + writePos=0; + pcmSum=0; + abs_thread_mutex_init(&writeInMut); + abs_thread_mutex_init(&changeMut); + + audioDataArray=new AudioData*[entries]; + + int i; + for(i=0;i<entries;i++) { + audioDataArray[i]=new AudioData(); + } + + abs_thread_mutex_init(&writeInMut); + abs_thread_mutex_init(&changeMut); + +} + +AudioDataArray::~AudioDataArray() { + + int i; + for(i=0;i<entries;i++) { + delete audioDataArray[i]; + } + + delete audioDataArray; + + abs_thread_mutex_destroy(&writeInMut); + abs_thread_mutex_destroy(&changeMut); + +} + + + + +void AudioDataArray::lockStampArray() { + + abs_thread_mutex_lock(&changeMut); + abs_thread_mutex_lock(&writeInMut); + abs_thread_mutex_unlock(&changeMut); + +} + + +void AudioDataArray::unlockStampArray() { + abs_thread_mutex_unlock(&writeInMut); +} + + +void AudioDataArray::internalForward() { + pcmSum=pcmSum-readAudioData()->getPCMLen(); + readPos++; + fillgrade--; + if (readPos == entries-1) { + readPos=0; + } +} + +int AudioDataArray::getPCMSum() { + return pcmSum; +} + + + +int AudioDataArray::insertAudioData(AudioData* src) { + lockStampArray(); + + int back=true; + src->copyTo(audioDataArray[writePos]); + pcmSum+=src->getPCMLen(); + + writePos++; + fillgrade++; + if (writePos == entries-1) { + writePos=0; + } + if (fillgrade == entries) { + cout <<" Audiodata::array overfull forward"<<endl; + internalForward(); + back=false; + } + unlockStampArray(); + return back; +} + + +AudioData* AudioDataArray::readAudioData() { + return audioDataArray[readPos]; +} + + +int AudioDataArray::getFillgrade() { + return fillgrade; +} + + +void AudioDataArray::forward() { + lockStampArray(); + internalForward(); + unlockStampArray(); +} + + +void AudioDataArray::clear() { + lockStampArray(); + fillgrade=0; + readPos=0; + writePos=0; + pcmSum=0; + unlockStampArray(); +} + + diff --git a/mpeglib/lib/output/audioDataArray.h b/mpeglib/lib/output/audioDataArray.h new file mode 100644 index 00000000..81cebfee --- /dev/null +++ b/mpeglib/lib/output/audioDataArray.h @@ -0,0 +1,55 @@ +/* + fifo for audioData + 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 __AUDIODATAARRAY_H +#define __AUDIODATAARRAY_H + +#include "../util/abstract/abs_thread.h" +#include "audioData.h" + + +class AudioDataArray { + + AudioData** audioDataArray; + int fillgrade; + int entries; + + int writePos; + int readPos; + int pcmSum; + + public: + AudioDataArray(int entries); + ~AudioDataArray(); + + int insertAudioData(AudioData* src); + AudioData* readAudioData(); + + int getFillgrade(); + int getPCMSum(); + void forward(); + void clear(); + + private: + void lockStampArray(); + void unlockStampArray(); + void internalForward(); + + abs_thread_mutex_t writeInMut; + abs_thread_mutex_t changeMut; + + + +}; +#endif diff --git a/mpeglib/lib/output/audioTime.cpp b/mpeglib/lib/output/audioTime.cpp new file mode 100644 index 00000000..f4ed2e9c --- /dev/null +++ b/mpeglib/lib/output/audioTime.cpp @@ -0,0 +1,154 @@ +/* + defines the format of an audio stream + 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 "audioTime.h" + +#include <iostream> + +using namespace std; + + +AudioTime::AudioTime(){ + time=0.0; +} + + +AudioTime::~AudioTime() { +} + + +void AudioTime::setFormat(int stereo,int samplesize,int speed,int sign, int bigendian) { + setStereo(stereo); + setSampleSize(samplesize); + setSpeed(speed); + setSign(sign); + setBigendian(bigendian); +} + + +int AudioTime::getStereo() { + return stereo; +} + + +int AudioTime::getSampleSize() { + return samplesize; +} + + +int AudioTime::getSpeed() { + return speed; +} + +int AudioTime::getSign() { + return _sign; +} + +int AudioTime::getBigendian() { + return _bigendian; +} + +void AudioTime::setStereo(int stereo) { + this->stereo=stereo; +} + + +void AudioTime::setSampleSize(int samplesize) { + this->samplesize=samplesize; +} + + +void AudioTime::setSpeed(int speed) { + this->speed=speed; +} + +void AudioTime::setSign(int sign) { + this->_sign=sign; +} + +void AudioTime::setBigendian(int bigendian) { + this->_bigendian = bigendian; +} + +float AudioTime::getTime() { + return time; +} + + +void AudioTime::setTime(float time) { + this->time=time; +} + + +void AudioTime::forwardTime(int bytes){ + time+=calculateTime(bytes); +} + + +float AudioTime::calculateTime(int bytes) { + float back=0; + + bytes=bytes/(samplesize/8); + if (stereo==1) { + bytes=bytes/2; + } + if (speed != 0) { + back=(float)bytes/(float)speed; + } + return back; +} + + +/** + How much byte we need for time usecs? +*/ +int AudioTime::calculateBytes(float time) { + float back=time; + + if (speed != 0) { + back=back*(float)speed; + } + back=back*(float)(samplesize/8); + if (stereo==1) { + back=back*2.0; + } + return (int)back; +} + + + +void AudioTime::sleepWrite(int size) { + timeval_t time; + float timeLength=calculateTime(size); + time.tv_sec=(long)timeLength; + time.tv_usec=(long)(1000000*(timeLength-time.tv_sec)); + TimeWrapper::usleep(&time); +} + + +void AudioTime::print() { + cout << "AudioTime-begin-"<<endl; + cout << "stereo:"<<getStereo()<<" sampleSize:"<<getSampleSize() + << " speed: "<<getSpeed()<<endl; + + cout << "AudioTime-end-"<<endl; + +} + + +void AudioTime::copyTo(AudioTime* dest) { + dest->setStereo(getStereo()); + dest->setSampleSize(getSampleSize()); + dest->setSpeed(getSpeed()); +} + diff --git a/mpeglib/lib/output/audioTime.h b/mpeglib/lib/output/audioTime.h new file mode 100644 index 00000000..3b16bb02 --- /dev/null +++ b/mpeglib/lib/output/audioTime.h @@ -0,0 +1,68 @@ +/* + defines the format of an audio stream + 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 __AUDIOTIME_H +#define __AUDIOTIME_H + +#include "../util/timeWrapper.h" + +class AudioTime { + + int stereo; + int samplesize; + int speed; + int _sign; + int _bigendian; + float time; + + public: + AudioTime(); + ~AudioTime(); + + //cd-quality:true,16,44100 + void setFormat(int stereo,int samplesize,int speed,int sign=true, int bigendian=false); + + int getStereo(); + int getSampleSize(); + int getSpeed(); + int getSign(); + int getBigendian(); + + void setStereo(int stereo); + void setSampleSize(int samplesize); + void setSpeed(int speed); + void setSign(int sign); + void setBigendian(int bigendian); + + + float getTime(); + void setTime(float time); + void forwardTime(int bytes); + + // do not modify the internal time + float calculateTime(int bytes); + int calculateBytes(float time); + + void sleepWrite(int size); + + + void copyTo(AudioTime* audioTime); + void print(); + +}; + + + +#endif diff --git a/mpeglib/lib/output/avSyncer.cpp b/mpeglib/lib/output/avSyncer.cpp new file mode 100644 index 00000000..ca12a21e --- /dev/null +++ b/mpeglib/lib/output/avSyncer.cpp @@ -0,0 +1,386 @@ +/* + encapsulates the syncing methods, to use it in other classes + 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 "avSyncer.h" + +#include "audioDataArray.h" +#include "performance.h" + +#include <iostream> + +using namespace std; + +AVSyncer::AVSyncer(int bufferSize) { + oneFrameTime=0; + onePicFrameInAudioBytes=8192; + this->bufferSize=bufferSize; + + abs_thread_mutex_init(&writeInMut); + abs_thread_mutex_init(&changeMut); + + + audioDataInsert=new AudioData(); + audioDataArray=new AudioDataArray(400); + audioDataCurrent=audioDataArray->readAudioData(); + + startAudio=new TimeStamp(); + endAudio=new TimeStamp(); + audioTime=new AudioTime(); + lAudioRunning=false; + performance=new Performance(); + + waitTime=new TimeStamp(); + diffTime=new TimeStamp(); + videoTimeStamp=new TimeStamp(); + + lPerformance=false; + lavSync=true; + + +} + + +AVSyncer::~AVSyncer() { + delete audioDataArray; + delete audioDataInsert; + delete audioTime; + delete startAudio; + delete endAudio; + abs_thread_mutex_destroy(&writeInMut); + abs_thread_mutex_destroy(&changeMut); + delete waitTime; + delete diffTime; + delete performance; + delete videoTimeStamp; +} + + + +int AVSyncer::audioSetup(int frequency,int stereo,int sign, + int big,int sixteen) { + audioTime->setFormat(stereo,sixteen,frequency,sign,big); + setAudioRunning(true); + return true; +} + + +int AVSyncer::audioPlay(TimeStamp* startStamp, + TimeStamp* endStamp,char* , int size) { + + + + + audioDataInsert->setStart(startStamp); + audioDataInsert->setEnd(endStamp); + audioDataInsert->setAudioTime(audioTime); + audioDataInsert->setPCMLen(size); + + setAudioSync(audioDataInsert); + return size; +} + + + +void AVSyncer::audioClose(void) { + lockSyncData(); + setAudioRunning(false); + audioDataArray->clear(); + unlockSyncData(); +} + + + + + +int AVSyncer::getPreferredDeliverSize() { + return onePicFrameInAudioBytes; +} + + + +int AVSyncer::getFrameusec() { + lockSyncData(); + int back=oneFrameTime; + unlockSyncData(); + return back; +} + +void AVSyncer::setAudioBufferSize(int size) { + bufferSize=size; +} + + +void AVSyncer::config(const char* key,const char* value,void*) { + if (strcmp(key,"-s")==0) { + if (strcmp(value,"on")==0) { + lavSync=true; + cout << "******** lavSync on"<<endl; + } else { + lavSync=false; + cout << "******** lavSync off"<<endl; + } + } + if (strcmp(key,"-p")==0) { + cout << "setting perfomance test true"<<endl; + lPerformance=true; + } + +} + + + +void AVSyncer::setAudioSync(AudioData* audioData) { + + lockSyncData(); + + if (onePicFrameInAudioBytes <= 0) { + // no video present, we cannot calculate audio + // pcm length + //cout << "no video present, we cannot calculate audio pcm length"<<endl; + unlockSyncData(); + return; + } + // buffersize is the simulated size of /dev/dsp + + + + // we implement a fifo hopefully + // we check the right audio pts time out + // when /dev/dsp acutally plays it. + audioDataArray->insertAudioData(audioData); + int pcmSum=audioDataArray->getPCMSum(); + if (pcmSum >= bufferSize) { + audioDataCurrent=audioDataArray->readAudioData(); + setAudioRunning(true); + audioDataArray->forward(); + } + TimeStamp* startAudio=audioDataCurrent->getStart(); + int lpts=startAudio->getPTSFlag(); + + if (lpts==true) { + SyncClock* syncClock=startAudio->getSyncClock(); + if (syncClock != NULL) { + double pts=startAudio->getPTSTimeStamp(); + double scr=startAudio->getSCRTimeStamp(); + + syncClock->syncAudio(pts,scr); + + } else { + cout <<"syncClock == NULL (audio)"<<endl; + } + } else { + //cout << "lpts is false"<<endl; + } + unlockSyncData(); + +} + + + +int AVSyncer::syncPicture(YUVPicture* syncPic) { + if (syncPic == NULL) { + cout << "syncPic == NULL"<<endl; + return false; + } + + float picPerSec=syncPic->getPicturePerSecond(); + int oneFrameTime=0; + + if (picPerSec > 0.0) { + oneFrameTime=(int) (1000000.0/picPerSec); + } else { + syncPic->print("picPersec is 0"); + return true; + } + + if (lPerformance==true) { + waitTime->set(0,0); + syncPic->setWaitTime(waitTime); + performance->incPictureCount(); + return true; + } + + int lpacketSync=true; + + videoTimeStamp->gettimeofday(); + diffTime->minus(videoTimeStamp,videoTimeStamp); + + + if (lavSync==false) { + if (videoTimeStamp->isNegative()) { + diffTime->gettimeofday(); + diffTime->addOffset(0,oneFrameTime); + cout << "skip time based"<<endl; + return false; + } + } + + + + videoTimeStamp->copyTo(waitTime); + + TimeStamp* earlyTime=syncPic->getEarlyTime(); + earlyTime->set(0,0); + + + if (lavSync) { + + lpacketSync=avSync(syncPic->getStartTimeStamp(), + waitTime, + earlyTime, + syncPic->getPicturePerSecond()); + + } + + + + + if (lpacketSync == false) { + //cout << "skip"<<endl; + diffTime->gettimeofday(); + diffTime->addOffset(0,oneFrameTime); + return false; + } + + syncPic->setWaitTime(waitTime); + + if (lavSync) { + waitTime->minus(videoTimeStamp,waitTime); + if (waitTime->isPositive()) { + diffTime->addOffset(waitTime); + } + } + diffTime->addOffset(0,oneFrameTime); + return true; + + +} + + + +/** + Heart of the sync routine is here! + + Currently its more in a state of "try/test" + + +*/ +int AVSyncer::avSync(TimeStamp* startVideo, + TimeStamp* waitTime, + TimeStamp* earlyTime, + float picPerSec ) { + + + double videoStartPTSTime=startVideo->getPTSTimeStamp(); + double videoStartSCRTime=startVideo->getSCRTimeStamp(); + int videoFrameCounter=startVideo->getVideoFrameCounter(); + double frameTime=0.0; + + + + lockSyncData(); + if (picPerSec > 0) { + oneFrameTime=(long)(1000000.0/picPerSec); + frameTime=1.0/picPerSec; + onePicFrameInAudioBytes=audioTime->calculateBytes(1.0/picPerSec); + + } + if (lAudioRunning==false) { + waitTime->set(0,oneFrameTime); + + unlockSyncData(); + return true; + } + + + /* + startAudio->print("audio"); + startVideo->print("video"); + */ + + + + + + + /* + cout << "audioStartAudioPacketNrMinor:"<<audioStartAudioPacketNrMinor<<endl; + cout << "audioStartPTSTime:"<<audioStartPTSTime<<endl; + cout << "audioStartEndPTSTime:"<<audioStartEndPTSTime<<endl; + cout << "videoStartPTSTime:"<<videoStartPTSTime<<endl; + */ + + + /** + Here we make sure that we sync over an audio packet only one + time. + */ + + waitTime->set(0,0); + SyncClock* syncClock=startVideo->getSyncClock(); + int back=false; + double addPts=videoFrameCounter*frameTime; + double pts=videoStartPTSTime+addPts; + + if (syncClock != NULL) { + + back=syncClock->syncVideo(pts, + videoStartSCRTime,earlyTime,waitTime); + } else { + cout << "syncClock == NULL (video)"<<endl; + } + unlockSyncData(); + + if (back==true) { + //earlyTime->print("earlyTime"); + earlyTime->waitForIt(); + /* + double tmp; + double time=syncClock->getPTSTime(&tmp); + cout << "time after wait:"<<time<<endl; + */ + } + /* + if (back == false) { + cout <<"real pts:"<<videoStartPTSTime + <<" calc pts"<<pts + <<" frameNo:"<<videoFrameCounter + <<" frameTime:"<<frameTime<<endl; + } + */ + + + + return back; + +} + +int AVSyncer::getAudioRunning() { + return lAudioRunning; +} + + +void AVSyncer::setAudioRunning(int lAudioRunning) { + this->lAudioRunning=lAudioRunning; +} + + +void AVSyncer::lockSyncData() { + abs_thread_mutex_lock(&changeMut); + abs_thread_mutex_lock(&writeInMut); + abs_thread_mutex_unlock(&changeMut); +} + +void AVSyncer::unlockSyncData() { + abs_thread_mutex_unlock(&writeInMut); +} diff --git a/mpeglib/lib/output/avSyncer.h b/mpeglib/lib/output/avSyncer.h new file mode 100644 index 00000000..b5a7ae7d --- /dev/null +++ b/mpeglib/lib/output/avSyncer.h @@ -0,0 +1,96 @@ +/* + encapsulates the syncing methods, to use it in other classes + 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 __AVSYNCER_H +#define __AVSYNCER_H + +#include <stdlib.h> + +#include "../util/render/yuvPicture.h" +#include "../util/syncClock.h" +#include "audioTime.h" + +class Performance; +class AudioDataArray; +class AudioData; + +class AVSyncer { + + AudioData* audioDataInsert; + AudioData* audioDataCurrent; + AudioDataArray* audioDataArray; + Performance* performance; + + AudioTime* audioTime; + int onePicFrameInAudioBytes; + int oneFrameTime; + + int lAudioRunning; + + abs_thread_mutex_t writeInMut; + abs_thread_mutex_t changeMut; + + + int bufferSize; + + TimeStamp* startAudio; + TimeStamp* endAudio; + + TimeStamp* videoTimeStamp; + TimeStamp* diffTime; + TimeStamp* waitTime; + + int lPerformance; + int lavSync; + int lastAudioPacket; + double pts_jitter; + + + public: + AVSyncer(int bufferSize); + ~AVSyncer(); + + // audio + int audioSetup(int frequency,int stereo,int sign,int big,int sixteen); + int audioPlay(TimeStamp* startStamp, + TimeStamp* endStamp,char *buffer, int size); + void audioClose(void); + void setAudioBufferSize(int size); + + int getPreferredDeliverSize(); + + // video + int getFrameusec(); + int syncPicture(YUVPicture* syncPic); + + void config(const char* key,const char* value,void* user_data); + + + + private: + int getAudioRunning(); + void setAudioRunning(int lAudioRunning); + + void lockSyncData(); + void unlockSyncData(); + void setAudioSync(AudioData* audioData); + + // methods which belong not to the OutputStream interface + int avSync(TimeStamp* startVideoStamp, + TimeStamp* waitTime, + TimeStamp* earlyTime, + float picPerSec); + +}; +#endif diff --git a/mpeglib/lib/output/dspX11OutputStream.cpp b/mpeglib/lib/output/dspX11OutputStream.cpp new file mode 100644 index 00000000..05503ffa --- /dev/null +++ b/mpeglib/lib/output/dspX11OutputStream.cpp @@ -0,0 +1,236 @@ +/* + concret OutputClass + 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 "dspX11OutputStream.h" +#include "../util/audio/dspWrapper.h" +#include "windowOut.h" +#include "avSyncer.h" +#include "yuvDumper.h" + +#include <iostream> + +using namespace std; + +DspX11OutputStream::DspX11OutputStream(int bufferSize) { + dspWrapper=new DSPWrapper(); + x11Window=new WindowOut(); + avSyncer=new AVSyncer(bufferSize); + yuvDumper=new YUVDumper(); + + audioTime=new AudioTime(); + + lPerformance=false; + lneedInit=false; + lVideoInit=false; + lBufferSet=false; + lYUVDump=false; +} + + +DspX11OutputStream::~DspX11OutputStream() { + delete dspWrapper; + delete x11Window; + + delete avSyncer; + delete audioTime; + delete yuvDumper; +} + + + +int DspX11OutputStream::audioSetup(int frequency,int stereo, + int sign,int big,int sixteen) { + + dspWrapper->audioSetup(stereo,sixteen,sign,big,frequency); + audioTime->setFormat(stereo,sixteen,frequency,sign,big); + avSyncer->audioSetup(frequency,stereo,sign,big,sixteen); + if (dspWrapper->isOpenDevice() == true) { + if (lBufferSet==false) { + int size=dspWrapper->getAudioBufferSize(); + avSyncer->setAudioBufferSize(size); + } + } + return true; +} + + +void DspX11OutputStream::audioClose(void) { + avSyncer->audioClose(); + dspWrapper->closeDevice(); +} + + +void DspX11OutputStream::audioOpen() { + if (dspWrapper->isOpenDevice() == false) { + dspWrapper->openDevice(); + if (lBufferSet==false) { + int size=dspWrapper->getAudioBufferSize(); + avSyncer->setAudioBufferSize(size); + } + } +} + + + + +int DspX11OutputStream::audioPlay(TimeStamp* startStamp, + TimeStamp* endStamp,char *buffer, int size) { + + if (lneedInit) { + cout << "FIXME. work on audioFrames!!"<<endl; + lneedInit=false; + } + + if (lPerformance==false) { + // + // Now feed data smoothly into the dsp/avSyncer + // + int pos=0; + int rest=size; + int inc=getPreferredDeliverSize(); + int len; + + while (rest > 0) { + len=rest; + if (len>inc) { + len=inc; + } + if (dspWrapper->isOpenDevice()) { + if (dspWrapper->audioPlay(buffer,len) != len) { + cout << "write error to dsp"<<endl; + lneedInit=true; + return size-rest; + } + } + + avSyncer->audioPlay(startStamp,endStamp,buffer,len); + buffer+=len; + rest-=len; + } + return size; + } else { + return size; + } +} + + +int DspX11OutputStream::getPreferredDeliverSize() { + if (avSyncer->getPreferredDeliverSize() <= 500) { + return 500; + } + return avSyncer->getPreferredDeliverSize(); +} + + +int DspX11OutputStream::openWindow(int width, int height,const char *title) { + int back=x11Window->openWindow(width,height,title); + setOutputInit(true); + if (lYUVDump) { + yuvDumper->openWindow(width,height,title); + } + return back; +} + +int DspX11OutputStream::x11WindowId() { + return x11Window->x11WindowId(); +} + + +void DspX11OutputStream::closeWindow() { + x11Window->closeWindow(); +} + +void DspX11OutputStream::flushWindow() { + x11Window->flushWindow(); +} + + +PictureArray* DspX11OutputStream::lockPictureArray() { + return x11Window->lockPictureArray(); +} + + +void DspX11OutputStream::unlockPictureArray(PictureArray* pictureArray) { + + + + YUVPicture* pic=pictureArray->getYUVPictureCallback(); + + if (lYUVDump) { + yuvDumper->unlockPictureArray(pictureArray); + } + if (avSyncer->syncPicture(pic)==false) { + return; + } + + x11Window->unlockPictureArray(pictureArray); + + +} + +int DspX11OutputStream::getFrameusec() { + return avSyncer->getFrameusec(); +} + + + +int DspX11OutputStream::getOutputInit() { + return lVideoInit; +} + + +void DspX11OutputStream::setOutputInit(int lInit) { + this->lVideoInit=lInit; +} + + + +void DspX11OutputStream::config(const char* key, + const char* value,void* user_data) { + + cout << "key:"<<key<<endl; + if (strcmp(key,"-s")==0) { + avSyncer->config(key,value,user_data); + } + if (strcmp(key,"-b")==0) { + lBufferSet=true; + int size=strtol(value,(char **)NULL,10); + cout << "simulated audio buffersize:"<<size<<" bytes"<<endl; + avSyncer->setAudioBufferSize(size); + } + if (strcmp(key,"-p")==0) { + lPerformance=true; + avSyncer->config(key,value,user_data); + } + if (strcmp(key,"yufDump")==0) { + int method=atoi(value); + switch(method) { + case 2: + yuvDumper->setMethod(_DUMP_YUV_AS_STREAM); + break; + default: + cout << "unknown dump method"<<endl; + } + lYUVDump=true; + } + x11Window->config(key,value,user_data); +} + + +AVSyncer* DspX11OutputStream::getAVSyncer() { + return avSyncer; +} + + + diff --git a/mpeglib/lib/output/dspX11OutputStream.h b/mpeglib/lib/output/dspX11OutputStream.h new file mode 100644 index 00000000..9b3eb859 --- /dev/null +++ b/mpeglib/lib/output/dspX11OutputStream.h @@ -0,0 +1,89 @@ +/* + concret OutputClass + 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 __DSPX11OUTPUTSTREAM_H +#define __DSPX11OUTPUTSTREAM_H + +#include "outputStream.h" + + + +class DSPWrapper; +class WindowOut; +class AVSyncer; +class AudioTime; +class Performance; +class YUVDumper; + +class DspX11OutputStream : public OutputStream { + + DSPWrapper* dspWrapper; + WindowOut* x11Window; + AVSyncer* avSyncer; + + + int lBufferSet; + int lVideoInit; + int lavSync; + int lneedInit; + int lPerformance; + int lYUVDump; + + AudioTime* audioTime; + YUVDumper* yuvDumper; + + public: + DspX11OutputStream(int bufferSize); + ~DspX11OutputStream(); + + // Audio Output + + int audioSetup(int frequency,int stereo,int sign,int big,int sixteen); + void audioClose(); + void audioOpen(); + int audioPlay(TimeStamp* startStamp, + TimeStamp* endStamp,char *buffer, int size); + + + int getPreferredDeliverSize(); + + + // Video Output + + int openWindow(int width, int height,const char *title); + int x11WindowId(); + void closeWindow(); + void flushWindow(); + + PictureArray* lockPictureArray(); + void unlockPictureArray(PictureArray* pictureArray); + + int getFrameusec(); + + int getDepth(); + int getOutputInit(); + void setOutputInit(int lInit); + + void config(const char* key,const char* value,void* user_data); + + // methods which do not belong to the outputStream intferface; + AVSyncer* getAVSyncer(); + + +}; + + + +#endif diff --git a/mpeglib/lib/output/outPlugin.cpp b/mpeglib/lib/output/outPlugin.cpp new file mode 100644 index 00000000..cbae10ec --- /dev/null +++ b/mpeglib/lib/output/outPlugin.cpp @@ -0,0 +1,71 @@ +/* + generic output 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 "outPlugin.h" + +#include <iostream> + +using namespace std; + + +OutPlugin::OutPlugin() { +} + + +OutPlugin::~OutPlugin() { +} + + + +OutputStream* OutPlugin::createOutputStream(int outputType) { + + // make checks which input routine to use + OutputStream* outputStream; + int method; + + outputStream=NULL; + method=outputType; + + switch(method) { + case _OUTPUT_LOCAL: { + outputStream=new DspX11OutputStream(1024*64); + break; + } + case _OUTPUT_ARTS: { + outputStream=new ArtsOutputStream(NULL); + break; + } + case _OUTPUT_EMPTY: { + outputStream=new OutputStream(); + break; + } + default: + cout << "error cannot create default output stream"<<endl; + exit(0); + } + + return outputStream; + + +} + +OutputStream* OutPlugin::createOutputStream(int outputType,int lThreadSafe) { + OutputStream* output=OutPlugin::createOutputStream(outputType); + if (lThreadSafe==false) { + return output; + } + OutputStream* tsOutput=new ThreadSafeOutputStream(output); + return tsOutput; +} + diff --git a/mpeglib/lib/output/outPlugin.h b/mpeglib/lib/output/outPlugin.h new file mode 100644 index 00000000..b70620a6 --- /dev/null +++ b/mpeglib/lib/output/outPlugin.h @@ -0,0 +1,44 @@ +/* + generic output 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 __OUTPLUGIN_H +#define __OUTPLUGIN_H + + +#include "dspX11OutputStream.h" +#include "artsOutputStream.h" +#include "threadSafeOutputStream.h" +#include <kdemacros.h> + +#define _OUTPUT_LOCAL 1 +#define _OUTPUT_EMPTY 2 +#define _OUTPUT_YAF 3 +#define _OUTPUT_ARTS 4 + +#define _OUTPUT_THREADSAFE 1 + +class KDE_EXPORT OutPlugin { + + public: + OutPlugin(); + ~OutPlugin(); + + static OutputStream* createOutputStream(int outputType); + static OutputStream* createOutputStream(int outputType,int lThreadSafe); + +}; +#endif + + + + diff --git a/mpeglib/lib/output/outputStream.cpp b/mpeglib/lib/output/outputStream.cpp new file mode 100644 index 00000000..ef209cbc --- /dev/null +++ b/mpeglib/lib/output/outputStream.cpp @@ -0,0 +1,238 @@ +/* + generic output class + 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 "outputStream.h" +#include "../util/mmx/mmx.h" + +#include <iostream> + +using namespace std; + +OutputStream::OutputStream() { + // we call mm_support() here because it is the only position + // where we gurantee that not threads are + // running (the call is not thread safe) + // afer the call we never execute the asm part again + // and everything is fine + mm_support(); + abs_thread_mutex_init(&stateChangeMut); + abs_thread_cond_init(&stateChangeCond); + + audioState=0; + videoState=0; + audioInit(); + videoInit(); +} + + +OutputStream::~OutputStream() { + audioInit(); + videoInit(); + abs_thread_cond_destroy(&stateChangeCond); + abs_thread_mutex_destroy(&stateChangeMut); +} + + +int OutputStream::audioInit() { + sendSignal(_STREAM_MASK_IS_INIT,false,_STREAMTYPE_AUDIO); + sendSignal(_STREAM_MASK_IS_EOF,false,_STREAMTYPE_AUDIO); + sendSignal(_STREAM_MASK_IS_DATA,false,_STREAMTYPE_AUDIO); + return true; +} + + +int OutputStream::audioSetup(int ,int , + int ,int ,int ) { + sendSignal(_STREAM_MASK_IS_INIT,true,_STREAMTYPE_AUDIO); + return true; +} + + +int OutputStream::audioPlay(TimeStamp* , + TimeStamp* ,char* , int len) { + sendSignal(_STREAM_MASK_IS_DATA,true,_STREAMTYPE_AUDIO); + return len; +} + +void OutputStream::audioFlush() { + sendSignal(_STREAM_MASK_IS_EOF,true,_STREAMTYPE_AUDIO); +} + + +void OutputStream::audioClose() { + cerr << "direct virtual call OutputStream::audioClose"<<endl; + exit(0); +} + +void OutputStream::audioOpen() { + cerr << "direct virtual call OutputStream::audioOpen"<<endl; + exit(0); +} + + + +void OutputStream::sendSignal(int signal,int value,int streamType) { + abs_thread_mutex_lock(&stateChangeMut); + int* modifyState=NULL; + switch(streamType) { + case _STREAMTYPE_AUDIO: + modifyState=&audioState; + break; + case _STREAMTYPE_VIDEO: + modifyState=&videoState; + break; + default: + cout << "unknown streamType:"<<streamType + <<" in OutputStream::sendSignal"<<endl; + exit(0); + } + // should we set the bit? + if (value==true) { + // set it with "or" + *modifyState|=signal; + } else { + // we should remove the bit + // is it currently set? + if (*modifyState & signal) { + // remove it + *modifyState-=signal; + } + } + + + abs_thread_cond_signal(&stateChangeCond); + abs_thread_mutex_unlock(&stateChangeMut); + +} + + +int OutputStream::getPreferredDeliverSize() { + cerr << "direct virtual call OutputStream::getPreferredDeliverSize()"<<endl; + return 4096; +} + +int OutputStream::videoInit() { + sendSignal(_STREAM_MASK_IS_INIT,false,_STREAMTYPE_VIDEO); + sendSignal(_STREAM_MASK_IS_EOF,false,_STREAMTYPE_VIDEO); + sendSignal(_STREAM_MASK_IS_DATA,false,_STREAMTYPE_VIDEO); + return true; +} + +int OutputStream::openWindow(int , int ,const char* ) { + sendSignal(_STREAM_MASK_IS_INIT,true,_STREAMTYPE_VIDEO); + return true; +} + +int OutputStream::x11WindowId() { + cout << "direct virtual call OutputStream::x11WindowId()" << endl; + return -1; +} + +void OutputStream::closeWindow() { + cerr << "direct virtual call OutputStream::closeWindow"<<endl; + exit(0); +} + +void OutputStream::flushWindow() { + sendSignal(_STREAM_MASK_IS_EOF,true,_STREAMTYPE_VIDEO); +} + + +PictureArray* OutputStream::lockPictureArray() { + cerr << "direct virtual call OutputStream::lockPictureArray"<<endl; + exit(0); + return NULL; +} + + +void OutputStream::unlockPictureArray(PictureArray* ) { + sendSignal(_STREAM_MASK_IS_DATA,true,_STREAMTYPE_VIDEO); +} + + + + + +int OutputStream::getOutputInit() { + cerr << "direct virtual call OutputStream::getOutputInit"<<endl; + exit(0); + return false; +} + + +void OutputStream::setOutputInit(int lInit) { + cerr << "direct virtual call OutputStream::setOutputInit:"<<lInit<<endl; + exit(0); +} + + + +void OutputStream::writeInfo(PluginInfo* ) { + +} + + +void OutputStream::config(const char* key, + const char* value,void* user_data) { + cerr << "direct virtual call OutputStream::config"<<endl; + printf("key:%s\n",key); + printf("value:%s\n",value); + printf("user_data:%p\n",user_data); + exit(0); +} + +int OutputStream::getFrameusec() { + cerr << "direct virtual call OutputStream::getFrameusec"<<endl; + return 0; +} + + + +int OutputStream::waitStreamState(int method,int mask,int streamType) { + + int* waitState=NULL; + switch(streamType) { + case _STREAMTYPE_AUDIO: + waitState=&audioState; + break; + case _STREAMTYPE_VIDEO: + waitState=&videoState; + break; + default: + cout << "unknown streamType:"<<streamType + <<" in OutputStream::waitStreamState"<<endl; + exit(0); + } + + if (method == _OUTPUT_WAIT_METHOD_BLOCK) { + abs_thread_mutex_lock(&stateChangeMut); + while ((*waitState &= mask)==0) { + cout << "waitStreamState:"<<waitState<<endl; + cout << "mask:"<<mask<<endl; + abs_thread_cond_wait(&stateChangeCond,&stateChangeMut); + } + abs_thread_mutex_unlock(&stateChangeMut); + return true; + } + + int back=false; + if (method == _OUTPUT_WAIT_METHOD_POLL) { + abs_thread_mutex_lock(&stateChangeMut); + back=*waitState; + abs_thread_mutex_unlock(&stateChangeMut); + return back; + } + cout << " OutputStream::waitStreamState method not implemented"<<endl; + exit(0); + return 0; +} diff --git a/mpeglib/lib/output/outputStream.h b/mpeglib/lib/output/outputStream.h new file mode 100644 index 00000000..9ef538fd --- /dev/null +++ b/mpeglib/lib/output/outputStream.h @@ -0,0 +1,151 @@ +/* + generic output class + 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 __OUTPUTSTREAM_H +#define __OUTPUTSTREAM_H + +#include "../util/timeStamp.h" +#include "pluginInfo.h" +#include "../util/render/pictureArray.h" +#include "../util/abstract/abs_thread.h" +#include <kdemacros.h> + +#define _OUTPUT_WAIT_METHOD_BLOCK 1 +#define _OUTPUT_WAIT_METHOD_POLL 2 +#define _OUTPUT_WAIT_METHOD_CALLBACK 3 + + +#define _STREAM_MASK_IS_INIT 1 +#define _STREAM_MASK_IS_EOF 2 +#define _STREAM_MASK_IS_DATA 4 + +#define _STREAM_MASK_ALL 1+2+4 + +#define _STREAMTYPE_AUDIO 1 +#define _STREAMTYPE_VIDEO 2 + + +/** + Outputstream. A nice base class. Mostly obvious methods, + except PictureArray. + write your picture into this structure + and then put it on the surface with the unlock call. + +*/ + + +/** + life of stream states: + -------------- + method flag additional calls + construct audioInit() + + + + destruct audioInit() + + audioInit isInit=false + isEof=false + isData=false + + audioSetup isInit=true + audioFlush isEof=true + audioPlay isData=true + + + Note: after a call of streamInit we have an "invalid" state + obviously there is no stream where eof==false but + and has not been initialised. + + another invalid state is audioInit->audioPlay + +*/ + + + + +class KDE_EXPORT OutputStream { + + int audioState; + int videoState; + abs_thread_mutex_t stateChangeMut; + abs_thread_cond_t stateChangeCond; + + public: + OutputStream(); + + virtual ~OutputStream(); + + // Audio Stream handling + virtual int audioInit(); + virtual int audioSetup(int freq,int stereo,int sign,int big,int sampleSize); + virtual int audioPlay(TimeStamp* startStamp, + TimeStamp* endStamp,char *buffer, int size); + virtual void audioFlush(); + + // Audio device "/dev/dsp" handling + virtual void audioClose(); + virtual void audioOpen(); + + // hack: FIX it + virtual int getPreferredDeliverSize(); + + + // stream State handling + + // we return the mask which triggerd (by "AND") + // or the current polled mask when method is POLL + // Note: you can only wait for "true" signals + virtual int waitStreamState(int method,int mask,int streamType); + + + + + // Video Output + virtual int videoInit(); + virtual int openWindow(int width, int height,const char *title); + virtual int x11WindowId(); + virtual void closeWindow(); + virtual void flushWindow(); + + + // get the current surfaces to draw into + virtual PictureArray* lockPictureArray(); + virtual void unlockPictureArray(PictureArray* pictureArray); + + + + // maybe not needed: + virtual int getFrameusec(); + virtual int getOutputInit(); + virtual void setOutputInit(int lInit); + + // Info Output + virtual void writeInfo(class PluginInfo* pluginInfo); + + + // config Output + virtual void config(const char* key, + const char* value,void* user_data); + + private: + void initStream(); + + protected: + // sometimes useful, but use with care + void sendSignal(int signal,int value,int streamType); + +}; +#endif diff --git a/mpeglib/lib/output/performance.cpp b/mpeglib/lib/output/performance.cpp new file mode 100644 index 00000000..9e2b7f92 --- /dev/null +++ b/mpeglib/lib/output/performance.cpp @@ -0,0 +1,50 @@ +/* + measures picture/second + 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 "performance.h" + +#include <iostream> + +using namespace std; + + +Performance::Performance() { + picCnt=0; + startTime=new TimeStamp(); + endTime=new TimeStamp(); + +} + + +Performance::~Performance() { + delete startTime; + delete endTime; +} + + +void Performance::incPictureCount() { + if (picCnt==0) { + startTime->gettimeofday(); + } + picCnt++; + if (picCnt==200) { + endTime->gettimeofday(); + TimeStamp diffTime; + endTime->minus(startTime,&diffTime); + double secs=(double)diffTime.getAsSeconds(); + + double picSec=(double)picCnt/secs; + cout << "picPerSec:"<<picSec<<" secs:"<<secs<<endl; + picCnt=0; + } +} diff --git a/mpeglib/lib/output/performance.h b/mpeglib/lib/output/performance.h new file mode 100644 index 00000000..d7d54572 --- /dev/null +++ b/mpeglib/lib/output/performance.h @@ -0,0 +1,34 @@ +/* + measures picture/second + 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 __PERFORMANCE_H +#define __PERFORMANCE_H + +#include "../util/timeStamp.h" + +class Performance { + + int picCnt; + TimeStamp* startTime; + TimeStamp* endTime; + + + public: + + Performance(); + ~Performance(); + void incPictureCount(); + +}; +#endif diff --git a/mpeglib/lib/output/pluginInfo.cpp b/mpeglib/lib/output/pluginInfo.cpp new file mode 100644 index 00000000..c741852c --- /dev/null +++ b/mpeglib/lib/output/pluginInfo.cpp @@ -0,0 +1,65 @@ +/* + add on information about 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 "pluginInfo.h" + +#include <iostream> + +using namespace std; + + +PluginInfo::PluginInfo() { + musicName=new DynBuffer(20); + + reset(); + +} + + +PluginInfo::~PluginInfo() { + delete musicName; +} + +void PluginInfo::setLength(int sec) { + this->sec=sec; +} + + +int PluginInfo::getLength() { + return sec; +} + + +void PluginInfo::reset(){ + sec=0; + musicName->clear(); + musicName->append("none"); +} + +void PluginInfo::print() { + cerr << "length in sec:"<<sec<<endl; + cerr << "url:"<<getUrl()<<endl; +} + + +void PluginInfo::setUrl(char* name) { + musicName->clear(); + if (name != NULL) { + musicName->append(name); + } +} + + +char* PluginInfo::getUrl() { + return musicName->getData(); +} diff --git a/mpeglib/lib/output/pluginInfo.h b/mpeglib/lib/output/pluginInfo.h new file mode 100644 index 00000000..7026fce9 --- /dev/null +++ b/mpeglib/lib/output/pluginInfo.h @@ -0,0 +1,48 @@ +/* + add on information about 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 __PLUGININFO_H +#define __PLUGININFO_H + +#include "../util/dynBuffer.h" +#include <kdemacros.h> + +/** + Here we have the base class for all additional information + about a plugin. + The len in time of the current song belongs here, as + well as the author, version number etc.. +*/ + + +class KDE_EXPORT PluginInfo { + + int sec; + DynBuffer* musicName; + + + public: + PluginInfo(); + ~PluginInfo(); + + void setLength(int sec); + int getLength(); + + void setUrl(char* name); + char* getUrl(); + + void reset(); + void print(); +}; +#endif diff --git a/mpeglib/lib/output/threadSafeOutputStream.cpp b/mpeglib/lib/output/threadSafeOutputStream.cpp new file mode 100644 index 00000000..ec7ab510 --- /dev/null +++ b/mpeglib/lib/output/threadSafeOutputStream.cpp @@ -0,0 +1,153 @@ +/* + thread safe wrapper for output Stream + 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 "threadSafeOutputStream.h" + + +ThreadSafeOutputStream::ThreadSafeOutputStream(OutputStream* output) { + threadQueueAudio=new ThreadQueue(); + threadQueueVideo=new ThreadQueue(); + this->output=output; +} + + +ThreadSafeOutputStream::~ThreadSafeOutputStream() { + delete threadQueueAudio; + delete threadQueueVideo; + delete output; +} + +int ThreadSafeOutputStream::audioInit() { + int back; + threadQueueAudio->waitForExclusiveAccess(); + back=output->audioInit(); + threadQueueAudio->releaseExclusiveAccess(); + return back; +} + + +int ThreadSafeOutputStream::audioSetup(int freq,int stereo, + int sign,int big,int sampleSize) { + int back; + threadQueueAudio->waitForExclusiveAccess(); + back=output->audioSetup(freq,stereo,sign,big,sampleSize); + threadQueueAudio->releaseExclusiveAccess(); + return back; +} + + +int ThreadSafeOutputStream::audioPlay(TimeStamp* start, + TimeStamp* end,char* buf, int len) { + int back; + threadQueueAudio->waitForExclusiveAccess(); + back=output->audioPlay(start,end,buf,len); + threadQueueAudio->releaseExclusiveAccess(); + return back; +} + +void ThreadSafeOutputStream::audioFlush() { + threadQueueAudio->waitForExclusiveAccess(); + output->audioFlush(); + threadQueueAudio->releaseExclusiveAccess(); +} + + +void ThreadSafeOutputStream::audioClose() { + threadQueueAudio->waitForExclusiveAccess(); + output->audioClose(); + threadQueueAudio->releaseExclusiveAccess(); +} + +void ThreadSafeOutputStream::audioOpen() { + threadQueueAudio->waitForExclusiveAccess(); + output->audioOpen(); + threadQueueAudio->releaseExclusiveAccess(); +} + + + +int ThreadSafeOutputStream::getPreferredDeliverSize() { + int back; + threadQueueAudio->waitForExclusiveAccess(); + back=output->getPreferredDeliverSize(); + threadQueueAudio->releaseExclusiveAccess(); + return back; +} + +int ThreadSafeOutputStream::videoInit() { + int back; + threadQueueVideo->waitForExclusiveAccess(); + back=output->videoInit(); + threadQueueVideo->releaseExclusiveAccess(); + return back; +} + +int ThreadSafeOutputStream::openWindow(int w, int h,const char* title) { + int back; + threadQueueVideo->waitForExclusiveAccess(); + back=output->openWindow(w,h,title); + threadQueueVideo->releaseExclusiveAccess(); + return back; +} + + +void ThreadSafeOutputStream::closeWindow() { + threadQueueVideo->waitForExclusiveAccess(); + output->closeWindow(); + threadQueueVideo->releaseExclusiveAccess(); +} + +void ThreadSafeOutputStream::flushWindow() { + threadQueueVideo->waitForExclusiveAccess(); + output->flushWindow(); + threadQueueVideo->releaseExclusiveAccess(); +} + + +PictureArray* ThreadSafeOutputStream::lockPictureArray() { + PictureArray* back; + threadQueueVideo->waitForExclusiveAccess(); + back=output->lockPictureArray(); + threadQueueVideo->releaseExclusiveAccess(); + return back; +} + + +void ThreadSafeOutputStream::unlockPictureArray(PictureArray* array) { + threadQueueVideo->waitForExclusiveAccess(); + output->unlockPictureArray(array); + threadQueueVideo->releaseExclusiveAccess(); +} + + +int ThreadSafeOutputStream::getFrameusec() { + int back; + threadQueueVideo->waitForExclusiveAccess(); + back=output->getFrameusec(); + threadQueueVideo->releaseExclusiveAccess(); + return back; +} + +void ThreadSafeOutputStream::config(const char* key, + const char* value,void* user_data) { + + threadQueueVideo->waitForExclusiveAccess(); + threadQueueAudio->waitForExclusiveAccess(); + output->config(key,value,user_data); + threadQueueVideo->releaseExclusiveAccess(); + threadQueueAudio->releaseExclusiveAccess(); + +} + + + diff --git a/mpeglib/lib/output/threadSafeOutputStream.h b/mpeglib/lib/output/threadSafeOutputStream.h new file mode 100644 index 00000000..c9852a37 --- /dev/null +++ b/mpeglib/lib/output/threadSafeOutputStream.h @@ -0,0 +1,67 @@ +/* + thread safe wrapper for output Stream + 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 __THREADSAFEOUTPUTSTREAM_H +#define __THREADSAFEOUTPUTSTREAM_H + +// read INTRO in threadQueue.h +// This class makes the outputStream (given in constructor) +// threadsafe by wrapping each call with a threadqueue. +// +// Important NOTE: the output pointer is the owned by this class !!! +// which means: we call delete on it! +// More Important NOTES: +// +// We make the audio and video calls seperate threadsafe +// and ONLY the config call threadsafe to both! + +#include "../util/abstract/threadQueue.h" +#include "outputStream.h" + + +class ThreadSafeOutputStream : public OutputStream { + + ThreadQueue* threadQueueAudio; + ThreadQueue* threadQueueVideo; + OutputStream* output; + + public: + ThreadSafeOutputStream(OutputStream* output); + ~ThreadSafeOutputStream(); + + // Thread safe Audio Stream handling + int audioInit(); + int audioSetup(int freq,int stereo,int sign,int big,int sampleSize); + int audioPlay(TimeStamp* startStamp, + TimeStamp* endStamp,char *buffer, int size); + void audioFlush(); + void audioClose(); + void audioOpen(); + int getPreferredDeliverSize(); + + + // Video Output + int videoInit(); + int openWindow(int width, int height,const char *title); + void closeWindow(); + void flushWindow(); + PictureArray* lockPictureArray(); + void unlockPictureArray(PictureArray* pictureArray); + int getFrameusec(); + + // config Output + void config(const char* key, + const char* value,void* user_data); + + +}; +#endif diff --git a/mpeglib/lib/output/windowOut.cpp b/mpeglib/lib/output/windowOut.cpp new file mode 100644 index 00000000..3e199095 --- /dev/null +++ b/mpeglib/lib/output/windowOut.cpp @@ -0,0 +1,64 @@ +/* + wrapper for X11 Window + 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 "windowOut.h" + + + + + + + +WindowOut::WindowOut() { + + renderMachine=new RenderMachine(); + +} + + +WindowOut::~WindowOut() { + delete renderMachine; +} + +int WindowOut::openWindow(int width, int height,const char *title){ + return renderMachine->openWindow(width,height,title); +} + +int WindowOut::x11WindowId() { + return renderMachine->x11WindowId(); +} + +void WindowOut::flushWindow() { + renderMachine->flushWindow(); +} + + +void WindowOut::closeWindow() { + renderMachine->closeWindow(); +} + + +PictureArray* WindowOut::lockPictureArray() { + return renderMachine->lockPictureArray(); +} + + +void WindowOut::unlockPictureArray(PictureArray* pictureArray) { + renderMachine->unlockPictureArray(pictureArray); +} + + + +void WindowOut::config(const char* key, const char* value,void* user_data) { + renderMachine->config(key,value,user_data); +} diff --git a/mpeglib/lib/output/windowOut.h b/mpeglib/lib/output/windowOut.h new file mode 100644 index 00000000..648d1dc4 --- /dev/null +++ b/mpeglib/lib/output/windowOut.h @@ -0,0 +1,53 @@ +/* + wrapper for X11 Window + 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 __WINDOWOUT_H +#define __WINDOWOUT_H + + +#include "../util/abstract/abs_thread.h" +#include "../util/timeStamp.h" +#include "../util/render/renderMachine.h" + +/** + Stupid class. survivor of ancient days. +*/ + + +class WindowOut { + + + RenderMachine* renderMachine; + + public: + WindowOut(); + ~WindowOut(); + + int openWindow(int width, int height,const char *title); + int x11WindowId(); + void closeWindow(); + void flushWindow(); + + // get the current surfaces to draw into + PictureArray* lockPictureArray(); + void unlockPictureArray(PictureArray* pictureArray); + + void config(const char* key, const char* value,void* user_data); + + + private: + + +}; +#endif diff --git a/mpeglib/lib/output/yuvDumper.cpp b/mpeglib/lib/output/yuvDumper.cpp new file mode 100644 index 00000000..1962b151 --- /dev/null +++ b/mpeglib/lib/output/yuvDumper.cpp @@ -0,0 +1,81 @@ +/* + writes yuv images on HD + 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 "yuvDumper.h" + +YUVDumper::YUVDumper() { + picCnt=1; + method=_DUMP_YUV_AS_STREAM; +} + +YUVDumper::~YUVDumper() { +} + + +int YUVDumper::openWindow(int w, int h,const char*) { + + FILE* formatFile=fopen("stream.yuv.format","w+"); + fprintf(formatFile,"Version 0.1\nw:%dh:%d\n",w,h); + fclose(formatFile); + + + + if (method == _DUMP_YUV_AS_STREAM) { + FILE* outFile=fopen("stream.yuv","w+"); + fclose(outFile); + } + return true; +} + +void YUVDumper::closeWindow() { +} + + +void YUVDumper::flushWindow() { +} + + +int YUVDumper::getMethod() { + return method; +} + + +void YUVDumper::setMethod(int method) { + this->method=method; +} + +void YUVDumper::unlockPictureArray(PictureArray* pictureArray) { + YUVPicture* pic=pictureArray->getYUVPictureCallback(); + if (pic == NULL) { + return; + } + + FILE* outFile=NULL; + + if (method == _DUMP_YUV_AS_STREAM) { + outFile=fopen("stream.yuv","a+"); + } + + if (outFile == NULL) { + perror("fopen"); + return; + } + + int lumSize=pic->getLumLength(); + int colorSize=pic->getColorLength(); + fwrite(pic->getLuminancePtr(),1,lumSize,outFile); + fwrite(pic->getCrPtr(),1,colorSize,outFile); + fwrite(pic->getCbPtr(),1,colorSize,outFile); + fclose(outFile); + +} diff --git a/mpeglib/lib/output/yuvDumper.h b/mpeglib/lib/output/yuvDumper.h new file mode 100644 index 00000000..2e4880b0 --- /dev/null +++ b/mpeglib/lib/output/yuvDumper.h @@ -0,0 +1,51 @@ +/* + writes yuv images on HD + 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 __YUVDUMPER_H +#define __YUVDUMPER_H + +#include "outputStream.h" + +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdio.h> + + +#define _DUMP_YUV_AS_STREAM 2 + + +class YUVDumper : public OutputStream { + + + int picCnt; + int method; + + public: + YUVDumper(); + ~YUVDumper(); + + // Video Output + + int openWindow(int width, int height,const char *title); + void closeWindow(); + void flushWindow(); + + void unlockPictureArray(PictureArray* pictureArray); + int getMethod(); + void setMethod(int method); + + +}; + +#endif |