libyuv

把大尺寸UYVY格式图像转换为小尺寸RGB565格式图像,下面的两种方案哪个更好?为什么?
1:先使用libyuv的ConvertToI420函数把UYVY格式转换为I420格式,再对I420进行缩放,再对I420进行旋转,再使用libyuv的I420ToRGB565函数把I420格式转换为RGB565格式。
2:先使用libyuv的UYVYToARGB函数将UYVY格式转换为ARGB格式,再使用libyuv的ARGBToRGB565函数将ARGB格式转换为RGB565格式,再对RGB565进行缩放,最后对RGB565进行旋转

RGB565 是一种16位色彩模式,其中红色占据5位,绿色占据6位,蓝色占据5位。在进行旋转和缩放操作时,可能会导致像素的位置和值发生变化,进而引起颜色空间变换和精度损失。由于 RGB565 是一个固定位深度的格式,其颜色表示范围和精度有限,因此对像素进行缩放和旋转会引入一定的损失,导致输出图像质量降低。
而 I420 是一种YUV格式,其中包含亮度分量 Y 和色度分量 U、V。Y 分量存储亮度信息,而 U 和 V 分量存储色度信息。在进行旋转和缩放操作时,对 YUV 分量进行处理并不会引入颜色空间变换和精度损失,因为 YUV 格式相对于 RGB 格式来说,更适合进行图像处理操作。所以,在将 UYVY 转换为 I420 格式后,对 I420 进行旋转和缩放不会引起颜色空间变换和精度损失。
综上所述,为了保持较高的图像质量,建议在 I420 格式下进行旋转和缩放操作,而不是在 RGB565 格式下进行。

在使用 libyuv 对 UYVY 和 I420 图像进行缩放和旋转时,通常来说 I420 图像处理的效率会更高一些,因为 I420 格式的图像在处理过程中可以更好地利用硬件加速和优化算法。此外,由于 I420 格式的图像数据存储方式更符合现代处理器的内存访问模式,因此在进行图像处理时可能会有更好的性能表现。
至于图像质量,这取决于具体的应用场景和处理算法。一般来说,无论是 UYVY 还是 I420,libyuv 库都提供了高质量的图像处理函数,因此在正确使用的情况下,它们可以提供相似的图像质量。
总的来说,针对缩放和旋转操作,I420 图像在效率上可能会略胜一筹,但在实际应用中,最好进行实际的测试和评估,以找到最适合特定需求的图像格式和处理方式。


使用libyuv把大尺寸的UYVY转换为小尺寸的RGB565,要求转换效率高且输出的RGB565图像质量高,有下面两个方案:
方案1:先把UYVY转换为I420,再对I420进行缩放,最后把I420转换为RGB565。
方案2:先把UYVY转换为I420,再把I420转换为RGB565,最后对RGB565进行缩放。
请问方案1和方案2哪个更好?哪个方案转换效率和输出的RGB565图像质量更高?
在这两个方案中,方案1 更适合要求转换效率高且输出的 RGB565 图像质量高的情况。原因如下:
1:转换效率:方案1 中先将 UYVY 转换为 I420,然后对 I420 进行缩放,最后再将 I420 转换为 RGB565。这样可以将缩放操作和格式转换操作分离,使得每个操作的复杂度降低,从而提高整体的转换效率。
2:输出图像质量:通过将缩放操作放在格式转换之前,可以避免在 RGB565 格式下进行缩放可能引入的颜色空间变换和精度损失,因此方案1 在输出的 RGB565 图像质量上更有优势。
综上所述,方案1 更适合要求转换效率高且输出的 RGB565 图像质量高的场景。因此,建议选择方案1来实现 UYVY 到 RGB565 的转换。如果还有其他问题或者需要进一步解释,请随时告诉我。


使用libyuv把大尺寸的UYVY转换为小尺寸的RGB565,要求转换效率高且输出的RGB565图像质量高,有下面三个方案:
方案1:先把UYVY转换为I420,再对I420进行缩放,再把I420转换为RGB565,最后对RGB565进行旋转
方案2:先把UYVY转换为I420,再对I420进行缩放,再对I420进行旋转,最后把I420转换为RGB565
方案3:先把UYVY转换为I420,再把I420转换为RGB565,再对RGB565进行缩放,最后对RGB565进行旋转
哪个方案转换效率和输出的RGB565图像质量更高?


