change to fixed rate refresh stratigy for vicons
[goodguy/history.git] / cinelerra-5.0 / guicast / vicon.C
index 814ef2d4c605c30d3d401e30814ad66700c6b230..906fb6e938556377af762768e82dd8cd9428a823 100644 (file)
@@ -12,9 +12,10 @@ VIcon(int vw, int vh, double rate)
 {
        this->vw = vw;
        this->vh = vh;
-       this->period = 1000./rate;
+       this->frame_rate = rate;
+       this->cycle_start = 0;
        this->age = 0;
-        this->seq_no = 0;
+       this->seq_no = 0;
        this->in_use = 1;
 }
 
@@ -27,9 +28,10 @@ VIcon::
 void VIcon::
 add_image(VFrame *frm, int ww, int hh, int vcmdl)
 {
-       VFrame *img = new VFrame(ww, hh, vcmdl);
+       VIFrame *vifrm = new VIFrame(ww, hh, vcmdl);
+       VFrame *img = *vifrm;
        img->transfer_from(frm);
-       images.append(img);
+       images.append(vifrm);
 }
 
 void VIcon::
@@ -69,9 +71,10 @@ VIconThread(BC_WindowBase *wdw, int vw, int vh)
        this->wdw = wdw;
        this->view_win = 0;  this->vicon = 0;
        this->view_w = vw;   this->view_h = vh;
-       this->viewing = 0;   this->draw_flash = 0;
+       this->viewing = 0;
        draw_lock = new Condition(0, "VIconThread::draw_lock", 1);
        timer = new Timer();
+       this->refresh_rate = VICON_RATE;
        done = 0;
        interrupted = 1;
 }
@@ -95,6 +98,8 @@ void VIconThread::
 start_drawing()
 {
        wdw->lock_window("VIconThread::start_drawing");
+       if( view_win )
+               wdw->set_active_subwindow(view_win);
         if( interrupted )
                draw_lock->unlock();
        wdw->unlock_window();
@@ -104,6 +109,7 @@ void VIconThread::
 stop_drawing()
 {
        wdw->lock_window("VIconThread::stop_drawing");
+       set_view_popup(0);
        interrupted = 1;
        wdw->unlock_window();
 }
@@ -171,15 +177,14 @@ ViewPopup *VIconThread::new_view_window(VFrame *frame)
 void VIconThread::
 reset_images()
 {
-       for( int i=t_heap.size(); --i>=0; ) t_heap[i]->age = 0;
+       for( int i=t_heap.size(); --i>=0; ) t_heap[i]->reset();
        timer->update();
        img_dirty = win_dirty = 0;
-       draw_flash = 0;
 }
 
-void VIconThread::add_vicon(VIcon *vip, double age)
+void VIconThread::add_vicon(VIcon *vip)
 {
-       vip->age = age;
+       double age = vip->age;
        int i = t_heap.size();  t_heap.append(vip);
        for( int k; i>0 && age<t_heap[(k=(i-1)/2)]->age; i=k )
                t_heap[i] = t_heap[k];
@@ -210,6 +215,7 @@ update_view()
                view_win = new_view_window(frame);
                view_win->show_window();
        }
+       wdw->set_active_subwindow(view_win);
        return 1;
 }
 
@@ -226,7 +232,7 @@ flash()
 {
        if( !img_dirty && !win_dirty ) return;
        if( img_dirty ) wdw->flash();
-       if( win_dirty ) view_win->flash();
+       if( win_dirty && view_win ) view_win->flash();
        win_dirty = img_dirty = 0;
 }
 
@@ -237,6 +243,7 @@ draw(VIcon *vicon)
        int draw_img = visible(vicon, x, y);
        int draw_win = view_win && viewing == vicon ? 1 : 0;
        if( !draw_img && !draw_win ) return 0;
+       if( !vicon->frame() ) return 0;
        if( draw_img ) {
                vicon->draw_vframe(wdw, x, y);
                img_dirty = 1;
@@ -255,43 +262,54 @@ run()
                draw_lock->lock("VIconThread::run 0");
                if( done ) break;;
                wdw->lock_window("BC_WindowBase::run 1");
-               reset_images();
                interrupted = 0;
                drawing_started();
+               reset_images();
+               int64_t seq_no = 0, now = 0;
+               int64_t draw_flash = 1000 / refresh_rate;
                while( !interrupted ) {
                        if( viewing != vicon )
                                update_view();
                        VIcon *next = low_vicon();
-                       if( !next ) break;
-                       if( !next->frame() ) {
-                               delete next;  next = 0;
-                               continue;
+                       while( next && next->age < draw_flash ) {
+                               now = timer->get_difference();
+                               if( now >= draw_flash ) break;
+                               draw(next);
+                               if( !next->seq_no ) next->cycle_start = now;
+                               int64_t ref_no = (now - next->cycle_start) / 1000. * refresh_rate;
+                               int count = ref_no - next->seq_no;
+                               if( count < 1 ) count = 1;
+                               ref_no = next->seq_no + count;
+                               next->age =  next->cycle_start + 1000. * ref_no / refresh_rate;
+                               if( !next->set_seq_no(ref_no) )
+                                       next->age = now + 1000.;
+                               add_vicon(next);
+                               next = low_vicon();
                        }
-                       int64_t next_time = next->age;
-                       int64_t this_time = timer->get_difference();
-                       int64_t msec = this_time - next_time;
-                       int count = msec / next->period;
-                       int nfrms = count > 0 ? count : 1;
-                       if( !next->next_frame(nfrms) )
-                               next->age = this_time + 1000;
-                       add_vicon(next, next->age);
-                       if( msec < 1000 && draw(next) && !draw_flash )
-                               draw_flash = next_time;
+                       if( !next ) break;
+                       add_vicon(next);
+                       if( draw_flash < now+1 )
+                               draw_flash = now+1;
                        wdw->unlock_window();
-                       msec = next_time - timer->get_difference();
-                       if( msec < 1 ) msec = 1;
-                       while( msec > 0 && !interrupted ) {
-                               int ms = msec > 100 ? 100 : msec;
-                               Timer::delay(ms);  msec -= ms;
+                       while( !interrupted ) {
+                               now = timer->get_difference();
+                               int64_t ms = draw_flash - now;
+                               if( ms <= 0 ) break;
+                               if( ms > 100 ) ms = 100;
+                               Timer::delay(ms);
                        }
                        wdw->lock_window("BC_WindowBase::run 2");
-                       if( interrupted ) break;
-                       if( draw_flash ) {
-                               int64_t msec = timer->get_difference() - draw_flash;
-                               if( msec < 1000 ) flash();
-                               draw_flash = 0;
-                       }
+                       now = timer->get_difference();
+                       int64_t late = now - draw_flash;
+                       if( late < 1000 ) flash();
+                       int64_t ref_no = now / 1000. * refresh_rate;
+                       int64_t count = ref_no - seq_no;
+                       if( count < 1 ) count = 1;
+                       seq_no += count;
+                       draw_flash = seq_no * 1000. / refresh_rate;
                }
+               if( viewing != vicon )
+                       update_view();
                drawing_stopped();
                interrupted = -1;
                wdw->unlock_window();
@@ -304,7 +322,8 @@ void VIcon::dump(const char *dir)
        for( int i=0; i<images.size(); ++i ) {
                char fn[1024];  sprintf(fn,"%s/img%05d.png",dir,i);
                printf("\r%s",fn);
-               images[i]->write_png(fn);
+               VFrame *img = *images[i];
+               img->write_png(fn);
        }
        printf("\n");
 }