使用 C++ 和 FFmpeg创建RTSP 服务器示例
时间: 2024-05-13 19:15:31 浏览: 186
c++ rtsp server
创建RTSP服务器需要以下步骤:
1. 初始化FFmpeg库
2. 打开输入文件或设备
3. 设置视频和音频流的编码器和参数
4. 创建AVFormatContext和AVCodecContext
5. 打开输出网络流
6. 循环读取输入流并编码输出
7. 关闭输入输出流和编码器
8. 释放FFmpeg库
下面是一个使用C++和FFmpeg创建RTSP服务器的示例代码:
```cpp
#include <iostream>
#include <string>
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
#include <cstring>
extern "C" {
#include <libavformat/avformat.h>
}
#define RTSP_ADDRESS "rtsp://127.0.0.1:8554/test"
int main(int argc, char* argv[]) {
AVFormatContext* input_format_ctx = nullptr;
AVCodecContext* input_codec_ctx = nullptr;
AVStream* input_stream = nullptr;
AVFormatContext* output_format_ctx = nullptr;
AVCodecContext* output_codec_ctx = nullptr;
AVStream* output_stream = nullptr;
AVPacket* packet = nullptr;
int ret = 0, video_stream_index = -1, audio_stream_index = -1;
// Initialize FFmpeg library
av_register_all();
avformat_network_init();
// Open input file or device
if ((ret = avformat_open_input(&input_format_ctx, "video.mp4", nullptr, nullptr)) < 0) {
std::cerr << "Failed to open input file: " << av_err2str(ret) << std::endl;
goto end;
}
// Retrieve stream information
if ((ret = avformat_find_stream_info(input_format_ctx, nullptr)) < 0) {
std::cerr << "Failed to retrieve stream information: " << av_err2str(ret) << std::endl;
goto end;
}
// Find video and audio streams
for (int i = 0; i < input_format_ctx->nb_streams; i++) {
AVStream* stream = input_format_ctx->streams[i];
if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_stream_index < 0) {
video_stream_index = i;
}
if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_stream_index < 0) {
audio_stream_index = i;
}
}
// Create output format context
if ((ret = avformat_alloc_output_context2(&output_format_ctx, nullptr, "rtsp", RTSP_ADDRESS)) < 0) {
std::cerr << "Failed to create output format context: " << av_err2str(ret) << std::endl;
goto end;
}
// Create output video stream
input_stream = input_format_ctx->streams[video_stream_index];
output_stream = avformat_new_stream(output_format_ctx, input_stream->codecpar->codec);
output_stream->id = video_stream_index;
if ((ret = avcodec_parameters_copy(output_stream->codecpar, input_stream->codecpar)) < 0) {
std::cerr << "Failed to copy codec parameters: " << av_err2str(ret) << std::endl;
goto end;
}
output_codec_ctx = output_stream->codec;
output_codec_ctx->codec_tag = 0;
if ((ret = avcodec_open2(output_codec_ctx, nullptr, nullptr)) < 0) {
std::cerr << "Failed to open codec: " << av_err2str(ret) << std::endl;
goto end;
}
// Open output network stream
if (!(output_format_ctx->flags & AVFMT_NOFILE)) {
if ((ret = avio_open(&output_format_ctx->pb, RTSP_ADDRESS, AVIO_FLAG_WRITE)) < 0) {
std::cerr << "Failed to open output network stream: " << av_err2str(ret) << std::endl;
goto end;
}
}
// Write output stream header
if ((ret = avformat_write_header(output_format_ctx, nullptr)) < 0) {
std::cerr << "Failed to write output stream header: " << av_err2str(ret) << std::endl;
goto end;
}
// Initialize packet for encoding
packet = av_packet_alloc();
if (!packet) {
std::cerr << "Failed to allocate packet" << std::endl;
goto end;
}
// Read input stream and encode output stream
while (true) {
AVStream* in_stream = nullptr;
AVStream* out_stream = nullptr;
if ((ret = av_read_frame(input_format_ctx, packet)) < 0) {
break;
}
in_stream = input_format_ctx->streams[packet->stream_index];
if (packet->stream_index == video_stream_index) {
out_stream = output_format_ctx->streams[packet->stream_index];
packet->pts = av_rescale_q_rnd(packet->pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
packet->dts = av_rescale_q_rnd(packet->dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
packet->duration = av_rescale_q(packet->duration, in_stream->time_base, out_stream->time_base);
packet->pos = -1;
if ((ret = av_interleaved_write_frame(output_format_ctx, packet)) < 0) {
std::cerr << "Failed to encode video packet: " << av_err2str(ret) << std::endl;
goto end;
}
}
av_packet_unref(packet);
}
// Write output stream trailer
if ((ret = av_write_trailer(output_format_ctx)) < 0) {
std::cerr << "Failed to write output stream trailer: " << av_err2str(ret) << std::endl;
goto end;
}
end:
// Close input and output streams and codecs
if (input_format_ctx) {
avformat_close_input(&input_format_ctx);
}
if (output_format_ctx) {
avio_closep(&output_format_ctx->pb);
avformat_free_context(output_format_ctx);
}
if (packet) {
av_packet_free(&packet);
}
avformat_network_deinit();
avcodec_free_context(&input_codec_ctx);
avcodec_free_context(&output_codec_ctx);
return ret;
}
```
这个示例代码使用了一个名为"video.mp4"的文件作为输入文件,并将视频流编码为RTSP输出流。在实际使用中,您需要根据您的需求更改输入源和输出地址。
阅读全文