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

RgbDataSrcInfo.h

Go to the documentation of this file.
00001 #ifndef Impala_Core_Stream_RgbDataSrcInfo_h
00002 #define Impala_Core_Stream_RgbDataSrcInfo_h
00003 
00004 #include "Basis/FileName.h"
00005 #include "Basis/ILog.h"
00006 #include "Basis/Timer.h"
00007 #include "Util/StringParser.h"
00008 #include "Util/Database.h"
00009 #include "Util/IOBuffer.h"
00010 #include "Core/Stream/RgbDataSrc.h"
00011 #include "Core/Table/TableTem.h"
00012 #include "Core/Table/Write.h"
00013 #include "Core/Table/Read.h"
00014 #include "Core/Column/ColumnTem.h"
00015 #include "Core/Column/FixedStringColumn.h"
00016 
00017 namespace Impala
00018 {
00019 namespace Core
00020 {
00021 namespace Stream
00022 {
00023 
00024 
00025 class RgbDataSrcInfo : public RgbDataSrc
00026 {
00027     // frame nr | preceeding key frame nr | preceeding key frame position | frame hash
00028     typedef Table::TableTem<Column::ColumnTem<Int32>,
00029                             Column::ColumnTem<Int32>,
00030                             Column::ColumnTem<UInt64>,
00031                             Column::FixedStringColumn > IndexTableType;
00032 
00033     typedef Column::FixedStringColumn::ColElemType FixedString;
00034 
00035     static const int HASH_SIZE = 32;
00036 
00037 public:
00038 
00039     static const String DUMMY_FRAME_HASH;
00040     static const String MISSING_FRAME_HASH;
00041 
00042 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00043     RgbDataSrcInfo(int src, CString srcName, Util::Database* db,
00044                    CString infoName = "", bool newImpl = false) 
00045         : RgbDataSrc(src, srcName), mDb(db)
00046     {
00047 #else // REPOSITORY_USED
00048     RgbDataSrcInfo(int src, const Persistency::RgbDataSrcLocator& loc, 
00049                    CString infoName = "", bool newImpl = false) 
00050         : RgbDataSrc(src, loc.GetName())
00051     {
00052         String srcName = loc.GetName();
00053         mLoc = loc;
00054 #endif // REPOSITORY_USED
00055         mNewImpl = newImpl;
00056 
00057         //Determine the Info file path
00058         if (infoName.empty())
00059         {
00060 #ifdef USE_IFILE
00061             int posAfterProtocol = srcName.find(":") + 1;
00062             mInfoPath = srcName.substr(posAfterProtocol) + ".info";
00063 #else
00064             mInfoPath = srcName + ".info";
00065 #endif
00066         }
00067         else
00068             mInfoPath = infoName;
00069 
00070         InitInfo();
00071 
00072         // SK: Note that the following lines use 'magic numbers' in stead
00073         // of using corresponding symbolic constants from RgbDataSrcFactory 
00074         // which would create a mutual dependency between the two classes.
00075         // To be refactored.
00076         if ((src == 18) || (src == 19))
00077             ReadInfo();
00078         if (src == 19)
00079             DumpIndex();
00080     }
00081     
00082     //RgbDataSrcInfo(String InfoPath) 
00083     //    : RgbDataSrc(0,"RgbDataSrcInfo")
00084     //{
00085     //    mInfoPath=InfoPath;
00086     //    InitInfo();
00087     //}
00088 
00089     virtual
00090     ~RgbDataSrcInfo()
00091     {
00092         delete mIndex;
00093     }
00094 
00095     virtual bool
00096     ReadFrameData() = 0;
00097 
00098     virtual bool
00099     CurIsIFrame()
00100     {
00101         int f = FrameNr();
00102         return GetSeekableFrame(f) == f;
00103     }
00104 
00105     virtual bool
00106     Valid() const
00107     {
00108         return true;
00109     }
00110 
00111     Int64
00112     DumpHashValue(char* &buffer, const int maxChars, int bytesWritten, 
00113         CString hash) const
00114     {
00115         const int hashLen = hash.size();
00116         if (bytesWritten + hashLen + 1 > maxChars) // add 1 for '\t'
00117         {
00118             ILOG_ERROR("Buffer too small (" << maxChars << 
00119                 ") to write all index hashes");
00120             return -1;
00121         }
00122         sprintf(buffer, "%s\t", hash.c_str());
00123         buffer += (hashLen + 1);
00124         int written = bytesWritten + (hashLen + 1);
00125         return written;
00126     }
00127 
00128     Int64 
00129     DumpIndexHashes(char* buffer, const int maxChars) const
00130     {
00131         const int nrOfIndexedFrames = mIndex->Size();
00132         const int maxFrameNr = mIndex->Get1(nrOfIndexedFrames - 1);
00133 
00134         int indx = 0;
00135         Int64 bytesWritten = 0;
00136         int frameNr = 0;
00137         while (indx < nrOfIndexedFrames)
00138         {
00139             String hash;
00140             const int frameNrFromIndexEntry = mIndex->Get1(indx);
00141             if (frameNr < frameNrFromIndexEntry)
00142             {
00143                 ILOG_WARN("Index contains no entry for frame #" << frameNr);
00144                 hash = MISSING_FRAME_HASH;
00145             }
00146             else
00147             {
00148                 if (frameNr > frameNrFromIndexEntry)
00149                 {
00150                     ILOG_ERROR("[DumpIndexHashes] Index contains inconsistency for frame #" << 
00151                         frameNrFromIndexEntry << " at table position " << indx <<
00152                         "  (zero based)");
00153                 }
00154                 const String hash32(mIndex->Get4(indx).GetData(), HASH_SIZE);
00155                 hash = String(hash32.c_str()); // (dummy) hashes may be shorter
00156                 indx++;
00157             }
00158             bytesWritten = DumpHashValue(buffer, maxChars, bytesWritten, hash);
00159             if (bytesWritten < 0)
00160                 return -1;
00161             frameNr++;
00162         }
00163         return bytesWritten;
00164     }
00165 
00166 protected:
00167 
00168     String
00169     ReplaceWhite(String result)
00170     {
00171         String replaceWhat=" ";
00172         String replaceWithWhat="_";
00173         while(1)
00174         {
00175             const int pos = result.find(replaceWhat);
00176             if (pos==-1)
00177                 break;
00178             result.replace(pos,replaceWhat.size(),replaceWithWhat);
00179         }
00180         if(result=="")
00181         {
00182             ILOG_DEBUG("String was empty, resetting to _");
00183             result="_";
00184         }
00185         return result;
00186 
00187     }
00188 
00189     String 
00190     GetInfoFilePath(bool toWrite, bool silent=true) const
00191     {
00192         return mInfoPath;
00193     }
00194 
00195     Util::IOBuffer* 
00196     GetInfoIOBuffer(bool toWrite, bool silent=true) const
00197     {
00198         String fname = GetInfoFilePath(toWrite, silent);
00199         if (fname.empty())
00200         {
00201             if (!silent)
00202                 ILOG_ERROR("Unable to determine info file name!");
00203             return 0;
00204         }
00205 
00206         //Util::IOBuffer* buf=db.GetIOBuffer(fname, !toWrite, false, "tmp");
00207         String tmpFile = (toWrite) ? "tmp" : "";
00208 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00209         Util::IOBuffer* buf = mDb->GetIOBuffer(fname, !toWrite, false, tmpFile);
00210 #else // REPOSITORY_USED
00211         typedef Persistency::RepositoryInFileSystem RepFS;
00212         Persistency::File file = RepFS::GetInstance().GetFile(mLoc, "", fname,
00213                                                               toWrite, false);
00214         Util::IOBuffer* buf = (toWrite) ? file.GetWriteBuffer()
00215                                         : file.GetReadBuffer();
00216 #endif // REPOSITORY_USED
00217 
00218         if(!buf)
00219         {
00220             ILOG_DEBUG("Invalid File! "<<mInfoPath);
00221             return 0;
00222         }
00223 
00224         if(!buf->Valid())
00225         {
00226             ILOG_DEBUG("Invalid File! "<<mInfoPath);
00227             delete buf;
00228             return 0;
00229         }
00230 
00231         return buf;
00232     }
00233 
00234     void InitInfo()
00235     {
00236         mInfoVersion = "2.2";
00237         //For now, as long as applications do not register this parameter,
00238         //the indexes will be created in place (same location as the file)
00239         mIndexInPlace = true; //options.GetBool("IndexInPlace",true);
00240 
00241         mIndex = new IndexTableType(Column::ColumnTem<Int32>(1),
00242                                   Column::ColumnTem<Int32>(1),
00243                                   Column::ColumnTem<UInt64>(1),
00244                                   Column::FixedStringColumn(HASH_SIZE, 1));
00245         mIndex->SetColName(1, "frame_nr");
00246         mIndex->SetColName(2, "key_frame_nr");
00247         mIndex->SetColName(3, "key_frame_pos");
00248         mIndex->SetColName(4, "frame_hash");
00249 
00250         mFormatStr = String(
00251                           "INFO VERSION         : ") + mInfoVersion + "\n"
00252                         + "==================================\n"
00253                         + "File name            : %s\n"
00254                         + "\n"
00255                         + "Format name          : %s\n"
00256                         + "Format name (long)   : %s\n"
00257                         + "Bit rate (bps)       : %d \n"
00258                         + "Stream count         : %d \n"
00259                         + "\n"
00260                         + "Codec name           : %s\n"
00261                         + "Codec tag            : %s\n"
00262                         + "Time base            : %d / %d \n"
00263                         + "Duration (fractions) : %lld \n"
00264                         + "Duration (seconds)   : %lld \n"
00265                         + "Duration (human)     : %lldh %lldm %llds \n"
00266                         + "\n"
00267                         + "Frame width          : %d \n"
00268                         + "Frame height         : %d \n"
00269                         + "Aspect ratio         : %d / %d \n"
00270                         + "\n"
00271                         + "Frame count          : %d \n"
00272                         + "Frame rate (fps)     : %d / %d \n"
00273                         + "GOP size             : %d \n"
00274                         + "Leading bad frames   : %d \n"
00275                         + "Bad frame ID's       : %s \n"
00276                         + "\n"
00277                         + "Index exists         : %s \n";
00278     }
00279 
00280     bool ReadInfo(bool silent = false)
00281     {
00282         ILOG_DEBUG("Reading info file");
00283         Timer timer;
00284         Util::IOBuffer* infoBuf = GetInfoIOBuffer(false, silent);
00285         if (!infoBuf)
00286         {
00287             ILOG_WARN("Reading canceled");
00288             return false;
00289         }
00290 
00291         char buf[BUFFER_SIZE];
00292         infoBuf->Read(buf, BUFFER_SIZE);
00293         char srcName[100];
00294         char formatName[30];
00295         char formatLName[100];
00296         char codecName[30];
00297         char codecTag[5];
00298         char indexExists[5];
00299         
00300         int frameCount;
00301         char badFramesList[10000];
00302         int numberOfLeadingBadFrames;
00303         int res = sscanf(buf, mFormatStr.c_str(),
00304                     srcName,
00305                     formatName,
00306                     formatLName,
00307                     &mBitRate,
00308                     &mStreamCount,
00309                     codecName,
00310                     codecTag,
00311                     &mTimeBaseNum, &mTimeBaseDen,
00312                     &mVideoDuration,
00313                     &mDuration,
00314                     &mDurationHour, &mDurationMin, &mDurationSec,
00315                     &mFrameWidth,
00316                     &mFrameHeight,
00317                     &mAspectRatioNum, &mAspectRatioDen,
00318                     &frameCount,
00319                     &mFrameRateNum, &mFrameRateDen,
00320                     &mGopSize,
00321                     &numberOfLeadingBadFrames,
00322                     badFramesList,
00323                     indexExists);
00324         if (res != 25)
00325         {
00326             ILOG_ERROR("RGB data source info format not compatible; " <<
00327                 "expected version is: " << mInfoVersion);
00328             return false;
00329         }
00330 
00331         //if (frameCount != mLastFrame + 1)
00332         //{
00333         //    ILOG_ERROR("Number of frames according to info file (" << 
00334         //        frameCount << ") does not match currently " <<
00335         //        " established frame count (" << (mLastFrame + 1) << ")");
00336         //    return false;
00337         //}
00338 
00339         //Copy the scanned data to member variables
00340         mLastFrame = frameCount - 1;
00341         mFormatName = formatName;
00342         mFormatLName = formatLName;
00343         mCodecName = codecName;
00344         mCodecTag = codecTag;
00345 
00346         SetLeadingBadFrames(numberOfLeadingBadFrames);
00347         mBadFrameNrs.clear();
00348         const String badFramesListString(badFramesList);
00349         if (badFramesListString != "none")
00350         {
00351             Util::StringParser parser(badFramesListString);
00352             while (!parser.TheEnd())
00353             {
00354                 const int frameNr = parser.GetInt(';', false, true);
00355                 MarkBadFrame(frameNr);
00356             }
00357         }
00358 
00359         if (String(indexExists) == "yes")
00360             mIndexExists = true;
00361         else
00362             mIndexExists = false;
00363 
00364         // for debug log:
00365         {
00366             StringList badFramesString;
00367             for (int i = 0; i < mBadFrameNrs.size(); i++)
00368                 badFramesString << MakeString(mBadFrameNrs[i]);
00369 
00370             sprintf(buf, mFormatStr.c_str(),
00371                         srcName,
00372                         formatName,
00373                         formatLName,
00374                         mBitRate,
00375                         mStreamCount,
00376                         codecName,
00377                         codecTag,
00378                         mTimeBaseNum, mTimeBaseDen,
00379                         mVideoDuration,
00380                         mDuration,
00381                         mDurationHour, mDurationMin, mDurationSec,
00382                         mFrameWidth,
00383                         mFrameHeight,
00384                         mAspectRatioNum, mAspectRatioDen,
00385                         mLastFrame + 1,
00386                         mFrameRateNum, mFrameRateDen,
00387                         mGopSize,
00388                         mBlankFrames,
00389                         badFramesString.ToString(';').c_str(),
00390                         indexExists);
00391             ILOG_DEBUG("\n\n" << buf);
00392         }
00393 
00394         if (mIndexExists)
00395         {   
00396             ILOG_DEBUG("Reading the index attached to info file");
00397             ILOG_DEBUG("  start read " << timer.SplitTime());
00398             Read(mIndex, infoBuf);
00399             ILOG_DEBUG("  done actual read " << timer.SplitTime());
00400             ILOG_DEBUG(mIndex->Size() << " index entries read");
00401         }
00402 
00403         delete infoBuf; 
00404         return true;
00405     }
00406 
00407     void DumpIndex()
00408     {
00409         ILOG_DEBUG("Dumping index entries:");
00410         for (int i = 0; i < mIndex->Size(); i++)
00411             ILOG_DEBUG(i << " : " << mIndex->Get1(i) << " "
00412                          << mIndex->Get2(i) << " " << mIndex->Get3(i));
00413     }
00414 
00415     void WriteInfo()
00416     {
00417         ILOG_DEBUG("Writing info file");
00418 
00419         //Open the Info file for writing
00420         Util::IOBuffer* infoBuf = GetInfoIOBuffer(true);
00421 
00422         if (!infoBuf)
00423         {
00424             ILOG_WARN("Writing canceled: if file already exists, "
00425                         << "use the --override switch; "
00426                         << "otherwise make sure the directory is writable.");
00427             return;
00428         }
00429 
00430         //Write the video information to file
00431         char buf[BUFFER_SIZE];
00432         memset(buf, 0, BUFFER_SIZE);
00433         StringList badFramesStringList;
00434         for (int i = 0; i < mBadFrameNrs.size(); i++)
00435             badFramesStringList << MakeString(mBadFrameNrs[i]);
00436         String badFramesString = badFramesStringList.ToString(';');
00437         if (badFramesString.empty())
00438             badFramesString = "none";
00439         sprintf(buf, mFormatStr.c_str(),
00440                     ReplaceWhite(FileNameTail(mSrcName)).c_str(),
00441                     ReplaceWhite(mFormatName).c_str(),
00442                     ReplaceWhite(mFormatLName).c_str(),
00443                     mBitRate,
00444                     mStreamCount,
00445                     ReplaceWhite(mCodecName).c_str(),
00446                     ReplaceWhite(mCodecTag).c_str(),
00447                     mTimeBaseNum, mTimeBaseDen,
00448                     mVideoDuration,
00449                     mDuration,
00450                     mDurationHour, mDurationMin, mDurationSec,
00451                     mFrameWidth,
00452                     mFrameHeight,
00453                     mAspectRatioNum, mAspectRatioDen,
00454                     mLastFrame + 1,
00455                     mFrameRateNum, mFrameRateDen,
00456                     mGopSize,
00457                     mBlankFrames,
00458                     badFramesString.c_str(),
00459                     (mIndexExists ? "yes" : "no") );
00460         infoBuf->Write(buf, BUFFER_SIZE);
00461 
00462         if (mIndexExists)
00463         {
00464             ILOG_DEBUG("Index exists; writing table");
00465             Write(mIndex, infoBuf, true);
00466             ILOG_DEBUG(mIndex->Size() << " index entries written");
00467         }
00468 
00469         delete infoBuf;
00470     }
00471 
00472     void 
00473     AddIndex(int fr, int key, UInt64 pos, CString hash)
00474     {
00475         if (fr != (mIndex->Size() + (mNewImpl ? 0 : mBlankFrames))) // for backw.compat.
00476             ILOG_WARN("Frame numbers mismatch " << fr << " != " << mIndex->Size());
00477         FixedString fStr(HASH_SIZE, (char*) hash.c_str(), false);
00478         mIndex->Add(fr, key, pos, fStr);
00479     }
00480 
00481     int GetSeekableFrame(int fr) const
00482     {
00483         return mIndex->Get2(fr);
00484     }
00485 
00486     void SetKey(int fr, int key)
00487     {
00488         mIndex->Set2(fr, key);
00489     }
00490 
00491     UInt64 GetPos(int fr) const
00492     {
00493         const int indexPosition = fr;
00494 
00495         if (mIndexExists)
00496         {
00497             if (indexPosition < mIndex->Size())
00498             {
00499                 if (GetHash(indexPosition) == DUMMY_FRAME_HASH)
00500                 {
00501                     ILOG_WARN("No position for invalid frame: " << fr << 
00502                         "; returning next frame's position instead");
00503                     return GetPos(fr + 1);
00504                 }
00505                 else
00506                     return mIndex->Get3(indexPosition);
00507             }
00508             else
00509                 ILOG_ERROR("Index position out of bounds: " << indexPosition);
00510         }
00511         else
00512         {
00513             ILOG_WARN("No external index available; " <<
00514                 "cannot lookup seek position for frame: " << fr);
00515             if (!mNewImpl)
00516                 return 0; // backw.compat.
00517         }
00518 
00519         return -1;
00520     }
00521 
00522     // SK: 28-05-09: To be deleted once no longer used by RgbDataSrcLavc_old
00523     int GetFrameFromHash(String hash) const
00524     {
00525         for (int i = mBlankFrames; i < mIndex->Size(); i++)
00526             if (GetHash(i) == hash)
00527                 return i;
00528 
00529         return -1;
00530     }
00531 
00532     void SetPos(int fr, UInt64 pos)
00533     {
00534         mIndex->Set3(fr, pos);
00535     }
00536 
00537     virtual String 
00538     GetHash() const
00539     {
00540         if (HasIndex())
00541             return GetHash(FrameNr());
00542         else
00543             return RgbDataSrc::GetHash();
00544     }
00545 
00546     virtual String 
00547     GetHash(int fr) const
00548     {
00549         return String(mIndex->Get4(fr).GetData(), HASH_SIZE);
00550     }
00551 
00552     // all bad frames, including leading bad frames
00553     virtual const int 
00554     BadFrames() const
00555     {
00556         return mBadFrameNrs.size();
00557     }
00558 
00559 
00560 protected:
00561 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00562     Util::Database* mDb;
00563 #endif // REPOSITORY_USED
00564     IndexTableType* mIndex;
00565 
00566 
00567     virtual bool
00568     FrameValid(int frameNr) const
00569     {
00570         if (!RgbDataSrc::FrameValid(frameNr))
00571             return false;
00572 
00573         for (int i = 0; i < mBadFrameNrs.size(); i++)
00574             if (mBadFrameNrs[i] == frameNr)
00575                 return false;
00576 
00577         return true;
00578     }
00579 
00580     bool
00581     MarkBadFrame(int frameNr)
00582     {
00583         for (int i = 0; i < mBadFrameNrs.size(); i++)
00584             if (mBadFrameNrs[i] == frameNr)
00585                 return false;
00586 
00587         mBadFrameNrs.push_back(frameNr);
00588         return true;
00589     }
00590 
00591 
00592 private:
00593 
00594     const static int BUFFER_SIZE = 100000;
00595 
00596     String     mFormatStr;
00597     String     mInfoPath;
00598     String     mInfoVersion;
00599     bool            mIndexInPlace;
00600 
00601     std::vector<int> mBadFrameNrs;
00602     Persistency::RgbDataSrcLocator mLoc;
00603 
00604     ILOG_VAR_DEC;
00605         
00606 }; // class
00607 
00608 ILOG_VAR_INIT(RgbDataSrcInfo, Impala.Core.Stream);
00609 
00610 // fixed size 32:
00611 const String RgbDataSrcInfo::DUMMY_FRAME_HASH =   "DUMMY_FRAME_HASH________________";
00612 const String RgbDataSrcInfo::MISSING_FRAME_HASH = "MISSING_FRAME_HASH______________";
00613 
00614 } // namespace
00615 } // namespace
00616 } // namespace
00617 
00618 #endif

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