Opened 2 years ago

Closed 2 years ago

#9844 closed defect (fixed)

Memory leak in v4l2 input device if setting timestamps option to mono2abs or abs

Reported by: bermond Owned by:
Priority: normal Component: avdevice
Version: git-master Keywords: v4l2 video4linux2 leak
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description (last modified by bermond)

Summary of the bug:
ASan reports a memory leak when closing a 'v4l2' input device if the 'timestamps' option is setted to 'mono2abs' or 'abs'. These values convert the start timestamp.

Using the value 'default' (which does not convert start timestamp) does not cause a memory leak.

How to reproduce:

#include <stdio.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>

int main() {
    int ret;
    AVDictionary* inputOptions = NULL;
    AVFormatContext* inputFormatContext = NULL;
    AVPacket* inputPacket = NULL;
    
    // "mono2abs" and "abs" causes a memory leak ("default" does not leak)
    ret = av_dict_set(&inputOptions, "timestamps", "mono2abs", 0);
    if (ret < 0) {
        fprintf(stderr, "Failed to set v4l2 'timestamp' option");
        goto end;
    }
    
    avdevice_register_all();
    
    const AVInputFormat* inputFormat = av_find_input_format("v4l2");
    if (!inputFormat) {
        fprintf(stderr, "Failed to find input format");
        ret = -1;
        goto end;
    }
    
    inputFormatContext = avformat_alloc_context();
    if (!inputFormatContext) {
        fprintf(stderr, "Failed to allocate input format context");
        ret = AVERROR(ENOMEM);
        goto end;
    }
    
    ret = avformat_open_input(&inputFormatContext, "/dev/video0", inputFormat, &inputOptions);
    if (ret < 0) {
        fprintf(stderr, "Failed to open input device");
        goto end;
    }
    
    ret = avformat_find_stream_info(inputFormatContext, NULL);
    if (ret < 0) {
        fprintf(stderr, "Failed to find input stream info");
        goto end;
    }
    
    av_dump_format(inputFormatContext, 0, "/dev/video0", 0);
    
    inputPacket = av_packet_alloc();
    if (!inputPacket) {
        fprintf(stderr, "Failed to allocate input packet");
        ret = AVERROR(ENOMEM);
        goto end;
    }
    
    // read at least one frame to avoid this error on closing: "ioctl(VIDIOC_QBUF): Bad file descriptor"
    ret = av_read_frame(inputFormatContext, inputPacket);
    if (ret < 0) {
        fprintf(stderr, "Failed to read input packet");
        goto end;
    }
    
    ret = 0;
    
end:
    if (inputPacket)
        av_packet_free(&inputPacket);
    
    if (inputFormatContext)
        avformat_close_input(&inputFormatContext);
    
    if (inputOptions)
        av_dict_free(&inputOptions);
    
    return ret;
}

Compiled with:

$ gcc v4l2_mem_leak.c -o v4l2_mem_leak -g -Wall -Wextra -pedantic -fsanitize=address -fno-omit-frame-pointer -lavdevice -lavformat -lavutil -lavcodec

Output:

$ ./v4l2_mem_leak 
[video4linux2,v4l2 @ 0x617000002000] Detected monotonic timestamps, converting
Input #0, video4linux2,v4l2, from '/dev/video0':
  Duration: N/A, start: 1658787218.575150, bitrate: 110592 kb/s
  Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 640x480, 110592 kb/s, 30 fps, 30 tbr, 1000k tbn

=================================================================
==5506==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 40 byte(s) in 1 object(s) allocated from:
    #0 0x7f90b0ebefc7 in __interceptor_posix_memalign /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x7f90b064fdb5 in av_malloc (/usr/lib/libavutil.so.57+0x4fdb5)

SUMMARY: AddressSanitizer: 40 byte(s) leaked in 1 allocation(s).

Compiler is gcc 12.1.0.

Change History (5)

comment:1 by bermond, 2 years ago

Description: modified (diff)

comment:2 by quinkblack, 2 years ago

Could you help testing the following patch?

http://ffmpeg.org/pipermail/ffmpeg-devel/2022-July/299334.html

comment:3 by bermond, 2 years ago

I can confirm that applying the patch on top of git master fixes this memory leak. Using 'mono2abs' and 'abs' values does not leak anymore with it.

I'm using an android phone with droidcam as the camera device.

Thank you for working on this!

comment:4 by bermond, 2 years ago

This is now fixed on the current git master by commit 30aa0c3f4873a92c5e3da8ba8cf030de56bf4cf7.

Thanks to everyone involved.

comment:5 by bermond, 2 years ago

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.