int ConvertToI420(const uint8* sample,
                  size_t sample_size,
                  uint8* y,
                  int y_stride,
                  uint8* u,
                  int u_stride,
                  uint8* v,
                  int v_stride,
                  int crop_x,
                  int crop_y,
                  int src_width,
                  int src_height,
                  int crop_width,
                  int crop_height,
                  enum RotationMode rotation,
                  uint32 fourcc)
参数说明:
    sample:输入数据的指针。
    sample_size:输入数据的大小。
    y:输出 Y 分量数据的指针。
    y_stride:输出 Y 分量数据的跨度(stride)。
    u:输出 U 分量数据的指针。
    u_stride:输出 U 分量数据的跨度。
    v:输出 V 分量数据的指针。
    v_stride:输出 V 分量数据的跨度。
    crop_x:裁剪起始点的 x 坐标。
    crop_y:裁剪起始点的 y 坐标。
    src_width:输入图像的宽度。
    src_height:输入图像的高度。
    crop_width:裁剪的宽度。
    crop_height:裁剪的高度。
    rotation:旋转角度,可选值为 0(不旋转)、90、180 和 270。
    fourcc:输入图像的格式,例如 UYVY、YUY2 等。
    
int I420Scale(const uint8* src_y,
              int src_stride_y,
              const uint8* src_u,
              int src_stride_u,
              const uint8* src_v,
              int src_stride_v,
              int src_width,
              int src_height,
              uint8* dst_y,
              int dst_stride_y,
              uint8* dst_u,
              int dst_stride_u,
              uint8* dst_v,
              int dst_stride_v,
              int dst_width,
              int dst_height,
              enum FilterMode filtering)
    I420Scale 函数参数含义:
        src_y:源图像的 Y 分量数据指针。
        src_stride_y:源图像的 Y 分量数据行跨度(即每行像素数据占用的字节数)。
        src_u:源图像的 U 分量数据指针。
        src_stride_u:源图像的 U 分量数据行跨度。
        src_v:源图像的 V 分量数据指针。
        src_stride_v:源图像的 V 分量数据行跨度。
        src_width:源图像的宽度。
        src_height:源图像的高度。
        dst_y:目标图像的 Y 分量数据指针。
        dst_stride_y:目标图像的 Y 分量数据行跨度。
        dst_u:目标图像的 U 分量数据指针。
        dst_stride_u:目标图像的 U 分量数据行跨度。
        dst_v:目标图像的 V 分量数据指针。
        dst_stride_v:目标图像的 V 分量数据行跨度。
        dst_width:目标图像的宽度。
        dst_height:目标图像的高度。
        filtering:指定缩放时使用的滤波器模式。
       
int I420Rotate(const uint8* src_y,
               int src_stride_y,
               const uint8* src_u,
               int src_stride_u,
               const uint8* src_v,
               int src_stride_v,
               uint8* dst_y,
               int dst_stride_y,
               uint8* dst_u,
               int dst_stride_u,
               uint8* dst_v,
               int dst_stride_v,
               int width,
               int height,
               enum RotationMode mode)
    src_y:指向输入图像的 Y 分量数据的指针。
    src_stride_y:输入图像 Y 分量数据的跨度,即每行像素数据占用的字节数。
    src_u:指向输入图像的 U 分量数据的指针。
    src_stride_u:输入图像 U 分量数据的跨度,即每行像素数据占用的字节数。
    src_v:指向输入图像的 V 分量数据的指针。
    src_stride_v:输入图像 V 分量数据的跨度,即每行像素数据占用的字节数。
    dst_y:指向输出图像的 Y 分量数据的指针。
    dst_stride_y:输出图像 Y 分量数据的跨度,即每行像素数据占用的字节数。
    dst_u:指向输出图像的 U 分量数据的指针。
    dst_stride_u:输出图像 U 分量数据的跨度,即每行像素数据占用的字节数。
    dst_v:指向输出图像的 V 分量数据的指针。
    dst_stride_v:输出图像 V 分量数据的跨度,即每行像素数据占用的字节数。
    width:输入图像的宽度。
    height:输入图像的高度。
    mode:旋转模式,可以是 kRotate0(不旋转,默认值)、kRotate90(顺时针旋转90度)、kRotate180(顺时针旋转180度)和 kRotate270(顺时针旋转270度)。

        
        
