YUV422封包 | width*height+width/2*height*2 |
YUYV Y分量 | width*height |
YUYV U分量 | width/2*height |
YUYV V分量 | width/2*height |
YUV420空间大小计算
YUV420封包 | width*height+width/2*height/2*2 |
Y分量 | width*height |
U分量 | width/2*height/2 |
V分量 | width/2*height/2 |
extern "C" {
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "swscale.lib")
#pragma comment(lib, "avutil.lib")
};
YUV422分量实现(YUYV)
static void YUYV422Planes(uint8_t *yuv422, uint8_t *y_ptr, uint8_t *u_ptr, uint8_t *v_ptr, int width, int height)
{
//计算出空间大小
int numBytes = width*height+width/2*height*2;
unsigned int yIndex = 0;
unsigned int uIndex = 0;
unsigned int vIndex = 0;
//分量
for (unsigned int i = 0; i < numBytes; i += 4) {
memcpy((unsigned char *)y_ptr + yIndex, yuv422+i, 1);
yIndex++;
memcpy((unsigned char *)u_ptr + uIndex, yuv422+i+1, 1);
uIndex++;
memcpy((unsigned char *)y_ptr + yIndex, yuv422+i+2, 1);
yIndex++;
memcpy((unsigned char *)v_ptr + vIndex, yuv422+i+3, 1);
vIndex++;
}
}
YUV422封包实现(YUYV)
static void YUYV422Packages(uint8_t *yuv422, uint8_t *y_ptr, uint8_t *u_ptr, uint8_t *v_ptr, int width, int height)
{
//计算出空间大小
int numBytes = width * height + width / 2 * height * 2;
unsigned int yIndex = 0;
unsigned int uIndex = 0;
unsigned int vIndex = 0;
//封包
for (unsigned int i = 0; i < numBytes; i+=4) {
//y
memcpy((unsigned char *)yuv422+i,y_ptr+yIndex,1);
yIndex++;
//u
memcpy((unsigned char *)yuv422+i+1, u_ptr+uIndex, 1);
uIndex++;
//y
memcpy((unsigned char *)yuv422+i+2, y_ptr+yIndex, 1);
yIndex++;
//v
memcpy((unsigned char *)yuv422+i+3, v_ptr+vIndex, 1);
vIndex++;
}
}
YUV420封包实现
static void YUV420PPackages(uint8_t *yuv420, uint8_t *y_ptr, uint8_t *u_ptr,
uint8_t *v_ptr, int width, int height)
{
//Y分量的长度
int yLen = width * height;
//U和V分量的长度
int uvLen = width / 2 * height / 2;
memcpy((unsigned char *)yuv420, y_ptr, yLen);
memcpy((unsigned char *)yuv420 + yLen, u_ptr, uvLen);
memcpy((unsigned char *)yuv420+yLen+uvLen, v_ptr, uvLen);
}
YUV420分量实现
static void YUV420PPlanes(uint8_t *yuv420, uint8_t *y_ptr, uint8_t *u_ptr,
uint8_t *v_ptr, int width, int height)
{
//Y分量的长度
int yLen = width * height;
//U和V分量的长度
int uvLen = width / 2 * height / 2;
memcpy((unsigned char *)y_ptr, yuv420, yLen);
memcpy((unsigned char *)u_ptr, yuv420 + yLen, uvLen);
memcpy((unsigned char *)v_ptr, yuv420 + yLen + uvLen, uvLen);
}
YUV420P转YUYV422
static void YUV420P_TO_YUYV422(uint8_t *yuv420p, void *y_ptr, void *u_ptr, void *v_ptr, int width, int height)
{
AVFrame *Input_pFrame = nullptr;
AVFrame *Output_pFrame = nullptr;
struct SwsContext *img_convert_ctx = nullptr; //用于解码后的格式转换
/*1. 申请空间*/
Input_pFrame = av_frame_alloc();
Output_pFrame = av_frame_alloc();
/*2.设置转码参数*/
img_convert_ctx =
sws_getContext(width, height, AV_PIX_FMT_YUV420P, //输入
width, height, AV_PIX_FMT_YUYV422, //输出
SWS_BICUBIC, nullptr, nullptr, nullptr);
int numBytes = avpicture_get_size(AV_PIX_FMT_YUYV422, width, height);
//申请空间
uint8_t *yuv422 = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
/*3. 申请转码需要空间*/
/*4. 设置转码的源数据地址*/
avpicture_fill((AVPicture *)Input_pFrame, yuv420p, AV_PIX_FMT_YUV420P,
width, height);
avpicture_fill((AVPicture *)Output_pFrame, yuv422, AV_PIX_FMT_YUYV422,
width, height);
//转格式
sws_scale(img_convert_ctx, (uint8_t const **)Input_pFrame->data,
Input_pFrame->linesize, 0, height, Output_pFrame->data,
Output_pFrame->linesize);
//yuv422分量
YUYV422Planes(yuv422, (uint8_t *)y_ptr, (uint8_t *)u_ptr,
(uint8_t *)v_ptr, width, height);
//释放空间
if (Input_pFrame)
av_free(Input_pFrame);
if (Output_pFrame)
av_free(Output_pFrame);
if (yuv422)
av_free(yuv422);
if (img_convert_ctx)
sws_freeContext(img_convert_ctx);
}
YUYV转YUV420P格式
static void YUYV422_TO_YUV420P(uint8_t *yuyv422, uint8_t *yuv420p, int video_width, int video_height)
{
AVFrame *Input_pFrame = nullptr;
AVFrame *Output_pFrame = nullptr;
struct SwsContext *img_convert_ctx = nullptr; //用于解码后的格式转换
/*1. 申请空间*/
Input_pFrame = av_frame_alloc();
Output_pFrame = av_frame_alloc();
/*2.设置转码参数*/
img_convert_ctx = sws_getContext(
video_width, video_height, AV_PIX_FMT_YUYV422, //输入
video_width, video_height, AV_PIX_FMT_YUV420P, //输出
SWS_BICUBIC, nullptr, nullptr, nullptr);
/*3. 申请转码需要空间*/
/*4. 设置转码的源数据地址*/
avpicture_fill((AVPicture *)Input_pFrame, yuyv422, AV_PIX_FMT_YUYV422,
video_width, video_height);
avpicture_fill((AVPicture *)Output_pFrame, yuv420p, AV_PIX_FMT_YUV420P,
video_width, video_height);
//转格式
sws_scale(img_convert_ctx, (uint8_t const **)Input_pFrame->data,
Input_pFrame->linesize, 0, video_height, Output_pFrame->data,
Output_pFrame->linesize);
//释放空间
if (Input_pFrame)
av_free(Input_pFrame);
if (Output_pFrame)
av_free(Output_pFrame);
if (img_convert_ctx)
sws_freeContext(img_convert_ctx);
}
版权声明:本文为wu110112原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。