av_seek_frame函数

/*** Seek to the keyframe at timestamp.* 'timestamp' in 'stream_index'.** @param s media file handle* @param stream_index If stream_index is (-1), a default* stream is selected, and timestamp is automatically converted* from AV_TIME_BASE units to the stream specific time_base.* @param timestamp Timestamp in AVStream.time_base units*        or, if no stream is specified, in AV_TIME_BASE units.* @param flags flags which select direction and seeking mode* @return >= 0 on success*/
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);

stream_index:用于seek的流索引,-1为默认,一般0为视频流索引,1为音频流索引
timestamp:定位的时间戳,单位以流的time_base为单位,并非毫秒单位的时间戳,因此如果seek,需要结合具体的流的time_base计算对应单位的时间戳
flags:可以设置为按字节,在按时间seek时取该点之前还是之后的关键帧,以及不按关键帧seek等。具体的值有如下几个,可以通过运算符来进行组合
#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward
#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes
#define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes
#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number
ts一般使用AVSEEK_FLAG_BYTE,mp4一般使用AVSEEK_FLAG_ANY、AVSEEK_FLAG_BACKWARD(seek到对应时间戳之前的最后一个关键帧)

下面给出一段实例代码,代码中是对mp4文件按照音频流进行seek,seek的时间点为6秒。

 av_register_all();std::string path = "E:\\media\\test.mp4";const char *in_filename = path.c_str();//设置日志级别av_log_set_level(AV_LOG_INFO);//通过日志的形式打印av_log(NULL, AV_LOG_INFO, "\n in_filename = %s\n", in_filename);//AVFormatContext是描述一个媒体文件或媒体流构成和基本信息的结构体AVFormatContext *ifmt_ctx = NULL;   // 输入文件的demux(解复用)int videoindex = -1;  //视频索引int audioindex = -1;  //音频索引//1 打开文件,主要探测协议类型,如果是网络文件需要插件网络连接int ret = avformat_open_input(&ifmt_ctx, in_filename, NULL, NULL);if (ret < 0){//打印失败原因char buf[1024] = { 0 };av_strerror(ret, buf, sizeof(buf) - 1);av_log(NULL, AV_LOG_ERROR, "open %s failed:%s\n", in_filename, buf);//open believe.mp41 failed:No such file or directory//        goto failed;  //errorreturn;}//2 读取媒体的码流信息ret = avformat_find_stream_info(ifmt_ctx, NULL);if (ret < 0){char buf[1024] = { 0 };av_strerror(ret, buf, sizeof(buf) - 1);av_log(NULL, AV_LOG_ERROR, "avformat_find_stream_info %s failed:%s\n", in_filename, buf);//        goto filed;  //error ??return;}av_log(NULL, AV_LOG_INFO, "\n==== av_dump_format in_filename:%s ===\n", in_filename);//    打印输入或输出格式的详细信息//    void av_dump_format(AVFormatContext *ic, int index, const char *url,int is_output);av_dump_format(ifmt_ctx, 0, in_filename, 0);av_log(NULL, AV_LOG_INFO, "\n==== av_dump_format finish =======\n\n");//查看媒体文件的一些信息//打印媒体的路径av_log(NULL, AV_LOG_INFO, "media name: %s\n", ifmt_ctx->filename);//nb_streams媒体流数量printf("media stream number: %d\n", ifmt_ctx->nb_streams); //media stream number: 2//bit_rate: 媒体文件的码率,单位为bpsprintf("media average ratio:%11d\n", (int64_t)(ifmt_ctx->bit_rate / 1024));//时间int total_seconds, hours, minute, second;//duration: 媒体文件时长,单位微秒total_seconds = (ifmt_ctx->duration) / AV_TIME_BASE;  // 1000us = 1ms, 1000ms = 1秒hours = total_seconds / 3600;minute = (total_seconds % 3600) / 60;second = (total_seconds % 60);printf("total duration: %02d:%02d:%02d\n", hours, minute, second);printf("\n");AVRational in_timebase_v;AVRational in_timebase_a;/** 老版本通过遍历的方式读取媒体文件视频和音频的信息* 新版本的FFmpeg新增加了函数av_find_best_stream,也可以取得同样的效果*/for (uint32_t i = 0;i < ifmt_ctx->nb_streams;++i){AVStream *in_stream = ifmt_ctx->streams[i];  //音频流,视频流,字幕流//如果是音频流,则打印音频的信息if (AVMEDIA_TYPE_AUDIO == in_stream->codecpar->codec_type){in_timebase_a = in_stream->time_base;printf("----- Audio info timebase:%d/%d\n", in_timebase_a.num, in_timebase_a.den);//index: 每个流成分在ffmpeg解复用分析后都有唯一的index作为标书printf("index:%d\n", in_stream->index);//sample_rate: 音频编码解码器的采样率,单位为HZprintf("samplerate:%dnHZ\n", in_stream->codecpar->sample_rate);// codecpar->format:音频采样格式if (AV_SAMPLE_FMT_FLTP == in_stream->codecpar->format){printf("sampleformat:AV_SAMPLE_FMT_FLTP\n");}else if (AV_SAMPLE_FMT_S16P == in_stream->codecpar->format){printf("sampleformat:AV_SAMPLE_FMT_S16P\n");}//channels:音频信道数目printf("channels number:%d\n", in_stream->codecpar->channels);//codec_id: 音频压缩编码格式if (AV_CODEC_ID_AAC == in_stream->codecpar->codec_id)printf("audio codec:AAC\n");else if (AV_CODEC_ID_MP3 == in_stream->codecpar->codec_id)printf("audio codec:MP3\n");elseprintf("audio codec_id:%d\n", in_stream->codecpar->codec_id);// 音频总时长,单位为秒。注意如果把单位放大为毫秒或者微妙,音频总时长跟视频总时长不一定相等的if (in_stream->duration != AV_NOPTS_VALUE){int duration_audio = (in_stream->duration) * av_q2d(in_stream->time_base);//将音频总时长转换为时分秒的格式打印到控制台上printf("audio duration: %02d:%02d:%02d\n",duration_audio / 3600, (duration_audio % 3600) / 60, (duration_audio % 60));}else  //如果无效{printf("audio duration unknown");}printf("\n");audioindex = i;}else if (AVMEDIA_TYPE_VIDEO == in_stream->codec->codec_type){in_timebase_v = in_stream->time_base;printf("----- Video info:timebase:%d/%d\n", in_timebase_v.num, in_timebase_v.den);printf("index:%d\n", in_stream->index);// avg_frame_rate: 视频帧率,单位为fps,表示每秒出现多少帧printf("fps:%lf\n", av_q2d(in_stream->avg_frame_rate));if (AV_CODEC_ID_MPEG4 == in_stream->codecpar->codec_id) //视频压缩编码格式{printf("video codec:MPEG4\n");}else if (AV_CODEC_ID_H264 == in_stream->codecpar->codec_id) //视频压缩编码格式{printf("video codec:H264\n");}else{printf("video codec_id:%d\n", in_stream->codecpar->codec_id);}// 视频帧宽度和帧高度printf("width:%d height:%d\n", in_stream->codecpar->width,in_stream->codecpar->height);//视频总时长,单位为秒。注意如果把单位放大为毫秒或者微妙,音频总时长跟视频总时长不一定相等的if (in_stream->duration != AV_NOPTS_VALUE){int duration_video = (in_stream->duration) * av_q2d(in_stream->time_base);printf("video duration: %02d:%02d:%02d\n",duration_video / 3600,(duration_video % 3600) / 60,(duration_video % 60)); //将视频总时长转换为时分秒的格式打印到控制台上}else{printf("video duration unknown");}printf("\n");videoindex = i;}}//3 从文件中读取数据包AVPacket *pkt = av_packet_alloc();int pkt_count = 0;int print_max_count = 1000;printf("\n-----av_read_frame start\n");zint64 seekSecValue = 6;int64_t startTime = seekSecValue / av_q2d(in_timebase_a);ret = av_seek_frame(ifmt_ctx, audioindex , startTime, AVSEEK_FLAG_BACKWARD|AVSEEK_FLAG_ANY);while (1){//读取音视频包ret = av_read_frame(ifmt_ctx, pkt);if (ret < 0){printf("-----av_read_frame end\n");break;}if (pkt_count++ < print_max_count){if (pkt->stream_index == audioindex){zint64 pts = pkt->pts*1000.0*in_timebase_a.num / in_timebase_a.den;printf("audio pts: %lld(%lld)\n", pts, pkt->pts);printf("audio dts: %lld\n", pkt->dts);printf("audio size: %d\n", pkt->size);printf("audio pos: %lld\n", pkt->pos);printf("audio duration: %lf\n\n",pkt->duration * av_q2d(ifmt_ctx->streams[audioindex]->time_base));}else if (pkt->stream_index == videoindex){zint64 pts = pkt->pts*1000.0*in_timebase_v.num / in_timebase_v.den;printf("video pts: %lld(%lld)\n", pts, pkt->pts);printf("video dts: %lld\n", pkt->dts);printf("video size: %d\n", pkt->size);printf("video pos: %lld\n", pkt->pos);printf("video duration: %lf\n\n",pkt->duration * av_q2d(ifmt_ctx->streams[videoindex]->time_base));}else {printf("unknown stream_index:\n", pkt->stream_index);}}av_packet_unref(pkt);}if (pkt)av_packet_free(&pkt);//4 关闭复用器
//failed:if (ifmt_ctx)avformat_close_input(&ifmt_ctx);

输出信息如下图所示:

media stream number: 2
media average ratio:       2155
total duration: 00:19:47----- Video info:timebase:1/10240
index:0
fps:20.000000
video codec:H264
width:1920 height:1080
video duration: 00:19:47----- Audio info timebase:1/32000
index:1
samplerate:32000nHZ
sampleformat:AV_SAMPLE_FMT_FLTP
channels number:1
audio codec:AAC
audio duration: 00:19:47-----av_read_frame start
video pts: 5950(60928)
video dts: 60928
video size: 4136
video pos: 5898643
video duration: 0.050000audio pts: 5984(191488)
audio dts: 191488
audio size: 395
audio pos: 5903014
audio duration: 0.032000video pts: 6000(61440)
video dts: 61440
video size: 4319
video pos: 5903409
video duration: 0.050000audio pts: 6016(192512)
audio dts: 192512
audio size: 275
audio pos: 5907728
audio duration: 0.032000audio pts: 6048(193536)
audio dts: 193536
audio size: 260
audio pos: 5908003
audio duration: 0.032000video pts: 6050(61952)
video dts: 61952
video size: 2956
video pos: 5908263
video duration: 0.050000audio pts: 6080(194560)
audio dts: 194560
audio size: 283
audio pos: 5911219
audio duration: 0.032000video pts: 6100(62464)
video dts: 62464
video size: 4262
video pos: 5911502
video duration: 0.050000audio pts: 6112(195584)
audio dts: 195584
audio size: 266
audio pos: 5915764
audio duration: 0.032000audio pts: 6144(196608)
audio dts: 196608
audio size: 327
audio pos: 5916030
audio duration: 0.032000

ffmpeg新手成长之路——使用av_seek_frame做seek定位相关推荐

  1. ffmpeg新手成长之路——关于flv转封装过程中编码器信息变化如何处理(困扰已久的avc sequence header更新问题)

    ffmpeg新手成长之路 --关于flv转封装过程中编码器信息变化如何处理(困扰已久的avc sequence header更新问题) 一.背景介绍 私有协议传输H264裸流,进行录制,使用ffmpe ...

  2. 架构师成长之路:如何做基础框架设计?架构师落地的核心能力

    前面,已经统一了对框架的认识. 接下来看看如何做基础框架设计,聊聊要做些什么.以及如何做基础框架设计:然后再看看使用基础框架功能的基本方式. 一:基础框架要实现的功能的来源 1:持续积累的通用功能.公 ...

  3. 《小白H5成长之路50》js与PHP配合完成图片上传功能

    "小白!还记得之前我们说过的jQuery中的ajax异步加载数据的方法么?" "记得,之前的代码我这里还有,你看看是不是这个?" 老朱:"恩,没错,通 ...

  4. 京东无人超市的成长之路 | 如何利用人工智能技术在零售业做产品创新?

    随着消费及用户体验的需求升级.人货场的运营效率需求提升.人工智能技术的突破以及零售基础设施的变革等因素共同推动了第四次零售革命的到来,不仅在国内,国外一线巨头互联网亚马逊等企业都在研发无人驾驶.无人超 ...

  5. 音视频开发成长之路—进阶之路3个重要知识点丨WebRTC丨FFmpeg丨SRS流媒体服务器丨C++音视频丨嵌入式音视频

    音视频开发成长之路-进阶之路3个重要知识点 视频讲解如下,点击观看: 音视频开发成长之路-进阶之路3个重要知识点丨WebRTC丨FFmpeg丨SRS流媒体服务器丨C++音视频丨嵌入式音视频 音视频高级 ...

  6. 十年风雨,一个普通程序员的成长之路(八)不想做技术总监的项目经理,不是好程序员...

    目录 十年风雨,一个普通程序员的成长之路(八)不想做技术总监的项目经理,不是好程序员 01 技术总监写不写代码? 02 面试的坎坷与杯具 03 新的开始 & 旧的结束 十年风雨,一个普通程序员 ...

  7. 15 年腾讯老兵谈技术人成长之路

    作者:alexguo,腾讯TEG技术总监&技术专家 每个职场人都会经历从职场新人到骨干.专家亦或是管理者的蜕变过程.作为技术职业人,大家常会碰到一些困惑,在不同职业发展阶段所需要具备的认知和专 ...

  8. 写作—开启技术成长之路

    一.前言 作为一名程序员,经常在网络上查找各种各样的资料.此时,会检索到很多优秀的技术文章.一篇好的技术文章,可能不仅仅会解决我们的问题,更能在阅读的过程中带给我们一些美好的体验. 许多时候我们也憧憬 ...

  9. 原创电子书《菜鸟程序员成长之路:从技术小白到阿里巴巴Java工程师》

    <菜鸟程序员成长之路:从技术小白到阿里巴巴Java工程师> 国庆节快乐!一年一度长度排第二的假期终于来了. 难得有十一长假,作者也想要休息几天啦. 不管你是选择出门玩,还是在公司加班,在学 ...

