Ivan Sh.
Ivan Sh.

Reputation: 159

ffmpeg writes invalid fps to the mp4 container (and in avi it is true). What is the reason?

I need to record frames in real time. To test this situation, I make pts non-linear (since frames may be lost), thus:

// AVFrame
video_frame->pts = prev_pts + 2;

I use libavformat to write to a file. Parameters AVCodecContext and AVStream:

#define STREAM_FRAME_RATE 25
#define CODEC_PIX_FMT  AV_PIX_FMT_YUV420P
#define FRAME_WIDTH 1440
#define FRAME_HEIGHT 900

// AVCodecContext
cc->codec_id = video_codec->id;
cc->bit_rate = 400000;
cc->width = FRAME_WIDTH;
cc->height = FRAME_HEIGHT;
cc->gop_size = 12;
cc->pix_fmt = CODEC_PIX_FMT;

// AVStream
video_stream->time_base = AVRational{ 1, STREAM_FRAME_RATE };
cc->time_base = video_stream->time_base;
cc->framerate = AVRational{ STREAM_FRAME_RATE , 1 };

Write to file:

static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt)
{
    /* rescale output packet timestamp values from codec to stream timebase */
    //av_packet_rescale_ts(pkt, *time_base, st->time_base);
    pkt->pts = av_rescale_q(pkt->pts, *time_base, st->time_base);
    pkt->dts = av_rescale_q(pkt->dts, *time_base, st->time_base);
    pkt->stream_index = st->index;

    /* Write the compressed frame to the media file. */
    //log_packet(fmt_ctx, pkt);
    //return av_write_frame(fmt_ctx, pkt);
    return av_interleaved_write_frame(fmt_ctx, pkt);
}

If you use the avi container, then the information on the number of frames per second is indicated correctly in the file: 25 fps

enter image description here

If you use the mp4 container, then the file information about the number of frames per second is indicated incorrectly: 12.5 fps

enter image description here

Tell me, please, what other settings need to be added?

Upvotes: 1

Views: 715

Answers (1)

Gyan
Gyan

Reputation: 93221

MP4s do not store framerate, AVIs do.

In MP4s, only timing info for packets is stored. Since your pts expr is video_frame->pts = prev_pts + 2 and stream time base is 1/25, frames are spaced 80ms apart and hence ffmpeg probes the frame rate to be 12.5 fps (correctly).

AVIs do not have per-frame timing. Instead, they write the user-supplied frame rate. Should a packet timing be greater than the pervious frame pts by 1/fps, the muxer will write skip frame(s) which are empty packets, to maintain the frame rate.

Upvotes: 3

Related Questions