[FFmpeg-trac] #9666(avcodec:new): munmap_chunk(): invalid pointer encoding SEI with libx265

FFmpeg trac at avcodec.org
Tue Feb 22 11:50:05 EET 2022


#9666: munmap_chunk(): invalid pointer encoding SEI with libx265
-------------------------------------+-------------------------------------
             Reporter:  Brad Hards   |                     Type:  defect
               Status:  new          |                 Priority:  normal
            Component:  avcodec      |                  Version:
                                     |  unspecified
             Keywords:  libx265      |               Blocked By:
             Blocking:               |  Reproduced by developer:  0
Analyzed by developer:  0            |
-------------------------------------+-------------------------------------
 I'm seeing a problem encoding User Data Unregistered SEI messages with
 libx265 that I don't see in libx264. I'm seeing it via Java bindings
 (javacpp-presets), but I think I'm seeing something similar in this
 modified example:

 {{{
 /*
  * Copyright (c) 2001 Fabrice Bellard
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
 copy
  * of this software and associated documentation files (the "Software"),
 to deal
  * in the Software without restriction, including without limitation the
 rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or
 sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
  *
  * The above copyright notice and this permission notice shall be included
 in
  * all copies or substantial portions of the Software.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 IN
  * THE SOFTWARE.
  */

 /**
  * @file
  * video encoding with SEI (user unregistered) API example
  *
  * @example encode_unregistered.c
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 #include <libavcodec/avcodec.h>

 #include <libavutil/opt.h>
 #include <libavutil/imgutils.h>

 static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
                    FILE *outfile)
 {
     int ret;

     /* send the frame to the encoder */
     if (frame)
         printf("Send frame %3" PRId64 "\n", frame->pts);

     ret = avcodec_send_frame(enc_ctx, frame);
     if (ret < 0)
     {
         fprintf(stderr, "Error sending a frame for encoding\n");
         exit(1);
     }

     while (ret >= 0)
     {
         ret = avcodec_receive_packet(enc_ctx, pkt);
         if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
             return;
         else if (ret < 0)
         {
             fprintf(stderr, "Error during encoding\n");
             exit(1);
         }

         printf("Write packet %3" PRId64 " (size=%5d)\n", pkt->pts,
 pkt->size);
         fwrite(pkt->data, 1, pkt->size, outfile);
         av_packet_unref(pkt);
     }
 }

 int main(int argc, char **argv)
 {
     const char *filename, *codec_name;
     const AVCodec *codec;
     AVCodecContext *c = NULL;
     int i, ret, x, y;
     FILE *f;
     AVFrame *frame;
     AVPacket *pkt;
     AVBufferRef *ref;
     AVFrameSideData *side_data;
     char *tempBuf;
     // This is from MISB ST 2101
     char sei_message[] = {0xa5, 0x50, 0x52, 0xaf, 0x52, 0x16, 0x5f, 0x45,
                           0xa3, 0x18, 0x1c, 0xfc, 0x7a, 0xbb, 0xc2, 0x67,
                           0x01, 0x70, 0xF5, 0x92, 0xF0, 0x23, 0x73, 0x36,
                           0x4A, 0xF8, 0xAA, 0x91, 0x62, 0xC0, 0x0F, 0x2E,
                           0xB2, 0xDA, 0x16, 0xB7, 0x43, 0x41, 0x00, 0x08,
                           0x41, 0xA0, 0xBE, 0x36, 0x5B, 0x5A, 0xB9, 0x6A,
                           0x36, 0x45};

     if (argc <= 2) {
         fprintf(stderr, "Usage: %s <output file> <codec name>\n",
 argv[0]);
         exit(0);
     }
     filename = argv[1];
     codec_name = argv[2];

     codec = avcodec_find_encoder_by_name(codec_name);
     if (!codec) {
         fprintf(stderr, "Codec '%s' not found\n", codec_name);
         exit(1);
     }

     c = avcodec_alloc_context3(codec);
     if (!c)
     {
         fprintf(stderr, "Could not allocate video codec context\n");
         exit(1);
     }

     pkt = av_packet_alloc();
     if (!pkt)
         exit(1);

     c->bit_rate = 400000;
     c->width = 352;
     c->height = 288;
     /* frames per second */
     c->time_base = (AVRational){1, 25};
     c->framerate = (AVRational){25, 1};
     c->gop_size = 10;
     c->max_b_frames = 0;
     c->pix_fmt = AV_PIX_FMT_YUV420P;
     if (codec->id == AV_CODEC_ID_H264) {
         av_opt_set(c->priv_data, "preset", "medium", 0);

     }
     av_opt_set(c->priv_data, "udu_sei", "1", 0);

     /* open it */
     ret = avcodec_open2(c, codec, NULL);
     if (ret < 0)
     {
         fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
         exit(1);
     }

     f = fopen(filename, "wb");
     if (!f)
     {
         fprintf(stderr, "Could not open %s\n", filename);
         exit(1);
     }

     frame = av_frame_alloc();
     if (!frame)
     {
         fprintf(stderr, "Could not allocate video frame\n");
         exit(1);
     }
     frame->format = c->pix_fmt;
     frame->width = c->width;
     frame->height = c->height;

     ret = av_frame_get_buffer(frame, 0);
     if (ret < 0)
     {
         fprintf(stderr, "Could not allocate the video frame data\n");
         exit(1);
     }

     /* encode 1 second of video */
     for (i = 0; i < 25; i++)
     {
         fflush(stdout);

         /* make sure the frame data is writable */
         ret = av_frame_make_writable(frame);
         if (ret < 0)
             exit(1);
         side_data = av_frame_new_side_data(frame,
 AV_FRAME_DATA_SEI_UNREGISTERED, sizeof(sei_message));
         if (!side_data)
         {
             fprintf(stderr, "Could not allocate the video frame side
 data\n");
             exit(1);
         }
         memcpy(side_data->data, sei_message, side_data->size);

         /* prepare a dummy image */
         /* Y */
         for (y = 0; y < c->height; y++) {
             for (x = 0; x < c->width; x++) {
                 frame->data[0][y * frame->linesize[0] + x] = x + y + i *
 3;
             }
         }

         /* Cb and Cr */
         for (y = 0; y < c->height/2; y++) {
             for (x = 0; x < c->width/2; x++) {
                 frame->data[1][y * frame->linesize[1] + x] = 128 + y + i *
 2;
                 frame->data[2][y * frame->linesize[2] + x] = 64 + x + i *
 5;
             }
         }

         frame->pts = i;
         encode(c, frame, pkt, f);
     }

     /* flush the encoder */
     encode(c, NULL, pkt, f);
     fclose(f);

     avcodec_free_context(&c);
     av_frame_free(&frame);
     av_packet_free(&pkt);

     return 0;
 }
 }}}

 The backtrace for that looks like:
 {{{
 #0  __GI_raise (sig=sig at entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
 #1  0x00007ffff684d864 in __GI_abort () at abort.c:79
 #2  0x00007ffff68b0736 in __libc_message (action=action at entry=do_abort,
 fmt=fmt at entry=0x7ffff69d5b9c "%s\n") at ../sysdeps/posix/libc_fatal.c:155
 #3  0x00007ffff68b908c in malloc_printerr (str=str at entry=0x7ffff69d7ba0
 "munmap_chunk(): invalid pointer") at malloc.c:5628
 #4  0x00007ffff68b945c in munmap_chunk (p=<optimised out>) at
 malloc.c:2995
 #5  0x00007ffff68be7db in __GI___libc_free (mem=<optimised out>) at
 malloc.c:3302
 #6  0x00007ffff6acecac in x265::NALList::takeContents(x265::NALList&) ()
 from /lib/x86_64-linux-gnu/libx265.so.192
 #7  0x00007ffff6aca817 in
 x265::FrameEncoder::getEncodedPicture(x265::NALList&) () from /lib/x86_64
 -linux-gnu/libx265.so.192
 #8  0x00007ffff6af88bf in x265::Encoder::encode(x265_picture const*,
 x265_picture*) () from /lib/x86_64-linux-gnu/libx265.so.192
 #9  0x00007ffff6afbce0 in x265_encoder_encode () from /lib/x86_64-linux-
 gnu/libx265.so.192
 #10 0x000055555584a342 in libx265_encode_frame (avctx=0x555556a60d80,
 pkt=0x555556a62bc0, pic=<optimised out>, got_packet=0x7fffffffdab4) at
 libavcodec/libx265.c:576
 #11 0x0000555555723241 in encode_simple_internal (avpkt=0x555556a62bc0,
 avctx=0x555556a60d80) at libavcodec/encode.c:211
 #12 encode_simple_receive_packet (avpkt=<optimised out>, avctx=<optimised
 out>) at libavcodec/encode.c:266
 #13 encode_receive_packet_internal (avctx=avctx at entry=0x555556a60d80,
 avpkt=avpkt at entry=0x555556a62bc0) at libavcodec/encode.c:300
 #14 0x0000555555723962 in avcodec_receive_packet
 (avctx=avctx at entry=0x555556a60d80, avpkt=avpkt at entry=0x555556a62bc0) at
 libavcodec/encode.c:401
 #15 0x000055555562d2a1 in encode (enc_ctx=0x555556a60d80,
 frame=frame at entry=0x0, pkt=0x555556a62bc0,
 outfile=outfile at entry=0x555556a5feb0)
     at doc/examples/encode_unregistered.c:57
 #16 0x000055555562cf7b in main (argc=<optimised out>, argv=<optimised
 out>) at doc/examples/encode_unregistered.c:202
 }}}

 I had some involvement in the development of those, and
 https://git.ffmpeg.org/gitweb/ffmpeg.git/commit/66f8055c898887c33ab124ca5f00ee60bf5fcf19
 for libx264 looks like it deals with the underlying design issue - libx264
 doesn't cause the backtrace. Possibly something similar would be needed
 for libx265.
-- 
Ticket URL: <https://trac.ffmpeg.org/ticket/9666>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list