[mythtv] [PATCH] Plextor PX-TV402 / go7007 keyframe seek fix

Jack Porter jack at porter.net.au
Mon May 23 01:26:36 UTC 2005


This patch fixes the problem of up to a second of mpeg blockiess 
whenever you seek in a video captured with one of these devices.

The first frame the Plextor gives us isn't necessarily an I-frame, so 
the seek table isn't synced with what's in the mpeg stream.  Thanks to 
Mark Spieth for tracking down the root cause of this.   Simply throwing 
away everything before the first I-frame lets everything start off in sync.

But unfortunately things sometimes get out of sync again for the rest of 
the recording for some reason - perhaps if a frame is dropped.

My solution was to write a 'sync' frame to the nuv only when the frame 
data written is an MPEG4 I-frame.  Why are the sync frames placed so 
rigidly placed exactly 30 frames apart in the nuv?

Mark suggested it might be nicer to do something like what the firewire 
code does using SetPositionMapDelta.

I'm posting this because (1) it works for me (tm), (2) it doesn't change 
behavior for anyone not using a go7007, and (3) I won't have a chance to 
look at this again til next weekend at the earliest.

- Jack


-------------- next part --------------
Index: NuppelVideoRecorder.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoRecorder.cpp,v
retrieving revision 1.198
diff -u -r1.198 NuppelVideoRecorder.cpp
--- NuppelVideoRecorder.cpp	3 May 2005 18:58:58 -0000	1.198
+++ NuppelVideoRecorder.cpp	22 May 2005 13:44:00 -0000
@@ -160,6 +160,7 @@
 
     volume = 100;
     go7007 = false;
+    go7007keyframenumber = 0;
 }
 
 NuppelVideoRecorder::~NuppelVideoRecorder(void)
@@ -1347,6 +1348,8 @@
     encoding = true;
     recording = true;
 
+    int hadgo7007iframe = false;
+
     while (encoding) {
 again:
         if (paused)
@@ -1443,6 +1446,17 @@
 
                 BufferIt(conversion_buffer, video_buffer_size);
             }
+            else if (go7007)
+            {
+                // On go7007, don't write anything but S-frames until we
+                // get the first I-frame, to correctly synchronize
+                unsigned char frametype = buffers[frame][4]>>6;
+                if (!hadgo7007iframe && frametype==0)
+                    hadgo7007iframe = true;
+
+                if (hadgo7007iframe || frametype==3)
+                    BufferIt(buffers[frame], vbuf.bytesused);
+            }
             else
             {
                 // buffer the frame directly
@@ -3369,13 +3383,25 @@
     frameheader.keyframe  = frameofgop;             // no keyframe defaulted
 
     bool wantkeyframe = forcekey;
+    bool writesyncheader;
 
-    if (((fnum-startnum)>>1) % keyframedist == 0 && !skipsync) {
+    if (go7007)
+        writesyncheader = (frame->buf[4]>>6)==0;
+    else
+        writesyncheader = ((fnum-startnum)>>1) % keyframedist == 0;
+
+    if (writesyncheader && !skipsync) {
+        int keyframenumber;
+        if (go7007)
+            keyframenumber = go7007keyframenumber++;
+        else
+            keyframenumber = ((fnum - startnum) >> 1) / keyframedist;
+        
         frameheader.keyframe=0;
         frameofgop=0;
         ringBuffer->Write("RTjjjjjjjjjjjjjjjjjjjjjjjj", FRAMEHEADERSIZE);
 
-        UpdateSeekTable(((fnum - startnum) >> 1) / keyframedist, true);
+        UpdateSeekTable(keyframenumber, true);
 
         frameheader.frametype    = 'S';           // sync frame
         frameheader.comptype     = 'V';           // video sync information
Index: NuppelVideoRecorder.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoRecorder.h,v
retrieving revision 1.79
diff -u -r1.79 NuppelVideoRecorder.h
--- NuppelVideoRecorder.h	19 Mar 2005 06:51:41 -0000	1.79
+++ NuppelVideoRecorder.h	22 May 2005 13:44:00 -0000
@@ -278,6 +278,7 @@
 
     int volume;
     bool go7007;
+    int go7007keyframenumber;
 };
 
 #endif


More information about the mythtv-dev mailing list