Für UYVY werden die Daten ausschließlich in Rahmen-> data [0] gespeichert, und pro Zeile sollten Sie Breite * 2 Bytes kopieren:
for (y = 0; y < height; y++)
{
memcpy(output_buffer + y*frame->linesize[0],
frame->data[0] + y*frame->linesize[0], width * 2);
}
Es gibt einen Weg, dies zu programmatisch ableiten, Sie im Falle bin interessiert. Jede AVPixelFormat
hat eine AVPixFmtDescriptor
, die ihre Verpackung in AVFrame->data[]
beschreibt. Verwenden Sie av_pix_fmt_desc_get
(
AV_PIX_FMT_UYVY
)
. Das zurückgegebene Element ist this eins (siehe Strukturreferenz für AVComponentDescriptor
hier). Sie werden sehen, dass desc->nb_components
3 ist, desc->log2_chroma_w
ist 1, was bedeutet, U/V werden von 1 horizontal unterabgetastet, und desc->comp[0-2].plane
ist 0, was bedeutet, dass alle Daten in AVFrame->data[0]
sind. Die offset
/step
/depth
in desc->comp[0-2]
sagen Ihnen den Rest für den Fall, dass Sie eine vollständig dynamische Möglichkeit zum Lesen von Pix_Fmt. Ich glaube nicht, dass Sie es persönlich brauchen, aber zumindest erlaubt es jedem, das Packen eines beliebigen pix_fmt in AVFrame->data[]
abzuleiten.
[Bearbeiten] Beispielcode folgende (möglicherweise Buggy):
#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;
}
, die die folgende Ausgabe gibt:
$ 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)
Oh Gott, ich danke Ihnen so sehr. Ich habe keine Ahnung, dass ich das aus ihrer Quelle herausfinden könnte. Ich meine, offensichtlich muss die Beschreibung irgendwo sein, aber ich hatte keine Ahnung, wo ich hinschauen sollte. Das ist so gut, dass ich nicht einmal beschreiben kann, wie begeistert ich bin. Jetzt kann ich die Komprimierung zwischen jedem beliebigen Pixelformat ausprobieren und herausfinden, welche am besten/am schnellsten funktioniert. Eine Sache, die ich nicht ganz verstehe, ist der 'AVComponentDescriptor-> Schritt ', alles andere ist selbsterklärend. Zum Beispiel wird der Schritt von YUV420P auf 1 gesetzt, heißt das, dass zwischen zwei horizontal aufeinander folgenden Pixeln ein Chroma-Element liegt? –
Wie kann ich auch ableiten, wie viele Bytes ich von 'AVFrame-> Daten [0] pro Zeile kopieren muss? –
Der Schritt bedeutet "wie viele Elemente brauche ich, um meinen Zeiger zu erhöhen, um zum nächsten Element dieses Typs zu gelangen". Beispiel: UYVY Layout ist genau das: U1Y1V1Y2U2Y3V2Y4 [etc]. Also, wenn mein uint8_t * ptr auf U1 gesetzt ist, wie viele Elemente (uint8_t) muss ich inkrementieren, um zu U2 zu gelangen? 4! Und für Y1 bis Y2? 2! Für die meisten planaren Pixelformate ist dieser Wert immer 1. Der Wert ist nur für nicht planare Pixelformate (oder gemischte Formate wie die Chroma-Ebene in NV12)> 1. –