<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal">Hi,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I am having an odd issue migrating a module  to the new libav/libavcodec API. In the old code, a frame of raw data was encoded to JPEG as follows, after initializing the codec:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">/* lock the output plugin mutex */<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    this->mutex.lock();<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    /* Release the last jpeg created */<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    if (this->jpeg) {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">        this->jpeg->release();<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    <o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    /* Convert it to a jpeg */       
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    this->jpeg = this->pNDArrayPool->alloc(1, &size, NDInt8, 0, NULL);<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    AVPacket pkt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    int got_output;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    av_init_packet(&pkt);<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    pkt.data = (uint8_t*)this->jpeg->pData;    // packet data will be allocated by the encoder<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    pkt.size = c->width * c->height;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    //c: AVCodecContext*<br>
    //scPicture: AVPacket*<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    //jpeg: Pointer to wrapper for an N-dimensional array<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    //pkt: An AVPacket object initialized above<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    //scPicture: AVFrame*
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    if (avcodec_encode_video2(c, &pkt, scPicture, &got_output)) {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">            "%s:%s: Encoding jpeg failed\n",<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">            driverName, functionName);<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    this->jpeg->dims[0].size = pkt.size;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    <o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    /* signal fresh_frame to output plugin and unlock mutex */<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    epicsEvent *evt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    while(this->waiting.tryReceive(&evt, sizeof(evt)) != -1)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">        evt->signal();<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    this->mutex.unlock();<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal">This runs fine all day. I updated this snippet to use <span style="font-family:"Courier New"">
avcodec_send_frame/avcodec_receive_packet </span>below:<o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    // segfault here after a few successful frames<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    if (avcodec_send_frame(c,scPicture) < 0) {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">            "%s:%s: Encoding jpeg failed\n",<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">            driverName, functionName);<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    if (avcodec_receive_packet(c, &pkt) < 0){<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">            "%s:%s: Encoding jpeg failed\n",<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">            driverName, functionName);<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    this->jpeg->dims[0].size = pkt.size;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    this->jpeg->pData = pkt.data;<o:p></o:p></span></p>
<p class="MsoNormal"><o:p></o:p></p>
<p class="MsoNormal">In this case, a varying number of frames are correctly encoded, usually about 10. After that, something in libav is overrunning a buffer that it previously malloc’d. Here is the output from gdb and Valgrind – there are no other issues or
 overruns until the faulty frame occurs:<o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">Thread 151 "MJPG_Plugin_1" received signal SIGSEGV, Segmentation fault.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">[Switching to Thread 0x7fff6891fb00 (LWP 936195)]<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">tcache_get (tc_idx=<optimized out>) at malloc.c:2937<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">2937    malloc.c: No such file or directory.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">(gdb) bt<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#0  tcache_get (tc_idx=<optimized out>) at malloc.c:2937<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#1  __GI___libc_malloc (bytes=40) at malloc.c:3051<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#2  0x00007ffff78e8b42 in __posix_memalign (size=<optimized out>, alignment=<optimized out>, memptr=0x7fff6891e768) at malloc.c:5366<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#3  __posix_memalign (memptr=0x7fff6891e768, alignment=<optimized out>, size=<optimized out>) at malloc.c:5353<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#4  0x00007ffff5193911 in av_malloc (size=40) at libavutil/mem.c:86<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#5  0x00007ffff5193ae3 in av_mallocz (size=40) at libavutil/mem.c:239<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#6  0x00007ffff5183d9a in av_buffer_create<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    (data=0x2f2f303033313031 <error: Cannot access memory at address 0x2f2f303033313031>, size=609047, free=0x7ffff5183d1b <pool_release_buffer>, opaque=0x7fffdc455b50, flags=825307440) at libavutil/buffer.c:36<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#7  0x00007ffff5184313 in av_buffer_pool_get (pool=0x7fffdc0bdcd0) at libavutil/buffer.c:345<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#8  0x00007ffff55d7f42 in video_get_buffer (s=0x7fffdc013ee0, pic=0x7fffdc01f690) at libavcodec/decode.c:1626<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#9  0x00007ffff55d9dde in avcodec_default_get_buffer2 (avctx=0x7fffdc013ee0, frame=0x7fffdc01f690, flags=2) at libavcodec/decode.c:1665<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#10 0x00007ffff55da3bd in ff_get_buffer (avctx=0x7fffdc013ee0, frame=0x7fffdc01f690, flags=2) at libavcodec/decode.c:1898<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#11 0x00007ffff5868121 in thread_get_buffer_internal (avctx=0x7fffdc013ee0, f=0x7fffdc01c790, flags=2) at libavcodec/pthread_frame.c:924<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#12 0x00007ffff5868bce in ff_thread_get_buffer (avctx=0x7fffdc013ee0, f=0x28, flags=2) at libavcodec/pthread_frame.c:1000<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#13 0x00007ffff57faf03 in alloc_frame_buffer (avctx=0x7fffdc013ee0, pic=0x7fffdc01c788, me=0x2, sc=0x11, chroma_x_shift=1, chroma_y_shift=1, linesize=1952, uvlinesize=976)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    at libavcodec/mpegpicture.c:117<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#14 0x00007ffff57fb2ff in ff_alloc_picture<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    (avctx=0x7fffdc013ee0, pic=0x7fffdc01c788, me=0x2, sc=0x7fffdc015500, shared=0, encoding=1, chroma_x_shift=1, chroma_y_shift=1, out_format=3, mb_stride=121, mb_width=120, mb_height=75, b8_stride=241,
 linesize=0x7fffdc014db0, uvlinesize=0x7fffdc014db8) at libavcodec/mpegpicture.c:254<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#15 0x00007ffff58086db in alloc_picture (s=0x28, pic=0x28, shared=2) at libavcodec/mpegvideo_enc.c:1149<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#16 0x00007ffff5808843 in load_input_picture (s=0x7fffdc014ac0, pic_arg=0x5555557509d0) at libavcodec/mpegvideo_enc.c:1222<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#17 0x00007ffff580f982 in ff_mpv_encode_picture (avctx=0x7fffdc013ee0, pkt=0x7fffdc014a10, pic_arg=0x28, got_packet=0x11) at libavcodec/mpegvideo_enc.c:1835<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#18 0x00007ffff56115f1 in avcodec_encode_video2 (avctx=0x7fffdc013ee0, avpkt=0x7fffdc014a10, frame=0x5555557509d0, got_packet_ptr=0x7fff6891ec7c) at libavcodec/encode.c:300<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#19 0x00007ffff56118e6 in do_encode (avctx=0x7fffdc013ee0, frame=0x5555557509d0, got_packet=0x7fff6891ec7c) at libavcodec/encode.c:370<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#20 0x00007ffff5611a49 in avcodec_send_frame (avctx=0x7fffdc013ee0, frame=0x5555557509d0) at libavcodec/encode.c:419<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#21 0x00007ffff7ccd1f6 in ffmpegStream::processCallbacks(NDArray*) (this=0x555555754270, pArray=0x7fff6891ece0) at ../ffmpegServer.cpp:589<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#22 0x00007ffff7dc9f6f in NDPluginDriver::processTask() (this=0x555555754270) at ../NDPluginDriver.cpp:518<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#23 0x00007ffff7dcb7be in NDPluginDriver::run() (this=0x555555754270) at ../NDPluginDriver.cpp:935<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#24 0x00007ffff7a87baa in epicsThreadCallEntryPoint(void*) (pPvt=0x55555571b720) at ../../../src/libCom/osi/epicsThread.cpp:83<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#25 0x00007ffff7a9067a in start_routine (arg=0x555557847320) at ../../../src/libCom/osi/os/posix/osdThread.c:403<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#26 0x00007ffff7446ea7 in start_thread (arg=<optimized out>) at pthread_create.c:477<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">#27 0x00007ffff795adef in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Valgrind output: <o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    at 0x483F803: memmove (vg_replace_strmem.c:1270)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x531953F: ??? (in /usr/lib/x86_64-linux-gnu/libaravis-0.6.so.0.0.0)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x7BF30BC: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6600.8)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x53B9EA6: start_thread (pthread_create.c:477)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x4EECDEE: clone (clone.S:95)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==  Address 0x22d6bac8 is 5 bytes after a block of size 51,635 alloc'd<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    at 0x48386AF: malloc (vg_replace_malloc.c:306)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x483ADE7: realloc (vg_replace_malloc.c:834)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x7443958: av_realloc (in /usr/local/lib/libavutil.so.56.51.100)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x743413B: av_buffer_realloc (in /usr/local/lib/libavutil.so.56.51.100)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x637F0C7: packet_alloc (in /usr/local/lib/libavcodec.so.58.91.100)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x638039E: av_packet_make_refcounted (in /usr/local/lib/libavcodec.so.58.91.100)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x643F847: avcodec_encode_video2 (in /usr/local/lib/libavcodec.so.58.91.100)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x643F8E5: do_encode (in /usr/local/lib/libavcodec.so.58.91.100)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x643FA48: avcodec_send_frame (in /usr/local/lib/libavcodec.so.58.91.100)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x4B491F5: ffmpegStream::processCallbacks(NDArray*) (ffmpegServer.cpp:589)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x49E4F6E: NDPluginDriver::processTask() (NDPluginDriver.cpp:518)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">==1146775==    by 0x49E67BD: NDPluginDriver::run() (NDPluginDriver.cpp:935)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal">Is there some memory management that happened in the old libraries, that I now need to perform manually?
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks,<o:p></o:p></p>
<p class="MsoNormal">Evan<i><o:p></o:p></i></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>