mpeg2buff.cc
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:10k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /*
  2.    File: mpeg2buff.cc
  3.    By: Alex Theo de Jong
  4.    Created: February 1996
  5.    Description:
  6.    "Multi-Threading Save" read/write buffer
  7. */
  8. #ifdef GNU
  9. #pragma implementation
  10. #endif
  11. #include "athread.hh"
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <String.h>
  15. #include <sys/time.h>
  16. #include <fcntl.h>
  17. #ifdef HAVE_MMX
  18. #include <mmx.h>
  19. #endif
  20. #include "error.hh"
  21. #include "debug.hh"
  22. #include "util.hh"
  23. #include "mpeg2const.hh"
  24. #include "mpeg2buff.hh"
  25. /*
  26.  *
  27.  * Memory
  28.  *
  29.  */
  30. Memory::Memory(int size) : end_ahead(1), mem_size(size) {
  31.                mem_min=mem_begin=mem_end=new unsigned char[mem_size];
  32.                mem_max=mem_min+mem_size;
  33. }
  34. Memory::~Memory(){ delete[] mem_min; }
  35. int Memory::reset(){ mem_begin=mem_end=mem_min; end_ahead=1; return 0; }
  36. unsigned char Memory::getchr(){
  37.     if (mem_begin>=mem_max){
  38.       mem_begin=mem_min;
  39.       end_ahead=1;
  40.     }
  41.     return *mem_begin++;
  42. }
  43. unsigned int Memory::getbits32(){
  44. #ifdef HAVE_MMX
  45.       if (mem_begin+4>=mem_max)
  46. #endif
  47.         return ((getchr() << 24) | (getchr() << 16) | (getchr() << 8) | getchr());
  48. #ifdef HAVE_MMX
  49.       else {
  50.         mmx_m2r(movl,mem_begin,eax);
  51.         __asm__ ("movl (%eax),%eax");
  52.         __asm__ ("bswap %eax");
  53.         mem_begin += 4;
  54.       }
  55. #endif
  56. }
  57. int Memory::mem_skip(int size){
  58.   if (end_ahead){
  59.     mem_begin+=size;
  60.   }
  61.   else {
  62.     if (size<(mem_max-mem_begin)){
  63.       mem_begin+=size;
  64.     }
  65.     else {
  66.       end_ahead=1;
  67.       mem_begin=mem_min+size-(mem_max-mem_begin);
  68.     }
  69.   }
  70.   return size;
  71. }
  72. int Memory::put(unsigned char* data, int size){
  73.   if (!end_ahead){
  74.     memcpy(mem_end, data, size);
  75.     mem_end+=size; 
  76.   }
  77.   else {
  78.     if (size<(mem_max-mem_end)){
  79.       memcpy(mem_end, data, size);
  80.       mem_end+=size;
  81.     }
  82.     else {
  83.       unsigned char* dataptr=data;
  84.       int bytes=mem_max-mem_end;
  85.       memcpy(mem_end, dataptr, bytes);   
  86.       dataptr+=bytes;
  87.       mem_end=mem_min;
  88.       end_ahead=0;
  89.       int lastbytes=size-bytes;
  90.       memcpy(mem_end, dataptr, lastbytes);
  91.       mem_end+=lastbytes;
  92.       return bytes+lastbytes;
  93.     }
  94.   }
  95.   return size;
  96. }
  97.   int Memory::used(){ return (end_ahead) ? (mem_end-mem_begin) : (mem_size - (mem_begin - mem_end)); }
  98.   int Memory::unused(){ return (end_ahead) ? (mem_size - (mem_end - mem_begin)) : (mem_begin - mem_end); }
  99.   unsigned int Memory::getbyte(){ return getchr(); }
  100. int Memory::get(unsigned char* data, int size){
  101.   if (end_ahead){
  102.     memcpy(data, mem_begin, size);
  103.     mem_begin+=size;
  104.   }
  105.   else {
  106.     if (size<(mem_max-mem_begin)){
  107.       memcpy(data, mem_begin, size);
  108.       mem_begin+=size;
  109.     }
  110.     else {
  111.       unsigned char* dataptr=data;
  112.       int bytes=mem_max-mem_begin;
  113.       memcpy(dataptr, mem_begin, bytes);
  114.       dataptr+=bytes;
  115.       mem_begin=mem_min;
  116.       end_ahead=1;
  117.       int lastbytes=size-bytes;
  118.       memcpy(dataptr, mem_begin, lastbytes);
  119.       mem_begin+=lastbytes;
  120.       return bytes+lastbytes;
  121.     }
  122.   }
  123.   return size;
  124. }
  125. /*
  126.  *
  127.  *   Mpeg2Buffer
  128.  *
  129.  */
  130. Mpeg2Buffer::Mpeg2Buffer(int size) : Memory(size), completed(0) {
  131.   TRACER("Mpeg2Buffer::Mpeg2Buffer(int size)");
  132. }
  133. Mpeg2Buffer::~Mpeg2Buffer(){
  134.   TRACER("Mpeg2Buffer::~Mpeg2Buffer()");
  135. }
  136. int Mpeg2Buffer::close(){
  137.   TRACER("int Mpeg2Buffer::close()");
  138.   lock();
  139.   completed=1;
  140.   reset();
  141.   signal_read();
  142.   unlock();
  143.   return 0;
  144. }
  145. int Mpeg2Buffer::waitforbytes(int size){ 
  146.   lock();
  147.   signal_write();  // waitforbytes does not move the pointer, therefore
  148.                    // this should be done afterwards which means at the 
  149.                    // beginning of the next call (the first is redundant)
  150. #ifdef TRACEDEEP
  151.   while ((rsize=used())<size && !completed){
  152.     if (rsize < (0.05*mem_size)) msg("Memory usage < 5%");
  153.     wait_read();
  154.   }
  155. #else
  156.   while ((rsize=used())<size && !completed) {
  157. //  while ((rsize=used())<=0 && !completed) {
  158.     wait_read();
  159.   }
  160. #endif
  161.   unlock();
  162.   return (!completed) ? ((rsize < size) ? rsize : size) : rsize; 
  163. }
  164. int Mpeg2Buffer::skipbytes(int size){
  165.   DDEBUGGER("int Mpeg2Buffer::skipbytes(int size)");
  166.   lock();
  167.   while (used()<size && !completed) wait_read();
  168.   size = (completed && used()<size)
  169.     ? size=mem_skip(used())     // get what's available!
  170.     : size=mem_skip(size); 
  171.   signal_write();
  172.   unlock();
  173.   return size;
  174. }
  175. int Mpeg2Buffer::write(unsigned char* data, int size){
  176.   DDEBUGGER("int Mpeg2Buffer::write(unsigned char* data, int size)");
  177.   lock();
  178. #ifdef TRACEDEEP
  179.   if (unused() < 0.05*mem_size) msg("Memory usage > 95%");
  180. #endif
  181.   while (unused()<size && !completed){
  182.     wait_write();
  183.   }
  184.   size = (completed && unused()<size)
  185.     ? put(data, unused())          // put what's available
  186.     : put(data, size);
  187.   signal_read();
  188.   unlock();
  189.   return size;
  190. }
  191. int Mpeg2Buffer::read(unsigned char* data, int size){
  192.   DDEBUGGER("int Mpeg2Buffer::read(unsigned char* data, int size)");
  193.   lock();
  194.   while (used()<size && !completed) wait_read();
  195.   size = (completed && used()<size)
  196.     ? get(data, used())          // get what's available!
  197.     : get(data, size); 
  198.   signal_write();
  199.   unlock();
  200.   return size;
  201. }
  202.   void Mpeg2Buffer::lock(){ mem_lock.lock(); }
  203.   void Mpeg2Buffer::unlock(){ mem_lock.unlock(); }
  204.   void Mpeg2Buffer::wait_write(){ memory_in_cond.wait(&mem_lock); }
  205.   void Mpeg2Buffer::wait_read(){ memory_out_cond.wait(&mem_lock); }
  206.   void Mpeg2Buffer::signal_write(){ memory_in_cond.signal(); }
  207.   void Mpeg2Buffer::signal_read(){ memory_out_cond.signal(); }
  208.   int Mpeg2Buffer::available(){ lock(); int b=used(); unlock(); return b; }
  209.   int Mpeg2Buffer::maximum() { return mem_size; }
  210.   void Mpeg2Buffer::signal_buffer(){ lock(); signal_write(); unlock(); }
  211. /*
  212.  *
  213.  * Mpeg2Input
  214.  *
  215.  */
  216. Mpeg2Input::Mpeg2Input(const char* filename, int size, int b) : 
  217.   Mpeg2Buffer(size), buffer_size(size), bitrate(b)
  218. {
  219.   TRACER("Mpeg2Input::Mpeg2Input(const char* filename, int size, int b)");
  220.   if (filename[0] == '-' && filename[1] == '')
  221.     fd = 0;
  222.   else if ((fd=open(filename, O_RDONLY, 0))<=0){
  223.     String err="could not open file `";
  224.     err+=filename;
  225.     err+="' for reading";
  226.     cerr << err.chars();
  227.     return;
  228.   }
  229.   if (athr_create((void*(*)(void*)) Mpeg2Input::filereader, this, &id)<0){
  230.     error("could not create reader thread");
  231.     athr_exit(0);
  232.   }
  233. }
  234. void* Mpeg2Input::filereader(Mpeg2Input* base){
  235.   TRACER("void* Mpeg2Input::filereader(Mpeg2Input* base)");
  236.   int rsize=0, wsize=base->buffer_size/4;
  237.   unsigned char* data=new unsigned char[wsize];
  238.   int interval_usec=base->bitrate*wsize, time_real_usec;
  239.   Mpeg2Timer timer;
  240.   timeval tstart, tstop;
  241.   if (base->bitrate)
  242.     gettimeofday(&tstart, 0);
  243. TRACER("Bitrate " << itoa(base->bitrate));
  244.   int eof=0;
  245.   while (base->fd >= 0 && !eof){
  246.     {
  247.       int thisread, got = 0;
  248.       unsigned char *dp = data;
  249.       while (!eof && got < wsize) {    
  250.         thisread = ::read(base->fd, dp, wsize - got);
  251.         if (thisread > 0) {
  252.            got += thisread;
  253.            dp += thisread;
  254.         } else { 
  255.           eof = 1;
  256.         } 
  257.       }
  258.       rsize = got;
  259.     }
  260. #ifdef DEBUG
  261.     cout << "FileData: " << data << "n";
  262.     uint32 value;
  263.     value=((data[0] << 24) | (data[1] << 16) |  (data[2] << 8) |  data[3]);
  264.     cout << "FileValue: " << value << "n";
  265. #endif
  266.     if (base->write(data, rsize)!=rsize)
  267.       error("could not write file data in buffer");
  268.     if (base->bitrate>0){
  269.       gettimeofday(&tstop, 0);
  270.       time_real_usec=(tstop.tv_sec-tstart.tv_sec)*1000000+(tstop.tv_usec-tstart.tv_usec);   
  271.       if (time_real_usec<interval_usec)
  272. timer.wait(interval_usec - time_real_usec);
  273.       gettimeofday(&tstart, 0);
  274.     }
  275.   }
  276.   delete data;
  277.   base->close();
  278.   athr_exit(0);
  279.   return 0;
  280. }
  281. /*
  282.  *
  283.  * Mpeg2Timer
  284.  *
  285.  */
  286. Mpeg2Timer::Mpeg2Timer(){
  287. }
  288. Mpeg2Timer::~Mpeg2Timer(){
  289. }
  290. void Mpeg2Timer::lock(){ timer_lock.lock(); }
  291. void Mpeg2Timer::unlock(){ timer_lock.unlock(); }
  292. int Mpeg2Timer::wait(int interval_usec){ 
  293.   if (interval_usec<0) error("invalid interval for timer to wait");
  294. //  msg("!"); 
  295. // This is very primitive!!
  296.   gettimeofday(&time_new, 0);
  297.   time_out=time_new;
  298.   time_out.tv_usec+=interval_usec;
  299.   if (time_out.tv_usec>1000000){
  300.     time_out.tv_sec++;
  301.     time_out.tv_usec-=1000000;
  302.   }
  303.   while (time_new.tv_sec<time_out.tv_sec || 
  304.          (time_new.tv_sec==time_out.tv_sec && time_new.tv_usec<time_out.tv_usec)){
  305.     athr_yield();
  306.     gettimeofday(&time_new, 0);
  307.   }
  308.   return 1;
  309. int Mpeg2Timer::waitcond(int interval_usec){
  310.   lock();
  311.   gettimeofday(&time_new, 0);
  312.   time.tv_sec=time_new.tv_sec;
  313.   time.tv_nsec=(time_new.tv_usec+interval_usec)*1000;
  314.   if (time.tv_nsec>1000000000){
  315.     time.tv_sec+=(int)(time.tv_nsec/1000000000);
  316.     time.tv_nsec-=(time.tv_nsec - (time.tv_nsec % 1000000000));
  317.   }
  318.   int val=timer_cond.timedwait(&timer_lock, &time);
  319.   unlock();
  320.   return val;
  321. }
  322. /*
  323.   static sigset_t set;
  324.   static siginfo_t info;
  325.   info.si_signo=SIGALRM;
  326.   sigemptyset(&set);
  327.   sigaddset(&set, SIGALRM);
  328.   thr_sigsetmask(SIG_UNBLOCK, &set, 0);
  329.   int val=sigtimedwait(&set, &info, &time);
  330.  
  331. */
  332. /*
  333.   Static sigset_t set;
  334.   static itimerval val;
  335.   sigemptyset(&set);
  336.   sigaddset(&set, SIGVTALRM);
  337.   thr_sigsetmask(SIG_BLOCK, &set, NULL);
  338.   getitimer(ITIMER_VIRTUAL, &val);
  339.   gettimeofday(&time_new, 0);
  340.   val.it_interval.tv_usec=interval_usec;
  341.   val.it_value.tv_sec=time_new.tv_sec;
  342.   val.it_value.tv_usec=time_new.tv_usec + interval_usec;
  343.   if (val.it_value.tv_usec>1000000){
  344.     val.it_value.tv_sec++;
  345.     val.it_value.tv_usec-=1000000;
  346.   }
  347.   setitimer(ITIMER_VIRTUAL, &val, 0);
  348.   sigwait(&set);
  349. */
  350. #ifdef MAIN
  351. main(int argc, char** argv){
  352.   TRACER("main(int argc, char** argv)");
  353.   Mpeg2Input* myfile=new Mpeg2Input(argv[1], 10*418);
  354.   unsigned char* data=new unsigned char[418];
  355.   fflush(stdout);
  356.   cout.flush();
  357.   cerr.flush();
  358.   bool eof=False;
  359.   while (!eof){
  360.     myfile->waitforbytes(418);
  361.     //    TRACER("Data=" << data);
  362.     TRACER("Value=" << myfile->getbits32());
  363.     break;
  364.   }
  365.   fflush(stdout);
  366.   cout.flush();
  367.   cerr.flush();
  368.   delete myfile;
  369.   delete data;
  370. }
  371. #endif