FFmpeg 推流 RTSP 视频 - 完整教程及常见问题解决
使用 FFmpeg 推流 RTSP 视频 - 完整教程及常见问题解决
本文将介绍如何使用 FFmpeg 推流 RTSP 视频,并提供完整的代码示例以及常见问题的解决方法,帮助您快速入门 RTSP 视频推流。
1. 初始化 FFmpeg 库
av_register_all();
avformat_network_init();
2. 打开视频文件
AVFormatContext *formatContext = avformat_alloc_context();
if (avformat_open_input(&formatContext, 'path/to/your/mp4/file.mp4', nullptr, nullptr) != 0) {
qDebug() << 'Failed to open video file';
return -1;
}
3. 查找视频流
if (avformat_find_stream_info(formatContext, nullptr) < 0) {
qDebug() << 'Failed to find video stream';
return -1;
}
int videoStreamIndex = -1;
for (int i = 0; i < formatContext->nb_streams; i++) {
if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStreamIndex = i;
break;
}
}
if (videoStreamIndex == -1) {
qDebug() << 'Failed to find video stream';
return -1;
}
4. 获取视频流的解码器上下文
AVCodecContext *codecContext = avcodec_alloc_context3(nullptr);
avcodec_parameters_to_context(codecContext, formatContext->streams[videoStreamIndex]->codecpar);
5. 查找解码器
AVCodec *codec = avcodec_find_decoder(codecContext->codec_id);
if (codec == nullptr) {
qDebug() << 'Failed to find video decoder';
return -1;
}
6. 打开解码器
if (avcodec_open2(codecContext, codec, nullptr) < 0) {
qDebug() << 'Failed to open video decoder';
return -1;
}
7. 创建视频帧
AVFrame *frame = av_frame_alloc();
AVFrame *rgbFrame = av_frame_alloc();
8. 计算帧大小并分配帧缓冲区
int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codecContext->width, codecContext->height, 1);
uint8_t *buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize, buffer, AV_PIX_FMT_RGB24, codecContext->width, codecContext->height, 1);
9. 创建图像转换上下文
struct SwsContext *swsContext = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt,
codecContext->width, codecContext->height, AV_PIX_FMT_RGB24,
SWS_BILINEAR, nullptr, nullptr, nullptr);
10. 创建 RTSP 流的上下文并设置输出格式
AVFormatContext *rtspFormatContext = avformat_alloc_context();
AVOutputFormat *outputFormat = av_guess_format('rtsp', nullptr, nullptr);
rtspFormatContext->oformat = outputFormat;
11. 打开 RTSP 流
if (avio_open(&rtspFormatContext->pb, 'RTSP_URL', AVIO_FLAG_WRITE) < 0) {
qDebug() << 'Failed to open RTSP stream';
return -1;
}
12. 添加视频流到 RTSP 流
AVStream *rtspStream = avformat_new_stream(rtspFormatContext, nullptr);
avcodec_parameters_copy(rtspStream->codecpar, codecContext->codecpar);
rtspStream->codecpar->codec_tag = 0;
rtspStream->time_base = codecContext->time_base;
13. 写入 RTSP 流的头部
avformat_write_header(rtspFormatContext, nullptr);
14. 推送视频流到 RTSP 服务器
// 定义开始时间
qint64 startTime = QDateTime::currentMSecsSinceEpoch();
AVPacket packet;
while (av_read_frame(formatContext, &packet) >= 0) {
if (packet.stream_index == videoStreamIndex) {
// 解码视频帧
if (avcodec_send_packet(codecContext, &packet) >= 0) {
while (avcodec_receive_frame(codecContext, frame) >= 0) {
// 转换图像格式
sws_scale(swsContext, frame->data, frame->linesize, 0, codecContext->height, rgbFrame->data, rgbFrame->linesize);
// 设置时间戳
qint64 currentTime = QDateTime::currentMSecsSinceEpoch() - startTime;
rgbFrame->pts = av_rescale_q(currentTime, AV_TIME_BASE_Q, codecContext->time_base);
// 编码并写入 RTSP 流
av_interleaved_write_frame(rtspFormatContext, &packet);
}
}
}
av_packet_unref(&packet);
}
15. 写入 RTSP 流的尾部
av_write_trailer(rtspFormatContext);
16. 清理资源
avformat_close_input(&formatContext);
avcodec_free_context(&codecContext);
av_frame_free(&frame);
av_frame_free(&rgbFrame);
av_free(buffer);
avformat_free_context(rtspFormatContext);
常见问题解决
1. avcodec_parameters_copy(rtspStream->codecpar, codecContext->codecpar); 报错
该错误表示无法复制解码器上下文中的编解码器参数到 RTSP 流中的编解码器参数。这可能是由于编解码器参数类型不匹配导致的。
解决方法:
- 使用
avcodec_copy_context函数来复制解码器上下文中的参数,而不是使用avcodec_parameters_copy函数。
avcodec_copy_context(rtspStream->codec, codecContext);
- 如果使用
avcodec_copy_context函数仍然导致错误,可以尝试手动复制每个参数。
rtspStream->codecpar->codec_type = codecContext->codec_type;
rtspStream->codecpar->codec_id = codecContext->codec_id;
rtspStream->codecpar->bit_rate = codecContext->bit_rate;
// 继续复制其他参数...
请注意,根据 FFmpeg 版本的不同,代码可能需要进行相应的调整。另外,确保 RTSP_URL 变量包含正确的 RTSP 服务器 URL。
总结
本文详细介绍了使用 FFmpeg 推流 RTSP 视频的完整流程,并提供了一些常见问题的解决方法。希望本文能帮助您快速入门 RTSP 视频推流,并顺利实现您的项目需求。
原文地址: https://www.cveoy.top/t/topic/pxe8 著作权归作者所有。请勿转载和采集!