[Libav-user] libav + multithreading per frame

ahmed mobarack ahmed.mobarack123 at yahoo.com
Wed Oct 18 10:02:28 EEST 2017


Hello,
Thank for the marvelous work you did on this library. However I'm having a though time to understand how multithreading works.
I understood that the decoders have intern multithreading that they manage themselves. Now I'm trying to achieve something else, i.e. I have several frames (images) that I want to convert at the same time.Now I want to understand if I need several AVFormatContext, AVCodecContext to achieve this (one per thread).
I tried calling this method I wrote in 8 threads but it gives me an exception when calling avcodec_decode_video2.
Here is my sample code :
bool FFmpeg::ConvertHEICPartToRAW(Buffer& in, IFrameInfo& frameInfo, Buffer& out){    if (!IsLoaded())        return false;
    try    {        // create tampon buffer        const boost::shared_ptr<unsigned char> pBuffer(reinterpret_cast<unsigned char*>(av_malloc(8192)),                av_free);
        // create WBuffer<->FFmpeg adapter (AVIOContext)        const boost::shared_ptr<AVIOContext> pAvioContext(avio_alloc_context(pBuffer.get(), 8192, 0,                reinterpret_cast<void*>(&in), &readFunction, NULL, NULL), av_free);
        // create format context that will detect the file format        const boost::shared_ptr<AVFormatContext> pAvFormat = boost::shared_ptr<AVFormatContext>(                favformat_alloc_context(), favformat_free_context);
        // setup the format context with the buffer        AVFormatContext* pAvFormatPtr = pAvFormat.get();        pAvFormatPtr->pb              = pAvioContext.get();
        // open the input        int ret = favformat_open_input(&pAvFormatPtr, "dummyFilename", NULL, NULL);        if (ret < 0)            return false;
        // find stream info        ret = favformat_find_stream_info(pAvFormatPtr, NULL);        if (ret < 0)            return false;
        // find first video (image) stream        std::size_t videoStreamIndex = -1;        for (std::size_t a = 0; a < pAvFormatPtr->nb_streams; a++)            if (pAvFormatPtr->streams[a]->codec->codec_type == AVMEDIA_TYPE_VIDEO)            {                videoStreamIndex = a;                break;            }
        if (videoStreamIndex == -1)            return false;
        // get codec        const boost::shared_ptr<AVCodecContext> pCodecCtx(pAvFormatPtr->streams[videoStreamIndex]->codec,                avcodec_close);
        //  find decoder        AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);        if (pCodec == NULL)            return false;
        // open it        ret = avcodec_open2(pCodecCtx.get(), pCodec, NULL);        if (ret < 0)            return false;
        // creat packet to decode with auto destruct        AVPacket encodedPacket;        const boost::shared_ptr<AVPacket> pAVPacket(&encodedPacket, av_free_packet);
        // init packet        av_init_packet(pAVPacket.get());        encodedPacket.data = NULL;        encodedPacket.size = 0;
        // now read a frame into this AVPacket        ret = av_read_frame(pAvFormatPtr, &encodedPacket);        if (ret < 0)            return false;
        // create final decoded frame        int frameFinished = 0;        AVFrame* pDecodedFrame = av_frame_alloc();
        // decode frame        ret = avcodec_decode_video2(pCodecCtx.get(), pDecodedFrame, &frameFinished, &encodedPacket);        if (ret < 0)            return false;
        // create destination picture        AVPicture destPic;        AVPixelFormat destFormat = AV_PIX_FMT_RGB24;        ret = favpicture_alloc(&destPic, destFormat, pDecodedFrame->width, pDecodedFrame->height);        if (ret < 0)            return false;
        // auto destruct picture        const boost::shared_ptr<AVPicture> pAVPicture(&destPic, favpicture_free);
        // create picture scaling context        const boost::shared_ptr<SwsContext> pSWSCtxt(sws_getContext(pDecodedFrame->width,                pDecodedFrame->height, (AVPixelFormat)pDecodedFrame->format, pDecodedFrame->width,                pDecodedFrame->height, destFormat, SWS_BILINEAR, NULL, NULL, NULL), sws_freeContext);        if (pSWSCtxt.get() == NULL)            return false;
        // scale picture        sws_scale(pSWSCtxt.get(), pDecodedFrame->data, pDecodedFrame->linesize, 0, pDecodedFrame->height,                destPic.data, destPic.linesize);
        // create destination buffer        const std::size_t dataSize = pDecodedFrame->height * pDecodedFrame->width * 3;        const boost::shared_ptr<uint8_t> pData(reinterpret_cast<uint8_t*>(::malloc(dataSize)), ::free);
        // copy image to buffer        ret = av_image_copy_to_buffer(pData.get(), dataSize, destPic.data, destPic.linesize,                AV_PIX_FMT_RGB24, pDecodedFrame->width, pDecodedFrame->height, 1);        if (ret < 0)            return false;
        // write to output buffer        out.Write(pData.get(), dataSize);
        // update frame info        frameInfo.m_Width        = pDecodedFrame->width;        frameInfo.m_Height       = pDecodedFrame->height;        frameInfo.m_BitsPerPixel = 24;
        return true;    }    catch(...)    {}
    return false;}
Thank you for your time
Ahmed Mobarack
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20171018/a7e19b75/attachment.html>


More information about the Libav-user mailing list