int I420ToRGB565(const uint8* src_y,
                 int src_stride_y,
                 const uint8* src_u,
                 int src_stride_u,
                 const uint8* src_v,
                 int src_stride_v,
                 uint8* dst_rgb565,
                 int dst_stride_rgb565,
                 int width,
                 int height)
    I420ToRGB565 函数参数含义:
        src_y:源图像的 Y 分量数据指针。
        src_stride_y:源图像的 Y 分量数据行跨度。
        src_u:源图像的 U 分量数据指针。
        src_stride_u:源图像的 U 分量数据行跨度。
        src_v:源图像的 V 分量数据指针。
        src_stride_v:源图像的 V 分量数据行跨度。
        dst_rgb565:目标图像的 RGB565 数据指针。
        dst_stride_rgb565:目标图像的 RGB565 数据行跨度。
        width:图像的宽度。
        height:图像的高度。


int RotatePlane(const uint8* src,
                int src_stride,
                uint8* dst,
                int dst_stride,
                int width,
                int height,
                enum RotationMode mode)
    RotatePlane 函数参数含义:
        src:源图像数据指针。
        src_stride:源图像数据行跨度。
        dst:目标图像数据指针。
        dst_stride:目标图像数据行跨度。
        width:图像的宽度。
        height:图像的高度。
        mode:指定旋转的模式。
        
        
//i420裁剪
int Jni_CutI420(JNIEnv * env,jclass clazz,jbyteArray src,jint srcWidth,jint srcHeight,jbyteArray dst,jint xStart,jint yStart,jint xSize,jint ySize){
    jbyte * src_=env->GetByteArrayElements(src,JNI_FALSE);
    jbyte * dst_=env->GetByteArrayElements(dst,JNI_FALSE);
    libyuv::ConvertToI420(
            (uint8 *)src_,
            srcWidth*srcHeight*3/2,
            (uint8 *)dst_,
            xSize,
            (uint8 *)dst_+xSize*ySize,
            (xSize+1)/2,
            (uint8 *)dst_+xSize*ySize+((xSize+1)/2)*((ySize+1)/2),
            (xSize+1)/2,
            xStart,
            yStart,
            srcWidth,
            srcHeight,
            xSize,
            ySize,
            libyuv::kRotate0,
            libyuv::FOURCC_YU12);
    env->ReleaseByteArrayElements(src,src_,JNI_OK);
    env->ReleaseByteArrayElements(dst,dst_,JNI_OK);
    return 0;
}


用下面方案把大尺寸的UYVY视频转换为小尺寸的RGB565视频,输出画面内容混乱,偏绿,画面很不清晰,画面有很多小网格,请分析下面代码,并给出修正后能使输出的RGB565画面正常的代码,并给出完整的新方案
typedef enum RotationMode {
  kRotate0 = 0,      // No rotation.
  kRotate90 = 90,    // Rotate 90 degrees clockwise.
  kRotate180 = 180,  // Rotate 180 degrees.
  kRotate270 = 270,  // Rotate 270 degrees clockwise.

  // Deprecated.
  kRotateNone = 0,
  kRotateClockwise = 90,
  kRotateCounterClockwise = 270,
} RotationModeEnum;

typedef enum FilterMode {
  kFilterNone = 0,      // Point sample; Fastest.
  kFilterLinear = 1,    // Filter horizontally only.
  kFilterBilinear = 2,  // Faster than box, but lower quality scaling down.
  kFilterBox = 3        // Highest quality.
} FilterModeEnum;

typedef unsigned char uint8;
typedef unsigned int uint32;

