mpeg2buff.cc
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:10k
- /*
- File: mpeg2buff.cc
- By: Alex Theo de Jong
- Created: February 1996
- Description:
- "Multi-Threading Save" read/write buffer
- */
- #ifdef GNU
- #pragma implementation
- #endif
- #include "athread.hh"
- #include <stdio.h>
- #include <string.h>
- #include <String.h>
- #include <sys/time.h>
- #include <fcntl.h>
- #ifdef HAVE_MMX
- #include <mmx.h>
- #endif
- #include "error.hh"
- #include "debug.hh"
- #include "util.hh"
- #include "mpeg2const.hh"
- #include "mpeg2buff.hh"
- /*
- *
- * Memory
- *
- */
- Memory::Memory(int size) : end_ahead(1), mem_size(size) {
- mem_min=mem_begin=mem_end=new unsigned char[mem_size];
- mem_max=mem_min+mem_size;
- }
- Memory::~Memory(){ delete[] mem_min; }
- int Memory::reset(){ mem_begin=mem_end=mem_min; end_ahead=1; return 0; }
- unsigned char Memory::getchr(){
- if (mem_begin>=mem_max){
- mem_begin=mem_min;
- end_ahead=1;
- }
- return *mem_begin++;
- }
- unsigned int Memory::getbits32(){
- #ifdef HAVE_MMX
- if (mem_begin+4>=mem_max)
- #endif
- return ((getchr() << 24) | (getchr() << 16) | (getchr() << 8) | getchr());
- #ifdef HAVE_MMX
- else {
- mmx_m2r(movl,mem_begin,eax);
- __asm__ ("movl (%eax),%eax");
- __asm__ ("bswap %eax");
- mem_begin += 4;
- }
- #endif
- }
- int Memory::mem_skip(int size){
- if (end_ahead){
- mem_begin+=size;
- }
- else {
- if (size<(mem_max-mem_begin)){
- mem_begin+=size;
- }
- else {
- end_ahead=1;
- mem_begin=mem_min+size-(mem_max-mem_begin);
- }
- }
- return size;
- }
- int Memory::put(unsigned char* data, int size){
- if (!end_ahead){
- memcpy(mem_end, data, size);
- mem_end+=size;
- }
- else {
- if (size<(mem_max-mem_end)){
- memcpy(mem_end, data, size);
- mem_end+=size;
- }
- else {
- unsigned char* dataptr=data;
- int bytes=mem_max-mem_end;
- memcpy(mem_end, dataptr, bytes);
- dataptr+=bytes;
- mem_end=mem_min;
- end_ahead=0;
- int lastbytes=size-bytes;
- memcpy(mem_end, dataptr, lastbytes);
- mem_end+=lastbytes;
- return bytes+lastbytes;
- }
- }
- return size;
- }
- int Memory::used(){ return (end_ahead) ? (mem_end-mem_begin) : (mem_size - (mem_begin - mem_end)); }
- int Memory::unused(){ return (end_ahead) ? (mem_size - (mem_end - mem_begin)) : (mem_begin - mem_end); }
- unsigned int Memory::getbyte(){ return getchr(); }
- int Memory::get(unsigned char* data, int size){
- if (end_ahead){
- memcpy(data, mem_begin, size);
- mem_begin+=size;
- }
- else {
- if (size<(mem_max-mem_begin)){
- memcpy(data, mem_begin, size);
- mem_begin+=size;
- }
- else {
- unsigned char* dataptr=data;
- int bytes=mem_max-mem_begin;
- memcpy(dataptr, mem_begin, bytes);
- dataptr+=bytes;
- mem_begin=mem_min;
- end_ahead=1;
- int lastbytes=size-bytes;
- memcpy(dataptr, mem_begin, lastbytes);
- mem_begin+=lastbytes;
- return bytes+lastbytes;
- }
- }
- return size;
- }
- /*
- *
- * Mpeg2Buffer
- *
- */
- Mpeg2Buffer::Mpeg2Buffer(int size) : Memory(size), completed(0) {
- TRACER("Mpeg2Buffer::Mpeg2Buffer(int size)");
- }
- Mpeg2Buffer::~Mpeg2Buffer(){
- TRACER("Mpeg2Buffer::~Mpeg2Buffer()");
- }
- int Mpeg2Buffer::close(){
- TRACER("int Mpeg2Buffer::close()");
- lock();
- completed=1;
- reset();
- signal_read();
- unlock();
- return 0;
- }
- int Mpeg2Buffer::waitforbytes(int size){
- lock();
- signal_write(); // waitforbytes does not move the pointer, therefore
- // this should be done afterwards which means at the
- // beginning of the next call (the first is redundant)
- #ifdef TRACEDEEP
- while ((rsize=used())<size && !completed){
- if (rsize < (0.05*mem_size)) msg("Memory usage < 5%");
- wait_read();
- }
- #else
- while ((rsize=used())<size && !completed) {
- // while ((rsize=used())<=0 && !completed) {
- wait_read();
- }
- #endif
- unlock();
- return (!completed) ? ((rsize < size) ? rsize : size) : rsize;
- }
- int Mpeg2Buffer::skipbytes(int size){
- DDEBUGGER("int Mpeg2Buffer::skipbytes(int size)");
- lock();
- while (used()<size && !completed) wait_read();
- size = (completed && used()<size)
- ? size=mem_skip(used()) // get what's available!
- : size=mem_skip(size);
- signal_write();
- unlock();
- return size;
- }
- int Mpeg2Buffer::write(unsigned char* data, int size){
- DDEBUGGER("int Mpeg2Buffer::write(unsigned char* data, int size)");
- lock();
- #ifdef TRACEDEEP
- if (unused() < 0.05*mem_size) msg("Memory usage > 95%");
- #endif
- while (unused()<size && !completed){
- wait_write();
- }
- size = (completed && unused()<size)
- ? put(data, unused()) // put what's available
- : put(data, size);
- signal_read();
- unlock();
- return size;
- }
- int Mpeg2Buffer::read(unsigned char* data, int size){
- DDEBUGGER("int Mpeg2Buffer::read(unsigned char* data, int size)");
- lock();
- while (used()<size && !completed) wait_read();
- size = (completed && used()<size)
- ? get(data, used()) // get what's available!
- : get(data, size);
- signal_write();
- unlock();
- return size;
- }
- void Mpeg2Buffer::lock(){ mem_lock.lock(); }
- void Mpeg2Buffer::unlock(){ mem_lock.unlock(); }
- void Mpeg2Buffer::wait_write(){ memory_in_cond.wait(&mem_lock); }
- void Mpeg2Buffer::wait_read(){ memory_out_cond.wait(&mem_lock); }
- void Mpeg2Buffer::signal_write(){ memory_in_cond.signal(); }
- void Mpeg2Buffer::signal_read(){ memory_out_cond.signal(); }
- int Mpeg2Buffer::available(){ lock(); int b=used(); unlock(); return b; }
- int Mpeg2Buffer::maximum() { return mem_size; }
- void Mpeg2Buffer::signal_buffer(){ lock(); signal_write(); unlock(); }
- /*
- *
- * Mpeg2Input
- *
- */
- Mpeg2Input::Mpeg2Input(const char* filename, int size, int b) :
- Mpeg2Buffer(size), buffer_size(size), bitrate(b)
- {
- TRACER("Mpeg2Input::Mpeg2Input(const char* filename, int size, int b)");
- if (filename[0] == '-' && filename[1] == ' ')
- fd = 0;
- else if ((fd=open(filename, O_RDONLY, 0))<=0){
- String err="could not open file `";
- err+=filename;
- err+="' for reading";
- cerr << err.chars();
- return;
- }
- if (athr_create((void*(*)(void*)) Mpeg2Input::filereader, this, &id)<0){
- error("could not create reader thread");
- athr_exit(0);
- }
- }
- void* Mpeg2Input::filereader(Mpeg2Input* base){
- TRACER("void* Mpeg2Input::filereader(Mpeg2Input* base)");
- int rsize=0, wsize=base->buffer_size/4;
- unsigned char* data=new unsigned char[wsize];
- int interval_usec=base->bitrate*wsize, time_real_usec;
- Mpeg2Timer timer;
- timeval tstart, tstop;
- if (base->bitrate)
- gettimeofday(&tstart, 0);
- TRACER("Bitrate " << itoa(base->bitrate));
- int eof=0;
- while (base->fd >= 0 && !eof){
- {
- int thisread, got = 0;
- unsigned char *dp = data;
- while (!eof && got < wsize) {
- thisread = ::read(base->fd, dp, wsize - got);
- if (thisread > 0) {
- got += thisread;
- dp += thisread;
- } else {
- eof = 1;
- }
- }
- rsize = got;
- }
- #ifdef DEBUG
- cout << "FileData: " << data << "n";
- uint32 value;
- value=((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]);
- cout << "FileValue: " << value << "n";
- #endif
- if (base->write(data, rsize)!=rsize)
- error("could not write file data in buffer");
- if (base->bitrate>0){
- gettimeofday(&tstop, 0);
- time_real_usec=(tstop.tv_sec-tstart.tv_sec)*1000000+(tstop.tv_usec-tstart.tv_usec);
- if (time_real_usec<interval_usec)
- timer.wait(interval_usec - time_real_usec);
- gettimeofday(&tstart, 0);
- }
- }
- delete data;
- base->close();
- athr_exit(0);
- return 0;
- }
- /*
- *
- * Mpeg2Timer
- *
- */
- Mpeg2Timer::Mpeg2Timer(){
- }
- Mpeg2Timer::~Mpeg2Timer(){
- }
- void Mpeg2Timer::lock(){ timer_lock.lock(); }
- void Mpeg2Timer::unlock(){ timer_lock.unlock(); }
- int Mpeg2Timer::wait(int interval_usec){
- if (interval_usec<0) error("invalid interval for timer to wait");
- // msg("!");
- // This is very primitive!!
- gettimeofday(&time_new, 0);
- time_out=time_new;
- time_out.tv_usec+=interval_usec;
- if (time_out.tv_usec>1000000){
- time_out.tv_sec++;
- time_out.tv_usec-=1000000;
- }
- while (time_new.tv_sec<time_out.tv_sec ||
- (time_new.tv_sec==time_out.tv_sec && time_new.tv_usec<time_out.tv_usec)){
- athr_yield();
- gettimeofday(&time_new, 0);
- }
- return 1;
- }
- int Mpeg2Timer::waitcond(int interval_usec){
- lock();
- gettimeofday(&time_new, 0);
- time.tv_sec=time_new.tv_sec;
- time.tv_nsec=(time_new.tv_usec+interval_usec)*1000;
- if (time.tv_nsec>1000000000){
- time.tv_sec+=(int)(time.tv_nsec/1000000000);
- time.tv_nsec-=(time.tv_nsec - (time.tv_nsec % 1000000000));
- }
- int val=timer_cond.timedwait(&timer_lock, &time);
- unlock();
- return val;
- }
- /*
- static sigset_t set;
- static siginfo_t info;
- info.si_signo=SIGALRM;
- sigemptyset(&set);
- sigaddset(&set, SIGALRM);
- thr_sigsetmask(SIG_UNBLOCK, &set, 0);
- int val=sigtimedwait(&set, &info, &time);
-
- */
- /*
- Static sigset_t set;
- static itimerval val;
- sigemptyset(&set);
- sigaddset(&set, SIGVTALRM);
- thr_sigsetmask(SIG_BLOCK, &set, NULL);
- getitimer(ITIMER_VIRTUAL, &val);
- gettimeofday(&time_new, 0);
- val.it_interval.tv_usec=interval_usec;
- val.it_value.tv_sec=time_new.tv_sec;
- val.it_value.tv_usec=time_new.tv_usec + interval_usec;
- if (val.it_value.tv_usec>1000000){
- val.it_value.tv_sec++;
- val.it_value.tv_usec-=1000000;
- }
- setitimer(ITIMER_VIRTUAL, &val, 0);
- sigwait(&set);
- */
- #ifdef MAIN
- main(int argc, char** argv){
- TRACER("main(int argc, char** argv)");
- Mpeg2Input* myfile=new Mpeg2Input(argv[1], 10*418);
- unsigned char* data=new unsigned char[418];
- fflush(stdout);
- cout.flush();
- cerr.flush();
- bool eof=False;
- while (!eof){
- myfile->waitforbytes(418);
- // TRACER("Data=" << data);
- TRACER("Value=" << myfile->getbits32());
- break;
- }
- fflush(stdout);
- cout.flush();
- cerr.flush();
- delete myfile;
- delete data;
- }
- #endif