Hi,

Since I needed a looping overlay I patched vsrc_movie and added
an extra timestamp option where the overlay movie should stop 
and restart at the given start timestamp.

Zeger Knops
Index: vsrc_movie.c
===================================================================
--- vsrc_movie.c    (revision 4305)
+++ vsrc_movie.c    (working copy)
@@ -30,6 +30,7 @@
 typedef struct {
     // Filter parameters
     int64_t           seek_point; //< seekpoint in microseconds
+    int64_t           loop; //< start loop in microseconds
     char              format_name[16];
     char              file_name[255];
     // Needed to load movies
@@ -38,7 +39,7 @@
     AVCodecContext   *codec_ctx;
     int               is_done;
     AVFrame          *frame;
-
+    int loop_cnt, pck_cnt;
     int w, h;
     AVFilterPicRef *pic;
 } MovieContext;
@@ -131,9 +132,9 @@
     MovieContext *mv = ctx->priv;
 
     if(args) {
-        int num_fields = sscanf(args, "%"PRId64":%15[^:]:%255s",
-                            &mv->seek_point, mv->format_name, mv->file_name);
-        if (3 == num_fields)
+        int num_fields = sscanf(args, "%"PRId64":%15[^:]:%255[^:]:%"PRId64,
+                            &mv->seek_point, mv->format_name, mv->file_name, &mv->loop);
+        if (num_fields > 2)
             /* av_log(ctx, AV_LOG_INFO,
                 "init() args:'%s'\n\tseek:%lld format:%s name:%s\n",
                 args, mv->seek_point, mv->format_name, mv->file_name); */
@@ -142,7 +143,7 @@
                 return movie_init(ctx);
         }
         else
-            av_log(ctx, AV_LOG_ERROR, "init() expected 3 arguments:'%s'\n", args);
+            av_log(ctx, AV_LOG_ERROR, "init() expected at least 3 arguments:'%s'\n", args);
     return -1;
 }
 
@@ -165,6 +166,21 @@
     return 0;
 }
 
+static void reset_loop( AVFilterLink *link )
+{
+    int64_t  timestamp;
+
+    MovieContext *mv = link->src->priv;
+
+    // seek to seek point to start loop
+    timestamp = mv->seek_point;
+    // add the stream start time, should it exist
+    if (mv->format_ctx->start_time != AV_NOPTS_VALUE)
+        timestamp += mv->format_ctx->start_time;
+    av_seek_frame(mv->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD);
+    mv->loop_cnt++;
+}
+
 int movie_get_frame(AVFilterLink *link)
 {
     AVPacket packet;
@@ -195,14 +211,17 @@
                        sizeof(mv->frame->linesize));
 
                 // Advance in the time line
-                mv->pic->pts = av_rescale_q(packet.pts,
+                mv->pic->pts = av_rescale_q(packet.pts + mv->loop_cnt * ( mv->pck_cnt + 1 ),
                     mv->format_ctx->streams[mv->video_stream]->time_base,
                     AV_TIME_BASE_Q);
-                /* av_log(link->src, AV_LOG_INFO,
-                  "movie_get_frame(%s) packet pts:%lld %lf vfpts:%lld\n",
-                  mv->file_name, packet.pts, (double)packet.pts *
-                  av_q2d(mv->format_ctx->streams[mv->video_stream]->time_base),
-                  mv->pic->pts);*/
+
+                if ( !mv->loop_cnt )
+                    mv->pck_cnt++;
+
+                if ( mv->loop && av_rescale_q(packet.pts,
+                                  mv->format_ctx->streams[mv->video_stream]->time_base,
+                                  AV_TIME_BASE_Q) > mv->loop )
+                    reset_loop( link );
 
                 // We got it. Free the packet since we are returning
                 av_free_packet(&packet);
@@ -207,6 +226,12 @@
                 // We got it. Free the packet since we are returning
                 av_free_packet(&packet);
 
+                /*av_log(link->src, AV_LOG_INFO,
+                "movie_get_frame(%s) packet pts:%lld %lf vfpts:%lld\n",
+                mv->file_name, packet.pts, (double)packet.pts *
+                av_q2d(mv->format_ctx->streams[mv->video_stream]->time_base),
+                mv->pic->pts);*/
+
                 return 0;
             }
         }
@@ -213,9 +238,14 @@
         // Free the packet that was allocated by av_read_frame
         av_free_packet(&packet);
     }
-    // On multi-frame source we should stop the mixing process when
-    // the movie source does not have more frames
-    mv->is_done = 1;
+
+    if ( mv->loop )
+        reset_loop( link );
+    else
+        // On multi-frame source we should stop the mixing process when
+        // the movie source does not have more frames
+        mv->is_done = 1;
+
     return 0;
 }
 
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc

Reply via email to