ffmpeg 获取 rtsp 视频流 c++ 代码实现
时间: 2023-10-02 21:08:41 浏览: 169
下面是使用 FFmpeg 获取 RTSP 视频流的 C++ 代码实现,你可以参考一下:
```c++
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
#define STREAM_DURATION 10.0
#define STREAM_FRAME_RATE 25 /* 25 images/s */
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
#define SCALE_FLAGS SWS_BICUBIC
using namespace std;
int main(int argc, char **argv) {
AVFormatContext *fmt_ctx = NULL;
AVCodecContext *codec_ctx = NULL;
AVCodec *codec = NULL;
int ret;
AVFrame *frame = NULL;
AVPacket pkt = { 0 };
int video_stream_index;
int64_t pts = 0, last_pts = 0;
int frame_count = 0;
int got_output;
int i;
char *filename = argv[1];
av_register_all();
avformat_network_init();
fmt_ctx = avformat_alloc_context();
if (!fmt_ctx) {
cerr << "Could not allocate format context" << endl;
exit(1);
}
ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL);
if (ret < 0) {
cerr << "Could not open input file: " << filename << endl;
exit(1);
}
ret = avformat_find_stream_info(fmt_ctx, NULL);
if (ret < 0) {
cerr << "Could not find stream information" << endl;
exit(1);
}
av_dump_format(fmt_ctx, 0, filename, 0);
for (i = 0; i < fmt_ctx->nb_streams; i++) {
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
break;
}
}
if (i == fmt_ctx->nb_streams) {
cerr << "Could not find video stream" << endl;
exit(1);
}
codec = avcodec_find_decoder(fmt_ctx->streams[video_stream_index]->codecpar->codec_id);
if (!codec) {
cerr << "Codec not found" << endl;
exit(1);
}
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {
cerr << "Could not allocate codec context" << endl;
exit(1);
}
ret = avcodec_parameters_to_context(codec_ctx, fmt_ctx->streams[video_stream_index]->codecpar);
if (ret < 0) {
cerr << "Could not copy codec parameters to codec context" << endl;
exit(1);
}
ret = avcodec_open2(codec_ctx, codec, NULL);
if (ret < 0) {
cerr << "Could not open codec" << endl;
exit(1);
}
frame = av_frame_alloc();
if (!frame) {
cerr << "Could not allocate frame" << endl;
exit(1);
}
SwsContext *sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,
codec_ctx->width, codec_ctx->height, STREAM_PIX_FMT, SCALE_FLAGS, NULL, NULL, NULL);
if (!sws_ctx) {
cerr << "Could not initialize the conversion context" << endl;
exit(1);
}
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
AVFormatContext *out_fmt_ctx = NULL;
ret = avformat_alloc_output_context2(&out_fmt_ctx, NULL, "mpegts", NULL);
if (ret < 0) {
cerr << "Could not allocate output context" << endl;
exit(1);
}
AVStream *out_stream = avformat_new_stream(out_fmt_ctx, NULL);
if (!out_stream) {
cerr << "Could not allocate output stream" << endl;
exit(1);
}
ret = avcodec_parameters_copy(out_stream->codecpar, fmt_ctx->streams[video_stream_index]->codecpar);
if (ret < 0) {
cerr << "Could not copy codec parameters to output codec context" << endl;
exit(1);
}
out_stream->codecpar->codec_tag = 0;
out_stream->time_base = { 1, STREAM_FRAME_RATE };
out_stream->avg_frame_rate = { STREAM_FRAME_RATE, 1 };
ret = avio_open(&out_fmt_ctx->pb, "out.ts", AVIO_FLAG_WRITE);
if (ret < 0) {
cerr << "Could not open output file" << endl;
exit(1);
}
ret = avformat_write_header(out_fmt_ctx, NULL);
if (ret < 0) {
cerr << "Could not write output file header" << endl;
exit(1);
}
while (true) {
ret = av_read_frame(fmt_ctx, &pkt);
if (ret < 0) {
break;
}
if (pkt.stream_index != video_stream_index) {
continue;
}
ret = avcodec_send_packet(codec_ctx, &pkt);
if (ret < 0) {
cerr << "Error submitting packet to decoder" << endl;
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
cerr << "Error during decoding" << endl;
exit(1);
}
if (frame->format != STREAM_PIX_FMT) {
sws_scale(sws_ctx, frame->data, frame->linesize, 0, codec_ctx->height,
frame->data, frame->linesize);
frame->format = STREAM_PIX_FMT;
frame->width = codec_ctx->width;
frame->height = codec_ctx->height;
}
frame->pts = pts++;
ret = avcodec_send_frame(out_stream->codec, frame);
if (ret < 0) {
cerr << "Error submitting frame to encoder" << endl;
exit(1);
}
while (ret >= 0) {
AVPacket out_pkt = { 0 };
ret = avcodec_receive_packet(out_stream->codec, &out_pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
cerr << "Error during encoding" << endl;
exit(1);
}
out_pkt.stream_index = out_stream->index;
av_packet_rescale_ts(&out_pkt, out_stream->codec->time_base, out_stream->time_base);
out_pkt.pts = out_pkt.dts = pts;
out_pkt.duration = av_rescale_q(1, out_stream->codec->time_base, out_stream->time_base);
av_write_frame(out_fmt_ctx, &out_pkt);
av_packet_unref(&out_pkt);
}
av_frame_unref(frame);
}
av_packet_unref(&pkt);
}
av_write_trailer(out_fmt_ctx);
avformat_close_input(&fmt_ctx);
avcodec_free_context(&codec_ctx);
av_frame_free(&frame);
avformat_free_context(fmt_ctx);
avformat_free_context(out_fmt_ctx);
return 0;
}
```
注意:这个代码并没有加入异常处理,实际使用时需要根据自己的需要进行修改。
阅读全文