Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. New QImage is invalid (am I out of memory)?
Forum Updated to NodeBB v4.3 + New Features

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

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 3 Posters 1.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    kitfox
    wrote on last edited by kitfox
    #1

    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?

    1 Reply Last reply
    0
    • K Offline
      K Offline
      Kerndog73
      wrote on last edited by
      #2

      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?

      1 Reply Last reply
      0
      • K Offline
        K Offline
        kitfox
        wrote on last edited by kitfox
        #3

        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();
        }
        
        jsulmJ 1 Reply Last reply
        0
        • K kitfox

          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();
          }
          
          jsulmJ Online
          jsulmJ Online
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @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?

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          K 1 Reply Last reply
          2
          • jsulmJ jsulm

            @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?

            K Offline
            K Offline
            kitfox
            wrote on last edited by
            #5

            @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.

            jsulmJ 1 Reply Last reply
            0
            • K kitfox

              @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.

              jsulmJ Online
              jsulmJ Online
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #6

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

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              2

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved