Pour UYVY, les données sont stockées exclusivement dans DE CADRE> données [0], et par ligne, vous devez copier la largeur * 2 octets:
for (y = 0; y < height; y++)
{
memcpy(output_buffer + y*frame->linesize[0],
frame->data[0] + y*frame->linesize[0], width * 2);
}
Il y a une façon de tirer programme ce, au cas où vous êtes intéressé. Chaque AVPixelFormat
a un AVPixFmtDescriptor
qui décrit son emballage dans AVFrame->data[]
. Pour obtenir le vôtre, utilisez av_pix_fmt_desc_get
(
AV_PIX_FMT_UYVY
)
. L'article renvoyé est this (voir la référence de structure pour AVComponentDescriptor
ici). Vous verrez que desc->nb_components
est 3, desc->log2_chroma_w
est 1, ce qui signifie que U/V sont sous-échantillonnées par 1 horizontalement, et desc->comp[0-2].plane
est 0, ce qui signifie que toutes les données sont en AVFrame->data[0]
. Le offset
/step
/depth
dans desc->comp[0-2]
vous dire le reste au cas où vous voulez une façon entièrement dynamique de lire pix_fmt. Je ne pense pas que vous en ayez besoin personnellement, mais à tout le moins, cela permet à quiconque de dériver l'emballage de n'importe quel pix_fmt dans AVFrame->data[]
.
[modifier] suivant exemple de code (éventuellement voiturette):
#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;
}
Ce qui donne le résultat suivant:
$ 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 mon dieu, je vous remercie beaucoup. Je n'ai aucune idée que je pourrais trouver cela à partir de leur source. Je veux dire, évidemment, la description doit être quelque part mais je n'avais aucune idée de l'endroit où regarder. C'est tellement bon que je ne peux même pas décrire à quel point je suis ravi. Maintenant je peux essayer la compression entre n'importe quel format de pixel et découvrir lequel fonctionne le meilleur/le plus rapide. Une chose que je ne comprends pas bien est l'étape 'AVComponentDescriptor->, tout le reste est explicite. Par exemple, l'étape de YUV420P est définie sur 1, cela signifie-t-il qu'il y a 1 élément de chrominance entre 2 pixels consécutifs horizontaux? –
Aussi, comment puis-je déduire combien d'octets ai-je besoin de copier à partir de 'AVFrame-> data [0]' par ligne? –
L'étape signifie "de combien d'éléments ai-je besoin pour incrémenter mon pointeur pour accéder à l'élément suivant de ce type". Exemple: la disposition UYVY est exactement celle-ci: U1Y1V1Y2U2Y3V2Y4 [etc]. Donc, si mon uint8_t * ptr est mis à U1, combien d'éléments (uint8_t) ai-je besoin de l'incrémenter pour arriver à U2? 4! Et pour Y1 à Y2? 2! Pour la plupart des formats de pixels planaires, cette valeur est toujours 1. La valeur est seulement> 1 pour les formats de pixels non planaires (ou les formats mixtes comme le plan de chrominance dans NV12). –