代码是使用 ffmpeg 捕获 10 秒 rtsp 流,平台是 windows ,IDE 使用 visual studio 。代码是让 chatgpt 写的 demo,执行到avcodec_receive_frame
时,报错如下。
ffmpeg 使用的编译版本:ffmpeg-6.0-full_build-shared.7z
c++代码:
#include <iostream>
#include <chrono>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
int main(int argc, char *argv[]) {
std::string url = "rtsp://example.com/stream";
int duration = 10; // 获取 10 秒视频
av_register_all();
AVFormatContext *format_ctx = nullptr;
AVCodecContext *codec_ctx = nullptr;
AVPacket packet = { 0 };
AVFrame *frame = nullptr;
// 打开 RTSP 流并读取视频流信息
if (avformat_open_input(&format_ctx, url.c_str(), nullptr, nullptr) < 0) {
std::cerr << "Error: Could not open input file: " << url << std::endl;
return -1;
}
if (avformat_find_stream_info(format_ctx, nullptr) < 0) {
std::cerr << "Error: Could not find stream information" << std::endl;
return -1;
}
// 查找视频流索引
int video_stream_index = av_find_best_stream(format_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
if (video_stream_index < 0) {
std::cerr << "Error: Could not find video stream in input file" << std::endl;
return -1;
}
// 根据视频流索引获取视频解码器上下文
codec_ctx = avcodec_alloc_context3(nullptr);
if (!codec_ctx) {
std::cerr << "Error: Could not allocate video codec context" << std::endl;
return -1;
}
if (avcodec_parameters_to_context(codec_ctx, format_ctx->streams[video_stream_index]->codecpar) < 0) {
std::cerr << "Error: Could not initialize video codec parameters" << std::endl;
return -1;
}
AVCodec *codec = avcodec_find_decoder(codec_ctx->codec_id);
if (!codec) {
std::cerr << "Error: Could not find video codec" << std::endl;
return -1;
}
if (avcodec_open2(codec_ctx, codec, nullptr) < 0) {
std::cerr << "Error: Could not open video codec" << std::endl;
return -1;
}
// 分配视频帧内存
frame = av_frame_alloc();
if (!frame) {
std::cerr << "Error: Could not allocate video frame" << std::endl;
return -1;
}
// 读取视频帧直到达到指定的时长
int64_t start_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
while (true) {
if (av_read_frame(format_ctx, &packet) >= 0) {
if (packet.stream_index == video_stream_index) {
int ret = avcodec_send_packet(codec_ctx, &packet);
if (ret < 0) {
std::cerr << "Error: Could not send packet to video codec" << std::endl;
break;
}
while (ret >= 0) {
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
std::cerr << "Error: Could not receive frame from video codec" << std::endl;
break;
}
int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
if (now - start_time >= duration * 1000) { // 达到指定时长,退出循环
break;
}
// 处理视频帧,例如保存到文件或显示到屏幕上
// ...
av_frame_unref(frame);
}
av_packet_unref(&packet);
}
} else {
break;
}
}
// 清理资源
avcodec_free_context(&codec_ctx);
avformat_close_input(&format_ctx);
av_frame_free(&frame);
return 0;
}
环境搭建后,成功执行了官方源码doc/examples
中的remux.c
示例。
正在学习 c++,对于这个报错实在是没有头绪。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.