Skip to content

2025

Cropping part of video image – crop window issues

While working on cropping video image in my newest version of VideoEditor app, I came to solving an issue of cropping area being incompatible with possible codec’s input. There’re two issues with this matter: cropping an area out of a YUV image, and then feeding codec with that image.

Let’s see, what are the rules, regarding few pixel formats – and coming from aligning color planes:

  • YUV444P and all RGB/BGR formats: no restrictions, as they’re not packed;
  • YUV422P requires x offset to be even, and also the overall width to be even;
  • YUV420P (most common in H.264/H.265 codecs), and similar, like NV12 or YUVJ420P requires both x and y offset to be even, and also both width and height to be even.

Now, the second problem is a bit tricky – and sometimes it is a problem, while sometimes it’s not 😉 But, for encoding with codecs like H.264 or H.265, the safe choice is to have overall height to be divisible by 4 – or even by 16, to be on a super safe side.

So, that’s why I wrote this little helper function:

static QRect makeRectYUVCompliant(const QRect& rect, AVPixelFormat format, bool forceHeight4 = false, bool forceHeight16 = false)
{
    int x = rect.x();
    int y = rect.y();
    int w = rect.width();
    int h = rect.height();

    switch (format)
    {
      case AV_PIX_FMT_YUV420P:
      case AV_PIX_FMT_YUVJ420P:
    case AV_PIX_FMT_NV12:
          if (x % 2 != 0) x--;
          if (y % 2 != 0) y--;
      if (w % 2 != 0) w--;
      if (h % 2 != 0) h--;
          break;
    case AV_PIX_FMT_YUV422P:
        if (x % 2 != 0) x--;
        if (w % 2 != 0) w--;
        break;
      case AV_PIX_FMT_YUV444P:
      case AV_PIX_FMT_RGB24:
      case AV_PIX_FMT_BGR24:
      case AV_PIX_FMT_ARGB:
      case AV_PIX_FMT_ABGR:
      case AV_PIX_FMT_RGBA:
      case AV_PIX_FMT_BGRA:
        // no requirements
        break;
    default:
        // unknown format, assume YUV420P
        if (x % 2 != 0) x--;
        if (y % 2 != 0) y--;
        if (w % 2 != 0) w--;
        if (h % 2 != 0) h--;
        break;
    }

    if (forceHeight4)
    {
        while (h % 4 != 0) h--;
      }
    if (forceHeight16)
    {
        while (h % 16 != 0) h--;
      }

    return QRect(x, y, w, h);
}

Soon I’ll probably write more on the topic of cropping – and how to achieve it, using libavfilter library from ffmpeg.


Share on Share on Share on

VideoEditor 1.2.1.111

Recently, my VideoEditor app received some substantial updates, as I've completely reworked its underlying engine. Currently it no longer uses raw FFmpeg executables but instead relies on a shared FFmpeg libraries, so it's self-contained. Player works very smoothly now and it also plays audio.

VideoEditor 1.2.1.111

Changelog

  • It's no more using external ffmpeg binary. Now it's using dll libraries and has all transcoding built-in, rewritten from scratch.
  • Player is no longer using external media player component, now it's a rewritten from scratch player, which supports much more codecs.
  • Check Settings to see how to define presets.
  • Resizing video does work.
  • Cropping video is still not supported.

Codecs

Supported codecs for transcoding so far (more to come): Video:

  • H.264
  • H.265
  • DNxHD

Audio:

  • AAC
  • PCM signed 24-bit little-endian

Download:

You can get it here.

Have fun! 😄


Share on Share on Share on