最新文章

  1. Compiler编译过程
  2. linux下汇编程序gas,Linux 汇编语言(GNU GAS汇编)开发指南
  3. Linux-鸟菜-6-文件与目录的 默认权限、隐藏权、特殊权限
  4. nginx 配置expires
  5. Leet Code OJ 260. Single Number III [Difficulty: Medium]
  6. 使用ps制作旧羊皮纸
  7. Cesium:去除原生自带绿色选择框
  8. 接口测试及服务器性能压测,接口测试及服务器性能压测
  9. 疯狂涨知识!最全的java手机游戏免费下载基地
  10. 防御 DDoS 的终极奥义——又拍云 SCDN
  11. web前端开发技术----登录页面
  12. matlab 平滑曲线连接_曲线拟合的一些想法
  13. opencv subtract函数内存泄漏
  14. 秀动app抢票脚本_程序员硬核quot;Python抢票教程”,帮你抢回家车票
  15. 共享一个计算属相年份的咚咚-----javascript 代码
  16. uni-app实战之社区交友APP(4)首页开发
  17. word怎么自动换行
  18. 拍立淘-以图搜图中的图像搜索算法
  19. HTML页面、CSS样式的以及js学习与介绍
  20. 计算机二级c常用算法,闽高校计算机二级C语言常用算法

热门文章

  1. uniapp点击生成商品海报、下载海报、分享海报
  2. 中银涨停,A股牛市要启动了吗?
  3. ESP8266 MP3制作——esp8266联网
  4. 《闻官军收河南河北》 杜甫
  5. Android 3D滑动菜单完全解析,实现推拉门式的立体特效
  6. 【基础】HBuilderX 找不到手机或模拟器设备(安卓端)
  7. excel下拉列表数据筛选_从筛选的Excel列表中下拉
  8. Attribute特性定义及应用
  9. php如何实现简繁体互转
  10. 李沐-斯坦福《实用机器学习》-02章