// 声明libyuv.so中的函数原型
typedef int (*ConvertToI420Func)(const uint8* sample,
                                size_t sample_size,
                                uint8* y,
                                int y_stride,
                                uint8* u,
                                int u_stride,
                                uint8* v,
                                int v_stride,
                                int crop_x,
                                int crop_y,
                                int src_width,
                                int src_height,
                                int crop_width,
                                int crop_height,
                                enum RotationMode rotation,
                                uint32 fourcc);

typedef int (*I420ScaleFunc)(const uint8* src_y,
                             int src_stride_y,
                             const uint8* src_u,
                             int src_stride_u,
                             const uint8* src_v,
                             int src_stride_v,
                             int src_width,
                             int src_height,
                             uint8* dst_y,
                             int dst_stride_y,
                             uint8* dst_u,
                             int dst_stride_u,
                             uint8* dst_v,
                             int dst_stride_v,
                             int dst_width,
                             int dst_height,
                             enum FilterMode filtering);

typedef int (*I420RotateFunc)(const uint8* src_y,
                              int src_stride_y,
                              const uint8* src_u,
                              int src_stride_u,
                              const uint8* src_v,
                              int src_stride_v,
                              uint8* dst_y,
                              int dst_stride_y,
                              uint8* dst_u,
                              int dst_stride_u,
                              uint8* dst_v,
                              int dst_stride_v,
                              int width,
                              int height,
                              enum RotationMode mode);

typedef int (*I420ToRGB565Func)(const uint8* src_y,
                                int src_stride_y,
                                const uint8* src_u,
                                int src_stride_u,
                                const uint8* src_v,
                                int src_stride_v,
                                uint8* dst_rgb565,
                                int dst_stride_rgb565,
                                int width,
                                int height);

static int hw_convert_image(int in_fmt, int in_width, int in_height, uintptr_t in_addr, int out_fmt, int out_width, int out_height, uintptr_t out_addr, int rot) {
    void* libyuv = dlopen("/system/lib/vndk-28/libyuv.so", RTLD_LAZY);
    if (libyuv == NULL) {
        ERROR("Failed to load libyuv.so\n");
        return -1;
    }

    // 获取各个函数地址
    ConvertToI420Func convertToI420 = (ConvertToI420Func)dlsym(libyuv, "ConvertToI420");
    I420ScaleFunc i420Scale = (I420ScaleFunc)dlsym(libyuv, "I420Scale");
    I420RotateFunc i420Rotate = (I420RotateFunc)dlsym(libyuv, "I420Rotate");
    I420ToRGB565Func i420ToRGB565 = (I420ToRGB565Func)dlsym(libyuv, "I420ToRGB565");

    if (convertToI420 == NULL || i420Scale == NULL || i420Rotate == NULL || i420ToRGB565 == NULL) {
        ERROR("Failed to get function addresses\n");
        dlclose(libyuv);
        return -1;
    }

    // 输入参数
    const int src_width = in_width;
    const int src_height = in_height;
    const int src_stride_y = src_width * 2;
    const int src_stride_uv = src_width;
    const uint8* src = (const uint8*)in_addr;

    // 创建I420格式的临时数据存储转换结果
    const int i420_size = src_width * src_height * 3 / 2;
    uint8* i420_data = (uint8*)malloc(i420_size);
    uint8* y_plane = i420_data;
    uint8* u_plane = i420_data + src_width * src_height;
    uint8* v_plane = u_plane + (src_width + 1) / 2;

    // 将输入数据复制到临时缓冲区
    memcpy(i420_data, src, i420_size);

    // 转换为I420格式
    convertToI420(i420_data, i420_size, y_plane, src_width, u_plane, src_width / 2, v_plane, src_width / 2, 0, 0, src_width, src_height, src_width, src_height, (enum RotationMode)rot, 0);

    // 输出参数
    const int dst_width = out_width;
    const int dst_height = out_height;
    const int dst_stride_y = dst_width;
    const int dst_stride_uv = (dst_width + 1) / 2;
    uint8* dst = (uint8*)out_addr;

    // 创建输出RGB565或RGB888的缓冲区
    const int dst_size = dst_width * dst_height * (out_fmt == JPEG_OUT_FORMAT_RGB565 ? 2 : 3);
    uint8* dst_data = (uint8*)malloc(dst_size);

    // 图像缩放
    i420Scale(y_plane, src_width, u_plane, src_width / 2, v_plane, src_width / 2, src_width, src_height, y_plane, dst_stride_y, u_plane, dst_stride_uv, v_plane, dst_stride_uv, dst_width, dst_height, kFilterBilinear);

    // 图像旋转
    i420Rotate(y_plane, dst_stride_y, u_plane, dst_stride_uv, v_plane, dst_stride_uv, y_plane, dst_stride_y, u_plane, dst_stride_uv, v_plane, dst_stride_uv, dst_width, dst_height, (enum RotationMode)rot);

    // I420格式转换为RGB565或RGB888
    i420ToRGB565(y_plane, dst_stride_y, u_plane, dst_stride_uv, v_plane, dst_stride_uv, dst_data, dst_width * (out_fmt == JPEG_OUT_FORMAT_RGB565 ? 2 : 3), dst_width, dst_height);

    // 将结果拷贝到输出地址
    memcpy(dst, dst_data, dst_size);

    // 释放内存和关闭库
    free(i420_data);
    free(dst_data);
    dlclose(libyuv);

    return 0;
}


NO1
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>

// 定义 libyuv 函数指针类型
typedef int (*ConvertToI420Func)(const uint8_t* sample, size_t sample_size,
                                uint8_t* y, int y_stride,
                                uint8_t* u, int u_stride,
                                uint8_t* v, int v_stride,
                                int crop_x, int crop_y,
                                int src_width, int src_height,
                                int crop_width, int crop_height,
                                enum RotationMode rotation,
                                uint32_t fourcc);

typedef int (*I420ScaleFunc)(const uint8_t* src_y, int src_stride_y,
                             const uint8_t* src_u, int src_stride_u,
                             const uint8_t* src_v, int src_stride_v,
                             int src_width, int src_height,
                             uint8_t* dst_y, int dst_stride_y,
                             uint8_t* dst_u, int dst_stride_u,
                             uint8_t* dst_v, int dst_stride_v,
                             int dst_width, int dst_height,
                             enum FilterMode filtering);

typedef int (*I420ToRGB565Func)(const uint8_t* src_y, int src_stride_y,
                                const uint8_t* src_u, int src_stride_u,
                                const uint8_t* src_v, int src_stride_v,
                                uint8_t* dst_rgb565, int dst_stride_rgb565,
                                int width, int height);

typedef int (*RotatePlaneFunc)(const uint8_t* src, int src_stride,
                               uint8_t* dst, int dst_stride,
                               int width, int height,
                               enum RotationMode mode);

