00001 #ifndef Impala_Core_VideoSet_Keyframes_h
00002 #define Impala_Core_VideoSet_Keyframes_h
00003
00004 #include "Persistency/ImageSetRepository.h"
00005 #include "Basis/Quid.h"
00006 #include "Core/Table/MakeGroupIndex.h"
00007 #include "Core/VideoSet/VideoSet.h"
00008 #include "Core/ImageSet/ImageSet.h"
00009 #include "Core/Table/TableTem.h"
00010 #include "Core/Table/Read.h"
00011 #include "Core/Table/Write.h"
00012 #include "Core/Table/RemoveRow.h"
00013 #include "Core/Table/QuidTable.h"
00014 #include "Core/Column/Find.h"
00015 #include "Link/DiskImage/DiskImageFuncs.h"
00016
00017 namespace Impala
00018 {
00019 namespace Core
00020 {
00021 namespace VideoSet
00022 {
00023
00024
00025 typedef Table::TableTem<Column::ColumnTem<Int32>,
00026 Column::ColumnTem<Int32>,
00027 Column::ColumnTem<Int32>,
00028 Column::ColumnTem<String> > KeyframesBaseType;
00029
00030
00031 class Keyframes : public KeyframesBaseType
00032 {
00033 typedef Impala::Core::Table::GroupIndex GroupIndex;
00034
00035 public:
00036
00037 Keyframes(VideoSet* vidSet, String name) : KeyframesBaseType(0)
00038 {
00039 mVidSet = vidSet;
00040 mName = name;
00041 mVideoGroups = 0;
00042 mShotGroups = 0;
00043 SetColName(1, "videoId");
00044 SetColName(2, "shotId");
00045 SetColName(3, "frameNr");
00046 SetColName(4, "name");
00047 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00048 if (!mName.empty())
00049 Load();
00050 #else // REPOSITORY_USED
00051 if (!mName.empty())
00052 ILOG_ERROR("Load keyframes via repository");
00053 #endif // REPOSITORY_USED
00054 }
00055
00056
00057
00058 int
00059 GetNrKeyframes()
00060 {
00061 return Size();
00062 }
00063
00064 int
00065 GetVideoId(int keyId)
00066 {
00067 return Get1(keyId);
00068 }
00069
00070 int
00071 GetShotId(int keyId)
00072 {
00073 return Get2(keyId);
00074 }
00075
00076 String
00077 GetName(int keyId)
00078 {
00079 return Get4(keyId);
00080 }
00081
00082 bool
00083 IsRKF(int keyId)
00084 {
00085 return Get4(keyId).find("_RKF") != String::npos;
00086 }
00087
00088 int
00089 GetFrameNr(int keyId)
00090 {
00091 return Get3(keyId);
00092 }
00093
00094 Core::Table::QuidTable*
00095 MakeRkfTable()
00096 {
00097 Core::Table::QuidTable* quids = new Core::Table::QuidTable(0);
00098 for(int i=0 ; i<GetNrKeyframes() ; ++i)
00099 {
00100 if(IsRKF(i))
00101 quids->Add(GetQuidFrame(i));
00102 }
00103 return quids;
00104 }
00105
00106 Quid
00107 GetQuidFrame(int keyId)
00108 {
00109 return MakeQuidFrame(mVidSet->GetSetId(), GetVideoId(keyId),
00110 GetFrameNr(keyId));
00111 }
00112
00113 int
00114 GetFrameId(Quid quid)
00115 {
00116 if (QuidClass(quid) == QUID_CLASS_FRAME)
00117 {
00118 int vidId = QuidObject(quid);
00119 int frame = QuidId(quid);
00120 return GetFrameIdVideo(vidId, frame);
00121 }
00122 ILOG_ERROR("GetFrameId: Unknown quid : " << QuidObj(quid));
00123 return -1;
00124 }
00125
00126 int
00127 GetFrameId(String name)
00128 {
00129 int rank = Find(GetColumn4(), name, 0, Size());
00130 if (rank == Size())
00131 return -1;
00132 return rank;
00133 }
00134
00135
00136 int
00137 GetFrameId(int frameNr, int idxStart, int idxEnd)
00138 {
00139 int rank = Find(GetColumn3(), frameNr, idxStart, idxEnd);
00140 if (rank == idxEnd)
00141 return -1;
00142 return rank;
00143 }
00144
00145 void
00146 RemoveDuplicates()
00147 {
00148 int i=0;
00149 while (i < Size()-1)
00150 {
00151 int j = i+1;
00152 while ((Get1(i) == Get1(j)) && (Get2(i) == Get2(j)))
00153 {
00154 if (Get3(i) == Get3(j))
00155 {
00156 if (Get4(i).find("_RKF") != String::npos)
00157 {
00158 Core::Table::RemoveRow(this, j);
00159 }
00160 else
00161 {
00162 Core::Table::RemoveRow(this, i);
00163 j = i+1;
00164 }
00165 }
00166 else
00167 {
00168 j++;
00169 }
00170 }
00171 i++;
00172 }
00173 UpdateGroups();
00174 }
00175
00176 VideoSet*
00177 GetVideoSet()
00178 {
00179 return mVidSet;
00180 }
00181
00182
00183
00184 void
00185 UpdateGroups()
00186 {
00187 if (mVideoGroups == 0)
00188 {
00189 mVideoGroups = new GroupIndex(0);
00190 mVideoGroups->SetColName(1, "firstKeyframeId");
00191 mVideoGroups->SetColName(2, "nrKeyframes");
00192 }
00193 MakeGroupIndex(mVideoGroups, GetColumn1(), 0, Size());
00194 if (mShotGroups == 0)
00195 {
00196 mShotGroups = new GroupIndex(0);
00197 mShotGroups->SetColName(1, "firstKeyframeId");
00198 mShotGroups->SetColName(2, "nrKeyframes");
00199 }
00200
00201 MakeGroupIndex(mShotGroups, GetColumn2(), 0, Size());
00202 }
00203
00204 int
00205 GetNrVideos()
00206 {
00207 return mVideoGroups->Size();
00208 }
00209
00210 int
00211 GetFirstKeyframeVideo(int videoId)
00212 {
00213 return mVideoGroups->Get1(videoId);
00214 }
00215
00216 int
00217 GetNrKeyframesVideo(int videoId)
00218 {
00219 return mVideoGroups->Get2(videoId);
00220 }
00221
00222 int
00223 GetFrameIdVideo(int videoId, int frameNr)
00224 {
00225 int start = GetFirstKeyframeVideo(videoId);
00226 int nr = GetNrKeyframesVideo(videoId);
00227 return GetFrameId(frameNr, start, start+nr);
00228 }
00229
00230 int
00231 GetNrShots()
00232 {
00233 return mShotGroups->Size();
00234 }
00235
00236 int
00237 GetFirstKeyframeShot(int shotId)
00238 {
00239 return mShotGroups->Get1(shotId);
00240 }
00241
00242 int
00243 GetNrKeyframesShot(int shotId)
00244 {
00245 return mShotGroups->Get2(shotId);
00246 }
00247
00248 int
00249 GetShotRKF(int shotId)
00250 {
00251 int start = GetFirstKeyframeShot(shotId);
00252 int end = start + GetNrKeyframesShot(shotId);
00253 for (int i=start ; i<end ; i++)
00254 if (IsRKF(i))
00255 return i;
00256 return start;
00257 }
00258
00259
00260
00261 int
00262 Diff(Keyframes* arg)
00263 {
00264 if (GetNrKeyframes() != arg->GetNrKeyframes())
00265 {
00266 ILOG_ERROR("Diff: nrKeyframes differs: " << GetNrKeyframes() <<
00267 " vs " << arg->GetNrKeyframes());
00268 return 1;
00269 }
00270 int nDiff = 0;
00271 for (int i=0 ; i<GetNrKeyframes() ; i++)
00272 {
00273 if (GetVideoId(i) != arg->GetVideoId(i))
00274 {
00275 ILOG_DEBUG("Id " << i << " differs " << GetVideoId(i) <<
00276 " vs " << arg->GetVideoId(i));
00277 nDiff++;
00278 }
00279 else if (GetShotId(i) != arg->GetShotId(i))
00280 {
00281 ILOG_DEBUG("ShotId " << i << " differs " << GetShotId(i) <<
00282 " vs " << arg->GetShotId(i));
00283 nDiff++;
00284 }
00285 else if (GetFrameNr(i) != arg->GetFrameNr(i))
00286 {
00287 ILOG_DEBUG("FrameNr " << i << " differs " << GetFrameNr(i) <<
00288 " vs " << arg->GetFrameNr(i));
00289 nDiff++;
00290 }
00291 else if (GetName(i) != arg->GetName(i))
00292 {
00293 ILOG_DEBUG("Name " << i << " differs " << GetName(i) <<
00294 " vs " << arg->GetName(i));
00295 nDiff++;
00296 }
00297 }
00298 if (nDiff > 0)
00299 ILOG_ERROR("Found " << nDiff << " differences");
00300 return nDiff;
00301 }
00302
00303
00304
00305 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00306 void
00307 Load()
00308 {
00309 String fName = mVidSet->GetFilePathVideoIndex("", mName + ".tab",
00310 false, false);
00311 Read(this, fName, mVidSet->GetDatabase());
00312 UpdateGroups();
00313 }
00314
00315 void
00316 Save(String name, bool binary)
00317 {
00318 if (!name.empty())
00319 mName = name;
00320 String fName = mVidSet->GetFilePathVideoIndex("", mName + ".tab",
00321 true, false);
00322 Write(this, fName, mVidSet->GetDatabase(), binary);
00323 }
00324
00325 void
00326 Update(String name)
00327 {
00328 if (!name.empty())
00329 mName = name;
00330 String fName = mVidSet->GetFilePathVideoIndex("", mName + ".tab",
00331 true, true);
00332 if (fName.empty())
00333 fName = mVidSet->GetFilePathVideoIndex("", mName + ".tab",
00334 false, false);
00335 Write(this, fName, mVidSet->GetDatabase(), true);
00336 }
00337 #endif // REPOSITORY_USED
00338
00339 void
00340 WriteImageSets(bool writeIsUpdate = false)
00341 {
00342 UpdateGroups();
00343 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00344 ImageSet::ImageSet keySet(mVidSet->GetDatabase(), "keyframes.txt", false);
00345 ImageSet::ImageSet thumbSet(mVidSet->GetDatabase(), "thumbnails.txt", false);
00346 #else // REPOSITORY_USED
00347 ImageSet::ImageSet keySet("keyframes.txt");
00348 ImageSet::ImageSet thumbSet("thumbnails.txt");
00349 #endif // REPOSITORY_USED
00350 for (int s=0 ; s<GetNrShots() ; s++)
00351 {
00352 int start = GetFirstKeyframeShot(s);
00353 int end = start + GetNrKeyframesShot(s);
00354
00355
00356 int vid = Get1(start) - Get1(0);
00357 String vidName = mVidSet->GetFile(vid);
00358 String vidSec = mVidSet->GetSectionOfFile(vid);
00359 String vidDir = mVidSet->GetDirOfFile(vid);
00360
00361 String keySec = "keyframes/";
00362 if (Link::DiskImage::DiskImageUsed())
00363 {
00364 String videoPath = mVidSet->GetAsPath(vid);
00365 int posSep = videoPath.find_last_of('/');
00366 keySec += videoPath.substr(0, posSep);
00367 }
00368 else
00369 {
00370 keySec += vidSec + "/" + vidDir;
00371 }
00372
00373 String thumbSec = StringReplace(keySec, "keyframes", "thumbnails");
00374 for (int k=start ; k<end ; k++)
00375 {
00376 keySet.AddFile(Get4(k), keySec, vidName);
00377 thumbSet.AddFile(Get4(k), thumbSec, vidName);
00378 }
00379 }
00380 if (writeIsUpdate)
00381 {
00382 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00383 keySet.UpdateImageSet();
00384 thumbSet.UpdateImageSet();
00385 #else // REPOSITORY_USED
00386 ILOG_ERROR("WriteImageSets: Update not implemented yet");
00387 #endif // REPOSITORY_USED
00388 }
00389 else
00390 {
00391 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00392 keySet.SaveImageSet();
00393 thumbSet.SaveImageSet();
00394 #else // REPOSITORY_USED
00395 Persistency::ImageSetLocator keyLoc(mVidSet->GetLocator(),
00396 "keyframes.txt");
00397 Persistency::ImageSetRepository().Add(keyLoc, &keySet);
00398 Persistency::ImageSetLocator thumbLoc(mVidSet->GetLocator(),
00399 "thumbnails.txt");
00400 Persistency::ImageSetRepository().Add(thumbLoc, &thumbSet);
00401 #endif // REPOSITORY_USED
00402 }
00403 }
00404
00405 void
00406 DumpGroups()
00407 {
00408 mVideoGroups->Dump();
00409 mShotGroups->Dump();
00410 }
00411
00412 private:
00413
00414 VideoSet* mVidSet;
00415 String mName;
00416 GroupIndex* mVideoGroups;
00417 GroupIndex* mShotGroups;
00418
00419 ILOG_VAR_DEC;
00420
00421 };
00422
00423 ILOG_VAR_INIT(Keyframes, Impala.Core.VideoSet);
00424
00425 }
00426 }
00427 }
00428
00429 #endif