Audio and video portal -10- uses libyuv to zoom, rotate, mirror, cut and mix YUV data.

Posted by Scabby on Thu, 03 Oct 2019 19:45:03 +0200

Directory of Audio and Video Introduction Articles

libyuv

libyuv Google is open source to achieve a variety of YUV and RGB conversion, rotation, scaling and other libraries. It is cross platform and can be compiled and run on Windows, Linux, Mac, Android and other operating systems, x86, x64 and arm architectures. It supports the acceleration of SIMD instructions such as SSE, AVX and NEON.

Preparation

A picture

download rainbow-700x700.bmp BMP picture or prepare a picture by yourself (know the resolution, such as: 700x700)

FFmpeg Toolkit

FFmpeg Tool Download

Download the FFmpeg Static toolkit according to your system.

Get the required yuv420p file

Convert the above image into YUV420P format:

ffmpeg -i rainbow.bmp -video_size 700x700 -pix_fmt yuv420p rainbow-yuv420p.yuv

View YUV files

ffplay -f rawvideo -pixel_format yuv420p -video_size 700x700 rainbow-yuv420p.yuv

libyuv Operating YUV

YUV clipping

[rainbow-yuv420p.yuv] -> [rainbow-yuv420p-clip-x-y.yuv]

#include <stdio.h>
#include <stdint.h>
#include "libyuv.h"

void clip(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height, int cropX, int cropY, int cropWidth, int cropHeight) {
    ConvertToI420(
            srcYuvData,
            width*height*3/2,
            dstYuvData,
            cropWidth,
            dstYuvData+cropWidth*cropHeight,
            (cropWidth+1)/2,
            dstYuvData+cropWidth*cropHeight+((cropWidth+1)/2)*((cropHeight+1)/2),
            (cropWidth+1)/2,
            cropX,
            cropY,
            width,
            height,
            cropWidth,
            cropHeight,
            kRotate0,
            FOURCC_YU12);
}

int main() {
    uint32_t width = 700, height = 700;
    uint32_t clipWidth = 200, clipHeight = 200;
    uint8_t YUV[width*height*3/2];
    uint8_t YUV_CLIP[clipWidth*clipHeight*3/2];

    FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p.yuv", "rb");
    fread(YUV, sizeof(YUV), 1, yuv420pFile);

    clip(YUV, YUV_CLIP, width, height, 0, 0, clipWidth, clipHeight);

    FILE *yuvClipFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-clip-0-0.yuv", "wb");
    fwrite(YUV_CLIP, sizeof(YUV_CLIP), 1, yuvClipFile);

    fclose(yuvClipFile);
    fclose(yuv420pFile);
    return 0;
}

YUV zoom

[rainbow-yuv420p.yuv] -> [rainbow-yuv420p-scale-X.yuv]

#include <stdio.h>
#include <stdint.h>
#include "libyuv.h"

void scale(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height, int dstWidth, int dstHeight) {
    I420Scale(
            srcYuvData,
            width,
            srcYuvData+width*height,
            (width+1)/2,
            srcYuvData+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            width,
            height,
            dstYuvData,
            dstWidth,
            dstYuvData+dstWidth*dstWidth,
            (dstWidth+1)/2,
            dstYuvData+dstWidth*dstHeight+((dstWidth+1)/2)*((dstHeight+1)/2),
            (dstWidth+1)/2,
            dstWidth,
            dstHeight,
            kFilterNone
            );
}

int main() {
    uint32_t width = 700, height = 700;
    uint32_t dstWidth = 100, dstHeight = 100;
    uint8_t YUV[width*height*3/2];
    uint8_t YUV_SCALE[dstWidth*dstHeight*3/2];

    FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p.yuv", "rb");
    fread(YUV, sizeof(YUV), 1, yuv420pFile);

    scale(YUV, YUV_SCALE, width, height, dstWidth, dstHeight);

    FILE *yuvScaleFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-scale-6.yuv", "wb");
    fwrite(YUV_SCALE, sizeof(YUV_SCALE), 1, yuvScaleFile);

    fclose(yuvScaleFile);
    fclose(yuv420pFile);
    return 0;
}

YUV rotation