int hw_convert_image(int in_fmt, int in_width, int in_height, uintptr_t in_addr,
                     int out_fmt, int out_width, int out_height, uintptr_t out_addr,
                     int rot) {
    void* libyuv_lib = dlopen("libyuv.so", RTLD_NOW);
    if (!libyuv_lib) {
        printf("Failed to load libyuv.so: %s\n", dlerror());
        return -1;
    }

    // 使用 dlsym 获取函数指针
    ConvertToI420Func convertToI420 = (ConvertToI420Func)dlsym(libyuv_lib, "ConvertToI420");
    I420ScaleFunc i420Scale = (I420ScaleFunc)dlsym(libyuv_lib, "I420Scale");
    I420ToRGB565Func i420ToRGB565 = (I420ToRGB565Func)dlsym(libyuv_lib, "I420ToRGB565");
    RotatePlaneFunc rotatePlane = (RotatePlaneFunc)dlsym(libyuv_lib, "RotatePlane");

    if (!convertToI420 || !i420Scale || !i420ToRGB565 || !rotatePlane) {
        printf("Failed to get function pointers from libyuv.so: %s\n", dlerror());
        dlclose(libyuv_lib);
        return -1;
    }

    // 输入参数
    const uint8_t* in_data = (const uint8_t*)in_addr;
    int in_stride_y = in_width;
    int in_stride_uv = in_width;
    int crop_x = 0;
    int crop_y = 0;
    int crop_width = in_width;
    int crop_height = in_height;

    // 输出参数
    uint8_t* out_data = (uint8_t*)out_addr;
    int out_stride_rgb565 = out_width * 2;

    // 转换为 I420 格式
    uint8_t* y_plane = out_data;
    int y_stride = out_width;
    uint8_t* u_plane = y_plane + (y_stride * out_height);
    int u_stride = out_width / 2;
    uint8_t* v_plane = u_plane + (u_stride * out_height / 2);
    int v_stride = out_width / 2;

    convertToI420(in_data, in_width * in_height * 2, y_plane, y_stride, u_plane, u_stride, v_plane, v_stride,
                  crop_x, crop_y, in_width, in_height, crop_width, crop_height, rot, 'UYVY');

    // 缩放为目标尺寸
    uint8_t* scaled_y_plane = malloc(out_width * out_height);
    int scaled_y_stride = out_width;
    uint8_t* scaled_u_plane = malloc(out_width / 2 * out_height / 2);
    int scaled_u_stride = out_width / 2;
    uint8_t* scaled_v_plane = malloc(out_width / 2 * out_height / 2);
    int scaled_v_stride = out_width / 2;

    i420Scale(y_plane, y_stride, u_plane, u_stride, v_plane, v_stride, out_width, out_height,
              scaled_y_plane, scaled_y_stride, scaled_u_plane, scaled_u_stride,
              scaled_v_plane, scaled_v_stride, out_width, out_height, kFilterNone);

    // 转换为 RGB565
    uint8_t* rgb565_data = malloc(out_width * out_height * 2);
    int rgb565_stride = out_width * 2;

    i420ToRGB565(scaled_y_plane, scaled_y_stride, scaled_u_plane, scaled_u_stride,
                 scaled_v_plane, scaled_v_stride, rgb565_data, rgb565_stride, out_width, out_height);

    // 释放缓冲区内存
    free(scaled_y_plane);
    free(scaled_u_plane);
    free(scaled_v_plane);

    // 旋转图像
    rotatePlane(rgb565_data, rgb565_stride, out_data, out_stride_rgb565, out_width, out_height, rot);

    // 释放缓冲区内存
    free(rgb565_data);

    dlclose(libyuv_lib);

    return 0;
}


NO2
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "libyuv.h"

// 定义输入格式和输出格式的枚举类型
typedef enum {
    UYVY,
    YUYV
} InputFormat;

typedef enum {
    RGB565,
    RGB888
} OutputFormat;

