Home || Visual Search || Applications || Architecture || Important Messages || OGL || Src

VideoAccessStrategy.h

Go to the documentation of this file.
00001 #ifndef Impala_Core_Stream_Lavc_VideoAccessStrategy_h
00002 #define Impala_Core_Stream_Lavc_VideoAccessStrategy_h
00003 
00004 #include "Core/Table/TableTem.h"
00005 #include "Core/Column/FixedStringColumn.h"
00006 #include "Core/Stream/Lavc/VideoAccessObject.h"
00007 #include "Core/Stream/Lavc/VideoIndex.h"
00008 
00009 #include "Util/IOBufferFile.h"
00010 #include "Core/Table/Read.h"
00011 #include "Core/Table/Write.h"
00012 
00013 namespace Impala
00014 {
00015 namespace Core
00016 {
00017 namespace Stream
00018 {
00019 namespace Lavc
00020 {
00021 
00027 class VideoAccessStrategy
00028 {
00029 
00030 protected:
00031 
00032     // packet idx nr | size | flags | file position after read 
00033     typedef Table::TableTem< Column::ColumnTem<Int32>,
00034                              Column::ColumnTem<Int32>,
00035                              Column::ColumnTem<Int32>,
00036                              Column::ColumnTem<UInt64> > PacketTable;
00037 
00038     typedef Column::FixedStringColumn::ColElemType FixedString;
00039 
00040     // frame idx nr | packet idx nr | is valid | is key frame | hash 
00041     typedef Table::TableTem< Column::ColumnTem<Int32>,
00042                              Column::ColumnTem<Int32>,
00043                              Column::ColumnTem<Int32>,
00044                              Column::ColumnTem<Int32>,
00045                              Column::FixedStringColumn > FrameTable;
00046 
00047 public:
00048 
00049     static const int HASH_SIZE = 32;
00050     static const String INVALID_FRAME_HASH;
00051     static const String UNSTABLE_FRAME_HASH;
00052 
00053 
00054     VideoAccessStrategy(const Lavc::VideoAccessObject* const vao) : mVao(vao)
00055     {
00056         mVideoIsValid = false;
00057         mFailingKeyFrameNr = -1;
00058         mPackets = 0;
00059         mFrames = 0;
00060         mScanDataPresent = false;
00061         mNrOfFrames = -1;
00062         mBadFrameCount = -1;
00063         mLeadingBadFrameCount = -1;
00064     }
00065 
00066     virtual
00067     ~VideoAccessStrategy()
00068     {
00069         CleanUp();
00070         if (mVao != 0)
00071             delete mVao;
00072     }
00073 
00078     bool
00079     Scan()
00080     {
00081         if (!ResetVideoSrc())
00082             return false;
00083 
00084         ILOG_INFO("Scanning video data...");
00085         mPackets = new PacketTable(1);
00086         mFrames = new FrameTable(Column::ColumnTem<Int32>(1),
00087                              Column::ColumnTem<Int32>(1),
00088                              Column::ColumnTem<Int32>(1),
00089                              Column::ColumnTem<Int32>(1),
00090                              Column::FixedStringColumn(HASH_SIZE, 1));
00091         mNrOfFrames = 0;
00092         mBadFrameCount = 0;
00093         mLeadingBadFrameCount = 0;
00094 
00095         bool scanSuccess = ScanProtected();
00096         ResetVideoSrc();
00097         if (!scanSuccess)
00098         {
00099             CleanUp();
00100             return false;
00101         }
00102 
00103         mScanDataPresent = true;
00104         mNrOfFrames = mFrames->Size();
00105         ILOG_INFO("Finished video scan; frame count established: " << 
00106             NrOfFrames());
00107         return true;
00108     }
00109 
00110     // Should not be used, in order to isolate knowledge of the vao class
00111     const VideoAccessObject* const
00112     VideoAccessObj() const
00113     {
00114         return mVao;
00115     }
00116 
00117     virtual bool
00118     ResetVideoSrc() const
00119     {
00120         return mVao->Reset();
00121     }
00122 
00123     bool
00124     VideoIsValid() const
00125     {
00126         return mVideoIsValid;
00127     }
00128 
00129     virtual int
00130     NrOfFrames() const
00131     {
00132         return mNrOfFrames;
00133     }
00134 
00135     int
00136     LeadingBadFrames() const
00137     {
00138         return mLeadingBadFrameCount;
00139     }
00140 
00141     bool
00142     FrameIsValid(int frameNr) const
00143     {
00144         return mFrames->Get3(frameNr) != 0;
00145     }
00146     
00147     char
00148     FrameType() const
00149     {
00150         return mVao->FrameType();
00151     }
00152 
00153     UInt8*
00154     RgbDataPtr() const
00155     {
00156         return mVao->RgbDataPtr();
00157     }
00158 
00162     VideoIndex*
00163     ConstructIndex() 
00164     {
00165         if (!mScanDataPresent)
00166         {
00167             ILOG_ERROR("[ConstructIndex] No scan data");
00168             return 0;
00169         }
00170 
00171         ResetVideoSrc();
00172         VideoIndex* videoIndex = ConstructIndexPrivate();
00173         if (videoIndex == 0)
00174             return 0;
00175 
00176         const double percIndexedFrames = 100.0 *
00177             videoIndex->NrOfEntries() / NrOfFrames();
00178         const double percentageSeekable = 100.0 * 
00179             videoIndex->NrOfSeekableFrames() / videoIndex->NrOfEntries();
00180         const int maxNonTargetFrameReads = videoIndex->MaxNonTargetFrameReads();
00181 
00182         ILOG_INFO("Number of entries in index: " << 
00183             videoIndex->NrOfEntries() << " (" << percIndexedFrames <<
00184             " %)");
00185         ILOG_INFO("Number of seekable entries in index: " << 
00186             videoIndex->NrOfSeekableFrames() << " (" << percentageSeekable <<
00187             " %)");
00188         ILOG_INFO("Max. frame reads required to get to any frame: " << 
00189             maxNonTargetFrameReads + 1);
00190 
00191         return videoIndex;
00192     }
00193 
00194     virtual void
00195     CleanUp()
00196     {
00197         if (mPackets != 0)
00198         {
00199             delete mPackets;
00200             mPackets = 0;
00201         }
00202         if (mFrames != 0)
00203         {
00204             delete mFrames;
00205             mFrames = 0;
00206         }
00207         mScanDataPresent = false;
00208         mFailingKeyFrameNr = -1;
00209     }
00210 
00214     virtual int
00215     DecodeNextFrame(bool* isValidFrame, bool* isKeyFrame, PacketTrace* pktTrace) const
00216     {
00217         //avcodec_get_frame_defaults(mFrame);
00218 
00219         const int MAX_READ_FAILURES = Max(15, 5 * mVao->GopSize());
00220         int nrOfReadFailures = 0;
00221         bool atEndOfFile = mVao->AtEof();
00222 
00223         bool readPacketFailed = false;
00224         *isValidFrame = false;
00225         *isKeyFrame = false;
00226         int rc = 0;
00227         while (true)
00228         {
00229             int readPacketResult = mVao->ReadPacket();
00230             readPacketFailed = (readPacketResult < 0);
00231             if (readPacketFailed)
00232             {
00233                 // upon a negative value, there may still be 
00234                 // valid frames left to decode
00235                 ILOG_DEBUG("ReadPacket() failed and returned: " << 
00236                     readPacketResult);
00237             }
00238             else if (pktTrace)
00239                 pktTrace->Add(mVao->CurrentPacketSize(), mVao->CurrentPacketFlags(), 
00240                     mVao->CurrentFilePosition(), mVao->CurrentPacketIsVideo());
00241 
00242             if (mVao->CurrentPacketIsVideo()) 
00243             {
00244                 int frameDecoded = -1;
00245                 int len = mVao->DecodeFrame(&frameDecoded);
00246 
00247                 // SK: used for problem analysis
00248                 int doDecodeTwice = false;
00249                 if (doDecodeTwice)
00250                 {
00251                     //int frameDecoded2nd = -1;
00252                     //int len2 = DecodeFrame(&frameDecoded2nd);
00253                     //if (frameDecoded && frameDecoded2nd)
00254                     //    ...
00255                     len = mVao->DecodeFrame(&frameDecoded);
00256                 }
00257 
00258                 if (frameDecoded != 0)
00259                 {
00260                     *isValidFrame = true;
00261                     *isKeyFrame = 
00262                         (mVao->FrameType() == 'I' && mVao->FrameIsKey());
00263                     break;
00264                 }
00265                 else
00266                 {
00267                     // do not continue if reading reached eof
00268                     if (atEndOfFile)
00269                     {
00270                         rc = -3;
00271                         break;
00272                     }
00273 
00274                     // mPacket->flags unequal zero seems to indicate incomplete
00275                     // frames other than P or B frames missing I or P frame data
00276                     if (mVao->CurrentPacketFlags() == 0)
00277                         break;
00278                 }
00279             }
00280  
00281             // while the read buffer already reached eof, there may
00282             // still be some valid frames left to decode!
00283             nrOfReadFailures++;
00284             if ((atEndOfFile || readPacketFailed) 
00285                 && (nrOfReadFailures > MAX_READ_FAILURES))
00286             {
00287                 ILOG_WARN("Max. nr of frame read failures reached (" <<
00288                     MAX_READ_FAILURES << "); probably at end of file");
00289                 rc = -1;
00290                 break;
00291             }
00292         } // while (true)
00293 
00294         return rc;
00295     }
00296 
00297     int
00298     CurrentFrameToRgb() const
00299     {
00300         return mVao->CurrentFrameToRgb();
00301     }
00302 
00303     virtual String 
00304     CurrentFrameHash() const
00305     {
00306         return mVao->CurrentHash();
00307     }
00308 
00309     virtual String 
00310     CurrentFrameHashBeforeConversion() const
00311     {
00312         return mVao->CurrentHashBeforeConversion();
00313     }
00314 
00315     String
00316     FrameHash(int frameNr) const
00317     {
00318         if (mScanDataPresent)
00319             return String(mFrames->Get5(frameNr).GetData(), HASH_SIZE);
00320 
00321         ILOG_ERROR("[FrameHash] No scan data");
00322         return "";
00323     }
00324 
00325     bool
00326     JumpToFramePosition(const UInt64& target) const
00327     {
00328         const bool mustBeKey = true;
00329         const int flushMode = 2; // flush (if applies) after the jump
00330         return Jump(target, GetJumpFlags(), mustBeKey, flushMode);
00331     }
00332 
00333     bool
00334     FrameIsStable(int frameNr) const
00335     {
00336         if (mScanDataPresent)
00337             return FrameHash(frameNr) != UNSTABLE_FRAME_HASH;
00338         else
00339             ILOG_ERROR("[FrameHash] No scan data");
00340         return true;
00341     }
00342 
00343     // Returns whether a frame's data can be read from the stream
00344     virtual bool
00345     FrameCanBeRead(int frameNr) const = 0;
00346 
00347 
00348 protected:
00349 
00350     virtual int
00351     GetJumpFlags() const = 0;
00352 
00353     virtual bool
00354     ScanProtected() = 0;
00355 
00356     // Caller assumes responsibility for the returned object.
00357     virtual VideoIndex*
00358     ConstructIndexProtected() const = 0;
00359 
00368     virtual bool
00369     Jump(const UInt64& target, int flags, bool mustBeKey = false, 
00370         int flush = 0, PacketTrace* trace = 0) const
00371     {
00372         if (flush & 1) // flush before seek
00373             mVao->FlushCodecContext();
00374 
00375         if (!mVao->Seek(target, flags))
00376             return false;
00377 
00378         if (flush & 2) // flush after seek
00379             mVao->FlushCodecContext();
00380 
00381         return DecodeNextValidFrame(mustBeKey, trace);
00382     }
00383 
00384     virtual bool
00385     DecodeNextValidFrame(bool lookForKeyFrame, PacketTrace* pktTrace = 0)  const
00386     {
00387         bool isValidFrame;
00388         bool isKeyFrame;
00389         do
00390         {
00391             if (DecodeNextFrame(&isValidFrame, &isKeyFrame, pktTrace) != 0) 
00392                 // eof or error
00393                 return false; 
00394             if (!isValidFrame)
00395             {
00396                 //ILOG_DEBUG("Skipping invalid frame");
00397                 continue;
00398             }
00399             if (lookForKeyFrame && !isKeyFrame)
00400             {
00401                 //ILOG_DEBUG("Skipping non-keyframe");
00402                 continue;
00403             }
00404             break;
00405         } while (true);
00406 
00407         return true;
00408     }
00409 
00410     // Processes the currently read frame
00411     void
00412     ProcessFrame(bool isValid, bool isKey, int frameNr, bool validating = false)
00413     {
00414         static const FixedString invalidAsFixedStr(
00415             HASH_SIZE, (char*) INVALID_FRAME_HASH.c_str(), true);
00416 
00417         if (validating)
00418         {
00419             if (isValid)
00420             {
00421                 if (!FrameIsValid(frameNr) || 
00422                     (isKey && !FrameIsKey(frameNr)) ||
00423                     (!isKey && FrameIsKey(frameNr)))
00424                 {
00425                     ILOG_ERROR("Unsupported instability type detected for" <<
00426                         " frame " << frameNr << " (" << FrameIsValid(frameNr) <<
00427                         "->" << isValid << ", " << FrameIsKey(frameNr) << 
00428                         "->" << isKey << ")");
00429                 }
00430                 else
00431                 {
00432                     mVao->CurrentFrameToRgb();
00433                     if (!CurrentHashMatchesFrame(frameNr))
00434                         MarkFrameUnstable(frameNr);
00435                 }
00436             }
00437             else if (FrameIsValid(frameNr))
00438                 ILOG_ERROR("Unsupported instability type detected for" <<
00439                     " frame " << frameNr << " (" << FrameIsValid(frameNr) <<
00440                         "->" << isValid << ")");
00441 
00442             ILOG_DEBUG("Re-scanned frame " << frameNr);
00443         }
00444 
00445         else 
00446         {
00447             String hashPre = INVALID_FRAME_HASH;
00448             String hash = INVALID_FRAME_HASH;
00449             if (isValid)
00450             {
00451                 hashPre = mVao->CurrentHashBeforeConversion();
00452                 mVao->CurrentFrameToRgb();
00453                 hash = mVao->CurrentHash();
00454                 FixedString hashAsFixedStr(HASH_SIZE, (char*) hash.c_str(), true);
00455                 AddFrameToTable(isValid, isKey, hash, hashAsFixedStr);
00456             }
00457             else
00458                 AddFrameToTable(false, false, INVALID_FRAME_HASH, invalidAsFixedStr);
00459 
00460             ILOG_DEBUG("Scanned frame " << frameNr << " [" << 
00461                 (isValid ? mVao->FrameType() : '?') << "] " << hash << "  pre: " << hashPre);
00462         }
00463     }
00464 
00465     bool
00466     FrameIsKey(int frameNr) const
00467     {
00468         return mFrames->Get4(frameNr) != 0;
00469     }
00470 
00471     bool
00472     CurrentFrameMatchesFrame(int frameNr, const PacketTrace* trace = 0) const
00473     {
00474         if (mPackets != 0 && mPackets->Size() > 0)
00475         {
00476             const int packetNr = mFrames->Get2(frameNr);
00477             const int packetSize = mPackets->Get2(packetNr);
00478             if (mVao->CurrentPacketSize() != packetSize)
00479                 return false;
00480         }
00481 
00482         if (!CurrentHashMatchesFrame(frameNr))
00483             return false;
00484 
00485         if (trace && !PacketTraceMatchesFrame(*trace, frameNr))
00486         {
00487             ILOG_DEBUG("Packet trace does not match for frame " << frameNr);
00488             return false;
00489         }
00490 
00491         return true;
00492     }
00493 
00494     bool
00495     CurrentHashMatchesFrame(int frameNr) const
00496     {
00497         bool matched = false;
00498         const String currentHash = mVao->CurrentHash();
00499         if (currentHash.size() == HASH_SIZE)
00500         {
00501             const char* currentHashStr = currentHash.c_str();
00502             const char* frameHash = 
00503                 mFrames->GetColumn5()->GetVectorData(frameNr);
00504             matched = true;
00505             for (int i = 0; i < HASH_SIZE; i++)
00506                 if (frameHash[i] != currentHashStr[i])
00507                 {
00508                     matched = false;
00509                     break;
00510                 }
00511         }
00512 
00513         if (!matched)
00514             ILOG_DEBUG("Hash does not match for frame " << 
00515                 frameNr << "; found: " << mVao->CurrentHash());
00516         return matched;
00517     }
00518 
00519     virtual bool
00520     NextFrameMatchesFrame(int frameNr, const VideoIndex& videoIndex) const = 0;
00521 
00522     bool
00523     ScanDataPresent()
00524     {
00525         return mScanDataPresent;
00526     }
00527 
00528     virtual void
00529     MarkFrameUnstable(int frameNr)
00530     {
00531         ILOG_INFO("Instability detected for frame: " << frameNr);
00532         static const FixedString unstableAsFixedStr(
00533             HASH_SIZE, (char*) UNSTABLE_FRAME_HASH.c_str(), true);
00534         mFrames->Set5(frameNr, unstableAsFixedStr);
00535     }
00536 
00537     // for dev/debug purposes only
00538     void
00539     WriteScanData(CString fileName)
00540     {
00541         Util::IOBufferFile buf(fileName, false, false);
00542         Table::Write(mPackets, &buf, true);
00543         ILOG_INFO("Wrote " << mPackets->Size() << " packets to file");
00544         Table::Write(mFrames, &buf, true);
00545         ILOG_INFO("Wrote " << mFrames->Size() << " frames to file");
00546     }
00547 
00548     // for dev/debug purposes only
00549     void
00550     ReadScanData(CString fileName)
00551     {
00552         Util::IOBufferFile buf(fileName, true, false);
00553 
00554         if (mPackets)
00555             mPackets->SetEmpty();
00556         else
00557             mPackets = new PacketTable(1);
00558         Table::Read(mPackets, &buf);
00559         ILOG_INFO("Read " << mPackets->Size() << " packets from file");
00560 
00561         if (mFrames)
00562             mFrames->SetEmpty();
00563         else
00564             mFrames = new FrameTable(Column::ColumnTem<Int32>(1),
00565                                      Column::ColumnTem<Int32>(1),
00566                                      Column::ColumnTem<Int32>(1),
00567                                      Column::ColumnTem<Int32>(1),
00568                                      Column::FixedStringColumn(HASH_SIZE, 1));
00569         Table::Read(mFrames, &buf);
00570         ILOG_INFO("Read " << mFrames->Size() << " frames from file");
00571 
00572         bool oldScanDataPresent = mScanDataPresent;
00573         mScanDataPresent = true;
00574         mNrOfFrames = mFrames->Size();
00575         mBadFrameCount = 0;
00576         mLeadingBadFrameCount = 0;
00577         for (int f = 0; f < mNrOfFrames; f++)
00578             if (!FrameIsValid(f))
00579             {
00580                 mBadFrameCount++;
00581                 if (mBadFrameCount > f)
00582                     mLeadingBadFrameCount++;
00583             }
00584         mVideoIsValid = true;
00585         mScanDataPresent = oldScanDataPresent;
00586     }
00587 
00588     void
00589     SetNrOfFrames(int count)
00590     {
00591         mNrOfFrames = count;
00592     }
00593 
00594     const VideoAccessObject* const mVao;
00595 
00596     PacketTable* mPackets;
00597     FrameTable* mFrames;
00598 
00599     int mBadFrameCount;
00600     int mLeadingBadFrameCount;
00601 
00602     bool mScanDataPresent;
00603 
00604 
00605 private:
00606 
00607     void
00608     AddFrameToTable(bool isValid, bool isKey, CString hash, 
00609         const FixedString& hashAsFixedStr)
00610     {
00611         int frameIdx = mFrames->Size();
00612         const int lastPacketEntry = mPackets->Size() - 1;
00613         mFrames->Add(frameIdx, lastPacketEntry, isValid, isKey, 
00614             hashAsFixedStr);
00615     }
00616 
00617     // Caller assumes responsibility for the returned object.
00618     VideoIndex*
00619     ConstructIndexPrivate() 
00620     {
00621         VideoIndex* videoIndex = ConstructIndexProtected();
00622         if (videoIndex == 0)
00623             return 0;
00624 
00625         // disable the index' seekable entries that appear to be invalid
00626         while (!IndexValid(*videoIndex))
00627         {
00628             int failingFrameNr = mFailingKeyFrameNr;
00629             ILOG_DEBUG("Disabling invalid video index entry for frame " << 
00630                 failingFrameNr);
00631             if (!videoIndex->SetNotSeekable(failingFrameNr))
00632             {
00633                 ILOG_ERROR("Index entry could not be disabled for frame " << 
00634                     failingFrameNr);
00635                 delete videoIndex;
00636                 return 0;
00637             }
00638         }
00639 
00640         ILOG_DEBUG("Index validated");
00641 
00642         return videoIndex;
00643     }
00644 
00645     bool 
00646     IndexValid(const VideoIndex& idx) const
00647     {
00648         ILOG_DEBUG("Validating index...");
00649         return IndexValidTraversingBackwards(idx) &&
00650             IndexValidTraversingForwards(idx);
00651     }
00652     
00653     bool
00654     IndexValidTraversingBackwards(const VideoIndex& idx) const
00655     {
00656         const int startFrame = 
00657             (mFailingKeyFrameNr < 0) ? NrOfFrames() : mFailingKeyFrameNr;
00658         for (int f = startFrame; f > 0 ; )
00659             if (idx.IsSeekable(--f))
00660             {
00661                 //ResetVideoSrc();
00662                 if (!JumpValidForFrame(f, idx))
00663                 {
00664                     mFailingKeyFrameNr = f;
00665                     return false;
00666                 }
00667             }
00668         return true;
00669     }
00670 
00671     bool
00672     IndexValidTraversingForwards(const VideoIndex& idx) const
00673     {
00674         int startFrame = 0;
00675         for (int f = startFrame; f < mFailingKeyFrameNr; f++)
00676             if (idx.IsSeekable(f))
00677                 startFrame = f;
00678 
00679         ResetVideoSrc();
00680         for (int f = startFrame; f < NrOfFrames(); f++)
00681             if (idx.IsSeekable(f) && !JumpValidForFrame(f, idx))
00682             {
00683                 mFailingKeyFrameNr = f;
00684                 return false;
00685             }
00686         return true;
00687     }
00688 
00693     bool
00694     JumpValidForFrame(int frameNr, const VideoIndex& videoIndex) const
00695     {
00696         int seekableFrame = -1;
00697         UInt64 seekTarget = -1;
00698         videoIndex.GetSeekInfo(frameNr, &seekableFrame, &seekTarget);
00699         static const bool MUST_BE_KEY = true;
00700         const int flushMode = 2; // flush (if applies) after the jump
00701         Jump(seekTarget, GetJumpFlags(), MUST_BE_KEY, flushMode);
00702         mVao->CurrentFrameToRgb();
00703         if (!CurrentFrameMatchesFrame(seekableFrame))
00704         {
00705             ILOG_DEBUG("Index failed for (seekable) frame " << frameNr);
00706             return false;
00707         }
00708         ILOG_DEBUG("Jump validated for (seekable) frame " << frameNr);
00709 
00710         // now read sequentially some frames and validate these as well
00711         bool includedOneSeekable = false;
00712         while (++frameNr < NrOfFrames())
00713         {
00714             if (videoIndex.IsSeekable(frameNr))
00715                 if (includedOneSeekable)
00716                     break;
00717                 else
00718                     includedOneSeekable = true;
00719 
00720             if (!NextFrameMatchesFrame(frameNr, videoIndex))
00721                 return false;
00722         }
00723 
00724         return true;
00725     }
00726 
00741     bool
00742     PacketTraceMatchesFrame(const PacketTrace& trace, int frameNr) const
00743     {
00744         const int nrOfFrames = mFrames->Size();
00745         if (frameNr < 0 || frameNr >= nrOfFrames)
00746             return false;
00747 
00748         //if (!FrameIsKey(frameNr))
00749         //    return false;
00750 
00751         const int traceLen = trace.Size();
00752 
00753         int nrOfVideoPackets = 0;
00754         for (int t = 0; t < traceLen; t++)
00755             if (trace.Get4(t))
00756                 nrOfVideoPackets++;
00757         int nrOfNonVideoPackets = traceLen - nrOfVideoPackets;
00758 
00759         int packetIdx = mFrames->Get2(frameNr);
00760         for (int t = traceLen - 1; t >= 0; t--)
00761         {
00762             if (packetIdx < 0)
00763                 return false;
00764 
00765             const int sizeFromPackets = mPackets->Get2(packetIdx);
00766             const int sizeFromTrace = trace.Get1(t);
00767             const int flagsFromPackets = mPackets->Get3(packetIdx);
00768             const int flagsFromTrace = trace.Get2(t);
00769             bool sizeAndFlagsMatch = 
00770                 (sizeFromPackets == sizeFromTrace &&
00771                 flagsFromPackets == flagsFromTrace);
00772 
00773             if (trace.Get4(t)) // from video stream?
00774             {
00775                 if (--nrOfVideoPackets <= 0)
00776                     sizeAndFlagsMatch = true;
00777             }
00778             else
00779                 if (--nrOfNonVideoPackets <= 0)
00780                     sizeAndFlagsMatch = true;
00781 
00782             if (!sizeAndFlagsMatch)
00783             {
00784                 ILOG_DEBUG("Size and/or flags don't match at trace pos " << t << 
00785                     " of " << traceLen << " : " << sizeFromPackets <<
00786                     " vs. " << sizeFromTrace << " ; " << flagsFromPackets <<
00787                     " vs. " << flagsFromTrace);
00788                 return false;
00789             }
00790 
00791             packetIdx--;
00792 
00793             // SK: trace matching appears not to be trivial; use only last trace entry 
00794             break; 
00795         }
00796 
00797         // test match for post-read file position 
00798         packetIdx = mFrames->Get2(frameNr);
00799         const UInt64 postReadPosOfFrame = mPackets->Get4(packetIdx);
00800         const UInt64 lastPosOfTrace = trace.Get3(traceLen - 1);
00801         if (lastPosOfTrace > postReadPosOfFrame)
00802         {
00803             // locate next key frame
00804             int nextKeyFrame = frameNr + 1;
00805             for ( ; nextKeyFrame < nrOfFrames; nextKeyFrame++)
00806                 if (mFrames->Get4(nextKeyFrame)) // is key frame?
00807                     break; 
00808             if (nextKeyFrame >= nrOfFrames) 
00809                 return true; // assume a match if no more key frames
00810 
00811             // check current (post-read) file position against 
00812             // post-read-position of next key frame
00813             packetIdx = mFrames->Get2(nextKeyFrame);
00814             const UInt64 nextKeyFramesFilePos = mPackets->Get4(packetIdx);
00815             if (lastPosOfTrace > nextKeyFramesFilePos)
00816                 return false;
00817         }
00818 
00819         return true;
00820     }
00821 
00822 
00823     bool mVideoIsValid;
00824     int mNrOfFrames;
00825     mutable int mFailingKeyFrameNr;
00826 
00827     ILOG_VAR_DECL;
00828 
00829 }; //class
00830 
00831 ILOG_VAR_INIT(VideoAccessStrategy, Impala.Core.Stream.Lavc);
00832 
00833 const String VideoAccessStrategy::INVALID_FRAME_HASH =  "INVALID_FRAME___________________";
00834 const String VideoAccessStrategy::UNSTABLE_FRAME_HASH = "UNSTABLE_FRAME__________________";
00835 
00836 }}}} // namespace Impala::Core::Stream::Lavc
00837 
00838 #endif

Generated on Thu Jan 13 09:04:35 2011 for ImpalaSrc by  doxygen 1.5.1