[rainbow-yuv420p.yuv] -> [rainbow-yuv420p-rotation-90.yuv]

#include <stdio.h>
#include <stdint.h>
#include "libyuv.h"

void rotation(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height) {
    I420Rotate(
            srcYuvData,
            width,
            srcYuvData+width*height,
            (width+1)/2,
            srcYuvData+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            dstYuvData,
            width,
            dstYuvData+width*height,
            (width+1)/2,
            dstYuvData+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            width,
            height,
            kRotate90
            );
}

int main() {
    uint32_t width = 700, height = 700;
    uint8_t YUV[width*height*3/2];
    uint8_t YUV_ROTATION[width*height*3/2];

    FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p.yuv", "rb");
    fread(YUV, sizeof(YUV), 1, yuv420pFile);

    rotation(YUV, YUV_ROTATION, width, height);

    FILE *yuvRotationFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-rotation-90.yuv", "wb");
    fwrite(YUV_ROTATION, sizeof(YUV_ROTATION), 1, yuvRotationFile);

    fclose(yuvRotationFile);
    fclose(yuv420pFile);
    return 0;
}

YUV mirror image

[rainbow-yuv420p-rotation-90.yuv] -> [rainbow-yuv420p-rotation-90-mirror.yuv]

#include <stdio.h>
#include <stdint.h>
#include "libyuv.h"

void mirror(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height) {
    I420Mirror(
            srcYuvData,
            width,
            srcYuvData+width*height,
            (width+1)/2,
            srcYuvData+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            dstYuvData,
            width,
            dstYuvData+width*height,
            (width+1)/2,
            dstYuvData+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            width,
            height
            );
}

int main() {
    uint32_t width = 700, height = 700;
    uint8_t YUV[width*height*3/2];
    uint8_t YUV_MIRROR[width*height*3/2];

    FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-rotation-90.yuv", "rb");
    fread(YUV, sizeof(YUV), 1, yuv420pFile);

    mirror(YUV, YUV_MIRROR, width, height);

    FILE *yuvMirrorFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-rotation-90-mirror.yuv", "wb");
    fwrite(YUV_MIRROR, sizeof(YUV_MIRROR), 1, yuvMirrorFile);

    fclose(yuvMirrorFile);
    fclose(yuv420pFile);
    return 0;
}

YUV mixing

[rainbow-yuv420p.yuv] -> [rainbow-yuv420p-blend.yuv]

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "libyuv.h"

void blend(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height) {
    uint8_t YUV_ROTATION[width*height*3/2];
    I420Rotate(
            srcYuvData,
            width,
            srcYuvData+width*height,
            (width+1)/2,
            srcYuvData+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            YUV_ROTATION,
            width,
            YUV_ROTATION+width*height,
            (width+1)/2,
            YUV_ROTATION+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            width,
            height,
            kRotate90
    );

    // transparency
    uint8_t alpha[width*height];
    memset(alpha, 0X88, width*height);

    I420Blend(
            srcYuvData,
            width,
            srcYuvData+width*height,
            (width+1)/2,
            srcYuvData+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            YUV_ROTATION,
            width,
            YUV_ROTATION+width*height,
            (width+1)/2,
            YUV_ROTATION+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            alpha,
            width,
            dstYuvData,
            width,
            dstYuvData+width*height,
            (width+1)/2,
            dstYuvData+width*height+((width+1)/2)*((height+1)/2),
            (width+1)/2,
            width,
            height
            );
}

int main() {
    uint32_t width = 700, height = 700;
    uint8_t YUV[width*height*3/2];
    uint8_t YUV_BLEND[width*height*3/2];

    FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p.yuv", "rb");
    fread(YUV, sizeof(YUV), 1, yuv420pFile);

    blend(YUV, YUV_BLEND, width, height);

    FILE *yuvBlendFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-blend.yuv", "wb");
    fwrite(YUV_BLEND, sizeof(YUV_BLEND), 1, yuvBlendFile);

    fclose(yuvBlendFile);
    fclose(yuv420pFile);
    return 0;
}

Code:
10-yuv-conversion-libyuv

Reference material:

libyuv/libyuv

Is the content wrong? Contact author:

Topics: C++ Google Windows Linux Mac