[Bf-blender-cvs] [7eb3e77b94f] blender-v2.93-release: FFmpeg: Fix seeking not returning the correct frame when not using TC index

Sebastian Parborg noreply at git.blender.org
Wed Jun 30 09:47:15 CEST 2021


Commit: 7eb3e77b94f51bdeee719425ec4a533f662c5edd
Author: Sebastian Parborg
Date:   Sat Jun 5 02:47:02 2021 +0200
Branches: blender-v2.93-release
https://developer.blender.org/rB7eb3e77b94f51bdeee719425ec4a533f662c5edd

FFmpeg: Fix seeking not returning the correct frame when not using TC index

Fixed the logic for seeking in ffmpeg video files.
The main fix is that we now apply a small offset in ffmpeg_get_seek_pos
to make sure we don't get the frame in front of the seek position when
seeking backward.

The rest of the changes is general cleanup and untangling code.

Reviewed By: Richard Antalik

Differential Revision: http://developer.blender.org/D11492

===================================================================

M	release/scripts/startup/bl_ui/space_sequencer.py
M	source/blender/imbuf/IMB_imbuf.h
M	source/blender/imbuf/intern/IMB_anim.h
M	source/blender/imbuf/intern/anim_movie.c
M	source/blender/makesdna/DNA_sequence_types.h
M	source/blender/makesrna/intern/rna_sequencer.c
M	source/blender/sequencer/intern/render.c
M	source/blender/sequencer/intern/strip_add.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index f6a03b4769c..f4b08d6718e 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -1381,7 +1381,6 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel):
                 col = layout.column()
                 col.prop(strip, "filepath", text="")
                 col.prop(strip.colorspace_settings, "name", text="Color Space")
-                col.prop(strip, "mpeg_preseek")
                 col.prop(strip, "stream_index")
                 col.prop(strip, "use_deinterlace")
 
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index d131e4dacdc..9c84127105a 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -380,8 +380,6 @@ bool IMB_anim_can_produce_frames(const struct anim *anim);
  */
 
 int ismovie(const char *filepath);
