00001
00002 #ifndef Impala_Visualization_RotorBrowser_RotorView_h
00003 #define Impala_Visualization_RotorBrowser_RotorView_h
00004
00005 #include "Core/Trec/ThreadSet.h"
00006 #include "Basis/CmdOptions.h"
00007 #include "Core/ImageSet/ImageSet.h"
00008 #include "Core/VideoSet/Stills.h"
00009 #include "Core/Array/Arrays.h"
00010 #include "Core/Geometry/Rectangle.h"
00011
00012 #include "Visualization/RgbOglImage.h"
00013 #include "RotorDoDView.h"
00014 #include "RotorViewCacheResolver.h"
00015
00016 namespace Impala {
00017 namespace Visualization {
00018 namespace RotorBrowser {
00019
00020
00021
00022
00023 class RotorViewListener
00024 {
00025 public:
00026 virtual void
00027 OnRectangleSelect(int shotID, float x, float y, float w, float h)
00028 {
00029 }
00030 };
00031
00032 class RotorView : public RectangleListener
00033 {
00034 public:
00035 typedef Core::Trec::Thread Thread;
00036 typedef Core::Trec::ThreadSet ThreadSet;
00037 typedef Core::Array::Array2dVec3UInt8 Array2dVec3UInt8;
00038 typedef Core::ImageSet::ImageSet CoreImageSet;
00039 typedef Core::Stream::RgbDataSrc RgbDataSrc;
00040 typedef Core::Geometry::Rectangle GeoRectangle;
00041
00042
00043
00044 RotorView(OglGui::Window *browser, ThreadSet *threadset, CString name,
00045 int nr, float x, float y, RotorViewCacheResolver* resolver=NULL)
00046 {
00047 mViewListener = NULL;
00048 mNr = nr;
00049 mName = name;
00050 mThreadSet = threadset;
00051 mTurnsNotShown = 0;
00052 mDeleteThreshold = 5;
00053 mIsBookmarked = false;
00054 mIsBookmarkedNegative = false;
00055 mUseKeyframes = RotorView::KEYFRAMES_NEVER;
00056 mAspectRatio = 1.375f;
00057 mIsHighRes = false;
00058 mCurrentRes = false;
00059 mIsShowingStills = false;
00060 mStillImages = NULL;
00061 mVideoSource = NULL;
00062 mPlayUntilEnd = false;
00063 mViewBeingRecycled = false;
00064 mViewedProbability = 0.0;
00065 mBookmarked = GetThreadByName("bookmarked");
00066 mBookmarkedNegative = GetThreadByName("bookmarked_negative");
00067 mRect = GeoRectangle(10, 10, 50, 20);
00068 mTimer = new Timer(1);
00069 mLastTime = mTimer->SplitTime();
00070 CmdOptions &options = CmdOptions::GetInstance();
00071 mUseKeyframes = options.GetInt("mdBrowserUseKeyframes");
00072
00073 if (mUseKeyframes == KEYFRAMES_ALWAYS)
00074 mCurrentRes = mIsHighRes = true;
00075
00076 mAspectRatio = (float)options.GetDouble("mdBrowserAspectRatio");
00077 mForceAspect = mAspectRatio > 0.0 ? true : false;
00078
00079 RegisterView(browser, x, y, resolver);
00080 UpdateBookmarkState();
00081 }
00082
00083 ~RotorView()
00084 {
00085 if (!mViewBeingRecycled)
00086 delete mView;
00087
00088 if (mVideoSource)
00089 delete mVideoSource;
00090 }
00091
00092 void SetViewListener(RotorViewListener *t)
00093 {
00094 mViewListener = t;
00095 }
00096
00097 Thread* GetThreadByName(CString name)
00098 {
00099 return mThreadSet->GetThreadByName(name);
00100 }
00101
00102 inline String GetName() { return mName; }
00103 inline int GetNR() { return mNr; }
00104 inline float GetX() { return mReqX; }
00105 inline float GetY() { return mReqY; }
00106 inline float GetZ() { return mReqZ; }
00107 inline float GetRX() { return mReqW; }
00108 inline float GetRY() { return mReqH; }
00109
00110 void Rename(CString newname) { mName = newname; }
00111 void SetViewedProbability(float f) { mViewedProbability = f; }
00112 void SetPlayUntilEnd(bool v) { mPlayUntilEnd = v; }
00113 void Hide() { mIsShown = false; }
00114 bool IsCurrentlyShown() { return mIsShown; }
00115 bool GetPlayUntilEnd() { return mPlayUntilEnd; }
00116 bool GetVideoStillsEnabled() { return mVideoSource != 0; }
00117
00118
00119 bool DrawView()
00120 {
00121 if (!mIsShown) return false;
00122
00123 mView->SetVisible(true);
00124 if (mIsShowingStills)
00125 UpdateStill();
00126
00127 bool stillRequiresMovement = DoPhysics();
00128
00129 OGLVIEW3D *oglV3D = mView->GetOGLVIEW3D();
00130 if (oglV3D->object3D && oglV3D->im)
00131 {
00132 OGLIMAGE* im = oglV3D->im;
00133 CheckOglImageChanged(im);
00134
00135 float tW = im->noTexScaling ? im->texW : im->w;
00136 float tH = im->noTexScaling ? im->texH : im->h;
00137 float zX = (oglV3D->w)*(tW/im->w);
00138 float zY = (oglV3D->h)*(tH/im->h);
00139 view3DSys.SetZoom(oglV3D,zX,zY);
00140
00141 float f = (oglV3D->x == 0 || oglV3D->y == 0) ? 0.15 : 0.08;
00142 float opacity = fabs(oglV3D->x * f) + fabs(oglV3D->y * f);
00143 opacity = opacity > 0.8 ? 0.8 : opacity;
00144 mView->SetObscure(opacity);
00145
00146 float a = sShowPositiveBookmarks&&mIsBookmarked ? 0.2 : 0;
00147 mView->PositiveAlpha(a);
00148 a = sShowNegativeBookmarks&&mIsBookmarkedNegative ? 0.2 : 0;
00149 mView->NegativeAlpha(a);
00150 mView->ProbabiltyAlpha(0);
00151 if (sShowProbabilityFeedback && mViewedProbability > 0)
00152 mView->ProbabiltyAlpha(mViewedProbability);
00153 }
00154 view3DSys.DrawView(oglV3D);
00155 return stillRequiresMovement | mIsShowingStills;
00156 }
00157
00158
00159 void MoveTo(float x, float y, float z, float resX =0.0f, float resY = 0.0f)
00160 {
00161 mReqX = x; mReqY = y; mReqZ = z;
00162 mReqW = resX; mReqH = resY;
00163 }
00164
00165 void MoveFrom(float x, float y, float z, float resX, float resY)
00166 {
00167 if (!mMoveNow)
00168 return;
00169 mActX = x; mActY = y; mActZ = z;
00170 mActW = resX; mActH = resY;
00171 mMoveNow = false;
00172 }
00173
00174 void MoveNOW()
00175 {
00176 mActX = mReqX; mActY = mReqY; mActZ = mReqZ;
00177 mActW = mReqW; mActH = mReqH;
00178 }
00179
00180 void SetRect(GeoRectangle r)
00181 {
00182 mRect = r;
00183 mRect.CheckSize();
00184 }
00185
00186 GeoRectangle GetRect()
00187 {
00188 return mRect;
00189 }
00190
00191 void SetShowHighResolution(bool showhighresolution)
00192 {
00193 if (mUseKeyframes == RotorView::KEYFRAMES_ALWAYS)
00194 return;
00195 mIsHighRes = showhighresolution;
00196 UpdateResolution();
00197 }
00198
00199 bool GetShowHighResolution()
00200 {
00201 return mIsHighRes;
00202 }
00203
00204 void
00205 SetShowStills(Core::VideoSet::Stills *stills, CoreImageSet* stillImages)
00206 {
00207 mIsShowingStills = true;
00208 if (mStillImages != NULL)
00209 return;
00210
00211 mStillStart = stills->GetFirstStillShot(mNr);
00212 mStillEnd = mStillStart + stills->GetNrStillsShot(mNr);
00213 mStillPos = mStillStart;
00214 mStillImages = stillImages;
00215 }
00216
00217 void DisableVideoStills()
00218 {
00219 if (mVideoSource != NULL)
00220 {
00221 delete mVideoSource;
00222 mVideoSource = NULL;
00223 }
00224 }
00225
00226 bool EnableVideoStills(Core::VideoSet::SegmentationDocument* doc)
00227 {
00228 if (mVideoSource != NULL)
00229 return true;
00230
00231 int shot = doc->CurShot();
00232 int vidId = doc->CurFileId();
00233 Core::VideoSet::Segmentation* shots = doc->GetSegmentation();
00234 ILOG_DEBUG("RotorView::EnableVideoStills: initializing video stream..");
00235 mVideoSource = doc->GetVideoSet()->GetVideo(vidId);
00236 if (!mVideoSource)
00237 return false;
00238
00239
00240 #ifdef AS_TODS_BROWSER
00241 if (!mVideoSource->HasIndex())
00242 {
00243 ILOG_WARNING("Video [" << vidId << "] has no index: Not playing");
00244 DisableVideoStills();
00245 return false;
00246 }
00247 #endif
00248 mVideoStart = shots->GetStart(shot) + 1;
00249 mVideoEnd = shots->GetEnd(shot);
00250
00251 mVideoSource->GotoFrame(mVideoStart);
00252 ILOG_DEBUG( "RotorView::EnableVideoStills: video stream ready." );
00253
00254 return true;
00255 }
00256 void SetHideStills()
00257 {
00258 mIsShowingStills = false;
00259
00260
00261 }
00262
00263 void UpdateBookmarkState()
00264 {
00265 if (mBookmarked)
00266 mIsBookmarked = mBookmarked->GetShotPosition(mNr) != -1;
00267 if (mBookmarkedNegative)
00268 mIsBookmarkedNegative=mBookmarkedNegative->GetShotPosition(mNr)!=-1;
00269 }
00270
00271 bool IsInvalid()
00272 {
00273 if (mViewBeingRecycled)
00274 {
00275 ILOG_WARN( "RotorView::IsInvalid: yes. View is being recycled!" );
00276 return true;
00277 }
00278 return !mIsShown && mTurnsNotShown > mDeleteThreshold;
00279 }
00280
00281 void Show()
00282 {
00283 if (mViewBeingRecycled)
00284 {
00285 ILOG_WARN("RotorView::Show: view is being recycled! Can't show!" );
00286 return;
00287 }
00288 mIsShown = true;
00289 if (mTurnsNotShown > 2)
00290 mMoveNow = true;
00291 mTurnsNotShown = 0;
00292 }
00293
00294 void TryDelete()
00295 {
00296 mTurnsNotShown++;
00297 if (IsInvalid())
00298 delete this;
00299 }
00300
00301 bool IsUnused()
00302 {
00303 mTurnsNotShown++;
00304 return IsInvalid();
00305 }
00306
00307 RotorDoDView* RecycleView()
00308 {
00309 mIsShown = false;
00310 mViewBeingRecycled = true;
00311 mViewedProbability = 0.0;
00312 view3DSys.SetUserData(mView->GetOGLVIEW3D(), VIEW_ROTORVIEW, NULL);
00313 return mView;
00314 }
00315
00316 bool IsSameAs(CString name, int nr)
00317 {
00318 return (mNr == nr && mName == name);
00319 }
00320
00321
00322 virtual void
00323 OnRectangleSelect(float x, float y, float w, float h)
00324 {
00325 if (mViewListener)
00326 mViewListener->OnRectangleSelect(mNr, x, y, w, h);
00327 }
00328
00329 static void SetStillFrameWait(int fw) {
00330 RotorView::sStillFrameWait = fw;
00331 }
00332 static int GetStillFrameWait() {
00333 return RotorView::sStillFrameWait;
00334 }
00335
00336 static void SetShowPositiveBookmarks(bool val) {
00337 sShowPositiveBookmarks = val;
00338 }
00339 static bool GetShowPositiveBookmarks()
00340 {
00341 return sShowPositiveBookmarks;
00342 }
00343
00344 static void SetShowNegativeBookmarks(bool val) {
00345 sShowNegativeBookmarks = val;
00346 }
00347 static bool GetShowNegativeBookmarks() {
00348 return sShowNegativeBookmarks;
00349 }
00350
00351 static void SetShowProbabilityFeedback(bool val) {
00352 sShowProbabilityFeedback = val;
00353 }
00354 static bool GetShowProbabilityFeedback() {
00355 return sShowProbabilityFeedback;
00356 }
00357
00358 static void SetSpeedFactor(float f)
00359 {
00360 if (f > 1.0 && f < 20.0)
00361 RotorView::sFactor = f;
00362 if (f <= 1.0)
00363 RotorView::sFactor = 1.0;
00364 }
00365 static float GetSpeedFactor()
00366 {
00367 return RotorView::sFactor;
00368 }
00369
00370 private:
00371
00372 void UpdateResolution()
00373 {
00374 if (mUseKeyframes == KEYFRAMES_CENTER && mIsHighRes != mCurrentRes)
00375 {
00376
00377 if (!mIsHighRes) return;
00378
00379 ILOG_DEBUG("Switching to keyframe image for "<< mName << ":"<<mNr);
00380 DoUpdateCurrentImage();
00381 }
00382 }
00383
00384
00385
00386
00387 void UpdateWithImage(Array2dVec3UInt8* image)
00388 {
00389 if (image == NULL)
00390 {
00391 ILOG_WARN( "NULL image received for shot ID " << mNr );
00392 return;
00393 }
00394
00395 OGLIMAGE* oldOglIm = mView->GetOGLIMAGE();
00396 Array2dVec3UInt8* oldIm = (Array2dVec3UInt8*) oldOglIm->imageHandle;
00397
00398
00399
00400 if ((image->CW() > oldOglIm->texW) || (image->CH() > oldOglIm->texH))
00401 {
00402 ILOG_DEBUG( "Changed resolution from "
00403 << oldIm->CW() << "x" << oldIm->CH()
00404 << " to " << image->CW() << "x" << image->CH());
00405 OGLIMAGE *im = InitOGLIMAGE(image);
00406 mView->SetImage(im);
00407 oglSys.ReleaseOglImage(im);
00408 }
00409 else
00410 {
00411 delete oldIm;
00412 oldOglIm->imageHandle = image;
00413 oldOglIm->w = image->CW();
00414 oldOglIm->h = image->CH();
00415 oldOglIm->changed = 1;
00416 }
00417 oglSys.ReleaseOglImage(oldOglIm);
00418 }
00419
00420 void DoUpdateCurrentImage()
00421 {
00422 Array2dVec3UInt8* image = mThreadSet->GetImageByShotID(mNr,mIsHighRes);
00423 UpdateWithImage(image);
00424 mCurrentRes = mIsHighRes;
00425 }
00426
00427 bool HasNextStill()
00428 {
00429 double cpuTime = mTimer->SplitTime();
00430 double frTime = mVideoSource ? 0.04 : RotorView::sStillFrameWait*0.01;
00431 if (cpuTime-mLastTime >= frTime)
00432 {
00433 mLastTime = cpuTime;
00434 return true;
00435 }
00436 return false;
00437 }
00438
00439 Array2dVec3UInt8* getNextStill()
00440 {
00441 if (mVideoSource != NULL)
00442 {
00443 RgbDataSrc* src = mVideoSource;
00444 if (src->TheEnd())
00445 src->GotoFrame(mVideoStart);
00446 else if (!mPlayUntilEnd && src->FrameNr() > mVideoEnd)
00447 src->GotoFrame(mVideoStart);
00448 else
00449 src->NextFrame();
00450 return Core::Array::ArrayCreate<Array2dVec3UInt8>
00451 (src->FrameWidth(),src->FrameHeight(),0,0,src->DataPtr(),true);
00452 }
00453
00454 if ((mStillPos += 1) >= mStillEnd)
00455 mStillPos = mStillStart;
00456 return mStillImages->GetImage(mStillPos);
00457 }
00458
00459
00460 void UpdateStill()
00461 {
00462 if (!HasNextStill()) return;
00463
00464 Array2dVec3UInt8* image = getNextStill();
00465 UpdateWithImage(image);
00466 }
00467
00468 void
00469
00470 RegisterView(OglGui::Window *b, float x, float y, RotorViewCacheResolver* resolver)
00471 {
00472 mBrowser = b;
00473 mCurrentRes = mIsHighRes;
00474
00475 Array2dVec3UInt8* image = mThreadSet->GetImageByShotID(mNr,mIsHighRes);
00476 OGLWND* oglWnd = b->GetOGLWND();
00477 if (image == NULL)
00478 {
00479 ILOG_WARN("NULL image received for shot ID " << mNr);
00480 mView = new RotorDoDView(oglWnd,NULL,x,y,-10.0f,1.0f,1.0f,1.0f);
00481 }
00482 else
00483 {
00484 int imW = image->CW(), imH = image->CH();
00485 if (!mForceAspect)
00486 mAspectRatio = imH==0 ? 1.f : imW/(float)imH;
00487 if (resolver)
00488 {
00489
00490 if (!(mView = resolver->FindRecycledView(imW, imH)))
00491 ILOG_ERROR("RegisterView:resolver should not return NULL!");
00492 UpdateWithImage(image);
00493 }
00494 else
00495 {
00496 OGLIMAGE *im = InitOGLIMAGE(image);
00497 mView = new RotorDoDView(oglWnd,im,x,y,-100.0f,1.0f,1.0f,1.0f);
00498 oglSys.ReleaseOglImage(im);
00499 }
00500 }
00501
00502 view3DSys.SetUserData(mView->GetOGLVIEW3D(), VIEW_ROTORVIEW, this);
00503
00504
00505 mView->SetCurrentRotorView(this);
00506
00507 mActX = mReqX = x;
00508 mActY = mReqY = y;
00509 mActZ = mReqZ = -10.0f;
00510
00511 mActW = mActH = mReqW = mReqH = 0.0f;
00512 mMoveNow = true;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 protected:
00526 OGLIMAGE* InitOGLIMAGE(Array2dVec3UInt8* im)
00527 {
00528 OGLIMAGE* oglIm = RgbOglImage::OglImage(im);
00529 oglIm->noTexScaling = 1;
00530 oglIm->changed = 1;
00531 return oglIm;
00532 }
00533
00534 private:
00535 bool DoPhysics()
00536 {
00537 mView->GetDimensions3D(&mActX,&mActY,&mActZ,NULL,NULL,NULL);
00538
00539 if (mMoveNow)
00540 {
00541 mActX = mReqX; mActY = mReqY; mActZ = mReqZ;
00542 mActW = mReqW; mActH = mReqH;
00543 mMoveNow = false;
00544 }
00545 else
00546 {
00547 mActX += (mReqX - mActX) / sFactor;
00548 mActY += (mReqY - mActY) / sFactor;
00549 mActZ += (mReqZ - mActZ) / sFactor;
00550 mActW += (mReqW - mActW) / sFactor;
00551 mActH += (mReqH - mActH) / sFactor;
00552 }
00553 float vW = mAspectRatio > 1.0 ? mActW*mAspectRatio : mActW;
00554 float vH = mAspectRatio <= 1.0 ? mActW/mAspectRatio : mActW;
00555 mView->SetDimensions3D(mActX,mActY,mActZ,vW,vH,FRETAIN);
00556
00557 return AlmostAtDestiny() ? false : true;
00558 }
00559
00560 bool AlmostAtDestiny()
00561 {
00562 return IsAlmost(mActX, mReqX) &&
00563 IsAlmost(mActY, mReqY) &&
00564 IsAlmost(mActZ, mReqZ) &&
00565 IsAlmost(mActW, mReqW) &&
00566 IsAlmost(mActH, mReqH);
00567 }
00568
00569 bool IsAlmost(float a, float r)
00570 {
00571 return (a==r) || (a>r && a - r < 0.01) || (r>a && r - a < 0.01);
00572 }
00573
00574
00575 OglGui::Window* mBrowser;
00576 RotorDoDView* mView;
00577 RotorViewListener* mViewListener;
00578
00579 ThreadSet* mThreadSet;
00580 Thread* mBookmarked;
00581 Thread* mBookmarkedNegative;
00582
00583 GeoRectangle mRect;
00584
00585 CoreImageSet* mStillImages;
00586 RgbDataSrc* mVideoSource;
00587
00588 String mName;
00589
00590 Timer* mTimer;
00591 double mLastTime;
00592
00593 int mNr;
00594 int mTurnsNotShown;
00595 int mDeleteThreshold;
00596 int mUseKeyframes;
00597
00598 int mVideoStart, mVideoEnd;
00599 int mStillStart, mStillEnd;
00600 int mStillPos;
00601
00602 float mActX, mActY, mActZ, mActW, mActH;
00603 float mReqX, mReqY, mReqZ, mReqW, mReqH;
00604 float mAspectRatio;
00605 float mViewedProbability;
00606
00607 bool mIsShown;
00608 bool mMoveNow;
00609 bool mIsBookmarked;
00610 bool mIsBookmarkedNegative;
00611 bool mForceAspect;
00612 bool mIsHighRes;
00613 bool mCurrentRes;
00614 bool mViewBeingRecycled;
00615 bool mPlayUntilEnd;
00616 bool mIsShowingStills;
00617
00618 static float sFactor;
00619 static int sStillFrameWait;
00620 static bool sShowNegativeBookmarks;
00621 static bool sShowPositiveBookmarks;
00622 static bool sShowProbabilityFeedback;
00623
00624 public:
00625 static const int KEYFRAMES_NEVER = 0;
00626 static const int KEYFRAMES_CENTER = 1;
00627 static const int KEYFRAMES_ALWAYS = 2;
00628 static const int VIEW_ROTORVIEW = 4;
00629
00630 ILOG_VAR_DEC;
00631
00632 };
00633
00634 ILOG_VAR_INIT(RotorView, Visualization.RotorBrowser);
00635
00636 float RotorView::sFactor = 1.0;
00637 int RotorView::sStillFrameWait = 15;
00638
00639 bool RotorView::sShowNegativeBookmarks = true;
00640 bool RotorView::sShowPositiveBookmarks = true;
00641 bool RotorView::sShowProbabilityFeedback = false;
00642 }
00643 }
00644 }
00645 #endif