@@ -270,6 +270,8 @@ proc makeNewVideoFrames*(output: var OutputContainer, tl: v3, args: mainArgs):
270270  var  frameIndex =  - 1 
271271  var  frame: ptr  AVFrame  =  av_frame_clone (nullFrame)
272272  var  objList: seq [VideoFrame ] =  @ []
273+   var  lastProcessedFrame: ptr  AVFrame  =  nil 
274+   var  lastFrameIndex =  - 1 
273275
274276  return  (encoderCtx, outputStream, iterator (): (ptr  AVFrame , int ) = 
275277    #  Process each frame in timeline order like Python version
@@ -279,21 +281,34 @@ proc makeNewVideoFrames*(output: var OutputContainer, tl: v3, args: mainArgs):
279281      for  layer in  tl.v:
280282        for  obj in  layer.clips:
281283          if  index >=  obj.start and  index <  (obj.start +  obj.dur):
282-             let  i =  int  (round (float  (obj.offset +  index -  obj.start) *  obj.speed))
284+             #  Convert timeline position from target framerate to source framerate
285+             let  timelinePos =  obj.offset +  index -  obj.start
286+             let  srcStream =  cns[obj.src].video[0 ]
287+             let  srcTb =  srcStream.avg_frame_rate
288+             let  sourceFramePos =  int  (round (float  (timelinePos) *  srcTb.float  /  tl.tb.float ))
289+             let  i =  int  (round (float  (sourceFramePos) *  obj.speed))
283290            objList.add  VideoFrame  (index: i, src: obj.src)
284291
285292      if  tl.chunks.isSome:
286-         #  When there can be valid gaps in the timeline.
293+         #  When there can be valid gaps in the timeline and no objects for this frame .
287294        frame =  av_frame_clone (nullFrame)
288-       #  else, use the last frame
295+       #  else, use the last frame or process objects 
289296
290297      for  obj in  objList:
298+         #  Check if we can reuse the last processed frame
299+         if  obj.index ==  lastFrameIndex and  lastProcessedFrame !=  nil :
300+           frame =  av_frame_clone (lastProcessedFrame)
301+           continue 
302+           
291303        var  myStream: ptr  AVStream  =  cns[obj.src].video[0 ]
292304        if  frameIndex >  obj.index:
293305          debug (& " Seek: { frameIndex}   -> 0 " )
294306          cns[obj.src].seek (0 )
295307          avcodec_flush_buffers (decoders[obj.src])
296308
309+         #  obj.index is already in source frame coordinates, no conversion needed
310+         let  srcTb =  myStream.avg_frame_rate
311+         
297312        while  frameIndex <  obj.index:
298313          #  Check if skipping ahead is worth it.
299314          if  obj.index -  frameIndex >  seekCost[obj.src] and  frameIndex >  seekThreshold:
@@ -307,7 +322,7 @@ proc makeNewVideoFrames*(output: var OutputContainer, tl: v3, args: mainArgs):
307322          var  foundFrame =  false 
308323          for  decodedFrame in  cns[obj.src].flushDecode (myStream.index.cint , decoder, frame):
309324            frame =  decodedFrame
310-             frameIndex =  int  (round (decodedFrame.time (myStream.time_base) *  tl.tb .float ))
325+             frameIndex =  int  (round (decodedFrame.time (myStream.time_base) *  srcTb .float ))
311326            foundFrame =  true 
312327            break 
313328
@@ -353,9 +368,19 @@ proc makeNewVideoFrames*(output: var OutputContainer, tl: v3, args: mainArgs):
353368      frame.pts =  index.int64 
354369      frame.time_base =  av_inv_q (tl.tb)
355370      frame.duration =  index.int64 
371+       
372+       #  Update cache for frame reuse BEFORE yielding (which will unref the frame)
373+       if  objList.len >  0 :
374+         if  lastProcessedFrame !=  nil :
375+           av_frame_free (addr  lastProcessedFrame)
376+         lastProcessedFrame =  av_frame_clone (frame)
377+         lastFrameIndex =  objList[0 ].index
378+       
356379      yield  (frame, index)
357380
358381    if  scaleGraph !=  nil :
359382      scaleGraph.cleanup ()
360383    av_frame_free (addr  nullFrame)
384+     if  lastProcessedFrame !=  nil :
385+       av_frame_free (addr  lastProcessedFrame)
361386    debug (& " Total frames saved seeking: { framesSaved}  " ))
0 commit comments