gpt4 book ai didi

FFMPEG/libav : How is UYVY422 written inside AVFrame structure?

转载 作者:行者123 更新时间:2023-12-04 22:46:41 42 4
gpt4 key购买 nike

我正在尝试将帧数据从 AVFrame 结构复制到缓冲区。我知道如何使用 YUV420P 格式执行此操作,因为 Y 数据存储在 AVFrame 帧->data[0] 内部,U 数据存储在 AVFrame 帧-> 内部data[1]和V数据存储在AVFrameframe->data[2]内部,因此很容易memcpy()Y、U和V数据分开+它是平面格式,所以我能够轻松做到这一点:

for (y = 0; y < height; y++)
{
memcpy(buffer + y*frame->linesize[0], frame->data[0] + y*frame->linesize[0], width);
}

buffer += ySize;

for (y = 0; y < height / 2; y++)
{
memcpy(buffer + y*frame->linesize[1], frame->data[1] + y*frame->linesize[1], width / 2);
}

buffer += uSize;

for (y = 0; y < height / 2; y++)
{
memcpy(buffer + y*frame->linesize[2], frame->data[2] + y*frame->linesize[2], width / 2);
}

但是当谈到UYVY422时,我不知道数据是如何存储在结构内部的。我对 UYVY422 格式有一般了解,并且它的写法就像它的名字所暗示的 UYVYUYVYUYVY...等等。但我的问题是我如何知道 AVFrameframe->data[0]AVFrameframe->data[1]AVFrame 中存储了多少数据frame->data[2] 字段,以便我可以 memcpy() 准确地写入缓冲区?

最佳答案

对于UYVY,数据仅存储在frame->data[0]中,每行您应该复制宽度* 2个字节:

for (y = 0; y < height; y++)
{
memcpy(output_buffer + y*frame->linesize[0],
frame->data[0] + y*frame->linesize[0], width * 2);
}

如果您感兴趣的话,有一种方法可以通过编程方式导出它。每个AVPixelFormat都有一个AVPixFmtDescriptor描述了它在 AVFrame->data[] 中的打包。要获取您的,请使用 av_pix_fmt_desc_get ( AV_PIX_FMT_UYVY )。返回的项目是 this一个(请参阅此处 AVComponentDescriptor 的结构引用)。您会看到 desc->nb_components 为 3,desc->log2_chroma_w 为 1,这意味着 U/V 水平二次采样 1,而 desc->comp[0-2].plane为0,表示所有数据都在AVFrame->data[0]中。 desc->comp[0-2] 中的 offset/step/depth 告诉您其余的情况,以防万一您想要一种完全动态的方式来读取任何 pix_fmt。我认为您个人并不需要它,但至少它允许任何人导出 AVFrame->data[] 中任何 pix_fmt 的打包。

[编辑]请参阅以下示例代码(可能有错误):

#include <assert.h>
#include <stdio.h>
#include <libavutil/pixdesc.h>

int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s [fmt]\n", argv[0]);
return 1;
}
const char *fmtname = argv[1];
enum AVPixelFormat fmt = av_get_pix_fmt(fmtname);
if (fmt == AV_PIX_FMT_NONE) {
fprintf(stderr, "Unknown pixfmt %s\n", fmtname);
return 1;
}
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
assert(desc != NULL);
printf("N planes: %d, %d bits/element\n", desc->nb_components, desc->comp[0].depth);

int n;
int epl[4] = { 0, 0, 0, 0 };
int width = 0x100;
for (n = 0; n < desc->nb_components; n++) {
int is_y = n == 0;
int is_a = !(desc->nb_components & 1) && n == desc->nb_components - 1;
int h_ss = (is_y || is_a) ? 0 : desc->log2_chroma_w;

epl[desc->comp[n].plane] += width >> h_ss;
}

for (n = 0; n < 4; n++) {
int is_y = n == 0;
int is_a = !(desc->nb_components & 1) && n == desc->nb_components - 1;
int v_ss = (is_y || is_a) ? 0 : desc->log2_chroma_h;

if (epl[n] == 0) continue;
printf("Plane %d has %lf elements/y_pixel (horizontally) and %lf lines/y_pixel (vertically)\n",
n, epl[n] / (double) width, (width >> v_ss) / (double) width);
}

return 0;
}

输出如下:

$ for fmt in yuyv422 uyvy422 yuv420p yuva420p10; do /tmp/test $fmt; done
N planes: 3, 8 bits/element
Plane 0 has 2.000000 elements/y_pixel (horizontally) and 1.000000 lines/y_pixel (vertically)
N planes: 3, 8 bits/element
Plane 0 has 2.000000 elements/y_pixel (horizontally) and 1.000000 lines/y_pixel (vertically)
N planes: 3, 8 bits/element
Plane 0 has 1.000000 elements/y_pixel (horizontally) and 1.000000 lines/y_pixel (vertically)
Plane 1 has 0.500000 elements/y_pixel (horizontally) and 0.500000 lines/y_pixel (vertically)
Plane 2 has 0.500000 elements/y_pixel (horizontally) and 0.500000 lines/y_pixel (vertically)
N planes: 4, 10 bits/element
Plane 0 has 1.000000 elements/y_pixel (horizontally) and 1.000000 lines/y_pixel (vertically)
Plane 1 has 0.500000 elements/y_pixel (horizontally) and 0.500000 lines/y_pixel (vertically)
Plane 2 has 0.500000 elements/y_pixel (horizontally) and 0.500000 lines/y_pixel (vertically)
Plane 3 has 1.000000 elements/y_pixel (horizontally) and 1.000000 lines/y_pixel (vertically)

关于FFMPEG/libav : How is UYVY422 written inside AVFrame structure?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36741637/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com