[Libav-user] Looping a stream?

John Regan john at jrjrtech.com
Thu Feb 10 23:00:45 EET 2022


On Thu, 10 Feb 2022 06:19:47 +0100
Strahinja Radman <dr.strashni at gmail.com> wrote:

> On Thu, Feb 10, 2022 at 1:14 AM John Regan via Libav-user <
> libav-user at ffmpeg.org> wrote:
> 
> > Hi there, I was hoping somebody could offer advice on how to loop a
> > video with libavformat/libavcodec.
> >
> > I have a filter graph created, so my core decoding code is
> > basically:
> >
> > if( (err = av_read_frame(inputCtx, packet)) < 0) {
> >     if(err != AVERROR_EOF) {
> >         /* handle errors, return */
> >     }
> >     avformat_seek_file(inputCtx,videoStreamIndex, 0, 0, 0, 0));
> >     avcodec_flush_buffers(codecCtx);
> > }
> >
> > if(packet.stream_index == videoStreamIndex) {
> >     avcodec_send_packet(codecCtx,packet);
> >     avcodec_receive_frame(codecCtx,tmpFrame);
> >     av_buffersrc_write_frame(bufferSrcCtx,tmpFrame);
> >     if(av_buffersink_get_frame(bufferSinkCrx,frame) >= 0) {
> >         /* we have a frame */
> >     }
> > }
> >
> > I'm not sure if there's steps that need to be taken to reset the
> > filter graph? Like is there a timestamp discontinuity?
> >
> > It seems like this should work - but I'm missing something, it seems
> > like the buffersink_get_frame stops producing frames after I reset.
> >
> > Thank you in advance,
> > -John
> > _______________________________________________
> > Libav-user mailing list
> > Libav-user at ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/libav-user
> >
> > To unsubscribe, visit link above, or email
> > libav-user-request at ffmpeg.org with subject "unsubscribe".
> >  
> 
> Hello,
> 
> I dont think you need to reset the filter graph, in the end it simply
> takes in AVFrame* and does some processing. Timestamps in filters are
> only changed if you specify a different timebase for the filters (as
> far as I am aware). But timestamp discontinuity is something you have
> to take care of. For example you could generate them by using this
> formula
> 
> frame_timestamp = iteration_count * max_timestamp +
> current_frame_timestamp
> 
> max_timestamp is the last timestamp of the video stream.
> This should enable you to get a looped sequence of frames that can be
> properly played. On the other hand, check if you are actually getting
> a frame from your decoder by saving it to a PGM file. Here is the code
> 
> static void pgm_save(unsigned char* buf, int wrap, int xsize, int
> ysize, const char* filename)
> {
> 
> FILE* f;
> int i;
> 
> 
> f = fopen(filename, "w");
> fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
> for (i = 0; i < ysize; i++)
> 
> fwrite(buf + i * wrap, 1, xsize, f);
> 
> fclose(f);
> 
> }
> 

That tip about timestamps was a huge help, thank you!

I figured out the issue was non-sequential timestamps with the "fps"
filter.

What I'm doing now is saving the "pts offset" variable and a "last
pts" variable, and "pts offset" is initialized to zero. When I receive
a packet, I save its original PTS to the "last pts" variable, and add
the offset to the packet's PTS. Then, when av_read_frame returns EOF, I
add that last_pts to the offset.

Question, is it more appropriate to meddle with the packet PTS I get
from the demuxer, or the frame PTS I get from the decoder? Or does it
not really matter?



More information about the Libav-user mailing list