YUYV422转YUV420
YUYV422转YUV420
宇文成欣 发表于1年前
YUYV422转YUV420
  • 发表于 1年前
  • 阅读 42
  • 收藏 1
  • 点赞 0
  • 评论 0

【腾讯云】新注册用户域名抢购1元起>>>   

 这几天做一个音视频采集与传输的项目,用v4l2来采集视频数据,公司给的USB摄像头只支持packed yuyv422数据,需要将其转换为planar yuv420,折腾了一下,将代码贴出来,说不定有同学可以用到。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <sys/time.h>

uint32_t width = 1280;
uint32_t height = 720;

uint32_t getcurrenttime()
{
  struct timeval t;
  gettimeofday(&t, NULL);
  return (uint32_t)(t.tv_sec * 1000 + t.tv_usec / 1000);
}

int convert(uint8_t *inbuf, const uint32_t buflen, uint8_t *outbuf)
{
  uint8_t *y = NULL;
  uint8_t *u = NULL;
  uint8_t *v = NULL;
  y = outbuf;
  u = y + 1280 * 720;
  v = u + 1280 * 720 / 2;

  uint32_t i = 0;
  uint8_t swith = 0;
  while (i < buflen) {
    if (swith == 0 || swith == 2) {
      *y++ = inbuf[i];
      swith++;
    } else if (swith == 1) {
      *u++ = inbuf[i];
      swith++;
    } else if (swith == 3) {
      *v++ = inbuf[i];
      swith = 0;
    }
    i++;
  }
  return 0;
}

void yuyv2yuv420(uint8_t *inbuf, const uint32_t buflen, uint8_t *outbuf)
{
  uint8_t *y = NULL;
  uint8_t *u = NULL;
  uint8_t *v = NULL;
  int u_c = 0;
  int v_c = 0;
  y = outbuf;
  u = y + 1280 * 720;
  v = u + 1280 * 720 / 4;
  bool swith = true;
  uint32_t i = 0, j = 0;

  for (i = 0; i < buflen; i += 2) {
    *y++ = inbuf[i];
  }
  
  for (i = 0; i < height; i += 2) {
    for (j = 1; j < width << 1; j += 2) {
      if (swith) {
        *u++ = ((uint8_t *)(inbuf + (i * (width << 1))))[j];
        swith = false;
        u_c++;
      } else {
        *v++ = ((uint8_t *)(inbuf + (i * (width << 1))))[j];
        swith = true;
        v_c++;
      }
    }
  }
}

int main()
{
  int ret = 0;
  uint32_t inframesize = width * height * 2; 
  uint32_t outframesize = width * height * 3 / 2;
  printf("inframesize: %u\n", inframesize);
  printf("outframesize: %u\n", outframesize);
  printf("size: %u\n", width * height / 4);
  FILE *infb = NULL;
  FILE *outfb = NULL;
  uint8_t *inbuf = NULL;
  uint8_t *outbuf = NULL; 
  
  inbuf = (uint8_t *)malloc(sizeof(uint8_t) * inframesize);
  if (inbuf == NULL) {
    printf("malloc inbuf failed\n");
    ret = -1;
    goto Error;
  }
  outbuf = (uint8_t *)malloc(sizeof(uint8_t) * outframesize);
  if (outbuf == NULL) {
    printf("malloc outbuf failed\n");
    ret = -1;
    goto Error;
  }

  infb = fopen("./test.yuv", "rb");
  if (infb == NULL) {
    printf("open ./test.yuv failed\n");
    ret = -1;
    goto Error;
  }
  outfb = fopen("./test.yuv420", "wb");
  if (outfb == NULL) {
    printf("open ./test.yuv422 failed\n");
    ret = -1;
    goto Error;
  }

  uint32_t start;
  uint32_t end;
  while (fread(inbuf, 1, inframesize, infb) == inframesize) {
    //convert(inbuf, inframesize, outbuf);
    start = getcurrenttime();
    yuyv2yuv420(inbuf, inframesize, outbuf);
    end = getcurrenttime();
    printf("%d\n", end - start);
    fwrite(outbuf, 1, outframesize, outfb);
  }

Error:
  if (inbuf != NULL) free(inbuf);
  if (outbuf != NULL) free(outbuf);
  if (infb != NULL) fclose(infb);
  if (outfb != NULL) fclose(outfb);
  return ret;
}

代码中的convert函数,只是将packed yuyv422转换成planar。

 

 

 

标签: yuyv422 yuv420
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 1
博文 3
码字总数 623
×
宇文成欣
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: