yuyv(yuv422)转换为yuv420p

我的摄像头采集到的数据是yuyv格式(属于yuv422),而X264在进行编码的时候需要 标准的YUV(4:2:0)。所以有一个yuv422toyuv420的转换。在网上找了半天找到的方法拿过来转换了查看都很花。于是自己看了一下yuv 格式的解释,准备写一个转换代码。以下许多解释都是按我的理解:

一、yuv
yuv格式通常有两大类:打包(packed)和平面(planar)格式。前者在码流里是yuv挨一起,比如我的yuyv就是 Y0 U0 Y1 V1 Y2 U2 …. 每一个 Y对应一组UV分量。后者存储y u v分量是分开存储的,这种方式一般后面带P, 比如y uv420p就是Y0 Y1 Y2 … U0 U1 U2 … V0 V1 V2 … uv分量的多少根据格式来,yuv420也就是每四个 Y共用一组UV分量。
二、转换
理解了yuyv即yuv422与yuv420p中分量的排布,就要进行转换了。网上查到的资料说yuv422->yuv420p时 丢弃偶数行的uv分量。
三、编码


 
 
  1. 定义:
  2. unsignedchar *y = out;
  3. unsignedchar *u = out + width*height;
  4. unsigned char*v = out + width*height + width*height/ 4;

y u v分别指向yuv420buf中存储y u v分量的数组,这里out的类型为char型数组,按yuv420p的定义,4个y共用一对uv,那么一个y对应1/4个uv,一个分量占一个 byte,out的大小为:总共的y分量(width*height) + 总共的u分量(width*height/4) + 总共的v分量(width*height/4) = width*height*3/2。通过上面的转换也可以得到yuyv(yuv422)一个像素占用2个字节,yuv420p一个像素占1.5个字 节,rgb24的话占用3个字节,还是节约了一点点空间的。。。


 
 
  1. 获取y分量并存储到yuv420buf中:
  2. for(i=0; i <yuv422_length; i+=2){
  3. *(y+y_index) = *(in+i);
  4. y_index++;
  5. }
  6. 这里的yuv422_lengthwidth*height*2;y_index初始为0,存储一个y就自加一次。
  7. 获取uv分量并存储到yuv420buf中:
  8. for(i=0; i<height; i+=2){
  9. base_h = i*width*2;
  10. for(j=base_h+1;j<base_h+width*2; j+=2){
  11. if(is_u){
  12. *(u+u_index)= *(in+j);
  13. u_index++;
  14. is_u = 0;
  15. }
  16. else{
  17. *(v+v_index)= *(in+j);
  18. v_index++;
  19. is_u = 1;
  20. }
  21. }
  22. }

总结:初入视频图像,我还是一个菜鸟,对于很多理解也不深,这个代码应该还有很多没考虑,对于我可用了。当然以上都是废话,直接贴代码


 
 
  1. int yuv422toyuv420( unsigned char * out, const unsigned char * in, unsigned int width, unsigned int height)
  2. {
  3. unsigned char *y = out;
  4. unsigned char *u = out + width*height;
  5. unsigned char *v = out + width*height + width*height/ 4;
  6. unsigned int i,j;
  7. unsigned int base_h;
  8. unsigned int is_y = 1, is_u = 1;
  9. unsigned int y_index = 0, u_index = 0, v_index = 0;
  10. unsigned long yuv422_length = 2 * width * height;
  11. //序列为YU YV YU YV,一个yuv422帧的长度 width * height * 2 个字节
  12. //丢弃偶数行 u v
  13. for(i= 0; i<yuv422_length; i+= 2){
  14. *(y+y_index) = *( in+i);
  15. y_index++;
  16. }
  17. for(i= 0; i<height; i+= 2){
  18. base_h = i*width* 2;
  19. for(j=base_h+ 1; j<base_h+width* 2; j+= 2){
  20. if(is_u){
  21. *(u+u_index) = *( in+j);
  22. u_index++;
  23. is_u = 0;
  24. }
  25. else{
  26. *(v+v_index) = *( in+j);
  27. v_index++;
  28. is_u = 1;
  29. }
  30. }
  31. }
  32. return 1;
  33. }

转自 https://blog.csdn.net/weixin_37897683/article/details/81380412

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值