讲解一下将获取到视频数据,进行rgb转码,并且进行相应的缩放操作
// 存放解码过后的数据
unsigned char *decode_data;
int decode_size = 0;
/**
* 解码AVFrame中的yuv420数据并且转换为rgba数据
*
* @param frame 需要解码的帧结构
* @param src_width 需要转换的帧宽度
* @param src_height 需要转换的帧高度
* @param src_pix_fmt 需要转换的帧编码方式
* @param dst_width 转换后目标的宽度
* @param dst_height 转换后目标的高度
* @return
*
**/
int decode_frame(AVFrame *frame, int src_width, int src_height,
AVPixelFormat src_pix_fmt, int dst_width, int dst_height) {
struct SwsContext *pSwsCtx;
// 转换后的帧结构对象
AVFrame *dst_frameRGBA = NULL;
// 目标帧结构初始化
dst_frameRGBA = av_frame_alloc();
BYTE *outBuff = NULL;
// 初始化目标帧长度
int dst_frame_size;
// 计算RGBA下的目标长度
dst_frame_size = avpicture_get_size(AV_PIX_FMT_RGBA, dst_width, dst_height);
// 分配转换后输出的内存空间
outBuff = (uint8_t *) av_malloc(dst_frame_size);
// 初始化目标帧
avpicture_fill((AVPicture *) dst_frameRGBA, outBuff, AV_PIX_FMT_RGBA,
dst_width, dst_height);
// 获取缩放上下文
pSwsCtx = sws_getContext(src_width, src_height, src_pix_fmt, dst_width, dst_height, AV_PIX_FMT_RGBA,
SWS_BICUBIC, NULL, NULL, NULL);
// 缩放,结果保存在目标帧结构的dst_frameRGBA->data中
sws_scale(pSwsCtx, frame->data,
frame->linesize, 0, src_height,
dst_frameRGBA->data, dst_frameRGBA->linesize);
// 存储帧结果
if (decode_data == NULL) {
decode_data = malloc(dst_frame_size * sizeof(char));
// 测试保存成文件
// save_frame(frame, src_width, src_height);
// save_rgb(dst_frameRGBA->data[0], dst_frame_size);
} else if (decode_size != dst_frame_size * sizeof(char)) {
// 如果解码过后的数据大小不满足解码区域,那么重新分配内存
decode_data = realloc(decode_data, dst_frame_size * sizeof(char));
}
// 将解码后的数据拷贝到decode_data中
memcpy(decode_data, dst_frameRGBA->data[0], dst_frame_size * sizeof(char));
// 计算解码后的帧大小
decode_size = dst_frame_size * sizeof(char);
// 释放相关内容
av_free(outBuff);
av_free(dst_frameRGBA);
return 1;
}
/**
* 保存rgb数据
* @param data
* @param frameSize
* */
void save_rgb(uint8_t *data, int frameSize) {
FILE *pFile;
char *szFilename = "/sdcard/RGB";
int y;
pFile = fopen(szFilename, "wb");
if (pFile == NULL)
return;
//写入文件
fwrite(data, 1, frameSize, pFile);
// Close file
fclose(pFile);
}
/**
* 保存yuv数据
* @param data
* @param frameSize
* */
void save_frame(AVFrame *pFrame, int width, int height) {
FILE *pFile;
char *szFilename = "/sdcard/frame.yuv";
int y;
pFile = fopen(szFilename, "wb");
if (pFile == NULL)
return;
int y_size = width * height;
int u_size = y_size / 4;
int v_size = y_size / 4;
//写入文件
//首先写入Y,再是U,再是V
//in_frame_picture->data[0]表示Y
fwrite(pFrame->data[0], 1, y_size, pFile);
//in_frame_picture->data[1]表示U
fwrite(pFrame->data[1], 1, u_size, pFile);
//in_frame_picture->data[2]表示V
fwrite(pFrame->data[2], 1, v_size, pFile);
// Close file
fclose(pFile);
}
查看测试文件结果,windows下可以使用RawViewer,OSX可以使用YUView
image.png
OSX下:
image.png
注意由于我们是直接将数据保存在文件中,需要在YUView或者RawViewer中手动设置width和height属性。好了,这节就讲到这里,有什么问题,欢迎交流~~~
网友评论