// 实现hw_convert_image函数
int hw_convert_image(int in_fmt,  int in_width,  int in_height, uintptr_t in_addr,
                     int out_fmt, int out_width, int out_height, uintptr_t out_addr, int rot) {
    void *libyuv_handle = dlopen("libyuv.so", RTLD_LAZY); // 动态加载libyuv库
    if (!libyuv_handle) {
        fprintf(stderr, "Error opening libyuv.so: %s\n", dlerror());
        return -1;
    }

    // 获取ConvertToI420函数指针
    int (*ConvertToI420)(const uint8_t*, size_t, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int, int, int, int, int, enum RotationMode, uint32_t);
    ConvertToI420 = (int (*)(const uint8_t*, size_t, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int, int, int, int, int, enum RotationMode, uint32_t))dlsym(libyuv_handle, "ConvertToI420");

    // 获取I420Scale函数指针
    int (*I420Scale)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, int, int, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int, enum FilterMode);
    I420Scale = (int (*)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, int, int, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int, enum FilterMode))dlsym(libyuv_handle, "I420Scale");

    // 获取I420ToRGB565函数指针
    int (*I420ToRGB565)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, uint8_t*, int, int, int);
    I420ToRGB565 = (int (*)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, uint8_t*, int, int, int))dlsym(libyuv_handle, "I420ToRGB565");

    // 获取RotatePlane函数指针
    int (*RotatePlane)(const uint8_t*, int, uint8_t*, int, int, int, enum RotationMode);
    RotatePlane = (int (*)(const uint8_t*, int, uint8_t*, int, int, int, enum RotationMode))dlsym(libyuv_handle, "RotatePlane");

    if (!ConvertToI420 || !I420Scale || !I420ToRGB565 || !RotatePlane) {
        fprintf(stderr, "Error getting symbol for functions: %s\n", dlerror());
        dlclose(libyuv_handle);
        return -1;
    }

    // 其他参数设置
    int crop_x = 0;
    int crop_y = 0;
    int crop_width = in_width;
    int crop_height = in_height;
    uint32_t fourcc = 0;

    // 计算输入数据每行的字节数
    int in_stride = in_width * 2; // UYVY和YUYV格式每像素占2字节

    // 计算输出数据每行的字节数
    int out_stride = (out_fmt == RGB565) ? (out_width * 2) : (out_width * 3); // RGB565每像素占2字节,RGB888每像素占3字节

    // 分配输入和输出数据的内存
    uint8_t* in_data = (uint8_t*)malloc(in_stride * in_height);
    uint8_t* out_data = (uint8_t*)malloc(out_stride * out_height);

    // 将输入数据拷贝到内存中
    memcpy(in_data, (uint8_t*)in_addr, in_stride * in_height);

    // 分配I420数据内存
    int i420_size = out_width * out_height * 3 / 2;
    uint8_t* i420_data = (uint8_t*)malloc(i420_size);

    // 调用ConvertToI420函数将输入数据转换为I420格式
    ConvertToI420(in_data, in_stride, i420_data, out_width,
                 i420_data + out_width * out_height, out_width / 2,
                 i420_data + out_width * out_height * 5 / 4, out_width / 2,
                 crop_x, crop_y, in_width, in_height, crop_width, crop_height, (enum RotationMode)rot, fourcc);

    // 调用I420Scale函数将I420数据缩放到指定尺寸
    I420Scale(i420_data, out_width,
              i420_data + out_width * out_height, out_width / 2,
              i420_data + out_width * out_height * 5 / 4, out_width / 2,
              out_width, out_height,
              out_data, out_stride,
              out_data + out_width * out_height, out_stride / 2,
              out_data + out_width * out_height * 5 / 4, out_stride / 2,
              out_width, out_height,
              kFilterBox);

    // 根据输出格式选择相应的函数进行格式转换
    if (out_fmt == RGB565) {
        // 调用I420ToRGB565函数将I420数据转换为RGB565格式
        I420ToRGB565(out_data, out_stride,
                     out_data + out_width * out_height, out_stride / 2,
                     out_data + out_width * out_height * 5 / 4, out_stride / 2,
                     out_data, out_stride,
                     out_width, out_height);
    } else if (out_fmt == RGB888) {
        // 调用RotatePlane函数将RGB565格式旋转为RGB888格式
        RotatePlane(out_data, out_stride,
                    out_data, out_stride,
                    out_width, out_height, kRotate0);
    }

    // 将输出数据拷贝到指定地址
    memcpy((uint8_t*)out_addr, out_data, out_stride * out_height);

    // 释放内存
    free(in_data);
    free(out_data);
    free(i420_data);

    dlclose(libyuv_handle); // 关闭libyuv库

    return 0;
}

int main() {
    // 输入参数
    int in_fmt = UYVY;
    int in_width = 1884;
    int in_height = 1056;

    // 分配输入数据内存并初始化
    size_t in_size = in_width * in_height * 2; // UYVY格式每像素占2字节
    uint8_t* in_data = (uint8_t*)malloc(in_size);
    memset(in_data, 0xFF, in_size); // 假设输入数据全为白色

    // 输出参数
    int out_fmt = RGB565;
    int out_width = 1440;
    int out_height = 720;

    // 分配输出数据内存
    size_t out_size = out_width * out_height * 2; // RGB565格式每像素占2字节
    uint8_t* out_data = (uint8_t*)malloc(out_size);

    // 调用hw_convert_image函数进行图像格式转换
    hw_convert_image(in_fmt, in_width, in_height, (uintptr_t)in_data,
                     out_fmt, out_width, out_height, (uintptr_t)out_data, 0);

    // 在这里可以对输出数据进行处理或保存到文件

    // 释放内存
    free(in_data);
    free(out_data);

    return 0;
}


