diff options
Diffstat (limited to 'mpeglib/lib/input')
32 files changed, 3998 insertions, 0 deletions
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 <config.h> +#endif + +#ifdef CDDA_PARANOIA + +#include <iostream> + +using namespace std; + +#include "cddaInputStream.h" +#include "inputDetector.h" + + +void paranoiaCallback(long, int) { + //cout << "long:"<<a<<" int:"<<b<<endl; +} + +CDDAInputStream::CDDAInputStream() { + drive = NULL; + paranoia=NULL; + device=NULL; + track=1; +} + + +CDDAInputStream::~CDDAInputStream() { + close(); +} + +// here we should encdoe the track Nr. as well +// eg: /dev/cdrom#1 +int CDDAInputStream::getTrackAndDevice(const char* url) { + int matches=0; + // dest = "cdda:/dev/cdrom/track01.cda" + char* noprotoString=InputDetector::removeProtocol(url); + // noprotoString="/dev/cdrom/track01.cda" + char* filename=InputDetector::getFilename(noprotoString); + // filename="track01.cda" + char* filenameNoExt=InputDetector::getWithoutExtension(filename); + // filenameNoExt="track01" + char* dir=InputDetector::removeExtension(noprotoString,filename); + // dir="/dev/cdrom/" + device=InputDetector::removeSlash(dir); + track=1; + if (filenameNoExt != NULL) { + matches=sscanf(filenameNoExt,"track%02d",&track); + } + if (matches == 0) { + cout << "no trackNumber found using default"<<endl; + } + cout << "device:"<<device<<" track:"<<track<<endl; + + if (noprotoString != NULL) { + delete noprotoString; + } + if (filename != NULL) { + delete filename; + } + if (filenameNoExt != NULL) { + delete filenameNoExt; + } + if (dir != NULL) { + delete dir; + } + if (device == NULL) { + cout << "no device found, using any"<<endl; + return false; + } + return true; +} + +int CDDAInputStream::open(const char* dest) { + if (getTrackAndDevice(dest) == true) { + drive = cdda_identify(device, CDDA_MESSAGE_PRINTIT, 0); + } + + if (drive == NULL) { + cout << "cdda_identify failed trying to find a device"<<endl; + drive=cdda_find_a_cdrom(CDDA_MESSAGE_PRINTIT, 0); + } + if (drive == NULL) { + cout << "nope. nothing found. give up"<<endl; + return false; + } + cout << "cdda_open -s"<<endl; + if (cdda_open(drive) != 0) { + cout << "cdda_open(drive) failed"<<endl; + close(); + return false; + } + cout << "cdda_open -e"<<endl; + + // debug things a bit + int trackCount = drive->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"<<endl; + close(); + return false; + } + + firstSector=cdda_track_firstsector(drive, track); + lastSector=cdda_track_lastsector(drive, track); + currentSector=firstSector; + // paranoia && drive != NULL -> 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"<<endl; + exit(0); + } + int16_t * buf = paranoia_read(paranoia, paranoiaCallback); + currentSector++; + if (buf == NULL) { + cout << "paranoia_read failed"<<endl; + close(); + return 0; + } + memcpy(dest,buf,sizeof(int16_t)*CD_FRAMESIZE_RAW); + return CD_FRAMESIZE_RAW; +} + + +int CDDAInputStream::seek(long bytePos) { + int byteLength=getByteLength(); + float ratio=(float)bytePos/(float)(byteLength+1); + float wantSector=ratio*(float)((lastSector-firstSector)); + if (isOpen()) { + currentSector=(int)wantSector; + cout << "paranoia_seek:"<<currentSector<<endl; + paranoia_seek(paranoia, currentSector, SEEK_SET); + } + return true; +} + +void CDDAInputStream::clear() { + cout << "direct virtual call CDDAInputStream::clear:"<<endl; +} + + +long CDDAInputStream::getByteLength() { + int sectors=lastSector-firstSector; + int bytes=sectors*CD_FRAMESIZE_RAW*sizeof(int16_t); + cout << "getByteLength:"<<bytes<<endl; + return bytes; +} + + +long CDDAInputStream::getBytePosition() { + int readSectors=currentSector-firstSector; + int bytes=readSectors*CD_FRAMESIZE_RAW*sizeof(int16_t); + return bytes; +} + +#endif +//CDDA_PARANOIA + + + + + diff --git a/mpeglib/lib/input/cddaInputStream.h b/mpeglib/lib/input/cddaInputStream.h new file mode 100644 index 00000000..55989c65 --- /dev/null +++ b/mpeglib/lib/input/cddaInputStream.h @@ -0,0 +1,85 @@ +/* + 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 + + */ + + + + +#ifndef __CDDAINPUTSTREAM_H +#define __CDDAINPUTSTREAM_H + + +#include "inputStream.h" + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef CDDA_PARANOIA +class CDDAInputStream : public InputStream { +}; +#else + +#include <sys/types.h> +typedef int16_t size16; +typedef int32_t size32; + +extern "C" { +#include <cdda_interface.h> +#include <cdda_paranoia.h> +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 <getopt.h> +#endif + +void usage() { + cout << "cdigrab grabs video cds"<<endl; + cout << "Usage : cdigrab [s:b:f:h] cdi:/device"<<endl; + cout << endl; + cout << "-s : bytes start a positions <bytes>"<<endl; + cout << "-b : set block size (default: 32768)"<<endl; + cout << "-f : set filename (default: a.cdi)"<<endl; + cout << "-h : help"<<endl; + cout << "THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! " \ + << "USE AT YOUR OWN RISK!"<<endl; + cout << endl; +} + + +int main(int argn,char** args) { + + + if (argn <= 1) { + usage(); + exit(0); + } + long startBytes=0; + int len=32768; + char *fname = strdup("a.cdi"); + int c; + + while(1) { + c = getopt (argn, args, "s:b:f:h"); + if (c == -1) break; + switch(c) { + case 'h': { + usage(); + exit(0); + } + case 's': { + startBytes=atoi(optarg); + break; + } + case 'b': { + len=atoi(optarg); + break; + } + case 'f': { + fname = strdup(optarg); + break; + } + default: + printf ("?? getopt returned character code 0%o ??\n", c); + usage(); + exit(-1); + } + } + if (optind >= argn ) { + usage(); + exit(-1); + } + + InputStream* in=InputPlugin::createInputStream(args[optind]); + + in->open(args[optind]); + + if (startBytes != 0) { + cout << "seeking to :"<<startBytes<<endl; + in->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"<<endl; + break; + } + in->read(buffer,len); + fwrite(buffer,len,1,f); + cnt++; + cout << "grapped:"<<cnt*len<<endl; + } + fclose(f); +} + + + diff --git a/mpeglib/lib/input/cdromAccess.cpp b/mpeglib/lib/input/cdromAccess.cpp new file mode 100644 index 00000000..98d49779 --- /dev/null +++ b/mpeglib/lib/input/cdromAccess.cpp @@ -0,0 +1,54 @@ +/* + * system dependent wrapper for access to cdrom + * 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 + * + * $Id$ + * + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + + + +#ifdef OS_AIX + #include "cdromAccess_Empty.cpp" +#endif + +#ifdef OS_Linux + #include <sys/types.h> + #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 <iostream> +using namespace std; + + +int CDRomToc::getStartEnd(FILE* file,int& startToc,int& endToc) { + cout << "CDRomToc::getStartEnd not implemented on your system"<<endl; + return false; +} + + +int CDRomToc::readToc(FILE* file,int num,int& min,int& sec, int& frame) { + cout << "CDRomToc::readToc not implemented on your system"<<endl; + return false; +} + + +int CDRomToc::readLeadOut(FILE* file,int& min,int& sec, int& frame) { + cout << "CDRomToc::reatLeadOut not implemented on your system"<<endl; + return false; +} + + + +int CDRomRawAccess::readDirect(int minute,int second, int frame) { + + + cout << "no CDRomRawAccess::read implemented for your system"<<endl; + lData=false; + return true; +} + diff --git a/mpeglib/lib/input/cdromAccess_Linux.cpp b/mpeglib/lib/input/cdromAccess_Linux.cpp new file mode 100644 index 00000000..a3bde622 --- /dev/null +++ b/mpeglib/lib/input/cdromAccess_Linux.cpp @@ -0,0 +1,124 @@ +/* + system dependent wrapper for access to cdrom (Linux) + 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 + + */ + +#ifdef __STRICT_ANSI__ +#undef __STRICT_ANSI__ +#define _ANSI_WAS_HERE_ +#endif +#include <linux/types.h> +#include <linux/cdrom.h> +#ifdef _ANSI_WAS_HERE_ +#define __STRICT_ANSI__ +#endif +#include <sys/ioctl.h> + +#include "cdromToc.h" +#include "cdromRawAccess.h" + +#include <iostream> + +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:"<<minute + << " sec:"<<second + << " frame:"<<frame<<endl; + return false; + } else { + //cout << "read success ****************"<<endl; + } + + char* subheader=data+sizeof(int); + + + if ((subheader[1]==1) && + (((subheader[2]==0x62) && + (subheader[3]==0x0f)) || ((subheader[2]==0x64) && + (subheader[3]==0x7f)))) { + lData=true; + dataStart=sizeof(int)+4; + } else { + lData=false; + } + + len=2324; + + + return true; +} + diff --git a/mpeglib/lib/input/cdromInputStream.cpp b/mpeglib/lib/input/cdromInputStream.cpp new file mode 100644 index 00000000..1cf3f905 --- /dev/null +++ b/mpeglib/lib/input/cdromInputStream.cpp @@ -0,0 +1,309 @@ +/* + reads input data from cdrom + 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 "cdromInputStream.h" +#include "cdromRawAccess.h" +#include "cdromToc.h" +#include <string.h> +#include "inputDetector.h" + +#include <iostream> + +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 ..."<<endl; + ok=cdRomRawAccess->read(currentMinute,currentSecond,currentFrame); + if (ok) { + bufCurrent=cdRomRawAccess->getBufferStart(); + buflen=cdRomRawAccess->getBufferLen(); + return true; + } + cnt++; + if (cnt > 100) { + break; + } + } + cout << "last possible jump"<<endl; + if (pos > 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:"<<file<<endl; + char* noExtension=InputDetector::getWithoutExtension(file); + cout << "CDRomInputStream::noExt:"<<noExtension<<endl; + if (noExtension == NULL) { + return false; + } + cdRomToc->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"<<endl; + } + + // cdRomRawAccess->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"<<back<<endl; + return back; +} + +long CDRomInputStream::getByteLength() { + // we get the length out of the toc and then multiply like hell + long totalSecs=cdRomToc->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"<<endl; + cnt++; + } else { + return true; + } + } + return false; + } + return true; +} + + + + + + diff --git a/mpeglib/lib/input/cdromInputStream.h b/mpeglib/lib/input/cdromInputStream.h new file mode 100644 index 00000000..cda18efe --- /dev/null +++ b/mpeglib/lib/input/cdromInputStream.h @@ -0,0 +1,88 @@ +/* + reads input data from cdrom + 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 __VIDEOCDINPUTSTREAM_H +#define __VIDEOCDINPUTSTREAM_H + + + +#include "inputStream.h" + + + +#define _CDROM_FRAMES 75 +#define _CDROM_SECS 60 + + +/** + This is necessary because CD-I or VCD disks are not correctly + mounted by the linux kernel. + Windows seems to do it correct (sometimes, the other time it nearly crash) + During my test I found out that CD-I and VCD seems to be different. + One works with the CD-I loader the other with the VCD loader. + + This class tries to find out if its a CD-I / VCD stream. + Then you can set the interface and load from this interface. + + This class depends on the reader routines from xreadcdi/ xreadvcd, + Author: Ales Makarov <xmakarov@sun.felk.cvut.cz> + 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 <iostream> + +#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:"<<openfile<<endl; + cdfile=fopen(openfile, "rb"); + lOpen=false; + + if (cdfile == NULL) { + perror("open CDRomRawAccess"); + } else { + lOpen=true; + leof=false; + } + return lOpen; +} + + +int CDRomRawAccess::eof() { + return leof; +} + + +int CDRomRawAccess::read(int minute,int second, int frame) { + if (isOpen()==false) { + cerr << "CDRomRawAccess not open"<<endl; + return false; + } + + int lInRange=cdromToc->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 <iostream> + +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"<<endl; + exit(0); + } + for (j=maxEntries;j>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<maxEntries;i++) { + if (tocEntries[i].minute <= minute) { + continue; + } else { + break; + } + if (tocEntries[i].second <= second) { + continue; + } else { + break; + } + if (tocEntries[i].frame <= frame) { + continue; + } + break; + } + return i; +} + + + +int CDRomToc::isElement(int minute,int second,int frame) { + int i; + + for (i=0;i<maxEntries;i++) { + if (tocEntries[i].minute == minute) { + if (tocEntries[i].second == second) { + if (tocEntries[i].frame == frame) { + return true; + } + } + } + } + return false; +} + + + + + + +int CDRomToc::getTocEntries() { + return maxEntries; +} + + +TocEntry* CDRomToc::getTocEntry(int entry) { + return &(tocEntries[entry]); +} + + +void CDRomToc::print() { + int i; + cerr << "******* printing TOC [START]"<<endl; + for(i=0;i<maxEntries;i++) { + cerr << "i:"<<i + <<" M:"<<tocEntries[i].minute + <<" S:"<<tocEntries[i].second + <<" F:"<<tocEntries[i].frame<<endl; + } + cerr << "******* printing TOC [END}"<<endl; +} + + +int CDRomToc::isInRange(int minute,int second,int) { + long val=minute*60+second; + if (val < startByte) { + return false; + } + if (val > endByte) { + return false; + } + return true; +} + +int CDRomToc::calculateRange() { + + + if (maxEntries < 2) { + cout << "no two elemts in toc"<<endl; + return false; + } + startByte=tocEntries[0].minute*60*+tocEntries[0].second; + + // do a safty end because of the kernel bug + int minute=tocEntries[maxEntries-1].minute; + int second=tocEntries[maxEntries-1].second-20; + if (second < 0) { + minute--; + second=60+second; + } + if (minute < 0) { + endByte=0; + return true; + } + + endByte=minute*60+second; + + return true; + +} + + +int CDRomToc::getEndSecond() { + return endByte; +} + + + + +int CDRomToc::open(const char* openfile) { + int i; + int pos=0; + maxEntries=0; + const char* filename=strchr(openfile,'/'); + FILE* file =fopen(filename, "rb"); + if (file == NULL) { + perror("open"); + return false; + } + cout << "reading toc on:"<<filename<<" openfile:"<<openfile<<endl; + + int startToc=0; + int endToc=0; + + if (getStartEnd(file,startToc,endToc) == false) { + cout << "getStartEnd in CDRomToc failed"<<endl; + fclose(file); + return false; + } + cout << "startToc:"<<startToc<<" endToc:"<<endToc<<endl; + cout << "reading toc -2"<<endl; + /* read individual tracks */ + int min; + int sec; + int frame; + + for (i=startToc; i<=endToc; i++) { + int min; + int sec; + int frame; + + if (readToc(file,i,min,sec,frame) == false) { + cout << "error in CDRomToc::readToc"<<endl; + fclose(file); + return false; + } + cout << "min:"<<min<<endl; + cout << "sec:"<<sec<<endl; + cout << "frame:"<<frame<<endl; + + insertTocEntry(min,sec,frame); + pos++; + } + + + /* read the lead-out track */ + if (readLeadOut(file,min,sec,frame) == false) { + cout << "error in CDRomToc::reatLeadOut"<<endl; + return false; + } + pos++; + insertTocEntry(min,sec,frame); + + maxEntries=pos; + + fclose(file); + + return true; +} + diff --git a/mpeglib/lib/input/cdromToc.h b/mpeglib/lib/input/cdromToc.h new file mode 100644 index 00000000..20b60e10 --- /dev/null +++ b/mpeglib/lib/input/cdromToc.h @@ -0,0 +1,65 @@ +/* + 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 + + */ + + +#ifndef __CDROMTOC_H +#define __CDROMTOC_H + +extern "C" { +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +} + +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 <iostream> + +using namespace std; + +FileAccessWrapper::FileAccessWrapper(InputStream* input) { + this->input=input; +} + + +FileAccessWrapper::~FileAccessWrapper() { + +} + + +int FileAccessWrapper::open(const char*) { + cout << "FileAccessWrapper open not implemented"<<endl; + exit(0); +} + + +void FileAccessWrapper::close() { + cout << "FileAccessWrapper close not implemented"<<endl; + exit(0); +} + + +int FileAccessWrapper::read(char* dest,int len) { + return input->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 <iostream> + +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<<endl; + + } else { + lopen=true; + struct stat fileStat; + stat(dest,&fileStat); + fileLen=(long)fileStat.st_size; + } + int back=(file!=NULL); + return back; +} + + +void FileInputStream::close() { + if (isOpen()) { + ::fclose(file); + file=NULL; + lopen=false; + } +} + + +int FileInputStream::isOpen() { + return lopen; +} + + +int FileInputStream::eof() { + if (isOpen()==false){ + return true; + } + int back=true; + if (file != NULL) { + back=feof(file); + } + + return back; +} + + +int FileInputStream::read(char* ptr,int size) { + int bytesRead=-1; + if (isOpen()) { + if (size <= 0) { + cout << "size is <= 0!"<<endl; + return 0; + } + if (file != NULL) { + bytesRead=fread(ptr,1,size,file); + } + } else { + cerr << "read on not open file want:"<<size<<endl; + return 0; + } + return bytesRead; +} + + +int FileInputStream::seek(long posInBytes) { + int back=true; + if (isOpen()==false) { + return false; + } + long pos=-1; + if (file != NULL) { + pos=fseek(file,posInBytes,SEEK_SET); + } + + if (pos < 0) { + cout <<"seek error in FileInputStream::seek"<<endl; + back=false; + } + return back; +} + + +long FileInputStream::getByteLength() { + return fileLen; +} + + +long FileInputStream::getBytePosition() { + int back=0; + if (isOpen()) { + if (file != NULL) { + back=ftell(file); + } + } + return back; +} + + + +void FileInputStream::print() { + printf("pos in file:%8x\n",(int)getBytePosition()); +} + + diff --git a/mpeglib/lib/input/fileInputStream.h b/mpeglib/lib/input/fileInputStream.h new file mode 100644 index 00000000..ea421a55 --- /dev/null +++ b/mpeglib/lib/input/fileInputStream.h @@ -0,0 +1,46 @@ +/* + 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 __FILEINPUTSTREAM_H +#define __FILEINPUTSTREAM_H + + + +#include "inputStream.h" + + + +class FileInputStream : public InputStream{ + + FILE* file; + int lopen; + long fileLen; + public: + FileInputStream(); + ~FileInputStream(); + + 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(); + +}; +#endif diff --git a/mpeglib/lib/input/httpInputStream.cpp b/mpeglib/lib/input/httpInputStream.cpp new file mode 100644 index 00000000..df2f09c4 --- /dev/null +++ b/mpeglib/lib/input/httpInputStream.cpp @@ -0,0 +1,327 @@ +/* + 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 "httpInputStream.h" + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +#include <iostream> + +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)"<<endl; + delete filename2; + return false; + } + delete filename2; + lopen=true; + setUrl(filename); + return lopen; +} + + +void HttpInputStream::close() { + if (isOpen()) { + ::fclose(fp); + } + lopen=false; + setUrl(NULL); +} + + +int HttpInputStream::isOpen() { + return lopen; +} + + +int HttpInputStream::eof() { + if (isOpen()==false){ + return true; + } + return feof(fp); +} + + +int HttpInputStream::read(char* ptr,int size) { + int bytesRead=0; + if (isOpen()) { + bytesRead=fread(ptr, 1,size, fp); + if (ferror(fp) != 0){ + cout <<"http fread error"<<endl; + } else { + byteCnt+=bytesRead; + } + } + return bytesRead; +} + +int HttpInputStream::seek(long posInBytes) { + cout << "HttpInputStream::setBytePos not implemented:"<<posInBytes<<endl; + return false; +} + + + +long HttpInputStream::getByteLength() { + cout << "HttpInputStream::getByteLength not implemented"<<endl; + return 0; +} + + + +void HttpInputStream::print() { + printf("pos in file:%8x\n",(int)ftell(fp)); +} + + +int HttpInputStream::writestring(int fd, char *string) { + int result,bytes=strlen(string); + + while (bytes) { + if((result=SOCKETWRITEFUNC(fd,string,bytes))<0 && errno!=EINTR) { + cout << "writestring fail -1"<<endl; + return false; + } + else if(result==0) { + cout << "writestring fail -2"<<endl; + return false; + } + string += result; + bytes -= result; + } + return true; +} + + + +FILE* HttpInputStream::http_open(char *url) { + char *purl=NULL,*host,*request,*sptr; + char agent[50]; + int linelength; + unsigned long myip; + unsigned int myport; + int sock; + int relocate=0,numrelocs=0; + struct sockaddr_in server; + FILE *myfile; + if (url == NULL) { + cout << "cannot open NULL http_open"<<endl; + return NULL; + } + if (strlen(url)==0) { + cout << "zero length http_open"<<endl; + return NULL; + } + + if(!proxyip) + { + if(!proxyurl) + if(!(proxyurl=getenv("MP3_HTTP_PROXY"))) + if(!(proxyurl=getenv("http_proxy"))) + proxyurl = getenv("HTTP_PROXY"); + if (proxyurl && proxyurl[0] && strcmp(proxyurl, "none")) + { + if (!(url2hostport(proxyurl, &host, &proxyip, &proxyport))) + { + cout << "seterrorcode(SOUND_ERROR_UNKNOWNPROXY)"<<endl;; + return NULL; + } + if(host)free(host); + } + else + proxyip = INADDR_NONE; + } + + if((linelength=strlen(url)+100)<1024) + linelength=1024; + if(!(request=(char *)malloc(linelength)) || !(purl=(char *)malloc(1024))) + { + cout << "seterrorcode(SOUND_ERROR_MEMORYNOTENOUGH)"<<endl; + return NULL; + } + strncpy(purl,url,1023); + purl[1023]='\0'; + do{ + strcpy(request,"GET "); + if(proxyip!=INADDR_NONE) + { + if(strncmp(url,httpstr,7)) + strcat(request,httpstr); + strcat(request,purl); + myport=proxyport; + myip=proxyip; + } + else + { + if(!(sptr=url2hostport(purl,&host,&myip,&myport))) + { + cout << "seterrorcode(SOUND_ERROR_UNKNOWNHOST)"<<endl;; + return NULL; + } + if (host) + free (host); + strcat (request, sptr); + } + sprintf (agent, " HTTP/1.0\r\nUser-Agent: %s/%s\r\n\r\n", + "Splay","0.6"); + strcat (request, agent); + server.sin_family = AF_INET; + server.sin_port = htons(myport); + server.sin_addr.s_addr = myip; + if((sock=socket(PF_INET,SOCK_STREAM,6))<0) { + cout <<"seterrorcode(SOUND_ERROR_SOCKET)"<<endl; + return NULL; + } + if(connect(sock,(struct sockaddr *)&server,sizeof(server))) { + cout <<"seterrorcode(SOUND_ERROR_CONNECT)"<<endl; + return NULL; + } + if(!writestring(sock,request))return NULL; + if(!(myfile=::fdopen(sock, "rb"))) { + cout << "seterrorcode(SOUND_ERROR_FDOPEN)"<<endl; + return NULL; + }; + relocate=false; + purl[0]='\0'; + if(!readstring(request,linelength-1,myfile))return NULL; + if((sptr=strchr(request,' '))) { + switch(sptr[1]) { + case '3':relocate=true; + case '2':break; + default: + cout <<"seterrorcode(SOUND_ERROR_HTTPFAIL)"<<endl; + return NULL; + } + } + do { + if(!readstring(request,linelength-1,myfile))return NULL; + if(!strncmp(request,"Location:",9)) + strncpy (purl,request+10,1023); + } while (request[0]!='\r' && request[0]!='n'); + } while(relocate && purl[0] && numrelocs++<5); + if(relocate) { + cout << "seterrorcode(SOUND_ERROR_TOOMANYRELOC)"<<endl; + return NULL; + } + free(purl); + free(request); + return myfile; +} + +long HttpInputStream::getBytePosition() { + return 0; +} + +int HttpInputStream::readstring(char *string,int maxlen,FILE *f) { + char *result; + + do{ + result=fgets(string,maxlen,f); + }while(!result && errno==EINTR); + if(!result) + { + cout << "seterrorcode(SOUND_ERROR_FILEREADFAIL)"<<endl; + return false; + } + + return true; +} diff --git a/mpeglib/lib/input/httpInputStream.h b/mpeglib/lib/input/httpInputStream.h new file mode 100644 index 00000000..78ec10f0 --- /dev/null +++ b/mpeglib/lib/input/httpInputStream.h @@ -0,0 +1,84 @@ +/* + 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 __HTTPINPUTSTREAM_H +#define __HTTPINPUTSTREAM_H + + +#include "inputStream.h" + +#ifndef __STRICT_ANSI__ +#define __STRICT_ANSI__ +#endif + +#include <stdlib.h> +#include <string.h> + + + +#if defined WIN32 +#include <io.h> +#define SOCKETWRITEFUNC _write +#else + +extern "C" { +#include <netdb.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + } +#define SOCKETWRITEFUNC write +#endif + +#include <sys/types.h> +#include <errno.h> + +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 <iostream> + +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"<<endl; + return NULL; + } + char* back=NULL; + char* extStart=strrchr(url,'.'); + if (extStart != NULL) { + cout << "extStart:"<<extStart<<endl; + back=strdup(extStart); + } + return back; +} + +char* InputDetector::removeExtension(const char* url,char* extension) { + if (url == NULL) { + cout << "removeExtension url NULL"<<endl; + return NULL; + } + if (extension == NULL) { + cout << "removeExtension extension NULL"<<endl; + return strdup(url); + } + char* back=NULL; + int nExt=strlen(extension); + int nUrl=strlen(url); + cout << "extension:"<<extension<<" url:"<<url<<endl; + if (nUrl >= 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:"<<back<<endl; + return back; + +} + +char* InputDetector::getWithoutExtension(const char* url) { + char* extension=NULL; + char* back=NULL; + if (url == NULL) { + return NULL; + } + extension=InputDetector::getExtension(url); + if (extension == NULL) { + back=strdup(url); + } else { + back=InputDetector::removeExtension(url,extension); + delete extension; + } + return back; +} + +char* InputDetector::getFilename(const char* url) { + if (url == NULL) { + return NULL; + } + char* startSlash=strrchr(url,'/'); + if (startSlash == NULL) { + return NULL; + } + if (strlen(startSlash) == 1) { + return NULL; + } + startSlash++; + if (*startSlash == 0) { + return NULL; + } + return strdup(startSlash); +} + + +char* InputDetector::removeSlash(const char* url) { + return InputDetector::removeExtension(url,(char*)"/"); +} diff --git a/mpeglib/lib/input/inputDetector.h b/mpeglib/lib/input/inputDetector.h new file mode 100644 index 00000000..f4c3e47d --- /dev/null +++ b/mpeglib/lib/input/inputDetector.h @@ -0,0 +1,56 @@ +/* + 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 + + */ + + + +#ifndef __INPUTDETECTOR_H +#define __INPUTDETECTOR_H + + + +#define __INPUT_UNKNOWN 0 +#define __INPUT_FILE 1 +#define __INPUT_HTTP 2 +#define __INPUT_CDI 3 +#define __INPUT_BUFFER 4 +#define __INPUT_CDDA 5 + +extern "C" { +#include <string.h> +} + + +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 <iostream> + +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"<<endl; + exit(0); + } + + return inputStream; +} + +InputStream* InputPlugin::createInputStream(int inputType,int lThreadSafe) { + InputStream* input=InputPlugin::createInputStream(inputType); + if (lThreadSafe == false) { + return input; + } + InputStream* tsInput=new ThreadSafeInputStream(input); + return tsInput; +} + + +InputStream* InputPlugin::createInputStream(const char* dest) { + int method; + + method=InputPlugin::getInputType(dest); + return (InputPlugin::createInputStream(method)); +} + + +InputStream* InputPlugin::createInputStream(const char* dest,int lThreadSafe) { + int method; + + method=InputPlugin::getInputType(dest); + return (InputPlugin::createInputStream(method,lThreadSafe)); +} diff --git a/mpeglib/lib/input/inputPlugin.h b/mpeglib/lib/input/inputPlugin.h new file mode 100644 index 00000000..5ac68307 --- /dev/null +++ b/mpeglib/lib/input/inputPlugin.h @@ -0,0 +1,45 @@ +/* + 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 + + */ + + + + +#ifndef __INPUTPLUGIN_H +#define __INPUTPLUGIN_H + +#include "httpInputStream.h" +#include "fileInputStream.h" +#include "cdromInputStream.h" +#include "bufferInputStream.h" +#include "threadSafeInputStream.h" +#include "cddaInputStream.h" +#include <string.h> + +#include "inputDetector.h" +#include <kdemacros.h> + +#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 <iostream> + +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:"<<dest<<endl; + return false; +} + + +void InputStream::close() { + cout << "direct virtual call InputStream::close"<<endl; + exit(0); +} + + +int InputStream::isOpen() { + cout << "direct virtual call InputStream::isOpen"<<endl; + exit(0); + return false; +} + + +int InputStream::eof() { + cout << "direct virtual call InputStream::eof"<<endl; + exit(0); + return true; +} + + +int InputStream::read(char* ,int ) { + cout << "direct virtual call InputStream::read"<<endl; + exit(0); + return 0; +} + + +int InputStream::seek(long bytePos) { + cout << "direct virtual call InputStream::seek:"<<bytePos<<endl; + exit(0); + return false; +} + +void InputStream::clear() { + cout << "direct virtual call InputStream::clear:"<<endl; + exit(0); +} + + +long InputStream::getByteLength() { + cout << "direct virtual call InputStream::getByteLength"<<endl; + return 0; +} + + +long InputStream::getBytePosition() { + cout << "direct virtual call InputStream::getBytePosition"<<endl; + return 0; +} + + +void InputStream::insertTimeStamp(TimeStamp* src,long key,int len) { + timeStampArray->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"<<endl; +} + + + + + +char* InputStream::getUrl() { + return urlBuffer->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 <string.h> +#include <stdio.h> +#include <sys/stat.h> +} + +#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 <string.h> + +#include <iostream> + +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"<<endl; + } + } + + updateCanWrite(); + updateCanRead(); + if (fillgrade >= 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"<<endl; + waitMinSpace=0; + } + int currentSpace=size-fillgrade; + if (lCanWaitForSpace) { + if (currentSpace < waitMinSpace) { + lWaitForSpace=true; + // it is not possible to wait for data/space simultanously + if (lWaitForData == true) { + abs_thread_cond_signal(&dataCond); + } + abs_thread_cond_wait(&spaceCond,&mut); + lWaitForSpace=false; + } + } + if (size-fillgrade >= 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"<<endl; + pSize=size/2; + } + // + // Now the part the we deliver a minimum buffer if it is + // possible + // + + if ( (pSize > 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"<<endl; + waitMinData=0; + } + if (lCanWaitForData) { + if (fillgrade < waitMinData) { + lWaitForData=true; + // it is not possible to wait for data space simultanously + if (lWaitForSpace == true) { + abs_thread_cond_signal(&spaceCond); + } + abs_thread_cond_wait(&dataCond,&mut); + lWaitForData=false; + } + } + if (fillgrade >= 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 <stdio.h> +} + +/** + Note to parameter minLinBufSize in Constructor: + <p> + 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) + <p> + 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 |