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

StrategyUsingNativeIndex.h

Go to the documentation of this file.
00001 #ifndef Impala_Core_Stream_Lavc_StrategyUsingNativeIndex_h
00002 #define Impala_Core_Stream_Lavc_StrategyUsingNativeIndex_h
00003 
00004 #include "Core/Stream/Lavc/VideoAccessStrategy.h"
00005 #include "Core/Stream/Lavc/VideoIndex.h"
00006 
00007 namespace Impala
00008 {
00009 namespace Core
00010 {
00011 namespace Stream
00012 {
00013 namespace Lavc
00014 {
00015 
00016 class StrategyUsingNativeIndex : public VideoAccessStrategy
00017 {
00018 
00019 public:
00020 
00021     StrategyUsingNativeIndex(const Lavc::VideoAccessObject* const vao) 
00022         : VideoAccessStrategy(vao)
00023     {
00024         SetNrOfFrames(vao->NativeIndexSize());
00025 
00026         ILOG_DEBUG("Applying video access strategy using libavcodec's " <<
00027             "native frame index, measuring in PTS");
00028     }
00029 
00030     virtual bool
00031     FrameCanBeRead(int frameNr) const
00032     {
00033         // frames recognized by lavc to be bad, can not be read
00034         return !FrameIsBadInNativeIndex(frameNr);
00035     }
00036 
00037 
00038 protected:
00039 
00040     virtual int
00041     GetJumpFlags() const
00042     {
00043         //return AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD;
00044         return AVSEEK_FLAG_ANY;
00045     }
00046 
00047     virtual bool
00048     ScanProtected()
00049     {
00050         const AVIndexEntry* const nativeIndex = mVao->NativeIndexEntries();
00051         const int nativeIndexSize = mVao->NativeIndexSize();
00052         ILOG_INFO("Native index has size " << nativeIndexSize);
00053 
00054 
00055         // debug logging
00056         int offset = 0;
00057         for (int e = offset; e <= offset + 10 && e <= nativeIndexSize; e++)
00058             ILOG_DEBUG("index entry " << e << ": size=" << 
00059             nativeIndex[e].size << ", flags=" << nativeIndex[e].flags << 
00060             ", timestamp=" << nativeIndex[e].timestamp << ", pos=" << 
00061             nativeIndex[e].pos << ", min_distance=" << 
00062             nativeIndex[e].min_distance << ")"); 
00063 
00064 
00065         int nrOfBadFrames = 0;
00066         int nrOfLeadingBadFrames = 0;
00067         for (int indexPos = 0; indexPos < nativeIndexSize; indexPos++)
00068         //int debugMax = 320;
00069         //for (int indexPos = 0; indexPos < debugMax; indexPos++)
00070         //for (int indexPos = nativeIndexSize - 1; indexPos >= 0; indexPos--)
00071         {
00072             if (indexPos % 250 == 0)
00073                 ILOG_DEBUG("Scanning using native index entry " << indexPos);
00074 
00075             const int indexFlags = nativeIndex[indexPos].flags;
00076             const bool isKeyFrameAccToIndex = (indexFlags == AVINDEX_KEYFRAME);
00077 
00078             if (FrameIsBadInNativeIndex(indexPos))
00079             {
00080                 // don't attempt reading the frame since it cannot be 'seen'
00081                 ProcessFrame(false, false, indexPos);
00082                 nrOfBadFrames++;
00083                 if (indexPos < nrOfBadFrames)
00084                     nrOfLeadingBadFrames++;
00085                 continue;
00086             }
00087 
00088             if (isKeyFrameAccToIndex)
00089             {
00090                 const UInt64& pts = nativeIndex[indexPos].timestamp;
00091                 if (!mVao->Seek(pts, AVSEEK_FLAG_ANY))
00092                 {
00093                     ILOG_ERROR("Failed on PTS based seek for frame " << 
00094                         indexPos << "; native index flags: " << indexFlags << ")");
00095                     return false;
00096                 }
00097             }
00098 
00099             //bool isValidFrame = false; // value not used
00100             //bool isKeyFrame = false;  // value not used
00101             bool isValidFrame = true;
00102             bool isKeyFrame = isKeyFrameAccToIndex;
00103             //const int result = mVao->DecodeNextFrame(&isValidFrame, &isKeyFrame);
00104             //if (result < 0)
00105             //{
00106             //    ILOG_DEBUG("Frame " << indexPos << " is invalid");
00107             //    EvalFrame(false, false);
00108             //    continue;
00109             //}
00110             if (!DecodeNextValidFrame(isKeyFrameAccToIndex, 0))
00111             {
00112                 ILOG_ERROR("Failed to read valid frame " << indexPos);
00113                 return false;
00114             }
00115             if (!isKeyFrameAccToIndex && mVao->FrameIsKey())
00116             {
00117                 ILOG_WARN("Frame read is a key frame but not expected to be: " <<
00118                     indexPos);
00119                 //return false;
00120             }
00121 
00122             if (isValidFrame)
00123             {
00124                 if (isKeyFrameAccToIndex && !isKeyFrame)
00125                 {
00126                     ILOG_ERROR("Key frame " << indexPos << 
00127                         " according to native index, appears not to be " << 
00128                         "a key frame upon decoding");
00129                     return false;
00130                 }
00131 
00132                 if (!isKeyFrameAccToIndex && isKeyFrame)
00133                 {
00134                     ILOG_ERROR("Non-key frame " << indexPos << 
00135                         " according to native index, appears to be " << 
00136                         "a key frame upon decoding");
00137                     return false;
00138                 }
00139             }
00140 
00141             ProcessFrame(isValidFrame, isKeyFrame, indexPos);
00142         }
00143 
00144         ILOG_DEBUG("Bad frames according to native index: " << 
00145             nrOfBadFrames << " (of which are " <<
00146             "leading: " << nrOfLeadingBadFrames << ")");
00147         mBadFrameCount = nrOfBadFrames;
00148         mLeadingBadFrameCount = nrOfLeadingBadFrames;
00149         return true;
00150     }
00151 
00157     virtual VideoIndex*
00158     ConstructIndexProtected() const
00159     {
00160         const AVIndexEntry* const idx = mVao->NativeIndexEntries();
00161         const int nativeIndexSize = mVao->NativeIndexSize();
00162         VideoIndex* videoIndex = new VideoIndex();
00163 
00164         //const static int MAX_SEEKABLE_FRAME_DISTANCE = 15;
00165         //int currentDistance = 0;
00166         int prevSeekableFrame = -1;
00167         for (int frameNr = 0; frameNr < nativeIndexSize; frameNr++)
00168         //int debugMax = 50;
00169         //for (int frameNr = 0; frameNr < debugMax; frameNr++)
00170         {
00171             // note that currently the external index may be bypassed when
00172             // navigating to a frame; but for PTS this may not work because
00173             // certain invalid frames will not be 'seen' by sequential reads,
00174             // while certain valid frames will not be recognized (matched) when
00175             // reading sequentially. And so I have to introduce restrictions for
00176             // reading sequentially i.e. in ~Lavc.
00177 
00178 
00179             if (!FrameIsValid(frameNr))
00180             {
00181                 // if invalidity followed from flags or size in the index,
00182                 // I assume that the frame will not be 'seen' during sequential
00183                 // reads?!
00184 
00185                 // if invalidity followed from reading a bad frame, the frame 
00186                 // *will* be 'seen' by sequential reads.
00187 
00188                 if (idx[frameNr].size > 0 &&
00189                     ((idx[frameNr].flags | AVINDEX_KEYFRAME) == AVINDEX_KEYFRAME))
00190                 {
00191                     bool lookForKeyFrame = (idx[frameNr].flags == AVINDEX_KEYFRAME);
00192                     //bool foundFrame = 
00193                         //mVao->DecodeNextValidFrame(lookForKeyFrame, 0);
00194                     bool isValidFrame;
00195                     bool isKeyFrame;
00196                     int res = DecodeNextFrame(&isValidFrame, &isKeyFrame, 0);
00197                     //if (foundFrame)
00198                     if (res >= 0 && isValidFrame)
00199                     {
00200                         String hash = mVao->CurrentHash();
00201                         ILOG_WARN("Unexpectedly able to successfully read a (" << 
00202                             mVao->FrameType() << ") frame for (invalid) frame " << 
00203                             frameNr << ", having hash value " << hash <<
00204                             "; frame data will be ignored");
00205                     }
00206 
00207                     //currentDistance++;
00208                 }
00209 
00210                 continue;
00211             }
00212 
00213             const UInt64& pts = idx[frameNr].timestamp;
00214             bool isKeyFrame = FrameIsKey(frameNr);
00215             if (isKeyFrame)
00216             {
00217                 if (!mVao->Seek(pts, AVSEEK_FLAG_ANY))
00218                 {
00219                     ILOG_ERROR("Failed on PTS based seek for frame: " << 
00220                         frameNr << (isKeyFrame ? " (is key frame)" : ""));
00221                     return 0;
00222                 }
00223             }
00224 
00225             // read next frame
00226             //bool lookForKeyFrame = false;
00227             //PacketTrace trace(10);
00228             //bool foundFrame = 
00229             //    mVao->DecodeNextValidFrame(lookForKeyFrame, 0);
00230             //bool isValidFrame;
00232             //int res = mVao->DecodeNextFrame(&isValidFrame, &isKeyFrame);
00233             //if (res < 0 || !isValidFrame)
00234             //{
00235             //    ILOG_ERROR("Unexpectedly unable to successfully read frame: " << 
00236             //        frameNr);
00237             //    return 0;
00238             //}
00239             //mVao->CurrentFrameToRgb();
00240             if (!DecodeNextValidFrame(isKeyFrame, 0))
00241             {
00242                 ILOG_ERROR("Failed to read valid frame " << frameNr);
00243                 return 0;
00244             }
00245 
00246             mVao->CurrentFrameToRgb();
00247 
00248             // if not a key frame, check whether the frame is reproducable
00249             // using sequential reading from previous seekable frame
00250             //if (!mScanner.FrameIsKey(frameNr))
00251             if (!isKeyFrame)
00252             {
00253                 if (prevSeekableFrame >= 0)
00254                 {
00255                     // kijk of dit frame via seq read vanaf laatste seek reprodbr is
00256                     //if (foundFrame)
00257                     
00258                     if (CurrentFrameMatchesFrame(frameNr, 0))
00259                     {
00260                         //currentDistance++;
00261                         continue;
00262                     }
00263                     else
00264                     {
00265                         ILOG_ERROR("Non-reproducable frame: " << frameNr <<
00266                             ", current hash value is " << mVao->CurrentHash());
00267                         return 0;
00268                     }
00269                 }
00270             }
00271 
00272             if (!CurrentFrameMatchesFrame(frameNr, 0))
00273             {
00274                 ILOG_ERROR("Non-reproducable key frame: " << frameNr <<
00275                     ", current hash value is " << mVao->CurrentHash());
00276                 return 0;
00277             }
00278 
00279             // add an entry to the external index for this key frame
00280             videoIndex->AddFrame(frameNr, true, pts);
00281             ILOG_DEBUG("Indexed frame: " << frameNr << " " << 
00282                 frameNr << " " << true << " " << pts);
00283             prevSeekableFrame = frameNr;
00284             //currentDistance = 0;
00285         }
00286 
00287         return videoIndex;
00288     }
00289 
00290     virtual bool
00291     NextFrameMatchesFrame(int frameNr, const VideoIndex& videoIndex) const
00292     {
00293         return true; // already tested at index creation
00294     }
00295 
00296 
00297 private:
00298 
00299     // Returns 'true' if the specified frame is bad according to the
00300     // native index
00301     bool
00302     FrameIsBadInNativeIndex(int frameNr) const
00303     {
00304         const AVIndexEntry* const nativeIndex = mVao->NativeIndexEntries();
00305         const int indexFlags = nativeIndex[frameNr].flags;
00306         const bool isBad = (nativeIndex[frameNr].size <= 0) ||
00307             (indexFlags != 0 && indexFlags != AVINDEX_KEYFRAME);
00308         return isBad;
00309     }
00310 
00311 
00312     ILOG_VAR_DECL;
00313 
00314 }; //class
00315 
00316 ILOG_VAR_INIT(StrategyUsingNativeIndex, Impala.Core.Stream.Lavc);
00317 
00318 }}}} // namespace Impala::Core::Stream::Lavc
00319 
00320 #endif

Generated on Fri Mar 19 09:31:17 2010 for ImpalaSrc by  doxygen 1.5.1