-void IMB_anim_set_preseek(struct anim *anim, int preseek);
-int IMB_anim_get_preseek(struct anim *anim);
 int IMB_anim_get_image_width(struct anim *anim);
 int IMB_anim_get_image_height(struct anim *anim);
 
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index 7d7864306a1..cfeffcca0ea 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -87,7 +87,7 @@ struct anim_index;
 struct anim {
   int ib_flags;
   int curtype;
-  int curposition; /* index  0 = 1e,  1 = 2e, enz. */
+  int cur_position; /* index  0 = 1e,  1 = 2e, enz. */
   int duration_in_frames;
   int frs_sec;
   double frs_sec_base;
@@ -105,7 +105,6 @@ struct anim {
   int orientation;
   size_t framesize;
   int interlacing;
-  int preseek;
   int streamindex;
 
   /* avi */
@@ -132,10 +131,10 @@ struct anim {
   struct SwsContext *img_convert_ctx;
   int videoStream;
 
-  struct ImBuf *last_frame;
-  int64_t last_pts;
-  int64_t next_pts;
-  AVPacket *next_packet;
+  struct ImBuf *cur_frame_final;
+  int64_t cur_pts;
+  int64_t cur_key_frame_pts;
+  AVPacket *cur_packet;
 #endif
 
   char index_dir[768];
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 7c95983dfd5..4b5da22227b 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -433,8 +433,7 @@ static int startavi(struct anim *anim)
   anim->orientation = 0;
   anim->framesize = anim->x * anim->y * 4;
 
-  anim->curposition = 0;
-  anim->preseek = 0;
+  anim->cur_position = 0;
 
 #  if 0
   printf("x:%d y:%d size:%d interl:%d dur:%d\n",
@@ -650,12 +649,12 @@ static int startffmpeg(struct anim *anim)
   anim->orientation = 0;
   anim->framesize = anim->x * anim->y * 4;
 
-  anim->curposition = -1;
-  anim->last_frame = 0;
-  anim->last_pts = -1;
-  anim->next_pts = -1;
-  anim->next_packet = av_packet_alloc();
-  anim->next_packet->stream_index = -1;
+  anim->cur_position = -1;
+  anim->cur_frame_final = 0;
+  anim->cur_pts = -1;
+  anim->cur_key_frame_pts = -1;
+  anim->cur_packet = av_packet_alloc();
+  anim->cur_packet->stream_index = -1;
 
   anim->pFrame = av_frame_alloc();
   anim->pFrameComplete = false;
@@ -671,7 +670,7 @@ static int startffmpeg(struct anim *anim)
       fprintf(stderr, "Could not allocate frame data.\n");
       avcodec_free_context(&anim->pCodecCtx);
       avformat_close_input(&anim->pFormatCtx);
-      av_packet_free(&anim->next_packet);
+      av_packet_free(&anim->cur_packet);
       av_frame_free(&anim->pFrameRGB);
       av_frame_free(&anim->pFrameDeinterlaced);
       av_frame_free(&anim->pFrame);
@@ -684,7 +683,7 @@ static int startffmpeg(struct anim *anim)
     fprintf(stderr, "ffmpeg has changed alloc scheme ... ARGHHH!\n");
     avcodec_free_context(&anim->pCodecCtx);
     avformat_close_input(&anim->pFormatCtx);
-    av_packet_free(&anim->next_packet);
+    av_packet_free(&anim->cur_packet);
     av_frame_free(&anim->pFrameRGB);
     av_frame_free(&anim->pFrameDeinterlaced);
     av_frame_free(&anim->pFrame);
@@ -706,13 +705,6 @@ static int startffmpeg(struct anim *anim)
                          1);
   }
 
-  if (pCodecCtx->has_b_frames) {
-    anim->preseek = 25; /* FIXME: detect gopsize ... */
-  }
-  else {
-    anim->preseek = 0;
-  }
-
   anim->img_convert_ctx = sws_getContext(anim->x,
                                          anim->y,
                                          anim->pCodecCtx->pix_fmt,
@@ -728,7 +720,7 @@ static int startffmpeg(struct anim *anim)
     fprintf(stderr, "Can't transform color space??? Bailing out...\n");
     avcodec_free_context(&anim->pCodecCtx);
     avformat_close_input(&anim->pFormatCtx);
-    av_packet_free(&anim->next_packet);
+    av_packet_free(&anim->cur_packet);
     av_frame_free(&anim->pFrameRGB);
     av_frame_free(&anim->pFrameDeinterlaced);
     av_frame_free(&anim->pFrame);
@@ -769,13 +761,13 @@ static int startffmpeg(struct anim *anim)
 /* postprocess the image in anim->pFrame and do color conversion
  * and deinterlacing stuff.
  *
- * Output is anim->last_frame
+ * Output is anim->cur_frame_final
  */
 
 static void ffmpeg_postprocess(struct anim *anim)
 {
   AVFrame *input = anim->pFrame;
-  ImBuf *ibuf = anim->last_frame;
+  ImBuf *ibuf = anim->cur_frame_final;
   int filter_y = 0;
 
   if (!anim->pFrameComplete) {
@@ -902,7 +894,7 @@ static void ffmpeg_postprocess(struct anim *anim)
   }
 }
 
-/* decode one video frame also considering the packet read into next_packet */
+/* decode one video frame also considering the packet read into cur_packet */
 
 static int ffmpeg_decode_video_frame(struct anim *anim)
 {
@@ -910,40 +902,43 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
 
   av_log(anim->pFormatCtx, AV_LOG_DEBUG, "  DECODE VIDEO FRAME\n");
 
-  if (anim->next_packet->stream_index == anim->videoStream) {
-    av_packet_unref(anim->next_packet);
-    anim->next_packet->stream_index = -1;
+  if (anim->cur_packet->stream_index == anim->videoStream) {
+    av_packet_unref(anim->cur_packet);
+    anim->cur_packet->stream_index = -1;
   }
 
-  while ((rval = av_read_frame(anim->pFormatCtx, anim->next_packet)) >= 0) {
+  while ((rval = av_read_frame(anim->pFormatCtx, anim->cur_packet)) >= 0) {
     av_log(anim->pFormatCtx,
            AV_LOG_DEBUG,
            "%sREAD: strID=%d (VID: %d) dts=%" PRId64 " pts=%" PRId64 " %s\n",
-           (anim->next_packet->stream_index == anim->videoStream) ? "->" : "  ",
-           anim->next_packet->stream_index,
+           (anim->cur_packet->stream_index == anim->videoStream) ? "->" : "  ",
+           anim->cur_packet->stream_index,
            anim->videoStream,
-           (anim->next_packet->dts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet->dts,
-           (anim->next_packet->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet->pts,
-           (anim->next_packet->flags & AV_PKT_FLAG_KEY) ? " KEY" : "");
-    if (anim->next_packet->stream_index == anim->videoStream) {
+           (anim->cur_packet->dts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->cur_packet->dts,
+           (anim->cur_packet->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->cur_packet->pts,
+           (anim->cur_packet->flags & AV_PKT_FLAG_KEY) ? " KEY" : "");
+    if (anim->cur_packet->stream_index == anim->videoStream) {
       anim->pFrameComplete = 0;
 
-      avcodec_send_packet(anim->pCodecCtx, anim->next_packet);
+      avcodec_send_packet(anim->pCodecCtx, anim->cur_packet);
       anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0;
 
       if (anim->pFrameComplete) {
-        anim->next_pts = av_get_pts_from_frame(anim->pFormatCtx, anim->pFrame);
+        anim->cur_pts = av_get_pts_from_frame(anim->pFormatCtx, anim->pFrame);
 
+        if (anim->pFrame->key_frame) {
+          anim->cur_key_frame_pts = anim->cur_pts;
+        }
         av_log(anim->pFormatCtx,
                AV_LOG_DEBUG,
-               "  FRAME DONE: next_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
+               "  FRAME DONE: cur_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
                (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
-               (int64_t)anim->next_pts);
+               (int64_t)anim->cur_pts);
         break;
       }
     }
-    av_packet_unref(anim->next_packet);
-    anim->next_packet->stream_index = -1;
+    av_packet_unref(anim->cur_packet);
+    anim->cur_packet->stream_index = -1;
   }
 
   if (rval == AVERROR_EOF) {
@@ -954,20 +949,23 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
     anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0;
 
     if (anim->pFrameComplete) {
-      anim->next_pts = av_get_pts_from_frame(anim->pFormatCtx, anim->pFrame);
+      anim->cur_pts = av_get_pts_from_frame(anim->pFormatCtx, anim->pFrame);
 
+      if (anim->pFrame->key_frame) {
+        anim->cur_key_frame_pts = anim->cur_pts;
+      }
       av_log(anim->pFormatCtx,
              AV_LOG_DEBUG,
-             "  FRAME DONE (after EOF): next_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
+             "  FRAME DONE (after EOF): cur_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
              (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
-             (int64_t)anim->next_pts);
+             (int64_t)anim->cur_pts);
       rval = 0;
     }
   }
 
   if (rval < 0) {
-    av_packet_unref(anim->next_packet);
-    anim->next_packet->stream_index = -1;
+    av_packet_unref(anim->cur_packet);
+    anim->cur_packet->stream_index = -1;
 
     av_log(anim->pFormatCtx,
            AV_LOG_ERROR,
@@ -1021,6 +1019,35 @@ static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx)
   return false;
 }
 
+static int64_t ffmpeg_get_seek_pos(struct anim *anim, int position)
+{
+  AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
+  double frame_rate = av_q2d(av_guess_frame_rate(anim->pFormatCtx, v_st, NULL));
+  int64_t st_time = anim->pFormatCtx->start_time;
+  int64_t pos = (int64_t)(position)*AV_TIME_BASE;
+  /* Step back half a time base position to make sure that we get the requested
+   * frame and not the one after it.
+   */
+  pos 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list