From e2de64d6f1beb9e492daf5b886e19933c1fa41dd Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- mpeglib/lib/input/Makefile.am | 37 +++ mpeglib/lib/input/README | 15 + mpeglib/lib/input/bufferInputStream.cpp | 288 +++++++++++++++++++ mpeglib/lib/input/bufferInputStream.h | 88 ++++++ mpeglib/lib/input/cddaInputStream.cpp | 225 +++++++++++++++ mpeglib/lib/input/cddaInputStream.h | 85 ++++++ mpeglib/lib/input/cdigrap.cpp | 100 +++++++ mpeglib/lib/input/cdromAccess.cpp | 54 ++++ mpeglib/lib/input/cdromAccess_Empty.cpp | 47 ++++ mpeglib/lib/input/cdromAccess_Linux.cpp | 124 ++++++++ mpeglib/lib/input/cdromInputStream.cpp | 309 ++++++++++++++++++++ mpeglib/lib/input/cdromInputStream.h | 88 ++++++ mpeglib/lib/input/cdromRawAccess.cpp | 113 ++++++++ mpeglib/lib/input/cdromRawAccess.h | 67 +++++ mpeglib/lib/input/cdromToc.cpp | 234 ++++++++++++++++ mpeglib/lib/input/cdromToc.h | 65 +++++ mpeglib/lib/input/fileAccessWrapper.cpp | 65 +++++ mpeglib/lib/input/fileAccessWrapper.h | 41 +++ mpeglib/lib/input/fileInputStream.cpp | 148 ++++++++++ mpeglib/lib/input/fileInputStream.h | 46 +++ mpeglib/lib/input/httpInputStream.cpp | 327 ++++++++++++++++++++++ mpeglib/lib/input/httpInputStream.h | 84 ++++++ mpeglib/lib/input/inputDetector.cpp | 192 +++++++++++++ mpeglib/lib/input/inputDetector.h | 56 ++++ mpeglib/lib/input/inputPlugin.cpp | 92 ++++++ mpeglib/lib/input/inputPlugin.h | 45 +++ mpeglib/lib/input/inputStream.cpp | 135 +++++++++ mpeglib/lib/input/inputStream.h | 79 ++++++ mpeglib/lib/input/simpleRingBuffer.cpp | 420 ++++++++++++++++++++++++++++ mpeglib/lib/input/simpleRingBuffer.h | 136 +++++++++ mpeglib/lib/input/threadSafeInputStream.cpp | 137 +++++++++ mpeglib/lib/input/threadSafeInputStream.h | 56 ++++ 32 files changed, 3998 insertions(+) create mode 100644 mpeglib/lib/input/Makefile.am create mode 100644 mpeglib/lib/input/README create mode 100644 mpeglib/lib/input/bufferInputStream.cpp create mode 100644 mpeglib/lib/input/bufferInputStream.h create mode 100644 mpeglib/lib/input/cddaInputStream.cpp create mode 100644 mpeglib/lib/input/cddaInputStream.h create mode 100644 mpeglib/lib/input/cdigrap.cpp create mode 100644 mpeglib/lib/input/cdromAccess.cpp create mode 100644 mpeglib/lib/input/cdromAccess_Empty.cpp create mode 100644 mpeglib/lib/input/cdromAccess_Linux.cpp create mode 100644 mpeglib/lib/input/cdromInputStream.cpp create mode 100644 mpeglib/lib/input/cdromInputStream.h create mode 100644 mpeglib/lib/input/cdromRawAccess.cpp create mode 100644 mpeglib/lib/input/cdromRawAccess.h create mode 100644 mpeglib/lib/input/cdromToc.cpp create mode 100644 mpeglib/lib/input/cdromToc.h create mode 100644 mpeglib/lib/input/fileAccessWrapper.cpp create mode 100644 mpeglib/lib/input/fileAccessWrapper.h create mode 100644 mpeglib/lib/input/fileInputStream.cpp create mode 100644 mpeglib/lib/input/fileInputStream.h create mode 100644 mpeglib/lib/input/httpInputStream.cpp create mode 100644 mpeglib/lib/input/httpInputStream.h create mode 100644 mpeglib/lib/input/inputDetector.cpp create mode 100644 mpeglib/lib/input/inputDetector.h create mode 100644 mpeglib/lib/input/inputPlugin.cpp create mode 100644 mpeglib/lib/input/inputPlugin.h create mode 100644 mpeglib/lib/input/inputStream.cpp create mode 100644 mpeglib/lib/input/inputStream.h create mode 100644 mpeglib/lib/input/simpleRingBuffer.cpp create mode 100644 mpeglib/lib/input/simpleRingBuffer.h create mode 100644 mpeglib/lib/input/threadSafeInputStream.cpp create mode 100644 mpeglib/lib/input/threadSafeInputStream.h (limited to 'mpeglib/lib/input') diff --git a/mpeglib/lib/input/Makefile.am b/mpeglib/lib/input/Makefile.am new file mode 100644 index 00000000..f7e849eb --- /dev/null +++ b/mpeglib/lib/input/Makefile.am @@ -0,0 +1,37 @@ +# libinputplugin - Makefile.am + +EXTRA_DIST = cdromAccess_Linux.cpp cdromAccess_Empty.cpp \ + cdigrap.cpp README + +INCLUDES = $(all_includes) + +noinst_LTLIBRARIES = libinput.la + +noinst_HEADERS = cdromToc.h cdromRawAccess.h \ + simpleRingBuffer.h fileAccessWrapper.h + +kmpgincludedir = $(includedir)/$(THIS_LIB_NAME)/input + +kmpginclude_HEADERS = inputStream.h fileInputStream.h \ + inputPlugin.h \ + cdromInputStream.h bufferInputStream.h \ + inputDetector.h httpInputStream.h \ + threadSafeInputStream.h cddaInputStream.h + + + +libinput_la_SOURCES = inputStream.cpp fileInputStream.cpp \ + inputPlugin.cpp \ + cdromToc.cpp cdromRawAccess.cpp \ + cdromInputStream.cpp \ + bufferInputStream.cpp \ + simpleRingBuffer.cpp \ + cdromAccess.cpp inputDetector.cpp \ + httpInputStream.cpp \ + threadSafeInputStream.cpp \ + cddaInputStream.cpp \ + fileAccessWrapper.cpp + +# workaround for compile errors caused by linux/cdrom.h. +# Linux kernel headers suck donkeyballs. +KDE_CXXFLAGS = $(ENABLE_PERMISSIVE_FLAG) diff --git a/mpeglib/lib/input/README b/mpeglib/lib/input/README new file mode 100644 index 00000000..844a17bb --- /dev/null +++ b/mpeglib/lib/input/README @@ -0,0 +1,15 @@ + + +Here is the abstraction of the inputplugin. +Its a base class, with the usual open/seek/read methods. +The only nice thing is the factory inputPlugin which +creates you for a given url the correct class. + + +All inputStreams can take a timeStamp. Its necessary for +audio/video sync, but this must be supported +by the outputplugin and the playerPlugin! +Video is not that easy as audio :( + + + diff --git a/mpeglib/lib/input/bufferInputStream.cpp b/mpeglib/lib/input/bufferInputStream.cpp new file mode 100644 index 00000000..68e502ff --- /dev/null +++ b/mpeglib/lib/input/bufferInputStream.cpp @@ -0,0 +1,288 @@ +/* + reads input data + 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 "bufferInputStream.h" +#include "simpleRingBuffer.h" + + +BufferInputStream::BufferInputStream(int size,int minlinSize, + const char* name) { + ringBuffer=new SimpleRingBuffer(size,minlinSize); + leof=false; + bytePos=0; + fillgrade=0; + setUrl(name); + lLock=false; + abs_thread_mutex_init(&writeInMut); +} + + +BufferInputStream::~BufferInputStream() { + delete ringBuffer; + abs_thread_mutex_destroy(&writeInMut); +} + + +int BufferInputStream::open(const char*) { + leof=false; + setBlocking(true); + return true; +} + +void BufferInputStream::close() { + leof=true; + setBlocking(false); +} + +int BufferInputStream::eof() { + return (leof && (fillgrade==0)); +} + +int BufferInputStream::isOpen() { + return !leof; +} + +void BufferInputStream::setBlocking(int lblock) { + ringBuffer->setCanWaitForSpace(lblock); + ringBuffer->setCanWaitForData(lblock); +} + +int BufferInputStream::getHold() { + return lLock; +} + + +void BufferInputStream::setHold(int lLock) { + if (lLock) { + lockBuffer(); + } else { + unlockBuffer(); + } + this->lLock=lLock; +} + +int BufferInputStream::read(char* ptr,int size) { + int i=0; + int n=size; + int canCopy=n; + char* readPtr; + // here we read even if leof is true + // we make sure that we empty the whole buffer! + while((eof()==false) && (n > 0)) { + canCopy=n; + ringBuffer->getReadArea(readPtr,canCopy); + if (canCopy <= 0){ + ringBuffer->waitForData(1); + continue; + } + if (n < canCopy) { + canCopy=n; + } + memcpy((char*)ptr+i,readPtr,canCopy); + i=i+canCopy; + n=n-canCopy; + ringBuffer->forwardReadPtr(canCopy); + ringBuffer->forwardLockPtr(canCopy); + lockBuffer(); + bytePos+=canCopy; + fillgrade-=canCopy; + unlockBuffer(); + } + return i; +} + + +int BufferInputStream::write(char* ptr,int len,TimeStamp* stamp) { + int i=0; + int n=len; + int canWrite=n; + char* writePtr; + + if (stamp) { + lockBuffer(); + long key; + key=bytePos+fillgrade; + InputStream::insertTimeStamp(stamp,key,len); + unlockBuffer(); + } + // if eof is set we do not insert any more data + // we do not call eof() !!! + while((leof==false) && (n > 0)) { + canWrite=n; + ringBuffer->getWriteArea(writePtr,canWrite); + if (canWrite <= 0){ + ringBuffer->waitForSpace(1); + continue; + } + if (canWrite > n) { + canWrite=n; + } + memcpy(writePtr,(char*)ptr+i,canWrite); + i=i+canWrite; + n=n-canWrite; + ringBuffer->forwardWritePtr(canWrite); + lockBuffer(); + fillgrade+=canWrite; + unlockBuffer(); + } + + return i; +} + + + +int BufferInputStream::write(InputStream* input,int len,TimeStamp* stamp) { + int i=0; + int n=len; + int canWrite=n; + int didWrite; + char* writePtr; + + if (stamp) { + lockBuffer(); + long key; + key=bytePos+fillgrade; + InputStream::insertTimeStamp(stamp,key,len); + unlockBuffer(); + } + // if eof is set we do not insert any more data + // we do not call eof() !!! + while((leof==false) && (n > 0)) { + canWrite=n; + ringBuffer->getWriteArea(writePtr,canWrite); + if (canWrite <= 0){ + ringBuffer->waitForSpace(1); + continue; + } + if (canWrite > n) { + canWrite=n; + } + didWrite=input->read(writePtr,canWrite); + if (input->eof()) break; + i=i+didWrite; + n=n-didWrite; + ringBuffer->forwardWritePtr(didWrite); + lockBuffer(); + fillgrade+=canWrite; + unlockBuffer(); + } + + return i; +} + + + +long BufferInputStream::getByteLength() { + return ringBuffer->getFillgrade(); +} + +int BufferInputStream::getFillgrade() { + return ringBuffer->getFillgrade(); +} + + +int BufferInputStream::getFreeRead() { + return ringBuffer->getFreeRead(); +} + + +int BufferInputStream::getFreeSpace() { + return ringBuffer->getFreeWrite(); +} + + + +long BufferInputStream::getBytePosition() { + return bytePos; +} + +void BufferInputStream::setBytePosition(long bytePos) { + this->bytePos=bytePos; +} + + +int BufferInputStream::seek(long) { + return false; +} + + +void BufferInputStream::clear() { + + ringBuffer->emptyBuffer(); + ringBuffer->exitWaitForData(); + ringBuffer->exitWaitForSpace(); + timeStampArray->clear(); + + lockBuffer(); + bytePos=0; + fillgrade=0; + unlockBuffer(); + +} + + + + +// remote read extension +int BufferInputStream::readRemote(char** ptr,int size) { + int n=0; + char* readPtr; + while((eof()==false)) { + n=size; + ringBuffer->getReadArea(readPtr,n); + if (n < size){ + ringBuffer->waitForData(size); + if (ringBuffer->getCanWaitForData()==false) { + break; + } + continue; + } + break; + } + *ptr=readPtr; + return n; +} + + +void BufferInputStream::forwardReadPtr(int bytes) { + + ringBuffer->forwardReadPtr(bytes); + ringBuffer->forwardLockPtr(bytes); + lockBuffer(); + bytePos+=bytes; + fillgrade-=bytes; + unlockBuffer(); + getTimeStamp(bytePos); +} + + +void BufferInputStream::setCanWaitForData(int lBlock) { + ringBuffer->setCanWaitForData(lBlock); +} + + +void BufferInputStream::lockBuffer() { + abs_thread_mutex_lock(&writeInMut); +} + + +void BufferInputStream::unlockBuffer() { + abs_thread_mutex_unlock(&writeInMut); +} + + +int BufferInputStream::getSize() { + return ringBuffer->getSize(); +} + + diff --git a/mpeglib/lib/input/bufferInputStream.h b/mpeglib/lib/input/bufferInputStream.h new file mode 100644 index 00000000..3bd3e691 --- /dev/null +++ b/mpeglib/lib/input/bufferInputStream.h @@ -0,0 +1,88 @@ +/* + reads input data + 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 __BUFFERINPUTSTREAM_H +#define __BUFFERINPUTSTREAM_H + +#include "../util/abstract/abs_thread.h" + +#include "inputStream.h" + + +class SimpleRingBuffer; + +class BufferInputStream : public InputStream { + + SimpleRingBuffer* ringBuffer; + int leof; + long bytePos; + int fillgrade; + int lLock; + abs_thread_mutex_t writeInMut; + + public: + BufferInputStream(int size,int minlinSize,const char* name); + ~BufferInputStream(); + + int open(const char* name); + void close(); + + int isOpen(); + + + int eof(); + void setBlocking(int lblock); + int read(char* ptr,int size); + + // reads from a buffer + int write(char* ptr,int len,TimeStamp* stamp); + + // this method directy read from another inputstream (faster); + int write(InputStream* ptr,int len,TimeStamp* stamp); + + int seek(long bytePos); + + + long getByteLength(); + long getBytePosition(); + + void setBytePosition(long bytePos); + int getFillgrade(); + int getSize(); + int getFreeRead(); + int getFreeSpace(); + + void clear(); + + // remote read extension + // Note you _need_ to call always both methods + // readRemote and forwardReadPtr even if bytes==0!!! + // (we hold a resizeLock during this operation) + int readRemote(char** ptr,int size); + void forwardReadPtr(int bytes); + void setCanWaitForData(int lBlock); + + + // this method is only safe to call by the writer in the buffer + // a reader never should call this (segfault possible) + void resizeBuffer(int changeSize); + + // for pause/play over loopback + int getHold(); + void setHold(int lLock); + + private: + void lockBuffer(); + void unlockBuffer(); + +}; +#endif diff --git a/mpeglib/lib/input/cddaInputStream.cpp b/mpeglib/lib/input/cddaInputStream.cpp new file mode 100644 index 00000000..9bc8f5f2 --- /dev/null +++ b/mpeglib/lib/input/cddaInputStream.cpp @@ -0,0 +1,225 @@ +/* + cdda input class based on cdparanoia + 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 + + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef CDDA_PARANOIA + +#include + +using namespace std; + +#include "cddaInputStream.h" +#include "inputDetector.h" + + +void paranoiaCallback(long, int) { + //cout << "long:"<tracks; + for (int i = 1; i <= trackCount; i++) { + if (IS_AUDIO(drive, i)) { + printf("track%02d.cda\n", i); + } else { + printf("no audio:%d\n",i); + } + } + + paranoia = paranoia_init(drive); + if (paranoia == NULL) { + cout << "paranoia init failed"< initialized! + + int paranoiaLevel = PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP; + paranoia_modeset(paranoia, paranoiaLevel); + cdda_verbose_set(drive, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_PRINTIT); + paranoia_seek(paranoia, firstSector, SEEK_SET); + + return true; +} + + +void CDDAInputStream::close() { + if (isOpen() == false) { + return; + } + cdda_close(drive); + drive=NULL; + if (paranoia != NULL) { + paranoia_free(paranoia); + paranoia = 0; + } + if (device != NULL) { + delete device; + device=NULL; + } +} + + +int CDDAInputStream::isOpen() { + return (drive != NULL); +} + + +int CDDAInputStream::eof() { + if (isOpen()==false) { + return true; + } + if (currentSector >= lastSector) { + return true; + } + return false; +} + + +int CDDAInputStream::read(char* dest,int len) { + if (len != 2*CD_FRAMESIZE_RAW) { + cout << "len must be 2*CD_FRAMESIZE_RAW"< +#endif + +#ifndef CDDA_PARANOIA +class CDDAInputStream : public InputStream { +}; +#else + +#include +typedef int16_t size16; +typedef int32_t size32; + +extern "C" { +#include +#include +void paranoiaCallback(long, int); +} +//#define CDDA_INCLUDE + + +class CDDAInputStream : public InputStream { + +//#ifdef CDDA_INCLUDE + cdrom_paranoia * paranoia; + struct cdrom_drive * drive; +//#else +// void * drive; +// void * paranoia; +//#endif + + + char* device; + int track; + + int firstSector; + int lastSector; + int currentSector; + + public: + CDDAInputStream(); + ~CDDAInputStream(); + + int open(const char* dest); + void close(); + int isOpen(); + + int eof(); + int read(char* ptr,int size); + int seek(long bytePos); + // clears possible input buffers + // (called by the decoderPlugin after a resyncCommit) + void clear(); + + long getByteLength(); + long getBytePosition(); + private: + int getTrackAndDevice(const char* url); + +}; +#endif +//CDDA_PARANOIA + +#endif diff --git a/mpeglib/lib/input/cdigrap.cpp b/mpeglib/lib/input/cdigrap.cpp new file mode 100644 index 00000000..37d9de0e --- /dev/null +++ b/mpeglib/lib/input/cdigrap.cpp @@ -0,0 +1,100 @@ +/** + graps cdis + + Compile with + + g++ -o cdigrap cdigrap.cpp -lmpeg + +*/ +#ifdef CONFIG_H +#include "config.h" +#endif +#include "inputPlugin.h" + +#if defined(HAVE_GETOPT_H) +#include +#endif + +void usage() { + cout << "cdigrab grabs video cds"<"<= argn ) { + usage(); + exit(-1); + } + + InputStream* in=InputPlugin::createInputStream(args[optind]); + + in->open(args[optind]); + + if (startBytes != 0) { + cout << "seeking to :"<seek(startBytes); + } + char* buffer=new char[len]; + int cnt=0; + FILE* f=fopen(fname,"a+"); + while(1) { + if (in->eof() == true) { + cout << "******* plugin->getStreamState() EOF"<read(buffer,len); + fwrite(buffer,len,1,f); + cnt++; + cout << "grapped:"< +#endif + + + +#ifdef OS_AIX + #include "cdromAccess_Empty.cpp" +#endif + +#ifdef OS_Linux + #include + #include "cdromAccess_Linux.cpp" +#endif + +#ifdef OS_BSD + #include "cdromAccess_Empty.cpp" +#endif + +#if defined(OS_IRIX) || defined(OS_IRIX64) + #include "cdromAccess_Empty.cpp" +#endif + +#ifdef OS_HPUX + #include "cdromAccess_Empty.cpp" +#endif + +#ifdef OS_SunOS + #include "cdromAccess_Empty.cpp" +#endif + +#ifdef __BEOS__ + #include "cdromAccess_Empty.cpp" +#endif + +#ifdef WIN32 + #include "cdromAccess_Empty.cpp" +#endif + + diff --git a/mpeglib/lib/input/cdromAccess_Empty.cpp b/mpeglib/lib/input/cdromAccess_Empty.cpp new file mode 100644 index 00000000..63da4b69 --- /dev/null +++ b/mpeglib/lib/input/cdromAccess_Empty.cpp @@ -0,0 +1,47 @@ +/* + system dependent wrapper for access to cdrom (no system) + 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 "cdromToc.h" +#include "cdromRawAccess.h" + +#include +using namespace std; + + +int CDRomToc::getStartEnd(FILE* file,int& startToc,int& endToc) { + cout << "CDRomToc::getStartEnd not implemented on your system"< +#include +#ifdef _ANSI_WAS_HERE_ +#define __STRICT_ANSI__ +#endif +#include + +#include "cdromToc.h" +#include "cdromRawAccess.h" + +#include + +using namespace std; + +/** + here you find an example how to port the access method + to your system. +*/ + + +int CDRomToc::getStartEnd(FILE* file,int& startToc,int& endToc) { + struct cdrom_tochdr tochdr; + int fd=fileno(file); + if (ioctl(fd, CDROMREADTOCHDR, &tochdr) == -1) { + perror("ioctl cdromreadtochdr"); + return false; + } + + startToc=tochdr.cdth_trk0; + endToc=tochdr.cdth_trk1; + return true; +} + + +int CDRomToc::readToc(FILE* file,int num,int& min,int& sec, int& frame) { + struct cdrom_tocentry tocent; + int fd=fileno(file); + tocent.cdte_track = num; + tocent.cdte_format = CDROM_MSF; + if (ioctl(fd, CDROMREADTOCENTRY, &tocent) == -1 ) { + perror("ioctl cdromreadtocentry"); + return false; + } + min=tocent.cdte_addr.msf.minute; + sec=tocent.cdte_addr.msf.second; + frame=tocent.cdte_addr.msf.frame; + return true; +} + + +int CDRomToc::readLeadOut(FILE* file,int& min,int& sec, int& frame) { + struct cdrom_tocentry tocent; + int fd=fileno(file); + tocent.cdte_track = CDROM_LEADOUT; + tocent.cdte_format = CDROM_MSF; + if (ioctl(fd, CDROMREADTOCENTRY, &tocent) == -1 ) { + perror("ioctl cdromreadLeadoutn"); + return false; + } + min=tocent.cdte_addr.msf.minute; + sec=tocent.cdte_addr.msf.second; + frame=tocent.cdte_addr.msf.frame; + return true; +} + + + +int CDRomRawAccess::readDirect(int minute,int second, int frame) { + + // this comes from smpeg + // smpeg is an mpeg I player from lokigames www.lokigames.com + + struct cdrom_msf *msf; + int fd=fileno(cdfile); + + msf = (struct cdrom_msf*) data; + msf->cdmsf_min0 = minute; + msf->cdmsf_sec0 = second; + msf->cdmsf_frame0 = frame; + if (ioctl(fd, CDROMREADMODE2, msf) == -1) { + perror("ioctl cdromreadmode2"); + cout << "min:"< +#include "inputDetector.h" + +#include + +using namespace std; + +CDRomInputStream::CDRomInputStream() { + cdRomToc=new CDRomToc(); + cdRomRawAccess=new CDRomRawAccess(cdRomToc); + + buflen=0; + bufCurrent=NULL; + + currentMinute=0; + currentSecond=2; + currentFrame=0; + byteCounter=0; +} + + +CDRomInputStream::~CDRomInputStream() { + delete cdRomRawAccess; + delete cdRomToc; +} + + +int CDRomInputStream::readCurrent() { + int ok=cdRomRawAccess->read(currentMinute,currentSecond,currentFrame); + if (ok==false) { + if (cdRomRawAccess->eof() == false) { + int pos=cdRomToc->getNextTocEntryPos(currentMinute, + currentSecond, + currentFrame); + + // now try to read a few sectors + int cnt=0; + int back=false; + + while(1) { + // jump forward + int i; + for(i=0;i<_CDROM_FRAMES-currentFrame;i++) { + next_sector(); + } + cout << "trying next ..."<read(currentMinute,currentSecond,currentFrame); + if (ok) { + bufCurrent=cdRomRawAccess->getBufferStart(); + buflen=cdRomRawAccess->getBufferLen(); + return true; + } + cnt++; + if (cnt > 100) { + break; + } + } + cout << "last possible jump"< 1) { + TocEntry* tocEntry=cdRomToc->getTocEntry(pos-1); + currentMinute=tocEntry->minute; + currentSecond=tocEntry->second; + currentFrame=tocEntry->frame; + back=cdRomRawAccess->read(currentMinute,currentSecond,currentFrame); + if (back) { + bufCurrent=cdRomRawAccess->getBufferStart(); + buflen=cdRomRawAccess->getBufferLen(); + } + } + return back; + } + return false; + } + bufCurrent=cdRomRawAccess->getBufferStart(); + buflen=cdRomRawAccess->getBufferLen(); + return true; +} + + +int CDRomInputStream::getByteDirect() { + int back; + if (buflen==0) { + fillBuffer(); + } + if (buflen==0){ + return EOF; + } + back=*bufCurrent; + buflen--; + bufCurrent++; + byteCounter++; + return back; +} + + +int CDRomInputStream::read(char* ptr,int size) { + char* dest=(char*)ptr; + int bytesRead=0; + int doRead=size; + int canRead; + + while(eof() == false) { + if (buflen == 0) { + if (fillBuffer() == false) { + return 0; + } + continue; + } + canRead=buflen; + if (doRead < canRead) { + canRead=doRead; + } + memcpy((void*)dest,(void*)bufCurrent,canRead); + buflen-=canRead; + bufCurrent+=canRead; + bytesRead+=canRead; + dest+=canRead; + doRead-=canRead; + if (doRead == 0) { + byteCounter+=bytesRead; + return bytesRead; + } + } + return 0; +} + +int CDRomInputStream::eof() { + return cdRomRawAccess->eof(); +} + + + + +long CDRomInputStream::getBytePosition() { + return byteCounter; +} + + +void CDRomInputStream::print() { +} + + +void CDRomInputStream::next_sector() { + currentFrame++; + if (currentFrame>=_CDROM_FRAMES) { + currentFrame = 0; + currentSecond++; + if (currentSecond>=_CDROM_SECS) { + currentSecond = 0; + currentMinute++; + } + } +} + +int CDRomInputStream::open(const char* file) { + cout << "CDRomInputStream::open:"<open(noExtension); + cdRomRawAccess->open(noExtension); + if (isOpen()==false) { + return false; + } + setUrl(noExtension); + int entries=cdRomToc->getTocEntries(); + cdRomToc->print(); + if (entries == 1) { + cerr << "only lead out"<insertTocEntry(0,2,0); + //cdRomToc->insertTocEntry(1,13,5); + + TocEntry* tocEntry=cdRomToc->getTocEntry(0); + currentMinute=tocEntry->minute; + currentSecond=tocEntry->second; + currentFrame=tocEntry->frame; + delete noExtension; + + return readCurrent(); +} + + +void CDRomInputStream::close() { + cdRomRawAccess->close(); + byteCounter=0; + setUrl(NULL); +} + + +int CDRomInputStream::isOpen() { + return cdRomRawAccess->isOpen(); +} + + + + +long CDRomInputStream::getBytePos(int min,int sec) { + long back; + // 2324 is the size of a cdfram + back=sec*_CDROM_FRAMES*2324; + back=back+min*60*_CDROM_FRAMES*2324; + cout << "CDRomInputStream::getByteLength"<getEndSecond(); + long min=totalSecs/60; + long sec=totalSecs-60*min; + + long back=getBytePos(min,sec); + + return back; +} + + +int CDRomInputStream::seek(long posInBytes) { + int entries=cdRomToc->getTocEntries(); + + TocEntry* firstEntry; + if (entries == 0) { + return false; + } + if (posInBytes < 0) { + return false; + } + firstEntry=cdRomToc->getTocEntry(0); + + long startByte=getBytePos(firstEntry->minute,firstEntry->second+1); + + posInBytes=posInBytes+startByte; + + + float fmin=(float)posInBytes/(float)(60*_CDROM_FRAMES*2324); + int min=(int)fmin; + + + long sec=posInBytes-min*(60*_CDROM_FRAMES*2324); + sec=sec/(_CDROM_FRAMES*2324); + + byteCounter=posInBytes; + if (cdRomRawAccess->read(min,sec,0)==false) { + return false; + } + setTimePos(min*60+sec); + + return true; +} + + +int CDRomInputStream::setTimePos(int second) { + currentFrame=0; + currentMinute=second/60; + currentSecond=second%60; + + return fillBuffer(); +} + + + + + +int CDRomInputStream::fillBuffer() { + int maxNoData=30; + int cnt=0; + if (buflen==0) { + while (cnt < maxNoData) { + next_sector(); + if (readCurrent() == false) { + return false; + } + if (cdRomRawAccess->isData() == false) { + // cerr << "no data"< + FTP : ftp://mca.sh.cvut.cz/pub/readvcd/ + + The code is used in a few other packages, in which I looked as well. + +*/ + +class CDRomRawAccess; +class CDRomToc; + +class CDRomInputStream : public InputStream{ + + CDRomRawAccess* cdRomRawAccess; + CDRomToc* cdRomToc; + + int buflen; + char* bufCurrent; + + int currentFrame; + int currentMinute; + int currentSecond; + long byteCounter; + + public: + CDRomInputStream(); + ~CDRomInputStream(); + + int open(const char* dest); + void close(); + int isOpen(); + + int eof(); + int read(char* ptr,int size); + int seek(long bytePos); + + long getByteLength(); + long getBytePosition(); + + void print(); + + private: + long getBytePos(int min,int sec); + + int setTimePos(int posInTime); + int getByteDirect(); + void next_sector(); + int readCurrent(); + int fillBuffer(); +}; +#endif diff --git a/mpeglib/lib/input/cdromRawAccess.cpp b/mpeglib/lib/input/cdromRawAccess.cpp new file mode 100644 index 00000000..b0df4747 --- /dev/null +++ b/mpeglib/lib/input/cdromRawAccess.cpp @@ -0,0 +1,113 @@ +/* + reads raw input data from cdrom (system dependent) + 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 + +#include "cdromRawAccess.h" + +using namespace std; + +CDRomRawAccess::CDRomRawAccess(CDRomToc* cdromToc) { + cdfile=NULL; + lOpen=false; + leof=true; + this->cdromToc=cdromToc; + lData=false; + dataStart=0; + len=0; +} + + +CDRomRawAccess::~CDRomRawAccess() { + close(); +} + + + +char* CDRomRawAccess::getBufferStart() { + return (char*)(data+dataStart); +} + +int CDRomRawAccess::getBufferLen() { + if (eof()) { + return 0; + } + return len; +} + +int CDRomRawAccess::open(const char* filename) { + if (isOpen()) { + close(); + } + if (filename==NULL) { + filename=(char*)"/dev/cdrom"; + } + if (strlen(filename) <= 1) { + filename="/dev/cdrom"; + } + char* openfile=strchr(filename,'/'); + cout << "openfile:"<isInRange(minute,second,frame); + if (lInRange == false) { + if (minute*60+second+1 > cdromToc->getEndSecond()) { + leof=true; + } + return false; + } + return readDirect(minute,second,frame); +} + + +void CDRomRawAccess::close() { + if (isOpen()) { + fclose(cdfile); + lOpen=false; + leof=true; + } +} + +int CDRomRawAccess::isData() { + return lData; +} + +int CDRomRawAccess::isOpen() { + return lOpen; +} + + + + diff --git a/mpeglib/lib/input/cdromRawAccess.h b/mpeglib/lib/input/cdromRawAccess.h new file mode 100644 index 00000000..d089a85b --- /dev/null +++ b/mpeglib/lib/input/cdromRawAccess.h @@ -0,0 +1,67 @@ +/* + reads raw input data from cdrom (system dependent) + 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 __CDROMRAWACCESS_H +#define __CDROMRAWACCESS_H + +#include "cdromToc.h" +#include "inputStream.h" + + +/** + Here we have a system wrapper for raw cdrom access. + Currently this is tested on Linux. +*/ + + + + + +class CDRomRawAccess { + + CDRomToc* cdromToc; + char data[2352]; + int dataStart; + int len; + int lData; + + public: + CDRomRawAccess(CDRomToc* cdromToc); + virtual ~CDRomRawAccess(); + + // overload this for new Systems + virtual int readDirect(int minute,int second, int frame); + + // wrapper for readDirect + int read(int minute,int second, int frame); + + char* getBufferStart(); + int getBufferLen(); + + int open(const char* filename); + int eof(); + void close(); + int isOpen(); + + int isData(); + + private: + FILE* cdfile; + int lOpen; + int leof; + int buflen; +}; + +#endif + + diff --git a/mpeglib/lib/input/cdromToc.cpp b/mpeglib/lib/input/cdromToc.cpp new file mode 100644 index 00000000..919ecdc8 --- /dev/null +++ b/mpeglib/lib/input/cdromToc.cpp @@ -0,0 +1,234 @@ +/* + reads toc from cdrom (system dependent) + 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 "cdromToc.h" + +#include + +using namespace std; + +CDRomToc::CDRomToc() { + maxEntries=0; +} + + +CDRomToc::~CDRomToc() { +} + + +void CDRomToc::insertTocEntry(int minute,int second,int frame) { + int i; + int j; + if (isElement(minute,second,frame)) { + return; + } + + i=getNextTocEntryPos(minute,second,frame); + + // now shift from i to end + if (maxEntries == 100) { + cerr << "maximum of toc entries reached"<i;j--) { + tocEntries[j].minute=tocEntries[j-1].minute; + tocEntries[j].second=tocEntries[j-1].second; + tocEntries[j].frame=tocEntries[j-1].frame; + } + maxEntries++; + + tocEntries[i].minute=minute; + tocEntries[i].second=second; + tocEntries[i].frame=frame; + calculateRange(); +} + + +int CDRomToc::getNextTocEntryPos(int minute,int second,int frame) { + int i; + if (maxEntries == 0) { + return 0; + } + + for (i=0;i endByte) { + return false; + } + return true; +} + +int CDRomToc::calculateRange() { + + + if (maxEntries < 2) { + cout << "no two elemts in toc"< +#include +#include +} + +struct TocEntry { + int minute; + int second; + int frame; +}; + + +class CDRomToc { + + TocEntry tocEntries[100]; + int maxEntries; + int startByte; + int endByte; + + public: + CDRomToc(); + virtual ~CDRomToc(); + int open(const char* device); + int getTocEntries(); + TocEntry* getTocEntry(int entry); + void insertTocEntry(int minute,int second,int frame); + int getNextTocEntryPos(int minute,int second,int frame); + int isInRange(int minute,int second,int frame); + int isElement(int minute,int second,int frame); + + int getEndSecond(); + + void print(); + + private: + // platform specific calls. + int getStartEnd(FILE* file,int& start, int& end); + int readToc(FILE* file,int num,int& min,int& sec, int& frame); + int readLeadOut(FILE* file,int& min,int& sec, int& frame); + + + + + int calculateRange(); + +}; + +#endif diff --git a/mpeglib/lib/input/fileAccessWrapper.cpp b/mpeglib/lib/input/fileAccessWrapper.cpp new file mode 100644 index 00000000..246807a8 --- /dev/null +++ b/mpeglib/lib/input/fileAccessWrapper.cpp @@ -0,0 +1,65 @@ +/* + wraps an inputStream for the splayFileBuffer. + Copyright (C) 2001 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 "fileAccessWrapper.h" + +#include + +using namespace std; + +FileAccessWrapper::FileAccessWrapper(InputStream* input) { + this->input=input; +} + + +FileAccessWrapper::~FileAccessWrapper() { + +} + + +int FileAccessWrapper::open(const char*) { + cout << "FileAccessWrapper open not implemented"<read(dest,len); +} + +int FileAccessWrapper::eof() { + return input->eof(); +} + + +int FileAccessWrapper::seek(long pos) { + return input->seek(pos); +} + + +long FileAccessWrapper::getBytePosition() { + return input->getBytePosition(); +} + + +long FileAccessWrapper::getByteLength() { + return input->getByteLength(); +} + diff --git a/mpeglib/lib/input/fileAccessWrapper.h b/mpeglib/lib/input/fileAccessWrapper.h new file mode 100644 index 00000000..d7882abb --- /dev/null +++ b/mpeglib/lib/input/fileAccessWrapper.h @@ -0,0 +1,41 @@ +/* + wraps an inputStream for the splayFileBuffer. + Copyright (C) 2001 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 __FILEACCESSWRAPPER_H +#define __FILEACCESSWRAPPER_H + + +#include "../util/file/fileAccess.h" +#include "inputStream.h" + + +class FileAccessWrapper : public FileAccess { + + InputStream* input; + + public: + FileAccessWrapper(InputStream* input); + virtual ~FileAccessWrapper(); + + int open(const char* file); + void close(); + int read(char* dest,int len); + int eof(); + int seek(long pos); + long getBytePosition(); + long getByteLength(); + +}; + + +#endif diff --git a/mpeglib/lib/input/fileInputStream.cpp b/mpeglib/lib/input/fileInputStream.cpp new file mode 100644 index 00000000..77c31ed6 --- /dev/null +++ b/mpeglib/lib/input/fileInputStream.cpp @@ -0,0 +1,148 @@ +/* + reads input data + 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 "fileInputStream.h" + +#include + +using namespace std; + +FileInputStream::FileInputStream() { + file=NULL; + lopen=false; + fileLen=0; +} + + +FileInputStream::~FileInputStream() { + close(); +} + + +int FileInputStream::open(const char* dest) { + + close(); + if (dest == NULL) { + return false; + } + setUrl(dest); + if (strlen(dest) == 1) { + if (strncmp(dest,"-",1)==0) { + file=::fdopen(0,"rb"); + } + } + // load out of current dir if no full path is given + if (file == NULL) { + file=fopen(dest,"rb"); + } + fileLen=0; + if (file == NULL) { + cout <<"cannot open file:"<< dest< + +using namespace std; + +static const char *httpstr="http://"; + + + +static char *strndup(char *src,int num) { + char *dst; + + if(!(dst=(char *)malloc(num+1)))return NULL; + dst[num]='\0'; + + return strncpy(dst, src, num); +} + +static char *url2hostport(char *url,char **hname, + unsigned long *hip,unsigned int *port) { + char *cptr; + struct hostent *myhostent; + struct in_addr myaddr; + int isip=1; + + if(!(strncmp(url,httpstr,7)))url+=7; + cptr=url; + while(*cptr && *cptr!=':' && *cptr!='/') { + if((*cptr<'0' || *cptr>'9') && *cptr!='.')isip=0; + cptr++; + } + if(!(*hname=strndup(url,cptr-url))) { + *hname=NULL; + return NULL; + } + if(!isip) + { + if (!(myhostent=gethostbyname(*hname)))return NULL; + memcpy(&myaddr,myhostent->h_addr,sizeof(myaddr)); + *hip=myaddr.s_addr; + } + else if((*hip=inet_addr(*hname))==INADDR_NONE)return NULL; + if(!*cptr || *cptr=='/') { + *port=80; + return cptr; + } + *port=atoi(++cptr); + while(*cptr && *cptr!='/')cptr++; + return cptr; +} + + + + + + + + + + + + + +HttpInputStream::HttpInputStream() { + + proxyurl=NULL; + proxyip=0; + lopen=false; + byteCnt=0; +} + + +HttpInputStream::~HttpInputStream() { + close(); +} + + +int HttpInputStream::open(const char* filename) { + close(); + if (filename == NULL) { + return false; + } + /* + int matchPos=InputStream::getPath(filename,"http"); + if (matchPos=0) { + return false; + } + */ + + char* filename2=strdup(filename); + if((fp=http_open(filename2))==NULL) { + cout << "seterrorcode(SOUND_ERROR_FILEOPENFAIL)"< +#include + + + +#if defined WIN32 +#include +#define SOCKETWRITEFUNC _write +#else + +extern "C" { +#include +#include +#include +#include +#include + } +#define SOCKETWRITEFUNC write +#endif + +#include +#include + +class HttpInputStream : public InputStream{ + + long byteCnt; + + public: + HttpInputStream(); + ~HttpInputStream(); + + int open(const char* dest); + void close(); + int isOpen(); + + int eof(); + int read(char* ptr,int size); + int seek(long bytePos); + + long getByteLength(); + long getBytePosition(); + + void print(); + + private: + + FILE* fp; + int size; + + int writestring(int fd,char *string); + int readstring(char *string,int maxlen,FILE *f); + FILE* http_open(char *url); + + char* proxyurl; + unsigned long proxyip; + unsigned int proxyport; + + int lopen; + +}; +#endif diff --git a/mpeglib/lib/input/inputDetector.cpp b/mpeglib/lib/input/inputDetector.cpp new file mode 100644 index 00000000..28bcad5c --- /dev/null +++ b/mpeglib/lib/input/inputDetector.cpp @@ -0,0 +1,192 @@ +/* + returns inputtype for a given string + 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 "inputDetector.h" + +#include + +using namespace std; + +static const char *filestrglobal1="/"; +static const char *filestrglobal2="./"; + +typedef struct prot2type_s { + const char* name; + int type; +} prot2type; + +static prot2type protocols[]= { {"http:" , __INPUT_HTTP }, + {"cdi:" , __INPUT_CDI }, + {"vcd:" , __INPUT_CDI }, + {"file:" , __INPUT_FILE }, + {"cdda:" , __INPUT_CDDA }, + {"audiocd:", __INPUT_CDDA }, + {NULL , __INPUT_UNKNOWN} }; + + +InputDetector::InputDetector() { +} + + +InputDetector::~InputDetector() { +} + +int InputDetector::getProtocolPos(int type,const char* url) { + prot2type* current=protocols; + int i=0; + while(current->name != NULL) { + if (current->type == type) { + int len=strlen(current->name); + if (strncmp(url,current->name,len)==0) { + return i; + } + } + i++; + current++; + } + return -1; +} + +int InputDetector::getProtocolType(const char* url) { + prot2type* current=protocols; + int n=strlen(url); + if (n > 0) { + while(current->name != NULL) { + int k=strlen(current->name); + if (n >= k) { + if (strncmp(url,current->name,k)==0) { + return current->type; + } + } + current++; + } + } + return __INPUT_UNKNOWN; +} + +int InputDetector::getInputType(const char* url) { + int back=__INPUT_FILE; + + if (url == NULL) { + return back; + } + + back=InputDetector::getProtocolType(url); + if (back == __INPUT_UNKNOWN) { + back = __INPUT_FILE; + } + + return back; + +} + +char* InputDetector::removeProtocol(const char* url) { + int type=InputDetector::getProtocolType(url); + int n=strlen(url); + if (n == 0) { + return NULL; + } + if (type == __INPUT_UNKNOWN) { + return strdup(url); + } + int pos=InputDetector::getProtocolPos(type,url); + if (pos == -1) { + return NULL; + } + const char* name=protocols[pos].name; + int k=strlen(name); + if (n >= k) { + return strdup(url+k); + } + return NULL; + +} + +char* InputDetector::getExtension(const char* url) { + if (url == NULL) { + cout << "get url NULL"<= nExt) { + if(strncmp(url+nUrl-nExt,extension,nExt)==0) { + back=new char[nUrl-nExt+1]; + back[nUrl-nExt]=0; + strncpy(back,url,nUrl-nExt); + } + } + cout << "removeExt:"< +} + + +class InputDetector { + + + public: + InputDetector(); + ~InputDetector(); + + static int getInputType(const char* url); + + static int getProtocolType(const char* url); + // returns new allocated string without protocol specifier + static char* removeProtocol(const char* url); + static char* getWithoutExtension(const char* url); + static char* getExtension(const char* url); + static char* removeExtension(const char* url,char* extension); + static char* removeSlash(const char* url); + static char* getFilename(const char* url); + + private: + static int getProtocolPos(int type,const char* url); + +}; + +#endif + diff --git a/mpeglib/lib/input/inputPlugin.cpp b/mpeglib/lib/input/inputPlugin.cpp new file mode 100644 index 00000000..f3a33002 --- /dev/null +++ b/mpeglib/lib/input/inputPlugin.cpp @@ -0,0 +1,92 @@ +/* + C interface creator for input_plugins + 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 "inputPlugin.h" + +#include + +using namespace std; + + +InputPlugin::InputPlugin() { +} + + +InputPlugin::~InputPlugin() { +} + + + +int InputPlugin::getInputType(const char* dest) { + return InputDetector::getInputType(dest); +} + + +InputStream* InputPlugin::createInputStream(int inputType) { + // make checks which input routine to use + InputStream* inputStream; + int method; + + inputStream=NULL; + method=inputType; + + switch(method) { + case __INPUT_FILE: { + inputStream=new FileInputStream(); + break; + } + case __INPUT_CDDA: { + inputStream=new CDDAInputStream(); + break; + } + + case __INPUT_HTTP: { + inputStream=new HttpInputStream(); + break; + } + case __INPUT_CDI: { + inputStream=new CDRomInputStream(); + break; + } + default: + cout << "error cannot create default input stream"< + +#include "inputDetector.h" +#include + +#define _INPUT_THREADSAFE 1 + +class KDE_EXPORT InputPlugin { + + public: + InputPlugin(); + ~InputPlugin(); + + static InputStream* createInputStream(int inputType); + static InputStream* createInputStream(int inputType,int lThreadSafe); + static InputStream* createInputStream(const char* dest); + static InputStream* createInputStream(const char* dest,int lThreadSafe); + static int getInputType(const char* dest); + +}; +#endif diff --git a/mpeglib/lib/input/inputStream.cpp b/mpeglib/lib/input/inputStream.cpp new file mode 100644 index 00000000..7eb9943b --- /dev/null +++ b/mpeglib/lib/input/inputStream.cpp @@ -0,0 +1,135 @@ +/* + generic input 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 "inputStream.h" +#include "../util/mmx/mmx.h" + +#include + +using namespace std; + + +InputStream::InputStream() { + timeStampArray=new TimeStampArray((char*)"Input",3000); + urlBuffer=new DynBuffer(20); + // 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(); +} + + + +InputStream::~InputStream() { + delete timeStampArray; + delete urlBuffer; + +} + + +int InputStream::open(const char* dest) { + cout << "direct virtual call InputStream::open:"<insertTimeStamp(src,key,len); +} + +TimeStamp* InputStream::getTimeStamp(long key) { + return timeStampArray->getTimeStamp(key); +} + + +int InputStream::bytesUntilNext(long key) { + return timeStampArray->bytesUntilNext(key); +} + +void InputStream::print() { + cout << "direct virtual call InputStream::print"<getData(); +} + + +void InputStream::setUrl(const char* url) { + urlBuffer->clear(); + if (url != NULL) { + urlBuffer->append(url); + } +} + + + + + diff --git a/mpeglib/lib/input/inputStream.h b/mpeglib/lib/input/inputStream.h new file mode 100644 index 00000000..e232e99b --- /dev/null +++ b/mpeglib/lib/input/inputStream.h @@ -0,0 +1,79 @@ +/* + generic input 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 __MPEGLIBINPUTSTREAM_H +#define __MPEGLIBINPUTSTREAM_H + + +extern "C" { +#include +#include +#include +} + +#include "../util/timeStampArray.h" +#include "../util/dynBuffer.h" + + + + +/** + The abstraction for the input stream. In derived classes + we implement http,file and cdi access. +*/ + + +class InputStream { + + + + public: + InputStream(); + + + virtual ~InputStream(); + + virtual int open(const char* dest); + virtual void close(); + virtual int isOpen(); + + virtual int eof(); + virtual int read(char* ptr,int size); + virtual int seek(long bytePos); + // clears possible input buffers + // (called by the decoderPlugin after a resyncCommit) + virtual void clear(); + + virtual long getByteLength(); + virtual long getBytePosition(); + + virtual void insertTimeStamp(TimeStamp* src,long key,int len); + virtual TimeStamp* getTimeStamp(long key); + virtual int bytesUntilNext(long key); + virtual void print(); + char* getUrl(); + + + + protected: + DynBuffer* urlBuffer; + + + class TimeStampArray* timeStampArray; + void setUrl(const char* url); + + +}; +#endif diff --git a/mpeglib/lib/input/simpleRingBuffer.cpp b/mpeglib/lib/input/simpleRingBuffer.cpp new file mode 100644 index 00000000..71c92329 --- /dev/null +++ b/mpeglib/lib/input/simpleRingBuffer.cpp @@ -0,0 +1,420 @@ +/* + a thread safe ring buffer without dependencies + 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 "simpleRingBuffer.h" +#include + +#include + +using namespace std; + +static int instanceCnt=0; + +SimpleRingBuffer::SimpleRingBuffer(int size,int minLinSize) { + abs_thread_mutex_init(&mut); + abs_thread_cond_init(&dataCond); + abs_thread_cond_init(&spaceCond); + + instance=instanceCnt; + instanceCnt++; + this->size=size; + startPos=(char*)malloc(size); + readPos=startPos; + writePos=startPos; + lockPos=startPos; + + lockgrade=0; + fillgrade=0; + linAvail=size; + lastPos=(startPos+size-1); + eofPos=lastPos+1; + + canWrite=size; + canRead=0; + + minLinBuf=new char[minLinSize]; + this->minLinBufSize=minLinSize; + waitMinData=0; + waitMinSpace=0; + lWaitForData=false; + lWaitForSpace=false; + + readBytes=0; + writeBytes=0; + + lCanWaitForData=true; + lCanWaitForSpace=true; +} + + +SimpleRingBuffer::~SimpleRingBuffer() { + // The user of this class must take care that the threads + // have exited! + free(startPos); + delete [] minLinBuf; + abs_thread_mutex_destroy(&mut); + abs_thread_cond_destroy(&dataCond); + abs_thread_cond_destroy(&spaceCond); +} + + +int SimpleRingBuffer::getSize() { + return size; +} + + +int SimpleRingBuffer::getWriteArea(char* &ptr,int &size) { + + // When we are in this area the following + // can happen by the other thread + // fillgrade is decreased (because reader fowards) + // readPos is changed. + + ptr=writePos; + size=canWrite; + + return size; +} + + +void SimpleRingBuffer::updateCanWrite() { + if (lockPos < writePos) { + canWrite=eofPos-writePos; + //printf("1 c:%d l:%p w:%p",canWrite,lockPos,writePos); + } else if (lockPos > writePos) { + canWrite=lockPos-writePos; + //printf("2 c:%d l:%p w:%p",canWrite,lockPos,writePos); + } else { + if (fillgrade > 0) { + canWrite=0; + } else { + canWrite=eofPos-writePos; + } + //printf("2 c:%d ",canWrite); + + } + if (canWrite < 0) { + printf("error canWrite:%d fill:%d lock:%p start:%p eof:%p write:%p\n", + canWrite,fillgrade,lockPos,startPos,eofPos,writePos); + } + +} + + +void SimpleRingBuffer::updateCanRead() { + canRead=fillgrade-lockgrade; + int currentSpace=size-fillgrade; + if (currentSpace >= waitMinSpace) { + abs_thread_cond_signal(&spaceCond); + } + if (canRead < 0) { + printf("error canRead:%d fillgrade:%d lockgrade:%d \n", + canRead,fillgrade,lockgrade); + } + +} + + +void SimpleRingBuffer::forwardLockPtr(int nBytes) { + abs_thread_mutex_lock(&mut); + + if (fillgrade < lockgrade) { + printf("1:fillgrade:%d < lockgrade:%d\n",fillgrade,lockgrade); + } + fillgrade-=nBytes; + lockgrade-=nBytes; + if (fillgrade < lockgrade) { + printf("2:fillgrade:%d < lockgrade:%d nBytes:%d\n", + fillgrade,lockgrade,nBytes); + } + lockPos=lockPos+nBytes; + if (lockPos > lastPos) { // we expects that we had a linAvail part + // if user forwards more than buffer boundary + nBytes=lockPos-lastPos; + lockPos=startPos+nBytes-1; + } + updateCanWrite(); + updateCanRead(); + + abs_thread_mutex_unlock(&mut); + return; +} + + +void SimpleRingBuffer::forwardWritePtr(int nBytes) { + abs_thread_mutex_lock(&mut); + + fillgrade=fillgrade+nBytes; + if (fillgrade < lockgrade) { + printf("3:fillgrade:%d < lockgrade:%d nBytes:%d\n", + fillgrade,lockgrade,nBytes); + } + writeBytes+=nBytes; + writePos=writePos+nBytes; + if(writePos >= eofPos) { + if (writePos == eofPos) { + writePos=startPos; + } else { + cout << "writePos > eofPos ! forward error:"<<(eofPos-writePos) + <<" bytes"<= waitMinData) { + abs_thread_cond_signal(&dataCond); + } + abs_thread_mutex_unlock(&mut); +} + + +int SimpleRingBuffer::waitForSpace(int bytes){ + abs_thread_mutex_lock(&mut); + int back=0; + waitMinSpace=bytes; + if (waitMinSpace > size) { + waitMinSpace=size; + } + if (waitMinSpace < 0) { + cout << "negative waitForSpace"<= waitMinSpace) { + back=1; + } + abs_thread_mutex_unlock(&mut); + return back; +} + + +void SimpleRingBuffer::exitWaitForSpace(){ + abs_thread_mutex_lock(&mut); + abs_thread_cond_signal(&spaceCond); + abs_thread_mutex_unlock(&mut); +} + +void SimpleRingBuffer::setCanWaitForSpace(int lCanWaitForSpace) { + abs_thread_mutex_lock(&mut); + this->lCanWaitForSpace=lCanWaitForSpace; + abs_thread_cond_signal(&spaceCond); + abs_thread_mutex_unlock(&mut); + +} + + + +void SimpleRingBuffer::forwardReadPtr(int nBytes) { + abs_thread_mutex_lock(&mut); + readBytes+=nBytes; + readPos+=nBytes; + linAvail=linAvail-nBytes; + lockgrade+=nBytes; + if (readPos > lastPos) { // we expects that we had a linAvail part + // if user forwards more than buffer boundary + nBytes=readPos-lastPos; + readPos=startPos+nBytes-1; + linAvail=lastPos+1-readPos; + } + if (fillgrade < lockgrade) { + printf("5:fillgrade:%d < lockgrade:%d nBytes:%d\n", + fillgrade,lockgrade,nBytes); + } + updateCanRead(); + abs_thread_mutex_unlock(&mut); +} + + + +int SimpleRingBuffer::getReadArea(char* &ptr,int &readSize) { + int pSize=readSize; + ptr=readPos; + + if (canRead == 0) { + readSize=0; + return 0; + } + if (pSize < 0) { + cout << "Generic Memory Info invalid"< linAvail) && + (minLinBufSize >linAvail) && + (canRead > linAvail) ) { + int copySize; + copySize=canRead; // we cannot copy more than this + if (copySize > pSize) { // if it is too much reduche it + copySize=pSize; + } + if (copySize > minLinBufSize) { // if it does not fit in buffer->reduce + copySize=minLinBufSize; + } + memcpy(minLinBuf,readPos,linAvail); + memcpy(minLinBuf+linAvail,startPos,copySize-linAvail); + readSize=copySize; + ptr=minLinBuf; + return copySize; + } + + // linAvail part end + + int copyBytes=linAvail; + if (canRead < copyBytes) { + copyBytes=canRead; + } + if (copyBytes >= pSize) { + readSize=pSize; + } else { + readSize=copyBytes; + } + return readSize; +} + + + +void SimpleRingBuffer::exitWaitForData(){ + abs_thread_mutex_lock(&mut); + abs_thread_cond_signal(&dataCond); + abs_thread_mutex_unlock(&mut); +} + + + +int SimpleRingBuffer::waitForData(int bytes){ + abs_thread_mutex_lock(&mut); + int back=0; + waitMinData=bytes; + if (waitMinData > size) { + waitMinData=size; + } + if (waitMinData < 0) { + cout << "negative waitForData"<= waitMinData) { + back=1; + } + abs_thread_mutex_unlock(&mut); + return back; +} + +int SimpleRingBuffer::getCanWaitForData() { + return lCanWaitForData; +} + + +void SimpleRingBuffer::setCanWaitForData(int lCanWaitForData) { + abs_thread_mutex_lock(&mut); + this->lCanWaitForData=lCanWaitForData; + abs_thread_cond_signal(&dataCond); + abs_thread_mutex_unlock(&mut); + +} + +void SimpleRingBuffer::emptyBuffer() { + abs_thread_mutex_lock(&mut); + writePos=readPos; + if (fillgrade < lockgrade) { + printf("4:fillgrade:%d < lockgrade:%d\n",fillgrade,lockgrade); + } + linAvail=lastPos+1-writePos; + fillgrade=lockgrade; + updateCanRead(); + updateCanWrite(); + readBytes=0; + writeBytes=0; + if (size-fillgrade >= waitMinSpace) { + abs_thread_cond_signal(&spaceCond); + } + if (fillgrade >= waitMinData) { + abs_thread_cond_signal(&dataCond); + } + abs_thread_mutex_unlock(&mut); +} + + +int SimpleRingBuffer::getFillgrade() { + return fillgrade; +} + + +int SimpleRingBuffer::getReadBytes() { + return readBytes; +} + + +int SimpleRingBuffer::getWriteBytes() { + return writeBytes; +} + + +int SimpleRingBuffer::getFreeRead() { + return fillgrade; +} + +int SimpleRingBuffer::getFreeWrite() { + return size-fillgrade; +} + +void SimpleRingBuffer::resizeBuffer(int changeSize) { + abs_thread_mutex_lock(&mut); + int lPos=lockPos-startPos; + int wPos=writePos-startPos; + int rPos=readPos-startPos; + startPos=(char *)realloc(startPos,changeSize); + size=changeSize; + readPos=startPos+lPos; + writePos=startPos+wPos; + lockPos=startPos+rPos; + + lastPos=(startPos+size-1); + eofPos=lastPos+1; + + linAvail=lastPos+1-readPos; + + updateCanWrite(); + updateCanRead(); + abs_thread_mutex_unlock(&mut); + + +} diff --git a/mpeglib/lib/input/simpleRingBuffer.h b/mpeglib/lib/input/simpleRingBuffer.h new file mode 100644 index 00000000..101725bf --- /dev/null +++ b/mpeglib/lib/input/simpleRingBuffer.h @@ -0,0 +1,136 @@ +/* + a thread safe ring buffer without dependencies + 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 _SIMPLERINGBUFFER_H +#define _SIMPLERINGBUFFER_H + +#include "../util/abstract/abs_thread.h" + +extern "C" { + #include +} + +/** + Note to parameter minLinBufSize in Constructor: +

