ffmpeg 入门(二、打开视频文件)
·
二、打开视频文件
视频解码一般流程:
1. 打开视频文件
2. 查找视频流(音频流,视频流,字母流)
3. 获取解码器,创建解码器上下文(AVCodecContext)并初始化
4. 创建 AVPacket 和 AVFrame,用于接收存储编码后的媒体数据和解码后的数据
5. 读取 AVPacket,向解码器发送 AVPacket,接收解码后的数据
6. 将解码后的数据转成特定的数据格式(如: 解码后的图像一般是 yuv 数据格式,需转成 rgb)
7. 释放内存
extern "C" { // 用C规则编译指定的代码
#include <libavformat/avformat.h>
}
#include <iostream>
using namespace std;
int main() {
AVFormatContext *fmt_ctx = NULL;
const char *filename = "https://stream7.iqilu.com/10339/upload_transcode/202002/09/20200209104902N3v5Vpxuvb.mp4";
// const char *filename = "test.mp4"; // 替换成自己本地路径
// 已不再需要
// avformat_network_init();
// 打开输入文件
int ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL);
if (ret < 0) {
return ret;
}
ret = avformat_find_stream_info(fmt_ctx, NULL);
if (ret < 0) {
// 没有找到视频流信息
return ret;
}
// 打印时长(单位:秒)
printf("时长: %.2f 秒\n", (double)fmt_ctx->duration / AV_TIME_BASE);
// 查找视频流
int video_stream_idx = -1;
/*
遍历查找
for (unsigned int i = 0; i < fmt_ctx->nb_streams; i++) {
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_idx = i;
break;
}
}*/
video_stream_idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
if (video_stream_idx >= 0) {
AVStream *stream = fmt_ctx->streams[video_stream_idx];
cout << "帧率: " << av_q2d(stream->avg_frame_rate) << endl;
cout << "分辨率: " << stream->codecpar->width << " " <<
stream->codecpar->height << endl;
cout << "编码格式: " << avcodec_get_name(stream->codecpar->codec_id) << endl;
}
// 关闭文件并释放上下文
avformat_close_input(&fmt_ctx);
return 0;
}
函数说明
/**
* Open an input stream and read the header. The codecs are not opened.
* The stream must be closed with avformat_close_input().
*
* @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
* May be a pointer to NULL, in which case an AVFormatContext is allocated by this
* function and written into ps.
* Note that a user-supplied AVFormatContext will be freed on failure.
* @param url URL of the stream to open.
* @param fmt If non-NULL, this parameter forces a specific input format.
* Otherwise the format is autodetected.
* @param options A dictionary filled with AVFormatContext and demuxer-private options.
* On return this parameter will be destroyed and replaced with a dict containing
* options that were not found. May be NULL.
*
* @return 0 on success, a negative AVERROR on failure.
*
* @note If you want to use custom IO, preallocate the format context and set its pb field.
*/
int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);
ps
输出参数,指向 AVFormatContext 的指针。函数成功后,该指针将被初始化为有效的上下文。使用完毕后需通过 avformat_close_input() 释放。
url
输入媒体的路径或 URL:
本地文件:"input.mp4"
网络流:"rtsp://example.com/stream"
设备:"v4l2:/dev/video0"(Linux 摄像头)
fmt
指定输入格式(如 av_find_input_format(“mp4”))。通常设为 NULL,让 FFmpeg 自动探测格式。
const AVInputFormat *fmt = av_find_input_format("mp4");
//const AVInputFormat *fmt = av_find_input_format("rtsp");
//const AVInputFormat *fmt = av_find_input_format("rawvideo");
// 打开输入文件,强制使用指定格式
avformat_open_input(&fmt_ctx, filename, fmt, NULL);
options
传递额外选项(如网络超时、缓冲区大小)
AVDictionary *opts = NULL;
av_dict_set(&opts, "timeout", "5000000", 0); // 5 秒超时(微秒)
avformat_open_input(&fmt_ctx, url, NULL, &opts);
av_dict_free(&opts);
/**
* Find the "best" stream in the file.
* The best stream is determined according to various heuristics as the most
* likely to be what the user expects.
* If the decoder parameter is non-NULL, av_find_best_stream will find the
* default decoder for the stream's codec; streams for which no decoder can
* be found are ignored.
*
* @param ic media file handle
* @param type stream type: video, audio, subtitles, etc.
* @param wanted_stream_nb user-requested stream number,
* or -1 for automatic selection
* @param related_stream try to find a stream related (eg. in the same
* program) to this one, or -1 if none
* @param decoder_ret if non-NULL, returns the decoder for the
* selected stream
* @param flags flags; none are currently defined
* @return the non-negative stream number in case of success,
* AVERROR_STREAM_NOT_FOUND if no stream with the requested type
* could be found,
* AVERROR_DECODER_NOT_FOUND if streams were found but no decoder
* @note If av_find_best_stream returns successfully and decoder_ret is not
* NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec.
*
*/
int av_find_best_stream(AVFormatContext *ic,
enum AVMediaType type,
int wanted_stream_nb,
int related_stream,
AVCodec **decoder_ret,
int flags);
type
enum AVMediaType {
AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA
AVMEDIA_TYPE_VIDEO,
AVMEDIA_TYPE_AUDIO,
AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous
AVMEDIA_TYPE_SUBTITLE,
AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse
AVMEDIA_TYPE_NB
};
如果 decoder_ret 不为 NULL,自动查找并返回与该流匹配的解码器
更多推荐



所有评论(0)