• av_seek_frame() 定位为什么不准呢?


    初次学习和使用ffmpeg,电脑系统有点老,没办法使用最新版的ffmpeg 3.3,只能从别处下载了一个2.8版的用用,官网提供的历史版本都没有我电脑可用的版本。

    花了两天时间学习并写了一个简单的处理视频的程序,实现视频的截屏保存为jpg图片。

    本来想用SDL写个播放器,但写着写着,感觉实现视频、音频同步什么的有点难,有点累,就没再继续。

    今天在研究视频定位(seek)的时候,在测试代码时发现问题:

    我测试了不同格式的视频: mp4,flv,mov,3gp,wmv,mkv,avi

    定位,我用的是 av_seek_frame(),如果定位:wmv,avi,3gp 等,我只需简单的使用:

    int64_t seekTime_us = (int64_t)8 * AV_TIME_BASE; //单位: 微秒, 必须加 (int64_t),否则有可能发生数据溢出。
    av_seek_frame(pFormatCtx, -1 , seekTime_us, AVSEEK_FLAG_BACKWARD); // AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY | AVSEEK_FLAG_FRAME

    结果:定位很准确。

    但上面的代码用来定位:mp4,flv,mov,mkv等,经常会遇到定位不准的情况,误差在[0-5秒]左右。

    在网上搜索了半天,找到下面另一种计算方法,经测试和上面的效果其实是一样的,误差在[0-5秒]左右,还不如上面的简单。

    int startSecond = 8;
    int64_t seekTime_us = startSecond * AV_TIME_BASE; //单位: 微秒
    int64_t targetFrame = av_rescale_q(seekTime_us, AV_TIME_BASE_Q, pFormatCtx->streams[videoStream]->time_base);

    int64_t seekStreamDuration = pFormatCtx->streams[videoStream]->duration;
    int flags = AVSEEK_FLAG_BACKWARD; //默认使用
    if(targetFrame > 0 && targetFrame < seekStreamDuration)
    {
        // H.264 I frames don't always register as "keyframes" in FFmpeg
        flags |= AVSEEK_FLAG_ANY; //加了这个,有时定位更不准
    }

    av_seek_frame(pFormatCtx, videoStream, targetFrame, flags);
    avcodec_flush_buffers(pCodecCtx);

    我又换了个方式:先计算视频的总帧数(frameCount),然后通过fps计算出8秒位置的frame_index, 不用av_seek_frame,直接通过while(av_read_frame()),跳过frame_index,来实现seek,这个方法定位非常准,但不科学。因为如果要定位到60秒,我用的电脑光是花费在while(av_read_frame())上的时间就将近4秒,效率太低了,只适合定位开头几十秒内。

    谁能告诉我,怎样用 av_seek_frame 来定位 mp4,flv 格式的视频精准一点,不要定位到8秒,显示的是5秒时的内容。

  • 相关阅读:
    《maven实战》笔记(5)----maven的版本
    《maven实战》笔记(4)----maven的仓库
    《maven实战》笔记(2)----一个简单maven项目的搭建,测试和打包
    《maven实战》笔记(1)----maven的初识
    web项目jsp出现The superclass javax.servlet.http.HttpServlet was not found on the Java Build Path错误
    如何在国内使用google
    js实现仿购物车加减效果
    关于行内元素之间有空隙的问题,例如span与input之间
    jquery遍历DOM方法总结
    左侧手风琴下拉菜单导航(网页常用功能)
  • 原文地址:https://www.cnblogs.com/personnel/p/7265775.html
Copyright © 2020-2023  润新知