+ If the fillgrade is sufficient we can delivier at least + this amount of bytes with one "fill" + (If the fillgrade is not suffficient we can only deliever fillgrade) + This values adresses the problem that a ring buffer cannot + deliever linear memory the whole time(eg. if you read near the + upper end) +

+ If the requested Buffersize by the device is smaller than + this number you can be sure that you get exactly + your preferred buffersize. not more not less.(but + only if the fillgrade allows this) +*/ + + + + +class SimpleRingBuffer { + + + public: + + SimpleRingBuffer(int ringBufferSize, int minLinBufferSize); + virtual ~SimpleRingBuffer(); + + // Writer thread can call these: + + int getWriteArea(char* &ptr,int &size); + void forwardWritePtr(int bytes); + int waitForSpace(int minSpace); + void exitWaitForSpace(); + void setCanWaitForSpace(int lCanWaitForSpace); + + + // Reader thread these: + + void forwardReadPtr(int bytes); + int getReadArea(char* &ptr,int &size); + int waitForData(int minData); + void exitWaitForData(); + void setCanWaitForData(int lCanWaitForData); + int getCanWaitForData(); + + + // and the lockPos + void forwardLockPtr(int bytes); + + + // both: + + int getFillgrade(); // return how much buffer between reader/writer + void emptyBuffer(); // frees the space between them + int getFreeRead(); + int getFreeWrite(); + + int getSize(); + int getReadBytes(); + int getWriteBytes(); + + // make sure that no one calls getReadArea/getWriteArea + void resizeBuffer(int changeSize); + private: + void updateCanWrite(); + void updateCanRead(); + + int size; + + int lockgrade; + int fillgrade; + + char* readPos; + char* writePos; + char* lockPos; + + char* startPos; + + char* lastPos; + char* eofPos; + int canWrite; + int canRead; + + int waitMinData; + int waitMinSpace; + + abs_thread_mutex_t mut; + abs_thread_cond_t dataCond; + abs_thread_cond_t spaceCond; + + int insertBlock; + int readBlock; + int linAvail; + + char* minLinBuf; + int minLinBufSize; + int lWaitForData; + int lWaitForSpace; + + // statistic purpose: + int readBytes; + int writeBytes; + + int lCanWaitForSpace; + int lCanWaitForData; + int instance; +}; + +#endif + + + diff --git a/mpeglib/lib/input/threadSafeInputStream.cpp b/mpeglib/lib/input/threadSafeInputStream.cpp new file mode 100644 index 00000000..8b18a4c5 --- /dev/null +++ b/mpeglib/lib/input/threadSafeInputStream.cpp @@ -0,0 +1,137 @@ +/* + thread safe wrapper for input 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 "threadSafeInputStream.h" + + +ThreadSafeInputStream::ThreadSafeInputStream(InputStream* input) { + threadQueue=new ThreadQueue(); + this->input=input; +} + + +ThreadSafeInputStream::~ThreadSafeInputStream() { + delete threadQueue; + delete input; +} + + + +int ThreadSafeInputStream::open(const char* dest) { + int back; + threadQueue->waitForExclusiveAccess(); + back=input->open(dest); + threadQueue->releaseExclusiveAccess(); + return back; +} + + +void ThreadSafeInputStream::close() { + threadQueue->waitForExclusiveAccess(); + input->close(); + threadQueue->releaseExclusiveAccess(); +} + + +int ThreadSafeInputStream::isOpen() { + int back; + threadQueue->waitForExclusiveAccess(); + back=input->isOpen(); + threadQueue->releaseExclusiveAccess(); + return back; +} + + +int ThreadSafeInputStream::eof() { + int back; + threadQueue->waitForExclusiveAccess(); + back=input->eof(); + threadQueue->releaseExclusiveAccess(); + return back; +} + + +int ThreadSafeInputStream::read(char* buf,int len) { + int back; + threadQueue->waitForExclusiveAccess(); + back=input->read(buf,len); + threadQueue->releaseExclusiveAccess(); + return back; +} + + +int ThreadSafeInputStream::seek(long bytePos) { + int back; + threadQueue->waitForExclusiveAccess(); + back=input->seek(bytePos); + threadQueue->releaseExclusiveAccess(); + return back; +} + +void ThreadSafeInputStream::clear() { + threadQueue->waitForExclusiveAccess(); + input->clear(); + threadQueue->releaseExclusiveAccess(); +} + + +long ThreadSafeInputStream::getByteLength() { + long back; + threadQueue->waitForExclusiveAccess(); + back=input->getByteLength(); + threadQueue->releaseExclusiveAccess(); + return back; +} + + +long ThreadSafeInputStream::getBytePosition() { + long back; + threadQueue->waitForExclusiveAccess(); + back=input->getBytePosition(); + threadQueue->releaseExclusiveAccess(); + return back; +} + + +void ThreadSafeInputStream::insertTimeStamp(TimeStamp* src,long key,int len) { + threadQueue->waitForExclusiveAccess(); + input->insertTimeStamp(src,key,len); + threadQueue->releaseExclusiveAccess(); +} + + +TimeStamp* ThreadSafeInputStream::getTimeStamp(long key) { + TimeStamp* back; + threadQueue->waitForExclusiveAccess(); + back=input->getTimeStamp(key); + threadQueue->releaseExclusiveAccess(); + return back; +} + + +int ThreadSafeInputStream::bytesUntilNext(long key) { + int back; + threadQueue->waitForExclusiveAccess(); + back=input->bytesUntilNext(key); + threadQueue->releaseExclusiveAccess(); + return back; +} + +void ThreadSafeInputStream::print() { + threadQueue->waitForExclusiveAccess(); + input->print(); + threadQueue->releaseExclusiveAccess(); +} + + + diff --git a/mpeglib/lib/input/threadSafeInputStream.h b/mpeglib/lib/input/threadSafeInputStream.h new file mode 100644 index 00000000..0a29637b --- /dev/null +++ b/mpeglib/lib/input/threadSafeInputStream.h @@ -0,0 +1,56 @@ +/* + thread safe wrapper for input 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 __THREADSAFEINPUTSTREAM_H +#define __THREADSAFEINPUTSTREAM_H + +// read INTRO in threadQueue.h +// This class makes the inputStream (given in constructor) +// threadsafe by wrapping each call with a threadqueue. +// +// Important NOTE: the input pointer is the owned by this class !!! +// which means: we call delete on it! + +#include "../util/abstract/threadQueue.h" +#include "inputStream.h" + + +class ThreadSafeInputStream : public InputStream { + + ThreadQueue* threadQueue; + InputStream* input; + + public: + ThreadSafeInputStream(InputStream* input); + ~ThreadSafeInputStream(); + + + int open(const char* dest); + void close(); + int isOpen(); + + int eof(); + int read(char* ptr,int size); + int seek(long bytePos); + void clear(); + + long getByteLength(); + long getBytePosition(); + + void insertTimeStamp(TimeStamp* src,long key,int len); + TimeStamp* getTimeStamp(long key); + int bytesUntilNext(long key); + void print(); + +}; +#endif -- cgit v1.2.1