📄 mpeg2buff.cc
字号:
/* 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] == '\0') 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 MAINmain(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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -