这几天做一个音视频采集与传输的项目,用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。