[MPlayer-dev-eng] Precised/exact/to the frame seeking (-ss) in mencoder

Sam Wong sam at hellosam.net
Wed Apr 11 11:21:55 CEST 2007


On 4/11/07, Attila Kinali <attila at kinali.ch> wrote:
>
> On Tue, 10 Apr 2007 21:41:28 +0200
> Attila Kinali <attila at kinali.ch> wrote:
>
> > On Wed, 11 Apr 2007 03:38:18 +0800
> > Sam Wong <sam at hellosam.net> wrote:
> >
> > > Does that look good?
> >
> > No, asking the exact same question you asked already
> > on -users will not give you any substantialy different
> > answer on -dev-eng.
>
> Please disregard this mail... i was a little bit too fast. ^^;
>
>                         Attila Kinali


I just hope people won't stop reply because they miss your 2nd message...

I think people are all interested in real contribution, so attached is a
simple patch (against rev 22965) to the mencoder.c that implements the
idea...and surprisingly it works! =)
I didn't have test it throughly yet though, so far I have no problem with
it. and I hope someone could add some comment.

Appreciated if someone could really take a look at this, as I was just
copy-and-pasting the code around, I am expecting minor mistake like
off-by-1-frame error.

Sam
-------------- next part --------------
Index: mencoder.c
===================================================================
--- mencoder.c  (revision 22965)
+++ mencoder.c  (working copy)
@@ -1708,6 +1708,10 @@

 static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
     sh_video_t * sh_video = demuxer->video ? demuxer->video->sh : NULL;
+    float target = next_edl_record->stop_sec - 30;
+    float up_b  = next_edl_record->stop_sec;
+    float low_b = 0;
+    if (target < 0) target = up_b;

     if (!sh_video) return 0;
     if (sh_video->pts >= next_edl_record->stop_sec) return 1; // nothing to do...
@@ -1718,14 +1722,37 @@
             //if (vo_vobsub) vobsub_seek(vo_vobsub,sh_video->pts);
             resync_video_stream(sh_video);
             //if(vo_spudec) spudec_reset(vo_spudec);
-            if (audio_delay != 0.0) fixdelay(demuxer->video, d_audio, mux_a, frame_data, framecopy);
+            if (d_audio && audio_delay != 0.0) fixdelay(demuxer->video, d_audio, mux_a, frame_data, framecopy);
             return 1;
         }
         // non-seekable stream.
         return 0;
     }

+    while (demux_seek(demuxer, target - sh_video->pts, audio_delay, 0)) {
+        frame_data->in_size = video_read_frame(sh_video, &frame_data->frame_time, &frame_data->start, force_fps);
+        if (frame_data->in_size < 0) return 2; // EOF
+
+        // Do bisection
+       mp_msg(MSGT_MENCODER, MSGL_INFO, "hr-edl: bisection seeking: %f > _%f_ < %f, got %f\n",
+                low_b, target, up_b, sh_video->pts);
+        if (sh_video->pts > next_edl_record->stop_sec) { up_b = target; }
+        else if (sh_video->pts < next_edl_record->stop_sec) { low_b = target; }
+
+        if (up_b - low_b < 2.5) break; // Small enough range to do slowseek
+        target = (up_b + low_b) / 2;
+
+        if (frame_data->in_size < 0) return 2;
+    }
+    mp_msg(MSGT_MENCODER, MSGL_INFO,
+            "hr-edl: seeking to the previous seekable point at %f, now slowseek to %f\n",
+            low_b, next_edl_record->stop_sec);
+    frame_data->already_read = 0;
+    demux_seek(demuxer, low_b - sh_video->pts, audio_delay, 0);
+            sh_video->pts = demuxer->video->pts;
+    resync_video_stream(sh_video);
+    if (d_audio && audio_delay != 0.0) fixdelay(demuxer->video, d_audio, mux_a, frame_data, framecopy);
+
     // slow seek, read every frame.
-
     return slowseek(next_edl_record->stop_sec, demuxer->video, d_audio, mux_a, frame_data, framecopy, 1);
 }


More information about the MPlayer-dev-eng mailing list