繁体   English   中英

在带有FFmpeg的mp4容器中寻找h264编解码器的视频帧。 数据包pts始终为0

[英]Seeking to video frame of h264 codec in mp4 container with FFmpeg. Packet pts is always 0

我正在尝试使用FFmpeg搜索到特定帧的最近关键帧,但是无论何时我在搜索后使用av_read_frame获取下一帧时,数据包pts或dts始终为0。这仅适用于h264 / mp4视频,因为它可以正常工作.avi容器中的一些编解码器。

我尝试使用avformat_seek_fileav_seek_frame,但它们给我相同的结果。

我还读到我不应该从数据包中读取时间戳,因此我尝试首先使用avcodec_decode_video2解码数据包并读取AVFrame-> pts信息,但是此值对于h264 / mp4视频始终无效。

这是我正在尝试执行的相关代码:

/*Relevant from header*/
AVCodecContext pCodecCtx;
AVFormatContext *pFormatCtx;
int videoStreamIndex;

int Class::getFrame(int desiredFrame, bool seek)
if(seek)
{
    /* We seek to the selected frame */
    if(avformat_seek_file(pFormatCtx, videoStreamIndex, 0, desiredFrame, desiredFrame, AVSEEK_FLAG_BACKWARD) < 0)
    //if(av_seek_frame(pFormatCtx, mVideoStream, desiredFrame, AVSEEK_FLAG_BACKWARD) < 0)
    {
    // error management
    }
    avcodec_flush_buffers(pCodecCtx);
}

AVPacket packet;
int frameFinished;
/* Loop until we find the next video frame */
while(av_read_frame(pFormatCtx, &packet) >= 0 )
{
    if(packet.stream_index == videoStreamIndex)
    {
        avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
        int pcktPts;

        /*** management of other codecs here using av_frame_get_best_effort_timestamp() ***/


        /* With this approach I have been getting correct pts info after many av_read_frame loops */
        if(pCodecCtx->codec->id == AV_CODEC_ID_H264 && videoPath.toLower().endsWith(".mp4"))
        {
            pcktPts = av_rescale_q(packet.pts, //pFrame->pts always invalid here
                                      pFormatCtx->streams[videoStreamIndex]->time_base,
                                      pFormatCtx->streams[videoStreamIndex]->codec->time_base);
            pcktPts = (pcktPts/pCodecCtx->ticks_per_frame);
        }

        if(pcktPts == desiredFrame) ....
        /* more irrelevant code for reading, converting frame, etc */

也许我处理这种编解码器不正确,任何想法都会受到高度赞赏。

注意,我只对视频帧感兴趣。

好吧,我想我得到了一些东西。

似乎avformat_seek_file实际上想要您要查找的数据包的pts,而不是帧数,因此,由于我使用av_rescale_q将数据包pts转换为实际的帧号,我以为我必须执行相反的操作才能转换所需的数据包帧数到包点数。

现在在寻找之前,我像这样变换所需的帧号:

int target = desiredFrame *
             (pFormatCtx->streams[videoStreamIndex]->time_base.den /
              pFormatCtx->streams[videoStreamIndex]->time_base.num) /
             (pFormatCtx->streams[videoStreamIndex]->codec->time_base.den /
              pFormatCtx->streams[videoStreamIndex]->codec->time_base.num )*
              pCodecCtx->ticks_per_frame; 

目前,这似乎可以正常工作。 我仍然会提出任何建议,因为这是我想到的第一个解决方案,可能有点天真,我不确定它是否适用于所有情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM