赞
踩
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; //error return; } //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: 媒体文件的码率,单位为bps printf("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: 音频编码解码器的采样率,单位为HZ printf("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"); else printf("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.050000 audio pts: 5984(191488) audio dts: 191488 audio size: 395 audio pos: 5903014 audio duration: 0.032000 video pts: 6000(61440) video dts: 61440 video size: 4319 video pos: 5903409 video duration: 0.050000 audio pts: 6016(192512) audio dts: 192512 audio size: 275 audio pos: 5907728 audio duration: 0.032000 audio pts: 6048(193536) audio dts: 193536 audio size: 260 audio pos: 5908003 audio duration: 0.032000 video pts: 6050(61952) video dts: 61952 video size: 2956 video pos: 5908263 video duration: 0.050000 audio pts: 6080(194560) audio dts: 194560 audio size: 283 audio pos: 5911219 audio duration: 0.032000 video pts: 6100(62464) video dts: 62464 video size: 4262 video pos: 5911502 video duration: 0.050000 audio pts: 6112(195584) audio dts: 195584 audio size: 266 audio pos: 5915764 audio duration: 0.032000 audio pts: 6144(196608) audio dts: 196608 audio size: 327 audio pos: 5916030 audio duration: 0.032000
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。