TWO:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "libyuv.h"

// 实现hw_convert_video函数
int hw_convert_video(int in_width, int in_height, uintptr_t in_addr,
                     int out_width, int out_height, uintptr_t out_addr) {
    void *libyuv_handle = dlopen("libyuv.so", RTLD_LAZY); // 动态加载libyuv库
    if (!libyuv_handle) {
        fprintf(stderr, "Error opening libyuv.so: %s\n", dlerror());
        return -1;
    }

    // 获取UYVYToI420函数指针
    int (*UYVYToI420)(const uint8_t*, int, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int);
    UYVYToI420 = (int (*)(const uint8_t*, int, uint8_t*, int, uint8_t*, int, uint8_t*, int, int, int))dlsym(libyuv_handle, "UYVYToI420");

    // 获取I420ToRGB565函数指针
    int (*I420ToRGB565)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, uint8_t*, int, int, int);
    I420ToRGB565 = (int (*)(const uint8_t*, int, const uint8_t*, int, const uint8_t*, int, uint8_t*, int, int, int))dlsym(libyuv_handle, "I420ToRGB565");

    if (!UYVYToI420 || !I420ToRGB565) {
        fprintf(stderr, "Error getting symbol for functions: %s\n", dlerror());
        dlclose(libyuv_handle);
        return -1;
    }

    // 计算输入数据每行的字节数
    int in_stride = in_width * 2; // UYVY格式每像素占2字节

    // 计算输出数据每行的字节数
    int out_stride = out_width * 2; // RGB565每像素占2字节

    // 分配输入和输出数据的内存
    uint8_t* in_data = (uint8_t*)malloc(in_stride * in_height);
    uint8_t* out_data = (uint8_t*)malloc(out_stride * out_height);

    // 将输入数据拷贝到内存中
    memcpy(in_data, (uint8_t*)in_addr, in_stride * in_height);

    // 分配I420数据内存
    int i420_size = out_width * out_height * 3 / 2;
    uint8_t* i420_data = (uint8_t*)malloc(i420_size);

    // 调用UYVYToI420函数将输入数据转换为I420格式
    UYVYToI420(in_data, in_stride, i420_data, out_width,
               i420_data + out_width * out_height, out_width / 2,
               i420_data + out_width * out_height * 5 / 4, out_width / 2,
               in_width, in_height);

    // 调用I420ToRGB565函数将I420数据转换为RGB565格式
    I420ToRGB565(i420_data, out_width,
                 i420_data + out_width * out_height, out_width / 2,
                 i420_data + out_width * out_height * 5 / 4, out_width / 2,
                 out_data, out_stride,
                 out_width, out_height);

    // 将输出数据拷贝到指定地址
    memcpy((uint8_t*)out_addr, out_data, out_stride * out_height);

    // 释放内存
    free(in_data);
    free(out_data);
    free(i420_data);

    dlclose(libyuv_handle); // 关闭libyuv库

    return 0;
}

int main() {
    // 输入参数
    int in_width = 1884;
    int in_height = 1056;

    // 分配输入数据内存并初始化
    size_t in_size = in_width * in_height * 2; // UYVY格式每像素占2字节
    uint8_t* in_data = (uint8_t*)malloc(in_size);
    memset(in_data, 0xFF, in_size); // 假设输入数据全为白色

    // 输出参数
    int out_width = 1440;
    int out_height = 720;

    // 分配输出数据内存
    size_t out_size = out_width * out_height * 2; // RGB565格式每像素占2字节
    uint8_t* out_data = (uint8_t*)malloc(out_size);

    // 调用hw_convert_video函数进行视频格式转换
    hw_convert_video(in_width, in_height, (uintptr_t)in_data,
                     out_width, out_height, (uintptr_t)out_data);

    // 在这里可以对输出数据进行处理或保存到文件

    // 释放内存
    free(in_data);
    free(out_data);

    return 0;
}

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值