文章目录
- 视频存储格式
- NV12转I420
- NV12转I444
- P010转I420
视频存储格式
P010格式与NV12格式一样,区别就是两个字节存一个像素值。
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
U U U U U U V V V V V V U V U V U V V U V U V U
V V V V V V U U U U U U U V U V U V V U V U V U- I420 - - YV12 - - NV12 - - NV21 -Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y
U U U U U U V V V V V V
U U U U U U V V V V V V
U U U U U U V V V V V V
U U U U U U V V V V V V
V V V V V V U U U U U U
V V V V V V U U U U U U
V V V V V V U U U U U U
V V V V V V U U U U U U- I444 - - YV24 -
NV12转I420
//NV12 转 I420
void NV12_to_I420(uint8_t* nv12data, uint8_t* i420data, int frameWidth, int frameHeight) {uint8_t* nv12_src[2];nv12_src[0] = nv12data;nv12_src[1] = nv12_src[0] + frameWidth * frameHeight;uint8_t* yuv420_dst[3];yuv420_dst[0] = i420data;yuv420_dst[1] = yuv420_dst[0] + frameWidth * frameHeight;yuv420_dst[2] = yuv420_dst[1] + frameWidth * frameHeight / 4;//Ymemcpy(yuv420_dst[0], nv12_src[0], frameWidth * frameHeight);// for(int i = 0; i < frameWidth * frameHeight ; i++){// *(yuv420_dst[0]++) = *(nv12_src[0] + i);// }for (int i = 0; i < frameWidth * frameHeight / 2; i++) {unsigned char b = *(nv12_src[1] + i);if (i % 2 == 0) {//U*(yuv420_dst[1]++) = *(nv12_src[1] + i);}else {//V*(yuv420_dst[2]++) = *(nv12_src[1] + i);}}
}
NV12转I444
//NV12转YUV444
void NV12_to_I444(uint8_t* nv12data, uint8_t* i444data, int frameWidth, int frameHeight) {uint8_t* nv12_src[2];nv12_src[0] = nv12data;nv12_src[1] = nv12_src[0] + frameWidth * frameHeight;uint8_t* yuv444_dst[3];yuv444_dst[0] = i444data;yuv444_dst[1] = yuv444_dst[0] + frameWidth * frameHeight;yuv444_dst[2] = yuv444_dst[1] + frameWidth * frameHeight;//Ymemcpy(yuv444_dst[0], nv12_src[0], frameWidth * frameHeight);//UVfor (int i = 0; i < frameWidth * frameHeight / 2; i++) {if (i % 2 == 0) {//U,NV12中一位对应444中4位*(yuv444_dst[1]) = *(nv12_src[1] + i);*(yuv444_dst[1] + frameWidth) = *(nv12_src[1] + i);yuv444_dst[1]++;*(yuv444_dst[1]) = *(nv12_src[1] + i);*(yuv444_dst[1] + frameWidth) = *(nv12_src[1] + i);yuv444_dst[1]++;}else {//V,NV12中一位对应444中4位*(yuv444_dst[2]) = *(nv12_src[1] + i);*(yuv444_dst[2] + frameWidth) = *(nv12_src[1] + i);yuv444_dst[2]++;*(yuv444_dst[2]) = *(nv12_src[1] + i);*(yuv444_dst[2] + frameWidth) = *(nv12_src[1] + i);yuv444_dst[2]++;}if ((i > frameWidth && i % frameWidth == 0)) {//UV分量跳行yuv444_dst[1] = yuv444_dst[1] + frameWidth;yuv444_dst[2] = yuv444_dst[2] + frameWidth;}}
}
P010转I420
p010有多种格式,区别在于数据的存放位置,即10bit的数据是如何放在16bit的空间里面的。
//P010转I420
void P010le_to_I420(uint8_t* p010data, uint8_t* i420data, int frameWidth, int frameHeight) {uint8_t* p010_src[2];p010_src[0] = p010data;p010_src[1] = p010_src[0] + frameWidth * frameHeight * 2;uint8_t* yuv420_dst[3];yuv420_dst[0] = i420data;yuv420_dst[1] = yuv420_dst[0] + frameWidth * frameHeight;yuv420_dst[2] = yuv420_dst[1] + frameWidth * frameHeight / 4;uint16_t Y, U, V;//Yfor (int i = 0; i < frameWidth * frameHeight; i++) {Y = *((uint16_t*)p010_src[0] + i) >> 6;Y = Y < 64 ? 64 : Y;Y = Y > 940 ? 940 : Y;*(yuv420_dst[0]++) = (uint8_t)(Y >> 2);}//UVfor (int i = 0; i < frameWidth * frameHeight / 2; i++) {if (i % 2 == 0) {U = (*((uint16_t*)p010_src[1] + i)) & 0x00ff;*(yuv420_dst[1]++) = U;}else {V = (*((uint16_t*)p010_src[1] + i)) & 0x00ff;*(yuv420_dst[2]++) = V;}}
}
void P010_to_I420(uint8_t* P010data, uint8_t* I420data, int frameWidth, int frameHeight) {uint8_t* p010_src[2];p010_src[0] = P010data;p010_src[1] = p010_src[0] + frameWidth * frameHeight * 2;uint8_t* yuv420_dst[3];yuv420_dst[0] = I420data;yuv420_dst[1] = yuv420_dst[0] + frameWidth * frameHeight;yuv420_dst[2] = yuv420_dst[1] + frameWidth * frameHeight / 4;uint8_t Y, U, V;//Yfor (int i = 0; i < frameWidth * frameHeight; i++) {Y = *((uint16_t*)p010_src[0] + i) >> 8;Y = Y < 16 ? 16 : (Y > 235 ? 235 : Y);*(yuv420_dst[0]++) = Y;}//UVfor (int i = 0; i < frameWidth * frameHeight / 2; i++) {if (i % 2 == 0) {U = (*((uint16_t*)p010_src[1] + i)) >> 8;//U = (((U - 128) * (200 + 256)) >> 8) + 128;U = U < 16 ? 16 : (U > 235 ? 235 : U);*(yuv420_dst[1]++) = U;}else {V = (*((uint16_t*)p010_src[1] + i)) >> 8;//V = (((V - 128) * (200 + 256)) >> 8) + 128;V = V < 16 ? 16 : (V > 235 ? 235 : V);*(yuv420_dst[2]++) = V;}}
}