home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Riza / source / caplog.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  5.2 KB  |  218 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    A/V interface library
  3. //    Copyright (C) 1998-2005 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <vd2/Riza/caplog.h>
  20. #include <vd2/system/file.h>
  21. #include <vd2/system/thread.h>
  22.  
  23. namespace {
  24.     struct CapEntry {
  25.         sint64    global_clock;
  26.         sint64    timestamp;
  27.         uint32    size;
  28.         uint8    stream;
  29.         bool    key;
  30.     };
  31.  
  32.     struct CapBlock {
  33.         enum { kCount = 1024 };
  34.         CapEntry mEntries[kCount];
  35.         CapBlock *mpNext;
  36.     };
  37.  
  38.     struct CapBlockIterator {
  39.         CapBlock *mpCurrent;
  40.         int        mNext;
  41.         int        mLimit;
  42.         int        mLastLimit;
  43.  
  44.         CapBlockIterator(CapBlock *head, int lastLimit) : mpCurrent(head), mNext(0), mLimit(head && head->mpNext ? CapBlock::kCount : lastLimit), mLastLimit(lastLimit) {}
  45.  
  46.         bool operator!() const {
  47.             return !mpCurrent;
  48.         }
  49.  
  50.         const CapEntry& operator*() const {
  51.             return mpCurrent->mEntries[mNext];
  52.         }
  53.  
  54.         void operator++() {
  55.             if (++mNext >= mLimit) {
  56.                 mNext = 0;
  57.                 mpCurrent = mpCurrent->mpNext;
  58.                 if (mpCurrent)
  59.                     mLimit = mpCurrent->mpNext ? CapBlock::kCount : mLastLimit;
  60.             }
  61.         }
  62.     };
  63. }
  64.  
  65. class VDCaptureLogFilter : public IVDCaptureLogFilter {
  66. public:
  67.     VDCaptureLogFilter();
  68.     ~VDCaptureLogFilter();
  69.  
  70.     void Shutdown();
  71.  
  72.     void SetChildCallback(IVDCaptureDriverCallback *pChild);
  73.  
  74.     void WriteLog(const wchar_t *pszName);
  75.  
  76.     void CapBegin(sint64 global_clock);
  77.     void CapEnd(const MyError *pError);
  78.     bool CapEvent(nsVDCapture::DriverEvent event, int data);
  79.     void CapProcessData(int stream, const void *data, uint32 size, sint64 timestamp, bool key, sint64 global_clock);
  80.  
  81. protected:
  82.     VDCriticalSection mLock;
  83.     CapBlock *mpBlockHead;
  84.     CapBlock *mpBlockTail;
  85.     int        mNextEntry;
  86.     IVDCaptureDriverCallback *mpCB;
  87. };
  88.  
  89. VDCaptureLogFilter::VDCaptureLogFilter()
  90.     : mpBlockHead(NULL)
  91.     , mpBlockTail(NULL)
  92. {
  93. }
  94.  
  95. VDCaptureLogFilter::~VDCaptureLogFilter() {
  96.     Shutdown();
  97. }
  98.  
  99. IVDCaptureLogFilter *VDCreateCaptureLogFilter() {
  100.     return new VDCaptureLogFilter;
  101. }
  102.  
  103. void VDCaptureLogFilter::Shutdown() {
  104.     while(CapBlock *p = mpBlockHead) {
  105.         mpBlockHead = p->mpNext;
  106.         free(p);
  107.     }
  108.     mNextEntry = CapBlock::kCount;
  109. }
  110.  
  111. void VDCaptureLogFilter::SetChildCallback(IVDCaptureDriverCallback *pChild) {
  112.     mpCB = pChild;
  113. }
  114.  
  115. void VDCaptureLogFilter::WriteLog(const wchar_t *pszName) {
  116.     VDFileStream stream(pszName, nsVDFile::kWrite | nsVDFile::kDenyAll | nsVDFile::kCreateAlways);
  117.     VDTextOutputStream fout(&stream);
  118.  
  119.     fout.PutLine("VFrames,VCapTime,VGlobalTime,VSize,VKey,AFrames,ABytes,AGlobalTime,ASize");
  120.  
  121.     CapBlockIterator itV(mpBlockHead, mNextEntry);
  122.     CapBlockIterator itA(mpBlockHead, mNextEntry);
  123.  
  124.     char buf[512];
  125.     uint32 vframes = 0;
  126.     uint32 aframes = 0;
  127.     sint64 abytes = 0;
  128.  
  129.     for(;;) {
  130.         bool videoOK = false;
  131.         bool audioOK = false;
  132.         char *s = buf;
  133.  
  134.         while(!!itV) {
  135.             const CapEntry& vent = *itV;
  136.             ++itV;
  137.  
  138.             if (!vent.stream) {
  139.                 videoOK = true;
  140.                 s += sprintf(s, "%u,%.3f,%.3f,%u,%d,", ++vframes, vent.timestamp / 1000.0, vent.global_clock / 1000.0, vent.size, vent.key);
  141.                 break;
  142.             }
  143.         }
  144.  
  145.         if (!videoOK)
  146.             s += sprintf(s, ",,,,,");
  147.  
  148.         while(!!itA) {
  149.             const CapEntry& aent = *itA;
  150.             ++itA;
  151.  
  152.             if (aent.stream == 1) {
  153.                 audioOK = true;
  154.                 abytes += aent.size;
  155.                 s += sprintf(s, "%u,%I64d,%.3f,%u", ++aframes, abytes, aent.global_clock / 1000.0, aent.size);
  156.                 break;
  157.             }
  158.         }
  159.  
  160.         if (!audioOK)
  161.             s += sprintf(s, ",,,,");
  162.  
  163.         if (!videoOK && !audioOK)
  164.             break;
  165.  
  166.         fout.PutLine(buf);
  167.     }
  168.  
  169.     fout.Flush();
  170. }
  171.  
  172. void VDCaptureLogFilter::CapBegin(sint64 global_clock) {
  173.     Shutdown();
  174.  
  175.     mpCB->CapBegin(global_clock);
  176. }
  177.  
  178. void VDCaptureLogFilter::CapEnd(const MyError *pError) {
  179.     mpCB->CapEnd(pError);
  180. }
  181.  
  182. bool VDCaptureLogFilter::CapEvent(nsVDCapture::DriverEvent event, int data) {
  183.     return mpCB->CapEvent(event, data);
  184. }
  185.  
  186. void VDCaptureLogFilter::CapProcessData(int stream, const void *data, uint32 size, sint64 timestamp, bool key, sint64 global_clock)  {
  187.     if (stream >= 0) {
  188.         vdsynchronized(mLock) {
  189.             do {
  190.                 if (mNextEntry >= CapBlock::kCount) {
  191.                     CapBlock *p = new_nothrow CapBlock;
  192.  
  193.                     if (!p)
  194.                         break;
  195.  
  196.                     if (mpBlockTail)
  197.                         mpBlockTail->mpNext = p;
  198.                     p->mpNext = NULL;
  199.                     if (!mpBlockHead)
  200.                         mpBlockHead = p;
  201.                     mpBlockTail = p;
  202.                     mNextEntry = 0;
  203.                 }
  204.  
  205.                 CapEntry& ent = mpBlockTail->mEntries[mNextEntry++];
  206.  
  207.                 ent.global_clock    = global_clock;
  208.                 ent.timestamp        = timestamp;
  209.                 ent.size            = size;
  210.                 ent.stream            = stream;
  211.                 ent.key                = key;
  212.             } while(false);
  213.         }
  214.     }
  215.  
  216.     mpCB->CapProcessData(stream, data, size, timestamp, key, global_clock);
  217. }
  218.