关于视频文件和媒体流中的PTS的困惑

时间:2014-11-07 11:57:17

标签: c++ stream ffmpeg libavcodec libavformat

文件中特定帧的PTS在流式传输时是否可能与同一文件中同一帧的PTS不同?

当我使用av_read_frame读取帧时,我将视频流存储在AVStream中。在使用avcodec_decode_video2解码帧后,我使用av_frame_get_best_effort_timestamp将该帧的时间戳存储在int64_t中。现在,如果程序从文件中获取输入,我将获得与将输入(从同一文件)流式传输到程序时不同的时间戳。

要更改输入类型,我只需更改" /path/to/file.mp4"中的argv参数;对于" udp:// localhost:1234"之类的东西,然后我在命令行中使用ffmpeg流式传输文件:" ffmpeg -re -i /path/to/file.mp4 -f mpegts udp ://本地主机:1234&#34 ;.可能是因为" -f mpegts"论点改变了媒体的某些特征?

以下是我的代码(简化)。通过阅读ffmpeg邮件列表档案,我意识到我正在寻找的time_base是在AVStream而不是AVCodecContext。我没有使用av_frame_get_best_effort_timestamp,而是尝试使用packet.pts,但结果并没有改变。 我需要时间戳在正在接收的流视频中具有帧编号的概念。 我真的很感激任何帮助。

//..
//argv[1]="/file.mp4";
argv[1]="udp://localhost:7777";
// define AVFormatContext, AVFrame, etc.
// register av, avcodec, avformat_network_init(), etc.
avformat_open_input(&pFormatCtx, argv, NULL, NULL);
avformat_find_stream_info(pFormatCtx, NULL);
// find the video stream...
// pointer to the codec context...
// open codec...
pFrame=av_frame_alloc();
while(av_read_frame(pFormatCtx, &packet)>=0) {
        AVStream *strem = pFormatCtx->streams[videoStream];
        if(packet.stream_index==videoStream) {
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
            if(frameFinished) {
                int64_t perts = av_frame_get_best_effort_timestamp(pFrame);
                if (isMyFrame(pFrame)){
                     cout << perts*av_q2d(strem->time_base) << "\n";
                }
             }
}
//free allocated space
}
//..

1 个答案:

答案 0 :(得分:4)

时间戳存储在容器级别,因此更改容器可以更改时间戳。此外,TS为每个帧存储时间戳(基于90kHz时钟)。 MP4仅以假定的开始时间0存储帧持续时间(由于第一个PTS为零,因此第一个PTS为零,因此bframe变得更复杂,并且第一个DTS <0)。因此,为了获得时间戳,添加了所有帧持续时间。 Mp4还允许设置时钟速率。 29.97FPS通常为每秒1001/3000个刻度,但它可以设置为任何值。所以av_frame_get_best_effort_timestamp会返回codec-&gt; stream_base单位的滴答。对于TS编解码器 - &gt; stream_base总是1/90000