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

  1. #pragma warning(disable: 4786)
  2.  
  3. #include <crtdbg.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <map>
  7. #include <list>
  8. #include <set>
  9.  
  10. #include <vd2/system/vdtypes.h>
  11. #include <vd2/system/atomic.h>
  12. #include <vd2/system/file.h>
  13. #include <vd2/system/Progress.h>
  14.  
  15. #include <vd2/Meia/MPEGFile.h>
  16. #include "MPEGCache.h"
  17.  
  18. using namespace std;
  19.  
  20. #define printf sizeof
  21.  
  22. ///////////////////////////////////////////////////////////////////////////
  23.  
  24. enum eParseResult {
  25.     kParseContinue = 0,
  26.     kParseAbort = 1,
  27.     kParseComplete = 2,
  28.     kParseRewind = 3,        // seek only
  29. };
  30.  
  31. ///////////////////////////////////////////////////////////////////////////
  32.  
  33. class VDINTERFACE IVDMPEGPacketReader {
  34. public:
  35.     virtual bool DoScanByPos(int64 pos, int active_stream, int64 lower_bound, int64 upper_bound)=0;
  36.     virtual bool ReadPacket(int stream, int64 packet, int offset, char *dst, int length)=0;
  37. };
  38.  
  39. class VDMPEGStream {
  40. protected:
  41.     // <pos, len>
  42.  
  43.     typedef std::map<int64, int> tPackList;
  44.  
  45.     tPackList                mPackList;
  46.     tPackList::iterator        mLastPackEntry;
  47.  
  48.     IVDMPEGPacketReader        *mpReader;
  49.  
  50.     ////////////////////////////////
  51.  
  52.     VDMPEGStream(IVDMPEGPacketReader *pReader) : mpReader(pReader) {
  53.         mLastPackEntry = mPackList.begin();
  54.     }
  55.  
  56.     void RecordPacket(int64 pos, int length) {
  57.         mLastPackEntry = mPackList.insert(mLastPackEntry, tPackList::value_type(pos, length));
  58.     }
  59.  
  60.     bool ReadPackets(int stream, int64 first_packet, int offset, char *dst, int length) {
  61.         tPackList::iterator it = mPackList.find(first_packet);
  62.  
  63.         while(length > 0) {
  64.             if (it == mPackList.end()) {
  65.                 VDASSERT(false);
  66.                 return false;
  67.             }
  68.  
  69.             int blen = length;
  70.  
  71.             if (blen > (*it).second - offset)
  72.                 blen = (*it).second - offset;
  73.  
  74.             VDASSERT(blen>0);
  75.  
  76.             if (!mpReader->ReadPacket(stream, (*it).first, offset, dst, blen))
  77.                 return false;
  78.  
  79.             ++it;
  80.  
  81.             dst += blen;
  82.             length -= blen;
  83.  
  84.             offset = 0;
  85.         }
  86.  
  87.         return true;
  88.     }
  89. };
  90.  
  91.  
  92.  
  93.  
  94. ///////////////////////////////////////////////////////////////////////////
  95. //
  96. //    Audio stream handler
  97. //
  98. ///////////////////////////////////////////////////////////////////////////
  99.  
  100.  
  101.  
  102.  
  103. class VDMPEGAudioStream : public VDMPEGStream, public IVDMPEGAudioStream {
  104. private:
  105.     int                        mnStreamID;
  106.  
  107.     unsigned long master_header;
  108.     VDAtomicInt refCount;
  109.  
  110.     typedef pair<unsigned long, int64> tFrameLocation;    // offset:size, packet_offset
  111.     typedef map<long, tFrameLocation> tFrameMap;
  112.     tFrameMap mFrameMap;
  113.  
  114.     long        mFrameSize;        // frame size in samples -- 576 for MPEG-2, 1152 for MPEG-1
  115.     long        mSamplingRate;    // sampling rate in Hz
  116.     long        mInitialFrame;
  117.  
  118.     /////////////////////
  119.  
  120.     bool isValidAudioHeader(unsigned long hdr) {
  121.         // FFF00000 12 bits    sync mark
  122.         //
  123.         // 00080000  1 bit    version
  124.         // 00060000  2 bits    layer (3 = layer I, 2 = layer II, 1 = layer III)
  125.         // 00010000  1 bit    error protection (0 = enabled)
  126.         //
  127.         // 0000F000  4 bits    bitrate_index
  128.         // 00000C00  2 bits    sampling_freq
  129.         // 00000200  1 bit    padding
  130.         // 00000100  1 bit    extension
  131.         //
  132.         // 000000C0  2 bits    mode (0=stereo, 1=joint stereo, 2=dual channel, 3=mono)
  133.         // 00000030  2 bits    mode_ext
  134.         // 00000008  1 bit    copyright
  135.         // 00000004  1 bit    original
  136.         // 00000003  2 bits    emphasis
  137.         
  138.         // sync bits must be on
  139.         if ((hdr & 0xfff00000) != 0xfff00000)
  140.             return false;
  141.         
  142.         // 00 for layer ("layer 4") is not valid
  143.         if (!(hdr & 0x00060000))
  144.             return false;
  145.         
  146.         // 1111 for bitrate is not valid
  147.         if ((hdr & 0x0000F000) == 0x0000F000)
  148.             return false;
  149.         
  150.         // 11 for sampling frequency is not valid
  151.         if ((hdr & 0x00000C00) == 0x00000C00)
  152.             return false;
  153.         
  154.         // Looks okay to me...
  155.         return true;
  156.     }
  157.  
  158.     bool isConsistentAudioHeader(unsigned long hdr) {
  159.         return !((master_header ^ hdr) & 0xFFFEFC08);
  160.     }
  161.  
  162.     unsigned getFrameLengthFromHeader(unsigned long hdr) {
  163.         static const int bitrates[3][15] = {
  164.                   {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
  165.                   {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384},
  166.                   {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}
  167.                 };
  168.  
  169.         unsigned bitrate = bitrates[3 - ((hdr&0x60000) >> 17)][(hdr&0xf000)>>12];
  170.         unsigned padding = (hdr & 0x200) >> 9;
  171.  
  172.         // frame_size = floor(144000 * bitrate / sampling_rate) + padding;
  173.  
  174.         switch(hdr & 0xC00) {
  175.         case 0x000:        return (1440 * bitrate / 441) + padding;
  176.         case 0x400:        return 3*bitrate + padding;
  177.         case 0x800:        return 9*bitrate/2 + padding;
  178.         default:        VDNEVERHERE; return 0;
  179.         }
  180.     }
  181.  
  182. public:
  183.     VDMPEGAudioStream(IVDMPEGPacketReader *pReader, int id)
  184.             : VDMPEGStream(pReader)
  185.             , refCount(0)
  186.             , mnStreamID(id)
  187.             , mParseDesiredFrame(-1)
  188.             , mInitialFrame(-1)
  189.     {
  190.     }
  191.  
  192.     ~VDMPEGAudioStream() {
  193.     }
  194.     
  195.     int AddRef() { return refCount.inc(); }
  196.     int Release() { int rc = refCount.dec(); if (!rc) delete this; return rc; }
  197.  
  198.     void getInitialFormat(VDMPEGAudioFormat &format) {
  199.         format.sampling_rate = mSamplingRate;
  200.         format.channels = ((master_header & 0xC0) != 0xC0) ? 2 : 1;
  201.     }
  202.  
  203.     unsigned long getFrameCount() {
  204.         VDASSERT(mFrameMap.begin() != mFrameMap.end());
  205.  
  206.         tFrameMap::iterator it = mFrameMap.end();
  207.  
  208.         --it;
  209.         return (*it).first + 1;
  210.     }
  211.  
  212.     long ReadFrames(long frame_num, int frame_count, void *buf, long maxbuffer, long& bytes_read) {
  213.         if (frame_num < 0)
  214.             return -1;
  215.  
  216.         long samples_read = 0;
  217.         bytes_read = 0;
  218.  
  219.         while(frame_count>0) {
  220.             tFrameMap::iterator it = mFrameMap.find(frame_num);
  221.  
  222.             if (it == mFrameMap.end()) {
  223.                 tFrameMap::iterator itLo = mFrameMap.lower_bound(frame_num);
  224.                 tFrameMap::iterator itHi = mFrameMap.upper_bound(frame_num);
  225.  
  226.                 --itLo;
  227.  
  228.                 VDDEBUG("MPEGAudio: Interpolating between %d(%I64x) and %d(%I64x)\n", itLo->first, itLo->second.second, itHi->first, itHi->second.second);
  229.  
  230.                 int64 posLo = (*itLo).second.second;
  231.                 int64 posHi = (*itHi).second.second;
  232.                 int64 pos = posLo + (posHi-posLo) * (frame_num - (*itLo).first) / (frame_num - (*itHi).first) - 4096;
  233.  
  234.                 if (pos<0)
  235.                     pos = 0;
  236.  
  237.                 if (!mpReader->DoScanByPos(pos, mnStreamID, posLo, posHi))
  238.                     break;
  239.  
  240.                 continue;
  241.             }
  242.  
  243.             int length = (*it).second.first>>16;
  244.             int64 packetpos = (*it).second.second;
  245.             int offset = (*it).second.first&0xffff;
  246.  
  247. //            VDDEBUG("reading: %I64x+%ld (%d)\n", packetpos, offset, length);
  248.  
  249.             if (buf)
  250.                 if (!ReadPackets(mnStreamID, packetpos, offset, (char *)buf, length))
  251.                     break;
  252.  
  253.             ++samples_read;
  254.             bytes_read += length;
  255.             buf = (char *)buf + length;
  256.  
  257.             ++frame_num;
  258.             --frame_count;
  259.         }
  260.  
  261.         return samples_read;
  262.     }
  263.  
  264.  
  265.     ////////////////////////////
  266.  
  267.     eParseResult ParseInit(const unsigned char *buf, int length, int64 pts, int64 pos) {
  268.         if (!buf) {
  269.             master_header = 0;
  270.             ParseReset();
  271.         } else {
  272.             int t = -length;
  273.             const unsigned char *buf2 = buf + length;
  274.  
  275.             do {
  276.                 master_header = (master_header<<8) + buf2[t];
  277.  
  278.                 if (isValidAudioHeader(master_header)) {
  279.  
  280.                     mFrameSize = 1152;
  281.  
  282.                     switch(master_header & 0x00000C00) {
  283.                     case 0x00000000:    mSamplingRate = 44100; break;
  284.                     case 0x00000400:    mSamplingRate = 48000; break;
  285.                     case 0x00000800:    mSamplingRate = 32000; break;
  286.                     }
  287.  
  288.                     if (!mFrameMap.empty())
  289.                         return kParseComplete;
  290.  
  291.                     break;
  292.                 }
  293.             } while(++t);
  294.  
  295.             if (mFrameMap.empty())
  296.                 if (kParseAbort == Parse(buf, length, pts, pos))
  297.                     return kParseAbort;
  298.         }
  299.  
  300.         return kParseContinue;
  301.     }
  302.  
  303.     ////////////////////////
  304.  
  305.     long mParseFrame;
  306.     unsigned long mParseHeader;
  307.     unsigned long mParseDesiredFrame;
  308.     int64            mParseLastPacket;
  309.     unsigned long    mParseLastLength;
  310.     int                mParseSkip;
  311.  
  312.     void ParseReset() {
  313.         mParseFrame = -1;
  314.         mParseHeader = 0;
  315.         mParseSkip = 0;
  316.     }
  317.  
  318.     // Frames may consist of 576 or 1152 samples, and the sampling rate
  319.     // can be 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000.
  320.  
  321.     long getFrameFromPTS(int64 pts) {
  322.         return (long)((pts * mSamplingRate + mFrameSize * 45000) / (mFrameSize * 90000));
  323.     }
  324.  
  325.     eParseResult Parse(const unsigned char *buf, int length, int64 pts, int64 pos) {
  326.         const unsigned char *buf0 = buf;
  327.         const unsigned char *buflimit = buf + length;
  328.  
  329.         RecordPacket(pos, length);
  330.  
  331.         if (mParseFrame < 0) {
  332.             if (pts >= 0) {
  333.                 mParseFrame = getFrameFromPTS(pts);
  334.                 if (mInitialFrame < 0) {
  335.                     mInitialFrame = mParseFrame;
  336.                     mParseFrame = 0;
  337.                 } else
  338.                     mParseFrame -= mInitialFrame;
  339.             } else
  340.                 return kParseContinue;
  341.         }
  342.  
  343.         while(buf < buflimit) {
  344.             if (mParseSkip) {
  345.                 int tc = buflimit - buf;
  346.  
  347.                 if (tc > mParseSkip)
  348.                     tc = mParseSkip;
  349.  
  350.                 buf += tc;
  351.                 mParseSkip -= tc;
  352.                 continue;
  353.             }
  354.  
  355.             mParseHeader = (mParseHeader<<8) + (*buf++);
  356.  
  357. //            if (isValidAudioHeader(mParseHeader))
  358. //                VDDEBUG("%08lx\n", mParseHeader);
  359.  
  360.             if (isConsistentAudioHeader(mParseHeader)) {
  361.                 if (mParseFrame >= 0) {
  362.                     int offs = buf-buf0-4;
  363.                     int64 pktpos = pos;
  364.  
  365.                     if (offs < 0) {
  366.                         pktpos = mParseLastPacket;
  367.                         offs += mParseLastLength;
  368.                     }
  369.  
  370.                     unsigned framelen = getFrameLengthFromHeader(mParseHeader);
  371.  
  372.                     mFrameMap[mParseFrame] = tFrameLocation((framelen<<16) + offs, pktpos);
  373.  
  374.                     if (mParseFrame == mParseDesiredFrame)
  375.                         return kParseComplete;
  376.  
  377.                     if (mParseFrame > (long)mParseDesiredFrame)
  378.                         return kParseRewind;
  379.  
  380.                     ++mParseFrame;
  381.  
  382.                     mParseSkip = framelen - 4;
  383.                 }
  384.                 mParseHeader = 0;
  385.             }
  386.         }
  387.  
  388.         mParseLastPacket = pos;
  389.         mParseLastLength = length;
  390.  
  391.         return kParseContinue;
  392.     }
  393. };
  394.  
  395.  
  396.  
  397.  
  398. ///////////////////////////////////////////////////////////////////////////
  399. //
  400. //    Video stream handler
  401. //
  402. ///////////////////////////////////////////////////////////////////////////
  403.  
  404.  
  405.  
  406.  
  407. class VDMPEGVideoStream : public VDMPEGStream, public IVDMPEGVideoStream {
  408. private:
  409.  
  410.     struct GOPInfo {
  411.         long    first_frame;
  412.         long    frame_count;    // -1 means not yet scanned
  413.     };
  414.  
  415.     typedef map<int64, GOPInfo> GOPMap;
  416.  
  417.     struct FrameInfo {
  418.         int64        first_packet;
  419.         int            packet_offset;
  420.         int            length;
  421.         long        display_order;
  422.         FrameType    type;
  423.     };
  424.  
  425.     struct TentativeFrameInfo {
  426.         int64        first_packet;
  427.         int            packet_offset;
  428.         int            length;
  429.         int            frameno;
  430.         FrameType    type;
  431.     };
  432.  
  433.     typedef map<long, FrameInfo> FrameMap;
  434.     typedef list<TentativeFrameInfo> FrameList;
  435.  
  436.     ////////////
  437.  
  438.     int                        mnStreamID;
  439.  
  440.     VDMPEGSequenceHeader    mParsedHdr, mInitialSeqHdr;
  441.     VDAtomicInt refCount;
  442.  
  443.     // mGOPTable maps byte positions to GOPs.
  444.  
  445.     GOPMap        mGOPTable;
  446.  
  447.     // mFrameTable maps frame numbers to GOPs and pack positions.
  448.     // mFrameLimboTable stores frames that have been identified but haven't
  449.     // been associated with a timestamped GOP, usually because the GOP has
  450.     // been found but the timestamp hasn't.  If the timestamp is found before
  451.     // the next GOP tag is found, the limbo pictures are timestamped and
  452.     // added to the frame table.
  453.  
  454.     FrameMap    mFrameTable;
  455.     FrameList    mFrameLimboTable;
  456.  
  457.     TentativeFrameInfo    mFrameInProgress;
  458.     int64        mFrameInProgressStart;
  459.     bool        mbFrameInProgress;
  460.  
  461.     long        mFirstFrame;
  462.  
  463. public:
  464.  
  465.     VDMPEGVideoStream(IVDMPEGPacketReader *pReader, int id)
  466.             : VDMPEGStream(pReader)
  467.             , refCount(0)
  468.             , mnStreamID(id)
  469.             , mFirstFrame(-1)
  470.     {
  471.     }
  472.  
  473.     ~VDMPEGVideoStream() {
  474.     }
  475.     
  476.     int AddRef() { return refCount.inc(); }
  477.     int Release() { int rc = refCount.dec(); if (!rc) delete this; return rc; }
  478.  
  479.     void getInitialFormat(VDMPEGSequenceHeader& dst) {
  480.         dst = mInitialSeqHdr;
  481.     }
  482.  
  483.     long getFrameCount() {
  484.         long frames = 0;
  485.  
  486.         if (mFrameTable.end() != mFrameTable.begin()) {
  487.             FrameMap::iterator it = mFrameTable.end();
  488.  
  489.             --it;
  490.  
  491.             frames = (*it).first + 1;
  492.         }
  493.  
  494.         return frames;
  495.     }
  496.  
  497.     long getNearestI(long f) {
  498.         while(f>0) {
  499.             FrameType type;
  500.  
  501.             if (ReadPicture(f, NULL, 0, type)<0)
  502.                 return -1;
  503.  
  504.             if (type == kIFrame)
  505.                 break;
  506.  
  507.             --f;
  508.         }
  509.  
  510.         return f;
  511.     }
  512.  
  513.     long getPrevIP(long f) {
  514.         while(f>0) {
  515.             FrameType type;
  516.  
  517.             --f;
  518.  
  519.             if (ReadPicture(f, NULL, 0, type)<0)
  520.                 return -1;
  521.  
  522.             if (type == kIFrame || type == kPFrame)
  523.                 break;
  524.         }
  525.  
  526.         return f;
  527.     }
  528.  
  529.     long getNextIP(long f) {
  530.         FrameMap::iterator itEnd = mFrameTable.end();
  531.  
  532.         if (itEnd == mFrameTable.begin())
  533.             return -1;
  534.         
  535.         --itEnd;
  536.  
  537.         long lastframe = (*itEnd).first;
  538.         
  539.         for(;;) {
  540.             FrameType type;
  541.  
  542.             ++f;
  543.  
  544.             if (f > lastframe)
  545.                 return -1;
  546.  
  547.             if (ReadPicture(f, NULL, 0, type)<0)
  548.                 return -1;
  549.  
  550.             if (type == kIFrame || type == kPFrame)
  551.                 break;
  552.  
  553.         }
  554.  
  555.         return f;
  556.     }
  557.  
  558.     long DisplayToStreamOrder(long f) {
  559.         if (f<0)
  560.             return -1;
  561.  
  562.         // Look for the GOP holding the frame.
  563.  
  564.         GOPMap::iterator it, itEnd;
  565.         bool bAttemptedScan = false;
  566.  
  567.         for(;;) {
  568.             it = mGOPTable.begin();
  569.             itEnd = mGOPTable.end();
  570.  
  571.             for(; it!=itEnd; ++it) {
  572.                 long delta = f - (*it).second.first_frame;
  573.  
  574.                 if (delta >= 0 && delta < (*it).second.frame_count)
  575.                     break;
  576.             }
  577.  
  578.             if (it != itEnd)
  579.                 break;
  580.  
  581.             // If we haven't already done so, force a scan.  It doesn't
  582.             // matter the particular frames (we're requesting the wrong
  583.             // one anyway) as long as the GOP is pulled in.
  584.  
  585.             if (bAttemptedScan)
  586.                 return -1;
  587.  
  588.             FrameType t;
  589.             ReadPicture(f, NULL, 0, t);
  590.  
  591.             bAttemptedScan = true;
  592.  
  593.         } while(it == itEnd);
  594.  
  595.         // Okay, find the start of the GOP in the frame table and sweep it.
  596.  
  597.         FrameMap::iterator itF = mFrameTable.lower_bound((*it).second.first_frame);
  598.         FrameMap::iterator itFE = mFrameTable.end();
  599.         long limit = (*it).second.first_frame + (*it).second.frame_count;
  600.  
  601.         for(; itF != itFE && (*itF).first < limit; ++itF) {
  602.             if ((*itF).second.display_order == f) {
  603. //                _RPT2(0, "display %d -> stream %d\n", f, (*itF).first);
  604.                 return (*itF).first;
  605.             }
  606.         }
  607.  
  608.         return -1;
  609.     }
  610.  
  611.     // happily, this one is easier
  612.  
  613.     long StreamToDisplayOrder(long f) {
  614.         if (f<0)
  615.             return -1;
  616.  
  617.         FrameMap::iterator it = mFrameTable.find(f);
  618.  
  619.         if (it == mFrameTable.end()) {
  620.             FrameType t;
  621.             ReadPicture(f, NULL, 0, t);
  622.  
  623.             if (it == mFrameTable.end())
  624.                 return -1;
  625.         }
  626.  
  627.         return (*it).second.display_order;
  628.     }
  629.  
  630.     long ReadPicture(long stream_number, void *buf, long maxbuffer, FrameType &ftype) {
  631.  
  632.         if (stream_number < 0)
  633.             return -1;
  634.  
  635.         // check if we already have the frame.
  636.  
  637.         FrameMap::iterator    it = mFrameTable.find(stream_number);
  638.  
  639.         if (it == mFrameTable.end()) {
  640.             // Not found -- attempt scan.  Find nearest two frames
  641.             // and lerp between them.
  642.  
  643.             FrameMap::iterator itLower = mFrameTable.lower_bound(stream_number);            
  644.             FrameMap::iterator itUpper = mFrameTable.upper_bound(stream_number);
  645.  
  646.             // We should have received the very first and very last frames
  647.             // in our frame table from the initialization scan and thus be able
  648.             // to bound every frame in between.  If we can't, the frame is out
  649.             // of range.
  650.  
  651.             if (itUpper == mFrameTable.end())
  652.                 return -1;
  653.  
  654.             // lower_bound returns the first element >=.  boo.
  655.  
  656.             if (itLower != mFrameTable.begin())
  657.                 --itLower;
  658.  
  659.             // Grab the pack positions and lerp a guess at the seek position.
  660.  
  661.             long first_frame    = itLower==mFrameTable.begin() ? 0 : itLower->first;
  662.             int64 first_pos        = itLower==mFrameTable.begin() ? 0 : itLower->second.first_packet + itLower->second.packet_offset;
  663.             int64 second_pos    = itUpper->second.first_packet + itUpper->second.packet_offset;
  664.             int64 desired_pos    = first_pos + (second_pos - first_pos) * (stream_number - first_frame) / (itUpper->first - first_frame);
  665.  
  666.             // Call parent to do a pack scan and let's hope we find it!
  667.  
  668.             mParseScanDesiredFrame = stream_number;
  669.  
  670.             VDDEBUG("Looking for %d\n", stream_number);
  671.  
  672.             if (!mpReader->DoScanByPos(desired_pos, mnStreamID, first_pos, second_pos))
  673.                 return -1;
  674.  
  675.             // Try again.
  676.  
  677.             it = mFrameTable.find(stream_number);
  678.  
  679.             VDASSERT(it != mFrameTable.end());
  680.         }
  681.  
  682.         // Return frame type.
  683.  
  684.         ftype = it->second.type;
  685.  
  686. //        _RPT2(0, "Frame %d is of type %c\n", it->first, "0IPBD567"[ftype]);
  687.         
  688.         // I hope it's not too long.
  689.  
  690.         if (it->second.length > maxbuffer || !buf)
  691.             return it->second.length;
  692.  
  693.         // Yahoo!  Read the picture in.
  694.  
  695. //        _RPT2(0, "Reading from %I64x (%d)\n", it->second.first_packet, it->second.length);
  696.  
  697.         if (!ReadPackets(mnStreamID,
  698.                 it->second.first_packet,
  699.                 it->second.packet_offset,
  700.                 (char *)buf,
  701.                 it->second.length))
  702.                 return -1;
  703.  
  704.         return it->second.length;
  705.     }
  706.  
  707.     /////////////// scanner ///////////////
  708.  
  709. private:
  710.     bool mbSeenGOP;
  711.     bool mbSeenSeq;
  712.     int mPhase;
  713.     unsigned char mParseBuf[256];
  714.     int mnParseCount, mnParseLimit;
  715.     long        mGOPStartFrame;
  716.     int64        mposGOP;
  717.     long        mParseScanDesiredFrame;
  718.  
  719.     // This should only be set if we've found a GOP that is in our
  720.     // table.
  721.  
  722.     bool        mbParseCaptureGOP;
  723.  
  724.     // Records the relative byte position in the stream of the first
  725.     // byte after the current block being parsed.
  726.  
  727.     int64        mParseCounter;
  728.  
  729.     eParseResult (VDMPEGVideoStream::*mpOnSeqHeader)();
  730.     eParseResult (VDMPEGVideoStream::*mpOnGOPHeader)(int hr, int mn, int sc, int pc, bool drop);
  731.  
  732. private:
  733.     void _ParseResetScan() {
  734.         mFrameLimboTable.erase(mFrameLimboTable.begin(), mFrameLimboTable.end());
  735.         mbSeenGOP = false;
  736.         mbSeenSeq = false;
  737.         mPhase = 0;
  738.         mnParseCount = 0;
  739.         mnParseLimit = 0;
  740.         mParseCounter = 0;
  741.         mbFrameInProgress = false;
  742.         mbParseCaptureGOP = false;
  743.     }
  744.  
  745. public:
  746.     void ParseBeginInitialScan() {
  747.         _ParseResetScan();
  748.  
  749.         mpOnSeqHeader = &VDMPEGVideoStream::_ParseInitialSequenceHeader;
  750.         mpOnGOPHeader = &VDMPEGVideoStream::_ParseInitialGOPHeader;
  751.         mParseScanDesiredFrame = -1;
  752.  
  753.         printf("restarting!!!\n");
  754.     }
  755.  
  756.     void ParseBeginSeekScan(bool master) {
  757.         _ParseResetScan();
  758.  
  759.         mpOnSeqHeader = &VDMPEGVideoStream::_ParseSeekSequenceHeader;
  760.         mpOnGOPHeader = &VDMPEGVideoStream::_ParseGOPHeader;
  761.  
  762.         if (!master)
  763.             mParseScanDesiredFrame = -1;
  764.     }
  765.  
  766.     void ParseEnd() {
  767.         if (mbSeenGOP) {
  768.             long first, last;
  769.  
  770.             _LimboFlush(first, last);
  771.         }
  772.     }
  773.  
  774.     eParseResult ParseEndSeek() {
  775.         if (mbSeenGOP) {
  776.             long first, last;
  777.  
  778.             if (_LimboFlush(first, last)) {
  779.                 if (mParseScanDesiredFrame >= 0) {
  780.                     if (mParseScanDesiredFrame >= last)
  781.                         return kParseAbort;        // err, off end of file, chief...
  782.  
  783.                     if (mParseScanDesiredFrame < first) {
  784.                         return kParseRewind;    // uhh, go back more
  785.                     }
  786.                 }
  787.  
  788.                 // I guess we found it.
  789.  
  790.                 return kParseComplete;
  791.             }
  792.         }
  793.  
  794.         return kParseRewind;
  795.     }
  796.  
  797.     // frameno is derived from the PTS.
  798.  
  799.     eParseResult Parse(unsigned char *buf0, int length, int64 pts, int64 packet_pos) {
  800.         unsigned char *buf = buf0;
  801.         int i;
  802.         eParseResult r;
  803.  
  804.         RecordPacket(packet_pos, length);
  805.  
  806.         // Keep track of where we are.  This is only valid for one scan.
  807.  
  808.         mParseCounter += length;
  809.  
  810.         // sequence header:                000001B3
  811.         // group-of-pictures header:    000001B8
  812.  
  813.         unsigned char *limit = buf+length;
  814.  
  815.         while(buf < limit) {
  816.  
  817.             if (mnParseCount < mnParseLimit) {
  818.                 mParseBuf[mnParseCount++] = *buf++;
  819.                 continue;
  820.             }
  821.  
  822.             switch(mPhase) {
  823.             case 0:        // nothing
  824.             case 1:        // 00
  825.                 while(*buf) {
  826.                     mPhase = 0;
  827.                     if (++buf >= limit)
  828.                         goto reached_end;
  829.                 }
  830.                 ++mPhase;
  831.                 if (++buf >= limit)
  832.                     goto reached_end;
  833.                 break;
  834.             case 2:        // 00 00
  835.                 if (*buf == 0x01) {
  836.                     mPhase = 3;
  837.                 } else if (*buf != 0x00)
  838.                     mPhase = 0;
  839.  
  840.                 if (++buf >= limit)
  841.                     goto reached_end;;
  842.                 break;
  843.             case 3:        // 00 00 01
  844.  
  845.                 // if we have a frame open, close it!
  846.  
  847.                 if (mbFrameInProgress && (!*buf || *buf>=0xB0)) {
  848.                     mFrameInProgress.length        = (int)((mParseCounter-length) - mFrameInProgressStart + (buf-buf0));
  849.  
  850.                     mFrameLimboTable.push_back(mFrameInProgress);
  851.                     mbFrameInProgress = false;
  852.                 }
  853.  
  854.                 // begin processing header
  855.  
  856.                 if (*buf == 0xB3) {            // 000001B3 (sequence header)
  857.                     ++buf;
  858.                     mnParseCount = 0;
  859.                     mnParseLimit = 8;
  860.                     mPhase = 4;
  861.                 } else if (*buf == 0xB8) {    // 000001B8 (GOP header)
  862.                     GOPInfo ginfo;
  863.                     int64 bytepos = packet_pos+(buf-buf0);
  864.                     GOPMap::iterator it = mGOPTable.find(bytepos);
  865.  
  866.                     mbParseCaptureGOP = false;
  867.                     if (it == mGOPTable.end()) {
  868.                         ginfo.first_frame = -1;
  869.                         ginfo.frame_count = -1;
  870.  
  871.                         VDDEBUG("Adding new GOP (bytepos %I64x)\n", bytepos);
  872.  
  873.                         mGOPTable.insert(GOPMap::value_type(bytepos, ginfo));
  874.                         mbParseCaptureGOP = true;
  875.                     } else if (it->second.first_frame<0) {
  876.                         mbParseCaptureGOP = true;
  877.                         VDDEBUG("Scanning incomplete GOP %I64x (%I64x %d %d)\n", bytepos, it->first, it->second.first_frame, it->second.frame_count);
  878.                     } else if (mParseScanDesiredFrame>=0) {
  879.                         long first = it->second.first_frame;
  880.                         long last = first + it->second.frame_count;
  881.  
  882.                         VDDEBUG("This GOP range at %I64x is known: %d-%d\n", bytepos, first, last);
  883.  
  884.                         if (mParseScanDesiredFrame < first) {
  885.                             _LimboFlush(first, last);
  886.                             return kParseRewind;    // uhh, go back more
  887.                         }
  888.  
  889.                         if (mParseScanDesiredFrame < last)
  890.                             return kParseComplete;    // found it
  891.                     }
  892.  
  893.                     long first, last;
  894.  
  895.                     if (_LimboFlush(first, last) && mParseScanDesiredFrame >= 0) {
  896.                         if (mParseScanDesiredFrame < first) {
  897.                             return kParseRewind;    // uhh, go back more
  898.                         }
  899.  
  900.                         if (mParseScanDesiredFrame < last)
  901.                             return kParseComplete;    // found it
  902.                     }
  903.  
  904.                     mposGOP = bytepos;
  905.  
  906.                     ++buf;
  907.                     mPhase = 7;
  908.                     mnParseCount = 0;
  909.                     mnParseLimit = 4;
  910.                 } else if (!*buf && mbParseCaptureGOP) {            // 00000100 (picture header)
  911.  
  912. //                    _RPT3(0, "Beginning picture at %I64x+%x (pts=%I64d)\n", packet_pos, buf-buf0, mParsePTS);
  913.  
  914.                     mFrameInProgress.first_packet    = packet_pos;
  915.                     mFrameInProgress.packet_offset    = buf-buf0;
  916.                     mFrameInProgress.length            = 0;
  917.                     mFrameInProgress.frameno        = -1;
  918.                     mFrameInProgressStart            = (mParseCounter-length) + (buf-buf0);
  919.  
  920.                     ++buf;
  921.                     mPhase = 8;
  922.                     mnParseCount = 0;
  923.                     mnParseLimit = 4;
  924.                 } else {
  925.                     mPhase = 0;
  926.                 }
  927.  
  928.                 break;
  929.  
  930.             case 4:        // sequence header (8 bytes minimum)
  931.                 // woohoo!!  read the next 8 bytes in
  932.                 //
  933.                 // +-------------------------------+
  934.                 // |           width 4-11          | buf[0]
  935.                 // +---------------+---------------+
  936.                 // |   width 0-3   |  height 8-11  | buf[1]
  937.                 // +-------------------------------+
  938.                 // |           height 0-7          | buf[2]
  939.                 // +---------------+---------------+
  940.                 // |     aspect    |   framerate   | buf[3]
  941.                 // +---------------+---------------+
  942.                 // |         bitrate 10-17         | buf[4]
  943.                 // +-------------------------------+
  944.                 // |          bitrate 2-9          | buf[5]
  945.                 // +-------+---+-------------------+
  946.                 // | br0-1 | 1 |   VBV buffer 5-9  | buf[6]
  947.                 // +-------+---+-------+---+---+---+
  948.                 // |  VBV buffer 0-4   |CPF|CIQ|...| buf[7]
  949.                 // +-------------------+---+---+---+
  950.  
  951.                 mParsedHdr.width        = (mParseBuf[0]<<4) + (mParseBuf[1]>>4);
  952.                 mParsedHdr.height        = ((mParseBuf[1]<<8)&0xf00) + mParseBuf[2];
  953.                 mParsedHdr.aspect        = (mParseBuf[3]&0xf0)>>4;
  954.                 mParsedHdr.framerate    = mParseBuf[3]&0x0f;
  955.                 mParsedHdr.bitrate        = (mParseBuf[4]<<10) + (mParseBuf[5]<<2) + (mParseBuf[6]>>6);
  956.                 mParsedHdr.vbvbuffersize= ((mParseBuf[6]&0x1f)<<5) + (mParseBuf[7]>>3);
  957.                 mParsedHdr.constrained    = 0!=(mParseBuf[7]&4);
  958.                 mParsedHdr.custom_intra        = false;
  959.                 mParsedHdr.custom_nonintra    = false;
  960.  
  961.                 // Return a more sane number for VBR.
  962.  
  963.                 if (mParsedHdr.bitrate == 0x3FFFF)
  964.                     mParsedHdr.bitrate = -1;
  965.  
  966.                 // Sanity check -- width, height, aspect, framerate, and bitrate may not be zero.
  967.                 // Marker bit must be set.
  968.  
  969.                 if (!mParsedHdr.width || !mParsedHdr.height || !mParsedHdr.aspect
  970.                     || !mParsedHdr.framerate || !mParsedHdr.bitrate
  971.                     || !(mParseBuf[6]&0x20)) {
  972.  
  973.                     mPhase = 0;
  974.                     break;
  975.                 }
  976.  
  977.                 // Pass.
  978.  
  979.                 if (mParseBuf[7]&2) {        // custom intramatrix?
  980.                     ++mPhase;
  981.                     mnParseLimit += 64;
  982.                 } else {
  983.                     mPhase = 0;
  984.  
  985.                     if (kParseContinue != (r = (this->*mpOnSeqHeader)()))
  986.                         return r;
  987.                 }
  988.                 break;
  989.  
  990.             case 5:        // sequence header intramatrix
  991.                 mParsedHdr.custom_intra = true;
  992.  
  993.                 for(i=0; i<64; ++i)
  994.                     mParsedHdr.intra[i] = ((mParseBuf[7+i]&1)<<7) + ((mParseBuf[8+i]&0xfe)>>1);
  995.  
  996.                 if (mParseBuf[7+64]&1) {
  997.                     mnParseLimit += 64;
  998.                     ++mPhase;
  999.                 } else {
  1000.                     mPhase = 0;
  1001.  
  1002.                     if (kParseContinue != (r = (this->*mpOnSeqHeader)()))
  1003.                         return r;
  1004.                 }
  1005.  
  1006.                 break;
  1007.  
  1008.             case 6:        // sequence header nonintramatrix
  1009.                 mParsedHdr.custom_nonintra = true;
  1010.                 memcpy(mParsedHdr.nonintra, mParseBuf+8+64, 64);
  1011.  
  1012.                 mPhase = 0;
  1013.  
  1014.                 if (kParseContinue != (r = (this->*mpOnSeqHeader)()))
  1015.                     return r;
  1016.  
  1017.                 break;
  1018.  
  1019.             case 7:        // GOP header (4 bytes)
  1020.                 //
  1021.                 // +---+-------------------+-------+
  1022.                 // |DFF|       hours       | min4-5| buf[0]
  1023.                 // +---+-----------+---+---+-------+
  1024.                 // |  minutes 0-3  | 1 | secs 3-5  | buf[1]
  1025.                 // +-----------+---+---+-----------+
  1026.                 // |  secs 0-3 |   pictures 1-5    | buf[2]
  1027.                 // +---+---+---+-------------------+
  1028.                 // |pc0|C_G|B_L|xxxxxxxxxxxxxxxxxxx| buf[3] (closed_gop, broken_link)
  1029.                 // +---+---+---+-------------------+
  1030.  
  1031.                 {
  1032.                     int hours, minutes, seconds, pictures;
  1033.                     bool dropf;
  1034.  
  1035.                     mPhase = 0;
  1036.  
  1037.                     // Verify marker bit.
  1038.  
  1039.                     if (!(mParseBuf[1] & 0x08))
  1040.                         break;
  1041.  
  1042.                     // Decode the timestamp.
  1043.  
  1044.                     hours = (mParseBuf[0]>>2)&31;
  1045.                     minutes = ((mParseBuf[0]&3)<<4) + (mParseBuf[1]>>4);
  1046.                     seconds = ((mParseBuf[1]&7)<<3) + (mParseBuf[2]>>5);
  1047.                     pictures = (mParseBuf[2]&31)*2 + (mParseBuf[3]>>7);
  1048.                     dropf = 0 != (mParseBuf[0] & 0x80);
  1049.  
  1050.                     // XingMPEG Encoder kludge
  1051.  
  1052. #if 0
  1053.                     if (hours+minutes+seconds+pictures && !pictures) {
  1054.                         if (++seconds >= 60) {
  1055.                             seconds = 0;
  1056.                             if (++minutes >= 60) {
  1057.                                 minutes = 0;
  1058.                                 if (++hours >= 24)
  1059.                                     hours = 0;
  1060.                             }
  1061.                         }
  1062.                     }
  1063. #endif
  1064.  
  1065.                     // Verify that time components are legal.
  1066.  
  1067.                     if (hours>=24 || minutes>=60 || seconds>=60 || pictures>=60)
  1068.                         break;
  1069.  
  1070.                     if (kParseContinue != (r = (this->*mpOnGOPHeader)(hours, minutes, seconds, pictures, dropf)))
  1071.                         return r;
  1072.                     break;
  1073.                 }
  1074.  
  1075.             case 8:        // Picture header (4-5 bytes)
  1076.                 //
  1077.                 // +-------------------------------+
  1078.                 // |     temporal reference 2-9    | buf[0]
  1079.                 // +-------+-----------+-----------+
  1080.                 // | tr0-1 |   type    |delay 13-15| buf[1]
  1081.                 // +-------------------+-----------+
  1082.                 // |         VBV delay 5-12        | buf[2]
  1083.                 // +-------------------+---+-------+
  1084.                 // |     VBV delay 0-4 |FPF|FFC 1-2| buf[3] (full_pel_forward_vector, forward_f_code)
  1085.                 // +---+---+-----------+---+-------+
  1086.                 // |FFC|FPB|back f code|xxxxxxxxxxx| buf[4] (full_pel_backward_vector)
  1087.                 // +---+---+-----------+-----------+
  1088.  
  1089.                 // Type may not be zero.
  1090.  
  1091.                 if (!(mParseBuf[1] & 0x38)) {
  1092.                     mPhase = 0;
  1093.                     break;
  1094.                 }
  1095.  
  1096.                 // If the picture type is P or B (2 or 3), we will need an additional
  1097.                 // byte.
  1098.  
  1099.                 ++mPhase;
  1100.                 if ((mParseBuf[1]&0x30) == 0x10) {
  1101.                     ++mnParseLimit;
  1102.                     break;
  1103.                 }
  1104.  
  1105.             case 9:        // Picture header complete
  1106.  
  1107.                 mPhase = 0;
  1108.                 if ((mParseBuf[1] & 0x38) == 0x18) {    // B-frame: backward_f_code may not be zero.
  1109.                     int bfc = (mParseBuf[4]>>3)&7;
  1110.  
  1111.                     if (!bfc)
  1112.                         break;
  1113.                 }
  1114.  
  1115.                 if ((mParseBuf[1] & 0x30) == 0x10) {    // P-frame or B-frame: forward_f_code may not be zero.
  1116.                     int ffc = ((mParseBuf[3]&3)<<1) + ((mParseBuf[4]&0x80)>>7);
  1117.  
  1118.                     if (!ffc)
  1119.                         break;
  1120.                 }
  1121.  
  1122.                 // Looks okay.  Send it off.
  1123.  
  1124.                 if (kParseContinue != (r = _ParsePicHeader()))
  1125.                     return r;
  1126.  
  1127.                 break;
  1128.  
  1129.             }
  1130.         }
  1131.  
  1132. reached_end:
  1133.  
  1134.         return kParseContinue;
  1135.     }
  1136.  
  1137. private:
  1138.  
  1139.     eParseResult _ParseInitialSequenceHeader() {
  1140.         mInitialSeqHdr = mParsedHdr;
  1141.         mbSeenSeq = true;
  1142.         return kParseContinue;
  1143.     }
  1144.  
  1145.     eParseResult _ParseSeekSequenceHeader() {
  1146.         return kParseContinue;
  1147.     }
  1148.  
  1149.     eParseResult _ParseInitialGOPHeader(int h,int m,int s,int p,bool drop) {
  1150.         _ParseGOPHeader(h, m, s, p, drop);
  1151.         if (mbSeenGOP && mbSeenSeq)
  1152.             return kParseComplete;
  1153.  
  1154.         mbSeenGOP = true;
  1155.  
  1156.         return kParseContinue;
  1157.     }
  1158.  
  1159.     eParseResult _ParseGOPHeader(int h, int m, int s, int p, bool bDropFlag) {
  1160.         mbSeenGOP = true;
  1161.  
  1162.         // Figure out the current frame from the GOP time.
  1163.  
  1164.         VDDEBUG("Processing GOP: %d:%02d:%02d.%02d\n", h, m, s, p);
  1165.  
  1166.         switch(mInitialSeqHdr.framerate) {
  1167.         case 1:    p += (s+60*m + 1440*h)*24; break;        // drop_frame_flag cannot be set for 23.976
  1168.         case 2:    p += (s+60*m + 1440*h)*24; break;
  1169.         case 3:    p += (s+60*m + 1440*h)*25; break;
  1170.         case 4:
  1171.             if (bDropFlag) {
  1172.                 // This is a pain.
  1173.                 //
  1174.                 // drop_frame_flag is set, so pictures 0 and 1 at the start of each
  1175.                 // minute dropped, except for minutes 0, 10, 20, 30, 40, and 50.
  1176.                 // This gives 54*(60*30 - 2) + 6*60*30 = 107892 pictures per hour.
  1177.                 //
  1178.                 // Minutes divisible by 10 have 1800 pictures.
  1179.                 // Minutes not divisible by 10 have 1798 pictures.
  1180.                 // Every 10 minutes is 17982 pictures.
  1181.  
  1182.                 p += 17982 * (m / 10) + h * 107892;
  1183.  
  1184.                 // Every minute is 1798 pictures except the first, which is 1800.
  1185.                 // Strip off the two phantom pictures for non-10 minutes.
  1186.  
  1187.                 m %= 10;
  1188.  
  1189.                 if (m)
  1190.                     p += 1798*m;
  1191.  
  1192.                 // Every second is 30 pictures except the first second, which is 28,
  1193.                 // except for the first minute of every 10 minutes....
  1194.  
  1195.                 p += s*30;
  1196.  
  1197.                 if (s && m)
  1198.                     p -= 2;
  1199.  
  1200.             } else {
  1201.                 p += (s+60*m + 1440*h)*30;
  1202.             }
  1203.             break;
  1204.         case 5:    p += (s+60*m + 1440*h)*30; break;
  1205.         case 6:    p += (s+60*m + 1440*h)*50; break;
  1206.         case 7:    p += (s+60*m + 1440*h)*60; break;        // drop_frame_flag cannot be set for 59.94
  1207.         case 8:    p += (s+60*m + 1440*h)*60; break;
  1208.         }
  1209.  
  1210.         VDDEBUG("Frame is %d\n", p);
  1211.  
  1212.         mGOPStartFrame = p;
  1213.  
  1214.         return kParseContinue;
  1215.     }
  1216.  
  1217.     eParseResult _ParsePicHeader() {
  1218.         if (mbSeenGOP) {
  1219.             int tref = (mParseBuf[0]<<2) + ((mParseBuf[1]&0xc0)>>6);
  1220.             int type = (mParseBuf[1]>>3)&7;
  1221.             
  1222. //            _RPT2(0, "picture found: %c-frame (temporal ref: %d)\n", "0IPBD567"[type], tref);
  1223.             
  1224.             VDASSERT(type && type<=3);
  1225.                 
  1226.             // Document the frame.
  1227.             
  1228.             mbFrameInProgress = true;
  1229.  
  1230.             mFrameInProgress.type            = (FrameType)type;                
  1231.         } else
  1232.             _RPT0(0,"dropping picture\n");
  1233.                 
  1234.         return kParseContinue;
  1235.     }
  1236.  
  1237.     bool _LimboFlush(long& firstframe, long& lastframe) {
  1238.         FrameList::iterator it = mFrameLimboTable.begin();
  1239.         FrameList::iterator itEnd = mFrameLimboTable.end();
  1240.  
  1241.         if (it == itEnd) {
  1242.             return false;
  1243.         }
  1244.  
  1245.         FrameList::iterator itLastIP = itEnd;
  1246.         int bframeno = 0;
  1247.  
  1248.         // Number all pages and try to spot a base PTS.
  1249.  
  1250.         for(; it!=itEnd; ++it) {
  1251.             TentativeFrameInfo& info = *it;
  1252.  
  1253.             if (info.type == kBFrame)
  1254.                 info.frameno = bframeno++;
  1255.             else {
  1256.                 if (itLastIP != itEnd)
  1257.                     itLastIP->frameno = bframeno++;
  1258.  
  1259.                 itLastIP = it;
  1260.             }
  1261.         }
  1262.  
  1263.         if (itLastIP != itEnd)
  1264.             itLastIP->frameno = bframeno++;
  1265.  
  1266.         // Add GOP.
  1267.  
  1268.         GOPInfo ginfo;
  1269.  
  1270.         ginfo.first_frame        = mGOPStartFrame;
  1271.         ginfo.frame_count        = bframeno;
  1272.  
  1273.         pair<GOPMap::iterator,bool> insresult = mGOPTable.insert(GOPMap::value_type(mposGOP, ginfo));
  1274.  
  1275.         if (!insresult.second) {
  1276.             // Is it incomplete?
  1277.  
  1278.             firstframe = (*insresult.first).second.first_frame;
  1279.  
  1280.             if (firstframe < 0)
  1281.                 (*insresult.first).second = ginfo;
  1282.             else {
  1283.                 lastframe = firstframe + (*insresult.first).second.frame_count;
  1284.  
  1285.                 _RPT1(0,"Warning: LimboFlush called preexisting GOP %I64x!\n", (*insresult.first).first);
  1286.                 return true;
  1287.             }
  1288.         }
  1289.  
  1290. //        _RPT3(0, "range: %I64x %d %d\n", mposGOP, mGOPTable[mposGOP].first_frame, mGOPTable[mposGOP].frame_count);
  1291.  
  1292.         // Dump frames into the frame heap.
  1293.  
  1294.         long frame = mGOPStartFrame;
  1295.  
  1296.         for(it = mFrameLimboTable.begin(); it != itEnd; ++it) {
  1297.             TentativeFrameInfo& tinfo = *it;
  1298.             FrameInfo info;
  1299.  
  1300.             info.first_packet    = tinfo.first_packet;
  1301.             info.packet_offset    = tinfo.packet_offset;
  1302.             info.length            = tinfo.length;
  1303.             info.type            = tinfo.type;
  1304.             info.display_order    = tinfo.frameno + mGOPStartFrame;
  1305.  
  1306. #if 0
  1307.             VDDEBUG("Adding frame %d: pos(%I64x), length(%ld), type(%c)\n"
  1308.                     , frame
  1309.                     , info.first_packet + info.packet_offset
  1310.                     , info.length
  1311.                     , "0IPBD567"[tinfo.type]);
  1312. #endif
  1313.  
  1314.             mFrameTable[frame++] = info;
  1315.         }
  1316.  
  1317.         // Wipe limbo table.
  1318.  
  1319.         mFrameLimboTable.erase(mFrameLimboTable.begin(), mFrameLimboTable.end());
  1320.  
  1321.         // Return range.
  1322.  
  1323.         firstframe = mGOPStartFrame;
  1324.         lastframe = frame;
  1325.  
  1326. //        printf("flushing range: [%d,%d)\n", firstframe, lastframe);
  1327.  
  1328.         return true;
  1329.     }
  1330. };
  1331.  
  1332. ///////////////////////////////////////////////////////////////////////////
  1333.  
  1334. class VDMPEGFile : public IVDMPEGFile, public IVDMPEGPacketReader {
  1335. private:
  1336.     struct MPEGSystemHeader {
  1337.         int        header_length;
  1338.         int        rate_bound;
  1339.         int        audio_bound;
  1340.         int        video_bound;
  1341.         bool    fixed:1,
  1342.                 constrained:1,
  1343.                 audio_lock:1,
  1344.                 video_lock:1;
  1345.     };
  1346.  
  1347.     enum { kInitScanLimit = 131072 };
  1348.     enum { kBufferSize = 131072 };
  1349.  
  1350.     VDAtomicInt refCount;
  1351.  
  1352.     unsigned char *pBuffer;
  1353.     int64 posBufferBase;
  1354.     long nBufferLimit;
  1355.     long nBufferOffset;
  1356.     long nBufferSize;
  1357.  
  1358.     MPEGSystemHeader syshdr;
  1359.  
  1360.     VDMPEGAudioStream *pAudioStream[32];
  1361.     VDMPEGVideoStream *pVideoStream[16];
  1362.  
  1363.     long    nAudioStreamMask;
  1364.     long    nVideoStreamMask;
  1365.  
  1366.     unsigned char packetbuf[65536];
  1367.  
  1368.     VDMPEGCache mPacketCache;
  1369.  
  1370.     VDFile        mFile;
  1371.  
  1372. public:
  1373.     VDMPEGFile()
  1374.         : refCount(0)
  1375.         , pBuffer(new unsigned char[kBufferSize])
  1376.         , posBufferBase(0)
  1377.         , nBufferLimit(0)
  1378.         , nBufferOffset(0)
  1379.         , nBufferSize(kBufferSize)
  1380.         , mPacketCache(128, 4096)
  1381.     {
  1382.         memset(pAudioStream, 0, sizeof pAudioStream);
  1383.         memset(pVideoStream, 0, sizeof pVideoStream);
  1384.     }
  1385.  
  1386.     ~VDMPEGFile() {
  1387.         Close();
  1388.         delete[] pBuffer;
  1389.     }
  1390.  
  1391.     int AddRef() { return refCount.inc(); }
  1392.     int Release() { int rc = refCount.dec(); if (!rc) delete this; return rc; }
  1393.  
  1394.     void Open(const wchar_t *pszFile) {
  1395.         mFile.open(pszFile, nsVDFile::kRead | nsVDFile::kDenyWrite | nsVDFile::kOpenExisting | nsVDFile::kSequential);
  1396.         _streamFlush();
  1397.         posBufferBase = 0;
  1398.  
  1399.         nAudioStreamMask = 0;
  1400.         nVideoStreamMask = 0;
  1401.     }
  1402.  
  1403.     void Close() {
  1404.         int i;
  1405.  
  1406.         for(i=0; i<32; ++i) {
  1407.             delete pAudioStream[i];
  1408.             pAudioStream[i] = NULL;
  1409.         }
  1410.  
  1411.         for(i=0; i<16; ++i) {
  1412.             delete pVideoStream[i];
  1413.             pVideoStream[i] = NULL;
  1414.         }
  1415.  
  1416.         mFile.closeNT();        // It's open for read.  We don't care if the close fails.
  1417.     }
  1418.  
  1419.     bool Init() {
  1420.         int64 sysclk;
  1421.         long mux;
  1422.  
  1423.         // Scan for first packet.
  1424.  
  1425.         if (!_streamScanPackStart(sysclk, mux))
  1426.             return false;
  1427.  
  1428.         int stream;
  1429.         int length;
  1430.         int64 pts;
  1431.         int64 dts;
  1432.  
  1433.         if (!_streamScanSystemHeader(syshdr))
  1434.             return false;
  1435.  
  1436.         // Scan the first 128K for streams.  Once we've found a stream,
  1437.         // continue scanning until we get the first PTS for it.
  1438.  
  1439.         int nStreamsWithoutFormat = 0;
  1440.         long nVideoFormatMask = -1L;
  1441.         long nAudioFormatMask = -1L;
  1442.         int64 packetpos;
  1443.  
  1444.         while(_streamScanPacket(-1, -1, stream, length, pts, dts, packetpos) && (_streamPos() < kInitScanLimit || nStreamsWithoutFormat>0)) {
  1445. //        while(_streamScanPacket(-1, -1, stream, length, pts, dts, packetpos)) {
  1446.             _streamRead(packetbuf, length);
  1447.  
  1448.             mPacketCache.Write(packetbuf, packetpos, length);
  1449.  
  1450.             if (stream < 32) {
  1451.                 if (!pAudioStream[stream]) {
  1452.                     pAudioStream[stream] = new VDMPEGAudioStream(this, stream);
  1453.                     pAudioStream[stream]->AddRef();
  1454.                     pAudioStream[stream]->ParseInit(NULL, 0, -1, 0);
  1455.                     ++nStreamsWithoutFormat;
  1456.                     nAudioStreamMask |= (1<<stream);
  1457.                 }
  1458.  
  1459.                 if (nAudioFormatMask & (1<<stream)) {
  1460.                     eParseResult r = pAudioStream[stream]->ParseInit(packetbuf, length, pts, packetpos);
  1461.  
  1462.                     if (r == kParseAbort)
  1463.                         return false;
  1464.                     else if (r == kParseComplete) {
  1465.                         nAudioFormatMask &= ~(1<<stream);
  1466.                         --nStreamsWithoutFormat;
  1467.                     }
  1468.                 }
  1469.             } else {
  1470.                 if (!pVideoStream[stream-32]) {
  1471.                     pVideoStream[stream-32] = new VDMPEGVideoStream(this, stream);
  1472.                     pVideoStream[stream-32]->AddRef();
  1473.                     pVideoStream[stream-32]->ParseBeginInitialScan();
  1474.                     ++nStreamsWithoutFormat;
  1475.                     nVideoStreamMask |= (1<<(stream-32));
  1476.                 }
  1477.  
  1478. //                if (nVideoFormatMask & (1<<(stream-32))) {
  1479.                 {
  1480.                     eParseResult r = pVideoStream[stream-32]->Parse(packetbuf, length, pts, packetpos);
  1481.  
  1482.                     if (r == kParseAbort)
  1483.                         return false;
  1484.                     else if (r == kParseComplete) {
  1485.                         nVideoFormatMask &= ~(1<<(stream-32));
  1486.                         --nStreamsWithoutFormat;
  1487.                     }
  1488.                 }
  1489.             }
  1490.         }
  1491.  
  1492.         // Try to determine the length of streams.  PTS markers must be placed every
  1493.         // 0.7s, so we should hit the final PTSes for all streams if we seek back
  1494.         // a full second (~180K at VideoCD rates), assuming streams are the same
  1495.         // length.  From there, we can determine the total length of audio streams
  1496.         // by looking for packets past the PTS; with video streams we have to
  1497.         // count frames as well.
  1498. #if 1
  1499.         int64 pos = mFile.size() - syshdr.rate_bound*50;
  1500. //        int64 pos = 0;
  1501.  
  1502. //        printf("seeking to %I64d\n", pos);
  1503.  
  1504.         if (pos<0)
  1505.             pos = 0;
  1506.  
  1507.         _streamSeek(pos);
  1508.  
  1509.         // Reinitialize parsing for all audio streams.
  1510.  
  1511.         for(stream=0; stream<32; ++stream)
  1512.             if (pAudioStream[stream]) {
  1513.                 pAudioStream[stream]->ParseReset();
  1514.             }
  1515.  
  1516.         // Reinitialize parsing for all video streams.
  1517.  
  1518.         for(stream=0; stream<16; ++stream)
  1519.             if (pVideoStream[stream]) {
  1520.                 pVideoStream[stream]->ParseBeginSeekScan(false);
  1521.             }
  1522.  
  1523.         // Decode until we hit the end.
  1524.  
  1525.         if (!_streamScanPackStart(sysclk, mux))
  1526.             return false;
  1527.  
  1528.         while(_streamScanPacket(-1, -1, stream, length, pts, dts, packetpos)) {
  1529.             _streamRead(packetbuf, length);
  1530.  
  1531.             mPacketCache.Write(packetbuf, packetpos, length);
  1532.  
  1533. //            printf("%I64d\n", packetpos);
  1534.  
  1535.             if (stream >= 32) {
  1536.                 if (pVideoStream[stream-32]) {
  1537.                     eParseResult r = pVideoStream[stream-32]->Parse(packetbuf, length, pts, packetpos);
  1538.  
  1539.                     if (r == kParseAbort)
  1540.                         return false;
  1541.                 }
  1542.             } else {
  1543.                 if (pAudioStream[stream]) {
  1544.                     eParseResult r = pAudioStream[stream]->Parse(packetbuf, length, pts, packetpos);
  1545.  
  1546.                     if (r == kParseAbort)
  1547.                         return false;
  1548.                 }
  1549.             }
  1550.         }
  1551.  
  1552.         for(stream=0; stream<16; ++stream)
  1553.             if (pVideoStream[stream])
  1554.                 pVideoStream[stream]->ParseEndSeek();
  1555. #endif
  1556.  
  1557.         return true;
  1558.     }
  1559.  
  1560.     long getAudioStreamMask() { return nAudioStreamMask; }
  1561.     long getVideoStreamMask() { return nVideoStreamMask; }
  1562.  
  1563.     IVDMPEGAudioStream *getAudioStream(int n) {
  1564.         if (!pAudioStream[n])
  1565.             return NULL;
  1566.  
  1567.         pAudioStream[n]->AddRef();
  1568.  
  1569.         return pAudioStream[n];
  1570.     }
  1571.  
  1572.     IVDMPEGVideoStream *getVideoStream(int n) {
  1573.         if (!pVideoStream[n])
  1574.             return NULL;
  1575.  
  1576.         pVideoStream[n]->AddRef();
  1577.  
  1578.         return pVideoStream[n];
  1579.     }
  1580.  
  1581.     bool PreScan() {
  1582.         int64 sysclk;
  1583.         long mux;
  1584.         int stream;
  1585.  
  1586.         _streamSeek(0);
  1587.  
  1588.         // Reinitialize parsing for all audio streams.
  1589.  
  1590.         for(stream=0; stream<32; ++stream)
  1591.             if (pAudioStream[stream]) {
  1592.                 pAudioStream[stream]->ParseReset();
  1593.             }
  1594.  
  1595.         // Reinitialize parsing for all video streams.
  1596.  
  1597.         for(stream=0; stream<16; ++stream)
  1598.             if (pVideoStream[stream]) {
  1599.                 pVideoStream[stream]->ParseBeginSeekScan(false);
  1600.             }
  1601.  
  1602.         // Decode until we hit the end.
  1603.  
  1604.         if (!_streamScanPackStart(sysclk, mux))
  1605.             return false;
  1606.  
  1607.         long megabytes = (long)(mFile.size()+1048575)>>20;
  1608.  
  1609.         VDProgressAbortable progress(megabytes, "MPEG-1 file parser", "%ldMB of %ldMB", "Prescanning input file");
  1610.  
  1611.         int length;
  1612.         int64 pts;
  1613.         int64 dts;
  1614.         int64 packetpos;
  1615.  
  1616.         while(_streamScanPacket(-1, -1, stream, length, pts, dts, packetpos)) {
  1617.             progress.advance((long)(mFile.tell() >> 20));
  1618.  
  1619.             _streamRead(packetbuf, length);
  1620.  
  1621.             mPacketCache.Write(packetbuf, packetpos, length);
  1622.  
  1623.             if (stream >= 32) {
  1624.                 if (pVideoStream[stream-32]) {
  1625.                     eParseResult r = pVideoStream[stream-32]->Parse(packetbuf, length, pts, packetpos);
  1626.  
  1627.                     if (r == kParseAbort)
  1628.                         return false;
  1629.                 }
  1630.             } else {
  1631.                 if (pAudioStream[stream]) {
  1632.                     eParseResult r = pAudioStream[stream]->Parse(packetbuf, length, pts, packetpos);
  1633.  
  1634.                     if (r == kParseAbort)
  1635.                         return false;
  1636.                 }
  1637.             }
  1638.         }
  1639.  
  1640.         for(stream=0; stream<16; ++stream)
  1641.             if (pVideoStream[stream])
  1642.                 pVideoStream[stream]->ParseEndSeek();
  1643.  
  1644.         return true;
  1645.     }
  1646.  
  1647.     //////////////////
  1648.     //
  1649.     //    Scan for a desired packet or series of packets.  The scan begins
  1650.     //    one-second before the desired packet and continues until the
  1651.     //    stream handler discovers:
  1652.     //
  1653.     //        kParseComplete:        The desired packets have been found.
  1654.     //        kParseRewind:        The current read position is too far
  1655.     //                            forward.  Restart at the original
  1656.     //                            position minus a defined amount that
  1657.     //                            doubles each time (binary exp backoff).
  1658.     //        kParseAbort:        The desired packet is known to be
  1659.     //                            missing -- this can occur if the handler
  1660.     //                            spots timestamps before and after the
  1661.     //                            desired range during the scan.
  1662.     //                            
  1663.  
  1664.     bool DoScanByPos(int64 pos, int active_stream, int64 lobound, int64 hibound) {
  1665.         int64 sysclk;
  1666.         long mux;
  1667.         int stream;
  1668.         int length;
  1669.         int64 pts;
  1670.         int64 dts;
  1671.         int64 packetpos;
  1672.         int64 backoff = syshdr.rate_bound * 50;        // start with one-second backoff
  1673.  
  1674.         // round backoff up to 64K, and pos down by that amount
  1675.  
  1676.         backoff = (backoff + 65535) & ~65535;
  1677.  
  1678.         pos = (pos - backoff) & ~65535;
  1679.         if (pos<0) pos = 0;
  1680.  
  1681.         // Decode until we hit the end.
  1682.  
  1683. //        _RPT1(0, "DoScanByPos: beginning scan at %I64x\n", pos);
  1684.  
  1685.         for(;;) {
  1686.             bool successful;
  1687.  
  1688.             if (active_stream >= 32)
  1689.                 pVideoStream[active_stream-32]->ParseBeginSeekScan(true);
  1690.             else
  1691.                 pAudioStream[active_stream]->ParseReset();
  1692.  
  1693.             _streamSeek(pos & ~65535);
  1694.  
  1695.             if (!_streamScanPackStart(sysclk, mux))
  1696.                 return false;
  1697.  
  1698.             do {
  1699.                 eParseResult r;
  1700.  
  1701.                 successful = _streamScanPacket(-1, -1, stream, length, pts, dts, packetpos);
  1702.  
  1703.                 if (successful && stream != active_stream) {
  1704.                     _streamSkip(length);
  1705.                     continue;
  1706.                 }
  1707.  
  1708.                 if (successful) {
  1709.                     _streamRead(packetbuf, length);
  1710.                     mPacketCache.Write(packetbuf, packetpos, length);
  1711.                 } else
  1712.                     stream = active_stream;
  1713.  
  1714.                 if (stream >= 32) {        // video
  1715.                     if (successful)
  1716.                         r = pVideoStream[stream-32]->Parse(packetbuf, length, pts, packetpos);
  1717.                     else {
  1718.                         _RPT0(0, "DoScanByPos: end of file reached\n");
  1719.                         r = pVideoStream[stream-32]->ParseEndSeek();
  1720.                     }
  1721.                 } else {                // audio
  1722.  
  1723.                     if (successful)
  1724.                         r = pAudioStream[stream]->Parse(packetbuf, length, pts, packetpos);
  1725.                     else
  1726.                         r = kParseRewind;
  1727.                 }
  1728.  
  1729.                 if (r == kParseRewind) {
  1730.                     if (pos <= lobound)
  1731.                         return false;
  1732.  
  1733.                     pos -= backoff;
  1734.                     if (pos < 0)
  1735.                         pos = 0;
  1736.  
  1737.                     backoff *= 2;
  1738.  
  1739.                     if (pos < lobound)
  1740.                         pos = lobound;
  1741.  
  1742.                     _RPT1(0, "DoScanByPos: missed, restarting scan at %I64x\n", pos);
  1743.  
  1744.                     break;
  1745.                 } else if (r == kParseAbort) {
  1746.                     _RPT0(0, "DoScanByPos: scan aborted by handler\n");
  1747.                     return false;
  1748.                 } else if (r == kParseComplete)
  1749.                     return true;
  1750.             } while(successful);
  1751.         }
  1752.     }
  1753.  
  1754.     // The packet position given is the first byte after the start code.
  1755.  
  1756.     bool ReadPacket(int desired_stream, int64 packet, int offset, char *dst, int length) {
  1757.  
  1758.         if (mPacketCache.Read(dst, packet, length, offset))
  1759.             return true;
  1760.  
  1761.         int64 packetpos;
  1762.         int64 pts, dts;
  1763.         int pktlength;
  1764.         int stream;
  1765.         long audio_mask = 0, video_mask = 0;
  1766.  
  1767.         if (desired_stream<32)
  1768.             audio_mask = 1<<desired_stream;
  1769.         else
  1770.             video_mask = 1<<(desired_stream-32);
  1771.  
  1772.         _streamSeek(packet - 4);
  1773.  
  1774.         if (_streamScanPacket(audio_mask, video_mask, stream, pktlength, pts, dts, packetpos)) {
  1775.             VDASSERT(stream == desired_stream);
  1776.             pktlength -= offset;
  1777.             if (pktlength > length)
  1778.                 pktlength = length;
  1779.  
  1780.             if (offset)
  1781.                 _streamSkip(offset);
  1782.  
  1783.             if (!_streamRead(dst, pktlength))
  1784.                 return false;
  1785.  
  1786.             length -= pktlength;
  1787.             dst += pktlength;
  1788.             if (!length)
  1789.                 return true;
  1790.  
  1791.             offset = 0;
  1792.         }
  1793.  
  1794.         return false;
  1795.     }
  1796.  
  1797.     //////////////////
  1798.  
  1799. private:
  1800.     void _streamSeek(int64 pos) {
  1801.         if (pos >= posBufferBase && pos <= posBufferBase + nBufferLimit) {
  1802.             nBufferOffset = (long)(pos - posBufferBase);
  1803.             return;
  1804.         }
  1805.  
  1806.         _streamFlush();
  1807.         if (pos >= posBufferBase && pos < posBufferBase + nBufferSize) {
  1808.             long off = (long)(pos - posBufferBase);
  1809.  
  1810.             _streamReload();
  1811.             nBufferOffset += off;
  1812.  
  1813.             if (nBufferOffset >= nBufferLimit)
  1814.                 _streamFlush();
  1815.         } else {
  1816.             mFile.seek(pos, nsVDFile::kSeekStart);
  1817.             posBufferBase = pos;
  1818.         }
  1819.     }
  1820.  
  1821.     void _streamFlush() {
  1822.         posBufferBase += nBufferLimit;
  1823.         nBufferLimit = 0;
  1824.     }
  1825.  
  1826.     bool _streamReload() {
  1827.         posBufferBase += nBufferLimit;
  1828.         nBufferLimit = mFile.readData(pBuffer, nBufferSize);
  1829.         nBufferOffset = 0;
  1830.  
  1831.         return nBufferLimit > 0;
  1832.     }
  1833.  
  1834.     inline int _streamReadNextByte() {
  1835.         if (nBufferOffset >= nBufferLimit && !_streamReload())
  1836.             return -1;
  1837.  
  1838.         return (int)pBuffer[nBufferOffset++];
  1839.     }
  1840.  
  1841.     inline int _streamReadAndCompareNextLong(long cv) {
  1842.         if (nBufferOffset+4 <= nBufferLimit) {
  1843.             nBufferOffset += 4;
  1844.             return *(long *)&pBuffer[nBufferOffset-4] == cv;
  1845.         }
  1846.  
  1847.         // nuts.
  1848.  
  1849.         long v = 0;
  1850.         int i, c;
  1851.  
  1852.         for(i=0; i<4; ++i) {
  1853.             c = _streamReadNextByte();
  1854.  
  1855.             if (c<0)
  1856.                 return -1;
  1857.  
  1858.             v = (v<<8) + c;
  1859.         }
  1860.  
  1861.         return v == cv;
  1862.     }
  1863.  
  1864.     bool _streamSkip(int bytes) {
  1865.         while(bytes > 0) {
  1866.             if (nBufferOffset < nBufferLimit) {
  1867.                 int tc = nBufferLimit - nBufferOffset;
  1868.  
  1869.                 if (tc > bytes)
  1870.                     tc = bytes;
  1871.  
  1872.                 nBufferOffset += tc;
  1873.                 bytes -= tc;
  1874.             } else
  1875.                 if (!_streamReload())
  1876.                     return false;
  1877.         }
  1878.  
  1879.         return true;
  1880.     }
  1881.  
  1882.     bool _streamRead(void *dst, int bytes) {
  1883.         while(bytes > 0) {
  1884.             if (nBufferOffset < nBufferLimit) {
  1885.                 int tc = nBufferLimit - nBufferOffset;
  1886.  
  1887.                 if (tc > bytes)
  1888.                     tc = bytes;
  1889.  
  1890.                 memcpy(dst, pBuffer + nBufferOffset, tc);
  1891.  
  1892.                 nBufferOffset += tc;
  1893.                 dst = (char *)dst + tc;
  1894.                 bytes -= tc;
  1895.             } else
  1896.                 if (!_streamReload())
  1897.                     return false;
  1898.         }
  1899.  
  1900.         return true;
  1901.     }
  1902.  
  1903.     int64 _streamPos() {
  1904.         return posBufferBase + nBufferOffset;
  1905.     }
  1906.  
  1907.     int _streamScanStartCode() {
  1908.         for(;;) {
  1909.             int c;
  1910.  
  1911.             // Nothing
  1912.  
  1913.             do {
  1914.                 if ((c = _streamReadNextByte()) < 0)
  1915.                     return -1;
  1916.             } while(c);
  1917.  
  1918.             // 00
  1919.  
  1920.             if ((c = _streamReadNextByte()) < 0)
  1921.                 return -1;
  1922.  
  1923.             if (c)
  1924.                 continue;
  1925.                 
  1926.             // 00 00
  1927.  
  1928.             do {
  1929.                 if ((c = _streamReadNextByte()) < 0)
  1930.                     return -1;
  1931.             } while(!c);
  1932.  
  1933.             if (c != 1)
  1934.                 continue;
  1935.  
  1936.             return _streamReadNextByte();
  1937.         }
  1938.     }
  1939.  
  1940.     bool _streamScanPackStart(int64& sysclk_ref, long& mux_rate) {
  1941.         // Pack start codes are 000001BA.
  1942.  
  1943.         int c;
  1944.  
  1945.         while((c = _streamScanStartCode()) >= 0) {
  1946.  
  1947.             if (c == 0xBA) {
  1948.                 unsigned char buf[8];
  1949.  
  1950.                 // woohoo!!  read the next 8 bytes in
  1951.                 //
  1952.                 // +---+---+---+---+-----------+---+
  1953.                 // | 0 | 0 | 1 | 0 |sysclk32-30| 1 | buf[0]
  1954.                 // +---+---+---+---+-----------+---+
  1955.                 // |          sysclk 29-22         | buf[1]
  1956.                 // +---------------------------+---+
  1957.                 // |        sysclk 21-15       | 1 | buf[2]
  1958.                 // +---------------------------+---+
  1959.                 // |          sysclk 14-7          | buf[3]
  1960.                 // +---------------------------+---+
  1961.                 // |         sysclk 6-0        | 1 | buf[4]
  1962.                 // +---+-----------------------+---+
  1963.                 // | 1 |      mux rate 21-15       | buf[5]
  1964.                 // +---+---------------------------+
  1965.                 // |          mux rate 14-7        | buf[6]
  1966.                 // +---------------------------+---+
  1967.                 // |       mux rate  6-0       | 1 | buf[7]
  1968.                 // +---------------------------+---+
  1969.  
  1970.                 if (!_streamRead(buf, 8))
  1971.                     return false;
  1972.  
  1973.                 // decode scr and mux rate
  1974.  
  1975.                 sysclk_ref    = ((int64)(buf[0]&0x0e) << 29)
  1976.                             + ((int64) buf[1]       << 22)
  1977.                             + ((int64)(buf[2]&0xfe) << 14)
  1978.                             + ((int64) buf[3]       <<  7)
  1979.                             + (       (buf[4]&0xfe) >>  1);
  1980.  
  1981.                 mux_rate    =(((long)(buf[5]&0x7f) << 15)
  1982.                             + ((long)buf[6] << 7)
  1983.                             + ((buf[7]&0xfe) >> 1)) * 400;
  1984.  
  1985.                 // validate - mux rate cannot be zero
  1986.  
  1987.                 if (    (buf[0]&0xf1) != 0x21
  1988.                     ||    (buf[2]&buf[4]&buf[7]&1) != 1
  1989.                     ||    (buf[5]&0x80) != 0x80
  1990.                     ||    !mux_rate) {
  1991.  
  1992.                     // Oops, bad pack.  Back up and continue scanning.
  1993.  
  1994.                     _streamSeek(_streamPos() - 8);
  1995.                     continue;
  1996.                 }
  1997.  
  1998.                 // looks good to me!
  1999.  
  2000.                 return true;
  2001.             }
  2002.         }
  2003.  
  2004.         return false;
  2005.     }
  2006.  
  2007.     // This routine assumes you've already seeked up to a pack header.
  2008.  
  2009.     bool _streamScanSystemHeader(MPEGSystemHeader& header) {
  2010.         unsigned char buf[8];
  2011.  
  2012.         // System headers always follow pack headers, so it's safer
  2013.         // to look for a valid system header after a valid pack
  2014.         // header.
  2015.  
  2016.         for(;;) {
  2017.             int c = _streamReadAndCompareNextLong(0xBB010000);
  2018.  
  2019.             if (c<0)
  2020.                 return false;
  2021.             else if (!c) {
  2022.                 int64 sysref;
  2023.                 long muxrate;
  2024.  
  2025.                 if (!_streamScanPackStart(sysref, muxrate))
  2026.                     return false;
  2027.             } else {
  2028.                 // read in system header (8+ bytes)
  2029.                 //
  2030.                 // +-------------------------------+
  2031.                 // |       header length 15-8      | buf[0]
  2032.                 // +-------------------------------+
  2033.                 // |       header length  7-0      | buf[1]
  2034.                 // +---+---------------------------+
  2035.                 // | 1 |     rate bound 21-15      | buf[2]
  2036.                 // +---+---------------------------+
  2037.                 // |        rate bound 14-7        | buf[3]
  2038.                 // +---------------------------+---+
  2039.                 // |        rate bound 6-0     | 1 | buf[4]
  2040.                 // +-----------------------+---+---+
  2041.                 // |      audio bound      |F_F|C_P| buf[5]  fixed_flag, constrained_parameters
  2042.                 // +---+---+---+-----------+---+---+
  2043.                 // |A_L|V_L| 1 |    video bound    | buf[6]  audio_lock, video_lock
  2044.                 // +---+---+---+-------------------+
  2045.                 // |      reserved (1111 1111)     | buf[7]
  2046.                 // +-------------------------------+
  2047.  
  2048.                 if (!_streamRead(buf, 8))
  2049.                     return false;
  2050.  
  2051.                 // decode systems header
  2052.  
  2053.                 header.header_length    = ((int)buf[0]<<8) + buf[1];
  2054.                 header.rate_bound        = (((int)buf[2]&0x7f)<<15)
  2055.                                         + ((int)buf[3]<<7)
  2056.                                         + ((int)buf[4]>>1);
  2057.                 header.audio_bound        = (buf[5]&0xfc)>>2;
  2058.                 header.video_bound        = buf[6]&0x1f;
  2059.                 header.fixed            = 0!=(buf[5]&2);
  2060.                 header.constrained        = 0!=(buf[5]&1);
  2061.                 header.audio_lock        = 0!=(buf[6]&0x80);
  2062.                 header.video_lock        = 0!=(buf[6]&0x40);
  2063.  
  2064.                 // check system header for validity
  2065.  
  2066.                 int64 pos = _streamPos();
  2067.  
  2068.                 if (    (buf[2]&0x80) != 0x80
  2069.                     ||    (buf[4]&0x01) != 0x01
  2070.                     ||    (buf[6]&0x20) != 0x20
  2071.                     ||    header.header_length < 8
  2072.                     ||    header.audio_bound > 32
  2073.                     ||    header.video_bound > 16
  2074.                     ||    header.header_length < 6
  2075.                     ||    !_streamSkip(header.header_length - 6)
  2076.                     ) {
  2077.  
  2078.                     // failed -- continue search
  2079.  
  2080.                     _streamSeek(pos - 8);
  2081.                 } else
  2082.                     return true;
  2083.             }
  2084.         }
  2085.     }
  2086.  
  2087.     // This should be as robust as possible.  Preferably call after a pack.
  2088.  
  2089.     bool _streamScanPacket(long audio_mask, long video_mask, int& stream, int& length, int64& pts, int64& dts, int64 &packet_pos) {
  2090.         int c;
  2091.  
  2092.         for(;;) {
  2093.             while((c = _streamScanStartCode()) >= 0 && c < 0xBC)
  2094.                 ;
  2095.  
  2096.             if (c < 0)
  2097.                 return false;
  2098.  
  2099.             stream = c;
  2100.  
  2101.             packet_pos = _streamPos();
  2102.  
  2103.             // process packet
  2104.             //
  2105.             // BC        reserved
  2106.             // BD        private_stream_1
  2107.             // BE        padding
  2108.             // BF        private_stream_2
  2109.             // C0-DF    audio stream
  2110.             // E0-EF    video stream
  2111.             // F0-FF    reserved stream
  2112.  
  2113.             if ((c = _streamReadNextByte())<0) return false;
  2114.             length = c<<8;
  2115.             if ((c = _streamReadNextByte())<0) return false;
  2116.             length += c;
  2117.  
  2118.             if (stream != 0xBF) {    // private_stream_2 lacks stuff
  2119.                 int64 crap_start = _streamPos();
  2120.  
  2121.                 // eat stuffing bytes
  2122.  
  2123.                 do {
  2124.                     c = _streamReadNextByte();
  2125.                 } while(c == 0xff);
  2126.  
  2127.                 // 01 -> STD buffer scale / size
  2128.  
  2129.                 if ((c & 0xc0) == 0x40) {
  2130.                     if ((c = _streamReadNextByte())<0)
  2131.                         return false;
  2132.                     if ((c = _streamReadNextByte())<0)
  2133.                         return false;
  2134.                 }
  2135.  
  2136.                 // 0010 -> PTS only
  2137.                 // 0011 -> PTS + DTS
  2138.                 //
  2139.                 // +---+---+---+---+-----------+---+
  2140.                 // | 0 | 0 | 1 |DTS| PTS 32-30 | 1 | buf[0]
  2141.                 // +---+---+---+---+-----------+---+
  2142.                 // | Presentation timestamp 29-22  | buf[1]
  2143.                 // +---------------------------+---+
  2144.                 // |         PTS 21-15         | 1 | buf[2]
  2145.                 // +---------------------------+---+
  2146.                 // |  Presentation timestamp 14-7  | buf[3]
  2147.                 // +---------------------------+---+
  2148.                 // |          PTS 6-0          | 1 | buf[4]
  2149.                 // +---+---+---+---+-----------+---+
  2150.                 // | 0 | 0 | 0 | 1 | DTS 32-30 | 1 | buf[5]
  2151.                 // +---+---+---+---+-----------+---+
  2152.                 // |    Decoding timestamp 29-22   | buf[6]
  2153.                 // +---------------------------+---+
  2154.                 // |         DTS 21-15         | 1 | buf[7]
  2155.                 // +---------------------------+---+
  2156.                 // |    Decoding timestamp 14-7    | buf[8]
  2157.                 // +---------------------------+---+
  2158.                 // |          DTS 6-0          | 1 | buf[9]
  2159.                 // +---------------------------+---+
  2160.  
  2161.                 unsigned char buf[10];
  2162.                 bool pts_exists = !!(c&0x20);
  2163.                 bool dts_exists = !!(c&0x10);
  2164.  
  2165.                 buf[0] = c;
  2166.  
  2167.                 if ((c&0xf0) == 0x20) {            // 0010 -> PTS only
  2168.                     if (!_streamRead(buf+1, 4))
  2169.                         return false;
  2170.                 } else if ((c&0xf0) == 0x30) {    // 0011 -> PTS and DTS
  2171.                     if (!_streamRead(buf+1, 9))
  2172.                         return false;
  2173.                 } else if (c != 0x0f) {            // otherwise must be 00001111
  2174.                     // Uhh... uh oh.
  2175.                     //
  2176.                     // Looks like we were either fooled or something got
  2177.                     // corrupted.  Assume remainder of packet may be
  2178.                     // missing and drop immediately to start code scan.
  2179.  
  2180.                     continue;
  2181.                 }
  2182.  
  2183.                 if (pts_exists) {
  2184.  
  2185.                     // Validate PTS marker bits.  Force resync on failure.
  2186.  
  2187.                     if (!(buf[0]&buf[2]&buf[4]&1))
  2188.                         continue;
  2189.  
  2190.                     pts    = ((int64)(buf[0]&0x0e) << 29)
  2191.                         + ((int64) buf[1]       << 22)
  2192.                         + ((int64)(buf[2]&0xfe) << 14)
  2193.                         + ((int64) buf[3]       <<  7)
  2194.                         + (       (buf[4]&0xfe) >>  1);
  2195.                 } else
  2196.                     pts = -1;
  2197.  
  2198.                 if (dts_exists) {
  2199.  
  2200.                     // Validate DTS marker bits.  Force resync on failure.
  2201.  
  2202.                     if ((buf[5]&0xf1)!=0x011 || (buf[7]&buf[9]&1)!=1)
  2203.                         continue;
  2204.  
  2205.                     dts    = ((int64)(buf[5]&0x0e) << 29)
  2206.                         + ((int64) buf[6]       << 22)
  2207.                         + ((int64)(buf[7]&0xfe) << 14)
  2208.                         + ((int64) buf[8]       <<  7)
  2209.                         + (       (buf[9]&0xfe) >>  1);
  2210.                 } else
  2211.                     dts = pts;
  2212.  
  2213.                 // If STD_buffer and PTS/DTS stuff ends up longer
  2214.                 // than the header, someone fscked up and we should
  2215.                 // drop to resync.
  2216.  
  2217.                 length -= (long)(_streamPos() - crap_start);
  2218.  
  2219.                 if (length < 0)
  2220.                     continue;
  2221.             }
  2222.  
  2223.             // if this is a stream we're interested in, return,
  2224.             // otherwise skip the data in the stream
  2225.  
  2226.             switch(stream & 0xf0) {
  2227.             case 0xc0:        // C0-DF: audio
  2228.             case 0xd0:
  2229.                 if (audio_mask & (1<<(stream&0x1f))) {
  2230.                     stream -= 0xc0;
  2231.                     return true;
  2232.                 }
  2233.                 break;
  2234.             case 0xe0:
  2235.                 if (video_mask & (1<<(stream&0x1f))) {
  2236.                     stream -= 0xc0;
  2237.                     return true;
  2238.                 }
  2239.             }
  2240.  
  2241.             // Skip packet payload and continue looking for interesting streams
  2242.  
  2243.             _streamSkip(length);
  2244.         }
  2245.     }
  2246. };
  2247.  
  2248. IVDMPEGFile *CreateVDMPEGFile() {
  2249.     return new VDMPEGFile();
  2250. }
  2251.