<div dir="ltr"><div>Hello to all!</div><div><br></div><div>Recently I have faced a problem with decoding hevc annexB stream. Crash happens inside avcodec_decode_video2. I also use deprecated get_buffer/release_buffer method to decrease memory copy operations count. While decoding h264 or jpeg, or mpeg-4 there is no problems. Crash happens only with hevc.</div><div><br></div><div>I assumed that reason of those crashes is in deprecated get_buffer/release_buffer usage and tried to upgrade sources to get_buffer2 usage. But after upgrade decoder works well with h264 and still crashes on hevc. Without get_buffer2 it decodes well.</div><div><br></div><div>Could you please point me to what I am doing wrong with get_buffer2 implementation?</div><div><br></div><div>Sources of "upgraded" version of get_buffer2.</div><div><br></div><div>static void release_buffer2(void* opaque, uint8_t* data)</div><div>{</div><div>    // pSample into opaque.</div><div>    data[0] = 0;</div><div><br></div><div>    if (0 != opaque)</div><div>    {</div><div>        Sample* pSample = (Sample*)(opaque);</div><div>        pSample->Release();</div><div>    }</div><div>}</div><div><br></div><div>static int get_buffer2(struct AVCodecContext *c, AVFrame *pic, int flags)</div><div>{</div><div>    switch (c->codec_type)</div><div>            {</div><div>            case AVMEDIA_TYPE_VIDEO:</div><div>            {</div><div>                pic->width = c->width;</div><div>                pic->height = c->height;</div><div>                pic->format = c->pix_fmt;</div><div><br></div><div>                CFFmpegAllocator* pObj = (CFFmpegAllocator*)(c->opaque);</div><div>                return pObj ? pObj->get_buffer2_impl(c, pic, flags) : -1;</div><div>            }</div><div>            case AVMEDIA_TYPE_AUDIO:</div><div>                return avcodec_default_get_buffer2(c, pic, flags);</div><div>            default:</div><div>                return -1;</div><div>            }</div><div>}</div><div><br></div><div>int get_buffer2_impl(AVCodecContext* avctx, AVFrame *pic, int flags)</div><div>{</div><div>    int h_chroma_shift, v_chroma_shift;</div><div>    int i, unaligned;</div><div>    int size[4] = { 0 };</div><div>    int offset[4] = { 0 };</div><div><br></div><div>    if (!m_allocator)</div><div>    {</div><div>        return -1;</div><div>    }</div><div><br></div><div>    int w = pic->width,</div><div>        h = pic->height;</div><div><br></div><div>    const AVPixelFormat pix_fmt = static_cast<AVPixelFormat>(pic->format);</div><div><br></div><div>    if (av_image_check_size(w, h, 0, NULL) < 0)</div><div>    {</div><div>        return -1;</div><div>    }</div><div><br></div><div>    avcodec_get_chroma_sub_sample(pix_fmt, &h_chroma_shift, &v_chroma_shift);</div><div><br></div><div>    // Maximum alignment required is for AVX; use it to be on the safe side</div><div>    const int stride_align[4] = { 32, 32, 32, 32 };</div><div>    {</div><div>        // inlined stripped-down version of avcodec_align_dimensions2</div><div>        const int PIXEL_PER_MACROBLOCK = 16;            // assume 16 pixel per macroblock</div><div>        const int w_align = PIXEL_PER_MACROBLOCK;</div><div>        const int h_align = PIXEL_PER_MACROBLOCK * 2;   // interlaced needs 2 macroblocks height</div><div>        w = FFALIGN(w, w_align);</div><div>        h = FFALIGN(h, h_align);</div><div>    }</div><div><br></div><div>    do{</div><div>        av_image_fill_linesizes(pic->linesize, pix_fmt, w);</div><div>        w += w & ~(w - 1);</div><div><br></div><div>        unaligned = 0;</div><div>        for (i = 0; i < 4; i++){</div><div>            unaligned |= pic->linesize[i] % stride_align[i];</div><div>        }</div><div>    } while (unaligned);</div><div><br></div><div><br></div><div>    int image_size = av_image_fill_pointers(pic->data, pix_fmt,</div><div>        h, NULL, pic->linesize);</div><div><br></div><div>    if (image_size < 0)</div><div>        return -1;</div><div><br></div><div>    for (i = 0; i < 3 && pic->data[i + 1]; i++)</div><div>        size[i] = pic->data[i + 1] - pic->data[i];</div><div>    size[i] = image_size - (pic->data[i] - pic->data[0]);</div><div><br></div><div>    image_size = 0;</div><div>    for (i = 0; i < 4 && size[i]; ++i)</div><div>    {</div><div>        const int h_shift = (0 == i) ? 0 : h_chroma_shift;</div><div>        const int v_shift = (0 == i) ? 0 : v_chroma_shift;</div><div><br></div><div>        offset[i] = 0;</div><div><br></div><div>        size[i] += 16; //16 bytes at the end of each plane</div><div>        image_size += size[i] + offset[i];</div><div>    }</div><div><br></div><div>    Sample* pSample = m_allocator->Alloc(image_size);</div><div><br></div><div>    if (!pSample)</div><div>    {</div><div>        return -1;</div><div>    }</div><div>    </div><div>    SampleHeader& header = pSample->Header();</div><div>    header.BodySize = image_size;</div><div><br></div><div>    uint8_t *body = pSample->GetBody();</div><div><br></div><div>    pic->data[0] = body + offset[0];</div><div>    pic->buf[0] = av_buffer_create(pic->data[0] + offset[0], image_size /*size[0]*/, release_buffer2, pSample, 0);</div><div>    for (i = 1; i < 4 && size[i]; ++i)</div><div>    {</div><div>        pic->data[i] = pic->data[i - 1] + size[i - 1] + offset[i];</div><div>        // pic->buf[i] = av_buffer_create(pic->data[i] + offset[i], size[i], release_buffer2, NULL, 0);</div><div>    }</div><div><br></div><div>#if (LIBAVCODEC_VERSION_MAJOR < 54)</div><div>    pic->age = INT_MAX;</div><div>#endif</div><div><br></div><div>    pic->type = FF_BUFFER_TYPE_USER;</div><div>    pic->opaque = pSample;</div><div><br></div><div>    return 0;</div><div>}</div><div><br></div><div>I also found while debugging, that get_buffer2 is called two times both for codec_type AVMEDIA_TYPE_VIDEO. Why is that second call could be happen?</div><div><br></div><div>Stack trace don't show anything useful cause of missing symbols for ffmpeg libs. Crash happens inside avcodec_decode_video2 call. Will be also very appreciated if you also point me how to make windbg accept libav symbols and whow to build ffmpeg with symbols for Win (I use cygwin+mingw cross compiler).</div><div><br></div><div>AVPacket data contain only sequentually VPS, SPS, PPS and a single IDR_W_RADL.</div><div><br></div><div>Version:</div><div><div>ffmpeg version 0.11.5 Copyright (c) 2000-2014 the FFmpeg developers</div><div>built on Sep 26 2014 01:00:11 with gcc 4.9-win32 (GCC)</div><div>configuration: --arch=x86 --target-os=mingw32 --cross-prefix=i686-w64-mingw32- -</div><div>-disable-pthreads --enable-w32threads --disable-ffprobe --disable-ffplay --build</div><div>-suffix=-ovs-3.1 --enable-shared --disable-static --extra-libs='-Wl,-Bstatic -lw</div><div>inpthread -Wl,-Bdynamic' --enable-libass --prefix=/home/gzh/sdk/mingw-i686/ffmpe</div><div>g-ovs-3.1</div><div>libavutil      54.  7.100 / 54.  7.100</div><div>libavcodec     56.  1.100 / 56.  1.100</div><div>libavformat    56.  4.101 / 56.  4.101</div><div>libavdevice    56.  0.100 / 56.  0.100</div><div>libavfilter     5.  1.100 /  5.  1.100</div><div>libswscale      3.  0.100 /  3.  0.100</div><div>libswresample   1.  1.100 /  1.  1.100</div></div><div><br></div><div>Looking forward to your answer,</div><div>Nikita</div></div>