00001 #ifndef Impala_Core_VideoSet_ExportStills_h
00002 #define Impala_Core_VideoSet_ExportStills_h
00003
00004 #include "Persistency/ImageSetRepository.h"
00005 #include "Persistency/StillsRepository.h"
00006 #include "Core/VideoSet/Reporter.h"
00007 #include "Core/VideoSet/Segmentation.h"
00008 #include "Core/VideoSet/Stills.h"
00009 #include "Core/ImageSet/MakeImageSet.h"
00010 #include "Core/Array/Set.h"
00011 #include "Core/Array/Scale.h"
00012 #include "Core/Array/WriteRaw.h"
00013 #include "Core/Array/WriteJpg.h"
00014 #include "Core/Array/ArrayListDelete.h"
00015 #include "Link/DiskImage/DiskImageFuncs.h"
00016
00017 namespace Impala
00018 {
00019 namespace Core
00020 {
00021 namespace VideoSet
00022 {
00023
00024
00025 class ExportStills : public Listener
00026 {
00027 public:
00028 typedef Array::Array2dVec3UInt8 Array2dVec3UInt8;
00029 typedef Array::Array2dScalarUInt8 Array2dScalarUInt8;
00030
00031 ExportStills(Reporter* reporter, CmdOptions& options)
00032 {
00033 mReporter = reporter;
00034 mImSet = 0;
00035 mStills = 0;
00036 mSkipFr = 15;
00037 mNrIm = 16;
00038 mDoFullSize = true;
00039 mBufSize = 1000000;
00040 mBuf = new char[mBufSize];
00041 mNr = 0;
00042 mDoDef = false;
00043 mDoData = false;
00044 if (options.GetNrArg() < 3)
00045 {
00046 ILOG_ERROR("Need argument [def|data]");
00047 }
00048 else
00049 {
00050 if (options.GetArg(2) == "def")
00051 mDoDef = true;
00052 else if (options.GetArg(2) == "data")
00053 mDoData = true;
00054 else
00055 {
00056 ILOG_ERROR("Argument should be def or data");
00057 }
00058 if (options.GetNrArg() > 3)
00059 Core::Array::gWriteJpgQuality = atol(options.GetArg(3));
00060 }
00061 }
00062
00063 virtual
00064 ~ExportStills()
00065 {
00066 delete mBuf;
00067 }
00068
00069 virtual void
00070 HandleNewWalk(VideoSet* vs)
00071 {
00072 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00073 mSegmentation = new Segmentation(vs, "segmentation");
00074 #else // REPOSITORY_USED
00075 Persistency::SegmentationLocator loc(vs->GetLocator(), "segmentation");
00076 mSegmentation = Persistency::SegmentationRepository().Get(loc, vs);
00077 #endif // REPOSITORY_USED
00078 ILOG_INFO(mSegmentation->GetNrShots() << " shots");
00079 String name("stills.txt");
00080 mImSetLoc = Persistency::ImageSetLocator(vs->GetLocator(), name);
00081 mStillsLoc = Persistency::StillsLocator(vs->GetLocator(), "stills");
00082
00083 if (mDoDef)
00084 {
00085 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00086 mImSet = new ImageSet::ImageSet(vs->GetDatabase(), name, false);
00087 #else // REPOSITORY_USED
00088 mImSet = new ImageSet::ImageSet(name);
00089 #endif // REPOSITORY_USED
00090 mStills = new Stills(vs, "");
00091 }
00092 if (mDoData)
00093 {
00094 ILOG_INFO("reading image set " << name);
00095 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00096 mImSet = new ImageSet::ImageSet(vs->GetDatabase(), name, true);
00097 mStills = new Stills(vs, "stills");
00098 #else // REPOSITORY_USED
00099 mImSet = Persistency::ImageSetRepository().Get(mImSetLoc);
00100 mStills = Persistency::StillsRepository().Get(mStillsLoc, vs);
00101 #endif // REPOSITORY_USED
00102 ILOG_INFO("reading stills");
00103 ILOG_INFO(mStills->GetNrStills() << " stills");
00104 if (mImSet->NrDirs() != vs->NrFiles())
00105 {
00106 ILOG_WARN("Number of still dirs doesn't match number of videos: "
00107 << mImSet->NrDirs() << " vs. " << vs->NrFiles());
00108 }
00109 }
00110 mTimer.Start();
00111 }
00112
00113 virtual void
00114 HandleNewFile(VideoSet* vs, int fileId, Stream::RgbDataSrc* src)
00115 {
00116 std::vector<Array2dScalarUInt8*> imList;
00117 String dbSec(FileNameBase(vs->GetSetName()) + "_stills");
00118 String dbDir = vs->GetFile(fileId);
00119 String dirOfFile = vs->GetDirOfFile(fileId);
00120
00121 if (Link::DiskImage::DiskImageUsed())
00122 {
00123 dbSec = vs->GetAsPath(fileId);
00124 int posSep = dbSec.find_last_of('/');
00125 dbSec = "stills/" + dbSec.substr(0, posSep);
00126 }
00127 else
00128 {
00129 dbSec = "stills/" + vs->GetSectionOfFile(fileId) + "/" + dirOfFile;
00130 }
00131
00132 int firstS = mSegmentation->GetFirstShotVideo(fileId);
00133 int lastS = firstS + mSegmentation->GetNrShotsVideo(fileId);
00134 for (int shot=firstS ; shot<lastS ; shot++)
00135 {
00136 int startF = mSegmentation->GetStart(shot);
00137 int endF = mSegmentation->GetEnd(shot);
00138 int interval = (endF - startF) / (mNrIm - 1);
00139 if (interval < mSkipFr)
00140 interval = mSkipFr;
00141 ILOG_DEBUG("Doing shot " << shot << " from " << startF << " to "
00142 << endF << " interval " << interval);
00143 if (mDoData && (interval < 100))
00144 src->SetInterval(interval);
00145
00146 int i=0;
00147 while (startF <= endF)
00148 {
00149 if (mDoData)
00150 {
00151 ILOG_DEBUG("Doing frame " << startF);
00152 src->GotoFrame(startF);
00153 Array2dVec3UInt8* im = Array::ArrayCreate<Array2dVec3UInt8>
00154 (src->FrameWidth(), src->FrameHeight(), 0, 0,
00155 src->DataPtr(), true);
00156 Array2dVec3UInt8* sc = 0;
00157 if (mDoFullSize)
00158 Array::Set(sc, im);
00159 else
00160 Array::Scale(sc, im, 0.5, 0.5, Geometry::NEAREST, true);
00161
00162 size_t nrBytes = 0;
00163 Array::WriteJpgToMemory(sc, mBuf, mBufSize, &nrBytes);
00164 delete sc;
00165 delete im;
00166
00167 Array2dScalarUInt8* jpgData =
00168 Array::MakeFromData<Array2dScalarUInt8>((UInt8*) mBuf,
00169 nrBytes, 1);
00170 imList.push_back(jpgData);
00171 }
00172 if (mDoDef)
00173 {
00174 String name(FileNameCtor("shot", fileId, shot, i++, ".jpg"));
00175 mImSet->AddFile(name, dbSec, dbDir);
00176 mStills->Add(fileId, shot, startF, name);
00177 }
00178 startF += interval;
00179 }
00180
00181 if (mDoData && (mNr % 100 == 0))
00182 ILOG_INFO("Did " << mNr + 1 << " shots in "
00183 << mTimer.SplitTime() << " sec");
00184 mNr++;
00185 }
00186
00187 if (!mDoData)
00188 return;
00189
00190 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00191 int id = mImSet->GetFirstFileId(fileId);
00192 String fName = mImSet->GetFilePathImageArchive(id, "images.raw",
00193 true, false);
00194 if (! fName.empty())
00195 {
00196 Array::WriteRawListVar(imList, fName, mImSet->GetDatabase(), true,
00197 true);
00198 }
00199 else
00200 {
00201 ILOG_ERROR("unable to write to " << fName);
00202 }
00203 #else // REPOSITORY_USED
00204 String container = mImSet->GetContainerDir(fileId);
00205 Persistency::ImageArchiveLocator loc(vs->GetLocator(), false,
00206 container, "images.raw", 0);
00207 Array::ImageArchiveMemory wrapper(&imList);
00208 Persistency::ImageArchiveRepository().Add(loc, &wrapper);
00209 #endif // REPOSITORY_USED
00210 Array::ArrayListDelete(&imList);
00211 }
00212
00213 virtual void
00214 HandleDoneWalk(VideoSet* vs)
00215 {
00216 if (mDoDef)
00217 {
00218 bool binary = true;
00219 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00220 mStills->Save("stills", binary);
00221 mImSet->SaveImageSet();
00222 #else // REPOSITORY_USED
00223 Persistency::StillsRepository().Add(mStillsLoc, mStills);
00224 Persistency::ImageSetRepository().Add(mImSetLoc, mImSet);
00225 #endif // REPOSITORY_USED
00226 }
00227 }
00228
00229 private:
00230
00231 Reporter* mReporter;
00232 Persistency::ImageSetLocator mImSetLoc;
00233 ImageSet::ImageSet* mImSet;
00234 Segmentation* mSegmentation;
00235 Persistency::StillsLocator mStillsLoc;
00236 Stills* mStills;
00237
00238 int mSkipFr;
00239 int mNrIm;
00240 bool mDoFullSize;
00241 int mBufSize;
00242 char* mBuf;
00243 bool mDoDef;
00244 bool mDoData;
00245
00246 int mNr;
00247 Timer mTimer;
00248
00249 ILOG_VAR_DEC;
00250 };
00251
00252 ILOG_VAR_INIT(ExportStills, Impala.Core.VideoSet);
00253
00254 }
00255 }
00256 }
00257
00258 #endif