下面是使用ffmpeg对rtsp流进行录像的代码,程序运行后,内存一直不停的往上涨,网上查过都说是内存泄露造成的,可是具体哪里泄露了,折腾好久了没找到原因。哪位熟悉ffmpeg的仁兄,帮忙看看,谢过!
void saveRtsp() {
AVFormatContext *pFormatCtx = nullptr; // FFMPEG所有的操作都要通过这个AVFormatContext来进行
AVCodecContext *pCodecCtx = nullptr;
AVCodec *pCodec = nullptr;
AVFrame *pFrame = nullptr, *pFrameRGB = nullptr;
AVPacket *packet = nullptr;
uint8_t *out_buffer = nullptr;
struct SwsContext *img_convert_ctx = nullptr;
AVDictionary *avdic = nullptr;
AVDictionary *params = nullptr;
int videoStream, numBytes;
long start = 0, finish = 0;
int frames = 0; // 保存的packet数量
// 初始化
avformat_network_init(); // 初始化FFmpeg网络模块
av_register_all(); // 初始化FFMPEG 调用了这个才能正常适用编码器和解码器
pFormatCtx = avformat_alloc_context(); // 分配一个AVFormatContext,查找用于输入的设备
av_dict_set(&avdic, "rtsp_transport", "tcp", 0);
av_dict_set(&avdic, "max_delay", "100", 0);
//av_dict_set(&avdic, "probesize", "32000000", 0);
av_dict_set(&avdic, "max_analyze_duration", "1000", 0);
av_dict_set(&avdic, "buffer_size", "1024000", 0);
av_dict_set(&avdic, "stimeout", "2000000", 0); // 如果没有设置stimeout
if (avformat_open_input(&pFormatCtx, rtspMain.c_str(), NULL, &avdic) != 0) {
cout<<"打不开视频,请检查路径是否正确:"<<rtspMain<<endl;
goto end;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
cout<<"找不到视频流的信息:"<<rtspMain<<endl;
goto end;
}
videoStream = -1;
for (int i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break;
}
}
if (videoStream == -1) {
cout<<"无法播放,找不到视频流:"<<rtspMain<<endl;
goto end;
}
pCodecCtx = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar);
pCodec = avcodec_find_decoder(pCodecCtx->codec_id); //指向AVCodec的指针.查找解码器
pCodecCtx->bit_rate = 0; // 初始化为0
pCodecCtx->time_base.num = 1; // 下面两行:一秒钟25帧
pCodecCtx->time_base.den = 25;
pCodecCtx->frame_number = 1; // 每包一个视频帧
if (pCodec == NULL) {
cout<<"无法播放,找不到解码器:"<<rtspMain<<endl;
goto end;
}
if(pCodecCtx->codec_id == AV_CODEC_ID_H264) {
av_dict_set(¶ms, "preset", "superfast", 0);
av_dict_set(¶ms, "tune", "zerolatency", 0);
} else if(pCodecCtx->codec_id == AV_CODEC_ID_H265) {
av_dict_set(¶ms, "x265-params", "qp=20", 0);
av_dict_set(¶ms, "preset", "ultrafast", 0);
av_dict_set(¶ms, "tune", "zero-latency", 0);
}
// 打开解码器
if (avcodec_open2(pCodecCtx, pCodec, ¶ms) < 0) {
cout<<"无法播放,无法打开解码器:"<<rtspMain<<endl;
goto end;
}
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
// 将解码后的YUV数据转换成RGB32
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
numBytes = avpicture_get_size(AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height);
out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) pFrameRGB, out_buffer, AV_PIX_FMT_RGB32,
pCodecCtx->width, pCodecCtx->height);
int y_size = pCodecCtx->width * pCodecCtx->height;
packet = (AVPacket *) malloc(sizeof(AVPacket)); // 分配一个packet
//av_new_packet(packet, y_size); // 分配packet的数据
av_init_packet(packet);
cout<<rtspMain<<endl;
while (true) {
if (av_read_frame(pFormatCtx, packet) < 0) {
break; // 这里认为视频读取完了
}
if (packet->stream_index == videoStream) {
frames++;
//fwrite(packet->data, 1, packet->size, fpSave); // 写数据到文件中
}
av_packet_unref(packet);
av_free_packet(packet);
}
end:
if(packet) {
av_packet_unref(packet);
av_free_packet(packet);
}
if(avdic) av_free(avdic);
if(params) av_free(params);
sws_freeContext(img_convert_ctx);
av_free(out_buffer);
av_frame_free(&pFrameRGB);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
avcodec_free_context(&pCodecCtx);
avformat_free_context(pFormatCtx);
}
FFmpeg
补充一下:用的是编译好的windows版本ffmpeg 4.0.2
自己顶吧,不顶又沉底了
因为不懂