[mythtv] Trick play patch

David Engel dlengel at attbi.com
Tue Aug 19 23:10:57 EDT 2003


On Tue, Aug 19, 2003 at 07:28:52PM -0500, David Engel wrote:
> On Tue, Aug 19, 2003 at 01:31:15PM -0400, Isaac Richards wrote:
> > patch =)  I'll probably add another variable sometime so it's not doing the
> > dividing by play_speed all the time later.
> 
> Great.  I'll take a look at this myself later tonight.  My intent was
> to get it working right first, then worry about any optimizations.

Here is the patch.  frame_interval is now set whenever play_speed is
changed.  That, along with a new normal_speed boolean removes all
floating point from the critical path.

On Tue, Aug 19, 2003 at 08:42:00PM -0400, Isaac Richards wrote:
> On Tuesday 19 August 2003 08:28 pm, David Engel wrote:
> > The patch for that is below.  It also fixes a compiler warning.
> 
> Do you think you could move that logic into tv_play.cpp?  I'm worried about 
> side effects if it's in NVP..

Sure, if you'll tell me how. :) The obvious approach won't work from
TV because of threading.  That leaves things like synchronizing the TV
and NVP threads (not very desirable) or having a timer in TV reset
exact seeks (pretty kludge, IMHO).

Of course, we could just punt and tell users who want exact single
frame rewinds that they need to turn on exact seeks.

> > One thing I didn't get entirely right though was the OSD.  The fade
> > speed is too fast or slow if the play speed isn't 1x.  Do you have any
> > suggestions for an acceptable fix?  It's not a high priority, but I'd
> > still like to fix it.
> 
> I think it's that the SetFPS function needs to propogate the fps value to the
> 'totalfadeframes' variable is all.

It's more complicated than that.  The fade movement needs to be
adjusted somehow too.

David
-- 
David Engel
dlengel at attbi.com

Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoPlayer.h,v
retrieving revision 1.110
diff -u -r1.110 NuppelVideoPlayer.h
--- libs/libmythtv/NuppelVideoPlayer.h	19 Aug 2003 17:26:08 -0000	1.110
+++ libs/libmythtv/NuppelVideoPlayer.h	20 Aug 2003 02:22:42 -0000
@@ -82,7 +82,9 @@
     void SetPlaySpeed(float speed) 
     { 
         play_speed = speed;
-        if (osd) osd->SetFPS((int)ceil(video_frame_rate*speed));
+	normal_speed = (speed == 1.0);
+	frame_interval = (int)(1000000.0 / video_frame_rate / speed);
+        if (osd) osd->SetFPS((int)ceil(video_frame_rate * speed));
     }
 
     bool FastForward(float seconds);
@@ -399,8 +401,9 @@
     int avsync_delay;
     int avsync_avg;
     int refreshrate;
-    int frame_interval;
+    int frame_interval;		// Always adjusted for play_speed
     float play_speed;  
+    bool normal_speed;
  
     bool delay_clipping;
     struct timeval nexttrigger, now;
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp,v
retrieving revision 1.254
diff -u -r1.254 NuppelVideoPlayer.cpp
--- libs/libmythtv/NuppelVideoPlayer.cpp	19 Aug 2003 17:26:08 -0000	1.254
+++ libs/libmythtv/NuppelVideoPlayer.cpp	20 Aug 2003 02:22:44 -0000
@@ -111,6 +111,8 @@
 
     totalLength = 0;
     totalFrames = 0;
+    play_speed = 1.0;
+    normal_speed = true;
 
     osdtheme = "none";
 
@@ -342,7 +344,8 @@
 
     videoOutput->GetDrawSize(dispx, dispy, dispw, disph);
 
-    osd->Reinit(video_width, video_height, (int)ceil(video_frame_rate),
+    osd->Reinit(video_width, video_height, 
+		(int)ceil(video_frame_rate * play_speed),
                 dispx, dispy, dispw, disph);
 
     VideoFrame *scratchFrame = &(vbuffers[MAXVBUFFER]);
@@ -376,7 +379,10 @@
     if (height > 0)
         video_height = height;
     if (fps > 0)
-        video_frame_rate = fps;
+    {
+	video_frame_rate = fps;
+	frame_interval = (int)(1000000.0 / video_frame_rate / play_speed);
+    }
 
     video_size = video_height * video_width * 3 / 2;
     keyframedist = keyframedistance;
@@ -670,7 +676,7 @@
        the video will play really fast for a while.*/
     
     gettimeofday(nexttrigger, NULL);
-    nexttrigger->tv_usec += (int)(1000000 / video_frame_rate / play_speed);
+    nexttrigger->tv_usec += frame_interval;
     NormalizeTimeval(nexttrigger);
 }
 
@@ -1011,15 +1017,15 @@
         {
             // If delay is sometwhat more than a frame or < 0ms,
             // we clip it to these amounts and reset nexttrigger
-            if ( delay > frame_interval / play_speed * 2)
+            if ( delay > frame_interval * 2)
             {
                 // cerr << "Delaying to next trigger: " << delay << endl;
-                usleep(frame_interval / play_speed);
+                usleep(frame_interval);
                 delay = 0;
                 avsync_avg = 0;
                 gettimeofday(&nexttrigger, NULL);
             }
-            else if (delay < 0 - frame_interval / play_speed)
+            else if (delay < 0 - frame_interval)
             {
                 // cerr << "clipped negative delay " << delay << endl;
                 delay = 0;
@@ -1027,7 +1033,7 @@
                 gettimeofday(&nexttrigger, NULL);
             }
 
-            if (reducejitter && play_speed == 1.0)
+            if (reducejitter && normal_speed)
                 ReduceJitter(&nexttrigger);
             else
             {
@@ -1046,9 +1052,9 @@
        be exactly one frame time after the previous frame,
        Show frames at the frame rate as long as audio is in sync */
 
-    nexttrigger.tv_usec += (int)(frame_interval / play_speed);
+    nexttrigger.tv_usec += frame_interval;
 
-    if (audioOutput && play_speed == 1.0)
+    if (audioOutput && normal_speed)
     {
         lastaudiotime = audioOutput->GetAudiotime(); // ms, same scale as timecodes
 
@@ -1108,7 +1114,7 @@
     delay = (nexttrigger.tv_sec - now.tv_sec) * 1000000 +
             (nexttrigger.tv_usec - now.tv_usec); // uSecs
 
-    if (reducejitter && play_speed == 1.0)
+    if (reducejitter && normal_speed)
     {
         /* If delay is sometwhat more than a frame or < 0ms,
            we clip it to these amounts and reset nexttrigger */
@@ -1185,7 +1191,7 @@
         be exactly one frame time after the previous frame,
         plus just enough feedback to stay synchronized with audio. */
 
-    nexttrigger.tv_usec += (int)(1000000 / video_frame_rate / play_speed);
+    nexttrigger.tv_usec += frame_interval;
 
     /* Apply just a little feedback. The ComputeAudiotime() function is
        jittery, so if we try to correct our entire A/V drift on each frame,
@@ -1195,7 +1201,7 @@
        In steady state, very little feedback is needed. However, if we are
        far out of sync, we need more feedback. So, we case on this. */
 
-    if (audioOutput && play_speed == 1.0)
+    if (audioOutput && normal_speed)
     {
         lastaudiotime = audioOutput->GetAudiotime(); // ms, same scale as timecodes
         if (lastaudiotime != 0) // lastaudiotime = 0 after a seek
@@ -1237,7 +1243,6 @@
     output_jmeter = NULL;
     //output_jmeter = new Jitterometer("video_output", 100);
 
-    frame_interval = (int)(1000000.0/video_frame_rate);
     refreshrate = frame_interval;
 
     VideoFrame *scratchFrame = &(vbuffers[MAXVBUFFER]);
@@ -1402,7 +1407,6 @@
     ClearAfterSeek();
 
     framesPlayed = 0;
-    play_speed = 1.0;
 
     decoder->Reset();
 }
@@ -1412,7 +1416,6 @@
     consecutive_blanks = 0;
     killplayer = false;
     framesPlayed = 0;
-    play_speed = 1.0;
 
     if (OpenFile() < 0)
         return;
@@ -1430,7 +1433,8 @@
         InitVideo();
         int dispx = 0, dispy = 0, dispw = video_width, disph = video_height;
         videoOutput->GetDrawSize(dispx, dispy, dispw, disph);
-        osd = new OSD(video_width, video_height, (int)ceil(video_frame_rate),
+        osd = new OSD(video_width, video_height, 
+		      (int)ceil(video_frame_rate * play_speed),
                       osdfontname, osdccfontname, osdprefix, osdtheme,
                       dispx, dispy, dispw, disph);
     }
@@ -1482,7 +1486,7 @@
 
     if (bookmarkseek > 30)
     {
-        GetFrame(audioOutput == NULL || play_speed != 1.0);
+        GetFrame(audioOutput == NULL || !normal_speed);
 
         bool seeks = exactseeks;
 
@@ -1535,7 +1539,7 @@
             {   
                 DoRewind();
                 
-                GetFrame(audioOutput == NULL || play_speed != 1.0);
+                GetFrame(audioOutput == NULL || !normal_speed);
                 resetvideo = true;
                 while (resetvideo)
                     usleep(50);
@@ -1548,7 +1552,7 @@
                 fftime = CalcMaxFFTime(fftime);
                 DoFastForward();
 
-                GetFrame(audioOutput == NULL || play_speed != 1.0);
+                GetFrame(audioOutput == NULL || !normal_speed);
                 resetvideo = true;
                 while (resetvideo)
                     usleep(50);
@@ -1605,7 +1609,7 @@
             continue;
         }
 
-        GetFrame(audioOutput == NULL || play_speed != 1.0);
+        GetFrame(audioOutput == NULL || !normal_speed);
 
         if (!hasdeletetable && autocommercialskip)
             AutoCommercialSkip();


More information about the mythtv-dev mailing list