c++ 使用ffmpeg4.x实现rtsp推流代码
时间: 2024-03-11 19:47:42 浏览: 76
MPEG4.zip_ffmpeg rtsp C++_ffmpeg mpeg4_ffmpeg rtsp_live555 rts
下面是一个简单的使用FFmpeg 4.x实现RTSP推流的C++代码示例:
```c++
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/time.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
using namespace std;
#define WIDTH 640
#define HEIGHT 480
#define FPS 25
#define BITRATE 400000
#define RTSP_URL "rtsp://localhost:8554/test.sdp"
int main(int argc, char **argv) {
AVFormatContext *fmt_ctx = NULL;
AVCodecContext *codec_ctx = NULL;
AVCodec *codec = NULL;
AVStream *stream = NULL;
AVFrame *frame = NULL;
AVPacket packet;
int ret = 0;
int frame_count = 0;
int64_t start_time = 0;
struct timeval tv;
int64_t pts = 0;
av_register_all();
avformat_network_init();
// 打开输出流
ret = avformat_alloc_output_context2(&fmt_ctx, NULL, "rtsp", RTSP_URL);
if (ret < 0) {
cout << "avformat_alloc_output_context2 failed: " << av_err2str(ret) << endl;
exit(1);
}
// 添加视频流
codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec) {
cout << "avcodec_find_encoder failed" << endl;
exit(1);
}
stream = avformat_new_stream(fmt_ctx, codec);
if (!stream) {
cout << "avformat_new_stream failed" << endl;
exit(1);
}
codec_ctx = stream->codec;
codec_ctx->codec_id = codec->id;
codec_ctx->bit_rate = BITRATE;
codec_ctx->width = WIDTH;
codec_ctx->height = HEIGHT;
codec_ctx->time_base = (AVRational){1, FPS};
codec_ctx->gop_size = 10;
codec_ctx->max_b_frames = 1;
codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
if (fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
ret = avcodec_open2(codec_ctx, codec, NULL);
if (ret < 0) {
cout << "avcodec_open2 failed: " << av_err2str(ret) << endl;
exit(1);
}
av_dump_format(fmt_ctx, 0, RTSP_URL, 1);
ret = avio_open(&fmt_ctx->pb, RTSP_URL, AVIO_FLAG_WRITE);
if (ret < 0) {
cout << "avio_open failed: " << av_err2str(ret) << endl;
exit(1);
}
ret = avformat_write_header(fmt_ctx, NULL);
if (ret < 0) {
cout << "avformat_write_header failed: " << av_err2str(ret) << endl;
exit(1);
}
// 创建帧
frame = av_frame_alloc();
frame->width = WIDTH;
frame->height = HEIGHT;
frame->format = AV_PIX_FMT_YUV420P;
ret = av_frame_get_buffer(frame, 32);
if (ret < 0) {
cout << "av_frame_get_buffer failed: " << av_err2str(ret) << endl;
exit(1);
}
// 循环推流
while (true) {
gettimeofday(&tv, NULL);
if (start_time == 0) {
start_time = tv.tv_sec * 1000000 + tv.tv_usec;
}
pts = (tv.tv_sec * 1000000 + tv.tv_usec - start_time) * (double)FPS / 1000000;
frame->pts = pts;
// 生成测试图像
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
frame->data[0][y * frame->linesize[0] + x] = rand() % 256; // Y
}
}
for (int y = 0; y < HEIGHT / 2; y++) {
for (int x = 0; x < WIDTH / 2; x++) {
frame->data[1][y * frame->linesize[1] + x] = rand() % 256; // U
frame->data[2][y * frame->linesize[2] + x] = rand() % 256; // V
}
}
ret = avcodec_send_frame(codec_ctx, frame);
if (ret < 0) {
cout << "avcodec_send_frame failed: " << av_err2str(ret) << endl;
exit(1);
}
while (true) {
ret = avcodec_receive_packet(codec_ctx, &packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
cout << "avcodec_receive_packet failed: " << av_err2str(ret) << endl;
exit(1);
}
packet.stream_index = stream->index;
av_packet_rescale_ts(&packet, codec_ctx->time_base, stream->time_base);
ret = av_interleaved_write_frame(fmt_ctx, &packet);
if (ret < 0) {
cout << "av_interleaved_write_frame failed: " << av_err2str(ret) << endl;
exit(1);
}
av_packet_unref(&packet);
}
frame_count++;
if (frame_count >= FPS * 10) {
break; // 推送 10 秒
}
usleep(1000000 / FPS);
}
// 结束推流
av_write_trailer(fmt_ctx);
avcodec_close(codec_ctx);
avformat_free_context(fmt_ctx);
av_frame_free(&frame);
return 0;
}
```
这个程序会生成一些随机图像,并将它们推送到一个名为"test.sdp"的RTSP流中。你可以使用VLC等流媒体播放器来查看这个流。
阅读全文