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

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