Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

there may be a memory leak in the av_read_frame code #2242

Closed
zhhades opened this issue Jun 19, 2024 · 2 comments
Closed

there may be a memory leak in the av_read_frame code #2242

zhhades opened this issue Jun 19, 2024 · 2 comments

Comments

@zhhades
Copy link

zhhades commented Jun 19, 2024

Hello, first of all, thank you for your dedication to the open source industry.
Currently, I am using javacpp1.5.10 & ffmpeg-platform 1.5.10 & ffmpeg-platform-gpl 1.5.10 & Cuda 12.1-8.9-1.5.9 for video stream decoding development work. In the following code, I have found that there may be a memory leak. Can you help me take a look?

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacpp</artifactId>
    <version>1.5.10</version>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg-platform</artifactId>
    <version>6.1.1-1.5.10</version>
</dependency>

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg-platform-gpl</artifactId>
    <version>6.1.1-1.5.10</version>
</dependency>

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>cuda</artifactId>
    <version>12.1-8.9-1.5.9</version>
</dependency>
public void doDecoder() throws NeedRetryException {

    AVFormatContext pFormatCtx = null;
    AVCodecContext pCodecCtx = null;
    AVPacket packet = av_packet_alloc();
    AVDictionary options = new AVDictionary(null);
    try {
        
        // due to network limitations, the TCP protocol must be used
        av_dict_set(options, "rtsp_transport", "tcp", 0);
        av_dict_set(options, "buffer_size", "2048000", 0);
        pFormatCtx = getFormatContext(decoderTask.getVideoUrl(), options);
        int videoStreamIndex = getVideoStreamIndex(pFormatCtx);
        if (videoStreamIndex < 0) {
            log.error("video streams has no stream video");
            return;
        }
        pCodecCtx = getCodecContext(pFormatCtx, videoStreamIndex, useGpu,options);
        if (null == pCodecCtx) {
            return;
        }
        int ret = 0;
        while (( ret = av_read_frame(pFormatCtx, packet))>=0) {
            try {
                if (packet.stream_index() == videoStreamIndex) {
                    ret = avcodec_send_packet(pCodecCtx,packet);
                    // to  test the mem leak , annotate this line
                    // decode(seiInfo,frameNumber,pCodecCtx,executorService);
                }
            }catch (Exception e){
                // ignore
            }finally {
                av_packet_unref(packet);
            }
        }
        av_packet_unref(packet);
        if (ret == AVERROR_EOF()) {
            if(decoderTask.getFileFlag()){
                decode(seiInfo,frameNumber,pCodecCtx,executorService);
            }else {
                throw new NeedRetryException("av_read_frame res "+ ret);
            }
        }
        log.warn("video split task[{}] run finished", JSONObject.toJSONString(decoderTask));
    } catch (NeedRetryException needRetryException) {
        throw needRetryException;
    } catch (Exception e) {
        log.error("video split  bizId = {}, error[{}]", decoderTask.getBizId(), e.getMessage());
    } finally {
        release(true, packet, null, pCodecCtx, pFormatCtx, null, null);
    }
}


private AVFormatContext getFormatContext(String url, AVDictionary avDictionary) {
    AVFormatContext pFormatCtx = new AVFormatContext(null);

    if (avformat_open_input(pFormatCtx, url, null, avDictionary) != 0) {
        log.error("open media stream has error");
        throw new NeedRetryException("open media stream has error");
    }

    if (avformat_find_stream_info(pFormatCtx, (PointerPointer<Pointer>) null) < 0) {
        log.error("avformat_find_stream_info has error");
        throw new NeedRetryException("read media stream has error");
    }
    return pFormatCtx;
}

public static int getVideoStreamIndex(AVFormatContext pFormatCtx) {
    int videoStream = -1;
    for (int i = 0; i < pFormatCtx.nb_streams(); i++) {
        if (pFormatCtx.streams(i).codecpar().codec_type() == AVMEDIA_TYPE_VIDEO) {
            videoStream = i;
            break;
        }
    }
    return videoStream;
}


public static AVCodecContext getCodecContext(AVFormatContext pFormatCtx, int videoStreamIndex,Boolean useGpu,AVDictionary dictionary) {
    AVCodec pCodec;

    AVCodecContext pCodecCtx = avcodec_alloc_context3(null);
    avcodec_parameters_to_context(pCodecCtx, pFormatCtx.streams(videoStreamIndex).codecpar());

    if(useGpu){
        int codecId = pCodecCtx.codec_id();
        if(codecId == AV_CODEC_ID_H264){
            pCodec = avcodec_find_decoder_by_name("h264_cuvid");
        }else if (codecId == AV_CODEC_ID_H265) {
            pCodec=  avcodec_find_decoder_by_name("hevc_cuvid");
        }else {
            pCodec = avcodec_find_decoder(pCodecCtx.codec_id());
        }
    }else {
        pCodec = avcodec_find_decoder(pCodecCtx.codec_id());
    }

    if (pCodec == null) {
        return null;
    }
    if (avcodec_open2(pCodecCtx, pCodec,dictionary) < 0) {
        return null;
    }

    return pCodecCtx;
}
@zhhades zhhades changed the title av_read_frame mayb there may be a memory leak in the av_read_frame code Jun 19, 2024
@zhhades
Copy link
Author

zhhades commented Jun 20, 2024

I am so sorry,this issue should not be created here, it should be created in javacpp

@saudet
Copy link
Member

saudet commented Jun 20, 2024

Duplicate of bytedeco/javacpp#763

@saudet saudet marked this as a duplicate of bytedeco/javacpp#763 Jun 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants