Ffmpeg录像的内存泄露问题

yangrfa 发布于 01/10 11:39
阅读 512
收藏 0

下面是使用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(&params, "preset", "superfast", 0);
        av_dict_set(&params, "tune", "zerolatency", 0);
    } else if(pCodecCtx->codec_id == AV_CODEC_ID_H265) {
        av_dict_set(&params, "x265-params", "qp=20", 0);
        av_dict_set(&params, "preset", "ultrafast", 0);
        av_dict_set(&params, "tune", "zero-latency", 0);
    }

    // 打开解码器
    if (avcodec_open2(pCodecCtx, pCodec, &params) < 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);
}

 

加载中
0
yangrfa
yangrfa

补充一下:用的是编译好的windows版本ffmpeg 4.0.2

0
yangrfa
yangrfa

自己顶吧,不顶又沉底了

返回顶部
顶部