New QImage is invalid (am I out of memory)?



  • I have a loop in my program where I'm loading several images into memory. They're all 1920x1080 RGBA images. Things go well until the 23rd image where I allocate a new QImage and try to write to it by doing a memcpy to image.scanline(0), which causes a crash. The debugger variable watch displays my image as (invalid). I'm wondering if maybe I'm running out of memory, and if so how I could monitor this? Also, I'd like to cache around 50 of these images. Is there a way to do that?



  • 1920 * 1080 * 4 * 50 ~ 400MB. That doesn't seem like enough for you to run out. You'd have to be seriously low on memory and disk space for that to be the case. Could you show us some code?



  • I'm deserializing from a stream. My method first looks to see if I've cached the frame I'm looking for. Then if it doesn't find it, it jumps to the keyframe image prior to it and scans in all the images to the next keyframe, placing them in the cache:

    QImage FfmpegMediaSource::getVideoFrame(int timeMs)
    {
        int frameFinished;
        AVPacket packet;
    
        //Seek to our goal time
        avcodec_flush_buffers(pCodecCtx);
        int64_t targetPts = timeMs * 1000;
        targetPts = av_rescale_q(targetPts, AV_TIME_BASE_Q,
                              pFormatCtx->streams[videoStream]->time_base);
    
        VideoFrame* vf = lookupVideoFrame(targetPts);
        if (!vf->image.isNull())
            return vf->image;
    
        int64_t keyframePts = vf->keyPts;
    
    
        int err = av_seek_frame(pFormatCtx, videoStream, keyframePts, AVSEEK_FLAG_BACKWARD);
    
        //Clear loaded image buffer
        for (VideoFrame* loaded: _loadedImageList)
        {
            loaded->image = QImage();
        }
        _loadedImageList.clear();
    
        //Read frame
        int seq = 0;
        while (av_read_frame(pFormatCtx, &packet) == 0)
        {
            if (packet.stream_index != videoStream)
                continue;
    
            int64_t pts = packet.pts == AV_NOPTS_VALUE ? packet.dts : packet.pts;
    
            if ((packet.flags & AV_PKT_FLAG_KEY) != 0 && pts != keyframePts)
            {
                //If we hit next keyframe, break
                break;
            }
    
            int err = avcodec_send_packet(pCodecCtx, &packet);
            if (err != 0)
            {
                qDebug() << "Error sendsing packet: " << err;
            }
    
            QImage img = readVideoFrame(packet);
    
            _videoPtsMap[pts]->image = img;
            _loadedImageList.append(_videoPtsMap[pts]);
    
    
            AVRational time_base = pFormatCtx->streams[videoStream]->time_base;
            int presentationTime = pts * av_q2d(time_base) * 1000;
        }
    
        return vf->image;
    }
    
    
    QImage FfmpegMediaSource::readVideoFrame(AVPacket& packet)
    {
        int err = 0;
        while (err >= 0)
        {
            err = avcodec_receive_frame(pCodecCtx, pFrame);
            if (err == AVERROR(EAGAIN) || err == AVERROR_EOF)
            {
                qDebug() << "Error decoding packet: " << err;
                break;
            }
            if (err < 0)
            {
                qDebug() << "Error decoding packet: " << err;
                break;
            }
    
            // Convert the image from its native format to RGB
            sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data,
                pFrame->linesize, 0, pCodecCtx->height,
                pFrameRGB->data, pFrameRGB->linesize);
    
            QImage videoFrame = QImage(pCodecCtx->width, pCodecCtx->height, QImage::Format_RGB32);
    
            for (int j = 0; j < pCodecCtx->height; ++j)
            {
                memcpy(videoFrame.scanLine(j), pFrameRGB->data[0] + j * pFrameRGB->linesize[0], pCodecCtx->width * 4);
            }
    
            return videoFrame;
        }
    
        return QImage();
    }
    

  • Qt Champions 2018

    @kitfox said in New QImage is invalid (am I out of memory)?:

    for (VideoFrame* loaded: _loadedImageList)
    {
    loaded->image = QImage();
    }

    Why do you need this? image is not a pointer.

    Did you observe memory consumption of your app?



  • @jsulm This was my attempt to clear memory by replacing the previously allocated image with a null one. Not sure if this is actually achieving what I want it to.

    I don't know how to observe memory consumption in my app. I'm doing this on windows with Qt Creator, and I'm not sure how to set up memory profiling.


  • Qt Champions 2018

    @kitfox You can simply open the Windows Task Manager and see what happens when your app is running.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.