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


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
_______________________________________________
mythtv-dev mailing list
[email protected]
http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-dev

Reply via email to