Для UYVY, данные хранятся исключительно в Frame-> данные [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]
. offset
/step
/depth
в desc->comp[0-2]
расскажет вам остальное, если вы хотите полностью динамический способ чтения любого pix_fmt. Я не думаю, что вам это лично нужно, но, по крайней мере, это позволяет любому получить упаковку любого pix_fmt в AVFrame->data[]
.
[править] См следующий пример кода (возможно, глючит):
#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)
О Боже, благодарю вас так много. Я понятия не имею, что я могу найти это из их источника. Я имею в виду, очевидно, что описание должно быть где-то, но я понятия не имел, где искать. Это так хорошо, что я даже не могу описать, насколько я взволнован. Теперь я могу попробовать сжатие между любыми пиксельными форматами и узнать, какой из них работает лучше всего/быстрее. Одна вещь, которую я не совсем понимаю, это «шаг AVComponentDescriptor->», все остальное самоочевидно. Например, шаг YUV420P установлен в 1, означает ли это, что имеется 1 элемент цветности между двумя горизонтально последовательными пикселями? –
Также, как я могу определить, сколько байтов мне нужно скопировать из 'AVFrame-> данных [0]' за строку? –
Этот шаг означает «сколько элементов мне нужно, чтобы увеличить мой указатель, чтобы перейти к следующему элементу этого типа». Пример: UYVY-макет точно такой: U1Y1V1Y2U2Y3V2Y4 [и т. Д.]. Итак, если my uint8_t * ptr установлен в U1, сколько элементов (uint8_t) нужно увеличить, чтобы получить U2? 4! А для Y1 - Y2? 2! Для большинства плоскостных форматов пикселей это значение всегда равно 1. Это значение равно> 1 для непланарных пиксельных форматов (или смешанных форматов, таких как цветная плоскость в NV12). –