[FFmpeg-trac] #9844(avdevice:new): Memory leak in v4l2 input device if setting timestamps option to mono2abs or abs

FFmpeg trac at avcodec.org
Wed Jul 27 04:02:29 EEST 2022


#9844: Memory leak in v4l2 input device if setting timestamps option to mono2abs
or abs
-------------------------------------+-------------------------------------
             Reporter:  bermond      |                    Owner:  (none)
                 Type:  defect       |                   Status:  new
             Priority:  normal       |                Component:  avdevice
              Version:  git-master   |               Resolution:
             Keywords:  v4l2         |               Blocked By:
  video4linux2 leak                  |
             Blocking:               |  Reproduced by developer:  0
Analyzed by developer:  0            |
-------------------------------------+-------------------------------------
Description changed by bermond:

Old description:

> 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
> converts of the start timestamp.
>
> Using the value `'default'` (which does not convert start timestamp) does
> not cause a memory leak.
>
> How to reproduce:
> {{{#!c
> #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;
>
>     // "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;
>     }
>
>     AVFormatContext* 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);
>
>     AVPacket* 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:
>     av_dict_free(&inputOptions);
>     av_packet_free(&inputPacket);
>     avformat_close_input(&inputFormatContext);
>
>     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.

New description:

 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:
 {{{#!c
 #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.

--
-- 
Ticket URL: <https://trac.ffmpeg.org/ticket/9844#comment:1>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list