写一个1920x1080的nv12数据分别旋转y通道和uv通道90度的示例代码
时间: 2024-01-21 07:16:51 浏览: 109
nv12旋转90度
以下是一个使用FFmpeg库实现旋转YUV数据的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
#include <libavutil/pixdesc.h>
#define WIDTH 1920
#define HEIGHT 1080
#define ROTATE_ANGLE 90
int main(int argc, char **argv)
{
AVFrame *frame = av_frame_alloc();
AVFrame *rotated_frame = av_frame_alloc();
uint8_t *src_data[4], *dst_data[4];
int src_linesize[4], dst_linesize[4];
int ret;
// 设置输入帧的信息
frame->format = AV_PIX_FMT_NV12;
frame->width = WIDTH;
frame->height = HEIGHT;
// 分配输入帧的缓冲区
ret = av_frame_get_buffer(frame, 32);
if (ret < 0) {
fprintf(stderr, "Could not allocate input frame buffer\n");
return ret;
}
// 填充输入帧的缓冲区,这里简单地将所有像素都设置为255
src_data[0] = frame->data[0];
src_data[1] = frame->data[1];
src_linesize[0] = frame->linesize[0];
src_linesize[1] = frame->linesize[1];
memset(src_data[0], 255, src_linesize[0] * HEIGHT);
memset(src_data[1], 255, src_linesize[1] * (HEIGHT / 2));
// 设置输出帧的信息
rotated_frame->format = AV_PIX_FMT_NV12;
rotated_frame->width = HEIGHT;
rotated_frame->height = WIDTH;
// 分配输出帧的缓冲区
ret = av_frame_get_buffer(rotated_frame, 32);
if (ret < 0) {
fprintf(stderr, "Could not allocate output frame buffer\n");
return ret;
}
// 获取输入和输出帧的数据指针和行大小
av_image_fill_pointers(src_data, AV_PIX_FMT_NV12, HEIGHT, src_data, src_linesize);
av_image_fill_pointers(dst_data, AV_PIX_FMT_NV12, WIDTH, dst_data, dst_linesize);
// 旋转Y通道
av_image_copy_plane(dst_data[0], dst_linesize[0], src_data[0], src_linesize[0], HEIGHT, WIDTH);
// 旋转UV通道
for (int y = 0; y < HEIGHT / 2; y++) {
for (int x = 0; x < WIDTH / 2; x++) {
dst_data[1][y * dst_linesize[1] + x] = src_data[1][(HEIGHT / 2 - 1 - x) * src_linesize[1] + y];
dst_data[1][y * dst_linesize[1] + x + WIDTH / 2] = src_data[1][(HEIGHT / 2 - 1 - x) * src_linesize[1] + y + WIDTH / 2];
}
}
// 输出旋转后的YUV数据
FILE *fp = fopen("rotated_nv12.yuv", "wb");
fwrite(rotated_frame->data[0], 1, rotated_frame->linesize[0] * rotated_frame->height, fp);
fwrite(rotated_frame->data[1], 1, rotated_frame->linesize[1] * rotated_frame->height / 2, fp);
fclose(fp);
// 释放帧和缓冲区
av_frame_free(&frame);
av_frame_free(&rotated_frame);
return 0;
}
```
在上面的示例代码中,我们首先使用`av_frame_alloc()`函数分配输入和输出帧的内存空间。然后,我们填充了输入帧的数据,这里简单地将所有像素都设置为255。接下来,我们设置了输出帧的信息,并分配了输出帧的缓冲区。然后,我们使用`av_image_fill_pointers()`函数获取输入和输出帧的数据指针和行大小。
接着,我们使用`av_image_copy_plane()`函数旋转了Y通道的数据。最后,我们循环遍历UV通道的数据,并把它们旋转90度后复制到输出帧的缓冲区中。最后,我们把旋转后的YUV数据写入到文件中。
需要注意的是,由于NV12格式是一种半平面格式,所以UV通道的数据在内存中是交叉存储的(即UVUVUV...),而不是分开存储的(即UUUU...VVVV...)。因此,在旋转UV通道的数据时,我们需要特别注意数据的存储顺序。
阅读全文