]> git.sesse.net Git - ffmpeg/blob - libavutil/frame.c
avfilter/vf_identity: fix typo
[ffmpeg] / libavutil / frame.c
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include "channel_layout.h"
20 #include "avassert.h"
21 #include "buffer.h"
22 #include "common.h"
23 #include "dict.h"
24 #include "frame.h"
25 #include "imgutils.h"
26 #include "mem.h"
27 #include "samplefmt.h"
28 #include "hwcontext.h"
29
30 #define CHECK_CHANNELS_CONSISTENCY(frame) \
31     av_assert2(!(frame)->channel_layout || \
32                (frame)->channels == \
33                av_get_channel_layout_nb_channels((frame)->channel_layout))
34
35 #if FF_API_COLORSPACE_NAME
36 const char *av_get_colorspace_name(enum AVColorSpace val)
37 {
38     static const char * const name[] = {
39         [AVCOL_SPC_RGB]       = "GBR",
40         [AVCOL_SPC_BT709]     = "bt709",
41         [AVCOL_SPC_FCC]       = "fcc",
42         [AVCOL_SPC_BT470BG]   = "bt470bg",
43         [AVCOL_SPC_SMPTE170M] = "smpte170m",
44         [AVCOL_SPC_SMPTE240M] = "smpte240m",
45         [AVCOL_SPC_YCOCG]     = "YCgCo",
46     };
47     if ((unsigned)val >= FF_ARRAY_ELEMS(name))
48         return NULL;
49     return name[val];
50 }
51 #endif
52 static void get_frame_defaults(AVFrame *frame)
53 {
54     if (frame->extended_data != frame->data)
55         av_freep(&frame->extended_data);
56
57     memset(frame, 0, sizeof(*frame));
58
59     frame->pts                   =
60     frame->pkt_dts               = AV_NOPTS_VALUE;
61     frame->best_effort_timestamp = AV_NOPTS_VALUE;
62     frame->pkt_duration        = 0;
63     frame->pkt_pos             = -1;
64     frame->pkt_size            = -1;
65     frame->key_frame           = 1;
66     frame->sample_aspect_ratio = (AVRational){ 0, 1 };
67     frame->format              = -1; /* unknown */
68     frame->extended_data       = frame->data;
69     frame->color_primaries     = AVCOL_PRI_UNSPECIFIED;
70     frame->color_trc           = AVCOL_TRC_UNSPECIFIED;
71     frame->colorspace          = AVCOL_SPC_UNSPECIFIED;
72     frame->color_range         = AVCOL_RANGE_UNSPECIFIED;
73     frame->chroma_location     = AVCHROMA_LOC_UNSPECIFIED;
74     frame->flags               = 0;
75 }
76
77 static void free_side_data(AVFrameSideData **ptr_sd)
78 {
79     AVFrameSideData *sd = *ptr_sd;
80
81     av_buffer_unref(&sd->buf);
82     av_dict_free(&sd->metadata);
83     av_freep(ptr_sd);
84 }
85
86 static void wipe_side_data(AVFrame *frame)
87 {
88     int i;
89
90     for (i = 0; i < frame->nb_side_data; i++) {
91         free_side_data(&frame->side_data[i]);
92     }
93     frame->nb_side_data = 0;
94
95     av_freep(&frame->side_data);
96 }
97
98 AVFrame *av_frame_alloc(void)
99 {
100     AVFrame *frame = av_mallocz(sizeof(*frame));
101
102     if (!frame)
103         return NULL;
104
105     frame->extended_data = NULL;
106     get_frame_defaults(frame);
107
108     return frame;
109 }
110
111 void av_frame_free(AVFrame **frame)
112 {
113     if (!frame || !*frame)
114         return;
115
116     av_frame_unref(*frame);
117     av_freep(frame);
118 }
119
120 static int get_video_buffer(AVFrame *frame, int align)
121 {
122     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
123     int ret, i, padded_height, total_size;
124     int plane_padding = FFMAX(16 + 16/*STRIDE_ALIGN*/, align);
125     ptrdiff_t linesizes[4];
126     size_t sizes[4];
127
128     if (!desc)
129         return AVERROR(EINVAL);
130
131     if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0)
132         return ret;
133
134     if (!frame->linesize[0]) {
135         if (align <= 0)
136             align = 32; /* STRIDE_ALIGN. Should be av_cpu_max_align() */
137
138         for(i=1; i<=align; i+=i) {
139             ret = av_image_fill_linesizes(frame->linesize, frame->format,
140                                           FFALIGN(frame->width, i));
141             if (ret < 0)
142                 return ret;
143             if (!(frame->linesize[0] & (align-1)))
144                 break;
145         }
146
147         for (i = 0; i < 4 && frame->linesize[i]; i++)
148             frame->linesize[i] = FFALIGN(frame->linesize[i], align);
149     }
150
151     for (i = 0; i < 4; i++)
152         linesizes[i] = frame->linesize[i];
153
154     padded_height = FFALIGN(frame->height, 32);
155     if ((ret = av_image_fill_plane_sizes(sizes, frame->format,
156                                          padded_height, linesizes)) < 0)
157         return ret;
158
159     total_size = 4*plane_padding;
160     for (i = 0; i < 4; i++) {
161         if (sizes[i] > INT_MAX - total_size)
162             return AVERROR(EINVAL);
163         total_size += sizes[i];
164     }
165
166     frame->buf[0] = av_buffer_alloc(total_size);
167     if (!frame->buf[0]) {
168         ret = AVERROR(ENOMEM);
169         goto fail;
170     }
171
172     if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height,
173                                       frame->buf[0]->data, frame->linesize)) < 0)
174         goto fail;
175
176     for (i = 1; i < 4; i++) {
177         if (frame->data[i])
178             frame->data[i] += i * plane_padding;
179     }
180
181     frame->extended_data = frame->data;
182
183     return 0;
184 fail:
185     av_frame_unref(frame);
186     return ret;
187 }
188
189 static int get_audio_buffer(AVFrame *frame, int align)
190 {
191     int channels;
192     int planar   = av_sample_fmt_is_planar(frame->format);
193     int planes;
194     int ret, i;
195
196     if (!frame->channels)
197         frame->channels = av_get_channel_layout_nb_channels(frame->channel_layout);
198
199     channels = frame->channels;
200     planes = planar ? channels : 1;
201
202     CHECK_CHANNELS_CONSISTENCY(frame);
203     if (!frame->linesize[0]) {
204         ret = av_samples_get_buffer_size(&frame->linesize[0], channels,
205                                          frame->nb_samples, frame->format,
206                                          align);
207         if (ret < 0)
208             return ret;
209     }
210
211     if (planes > AV_NUM_DATA_POINTERS) {
212         frame->extended_data = av_mallocz_array(planes,
213                                           sizeof(*frame->extended_data));
214         frame->extended_buf  = av_mallocz_array((planes - AV_NUM_DATA_POINTERS),
215                                           sizeof(*frame->extended_buf));
216         if (!frame->extended_data || !frame->extended_buf) {
217             av_freep(&frame->extended_data);
218             av_freep(&frame->extended_buf);
219             return AVERROR(ENOMEM);
220         }
221         frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS;
222     } else
223         frame->extended_data = frame->data;
224
225     for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
226         frame->buf[i] = av_buffer_alloc(frame->linesize[0]);
227         if (!frame->buf[i]) {
228             av_frame_unref(frame);
229             return AVERROR(ENOMEM);
230         }
231         frame->extended_data[i] = frame->data[i] = frame->buf[i]->data;
232     }
233     for (i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) {
234         frame->extended_buf[i] = av_buffer_alloc(frame->linesize[0]);
235         if (!frame->extended_buf[i]) {
236             av_frame_unref(frame);
237             return AVERROR(ENOMEM);
238         }
239         frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data;
240     }
241     return 0;
242
243 }
244
245 int av_frame_get_buffer(AVFrame *frame, int align)
246 {
247     if (frame->format < 0)
248         return AVERROR(EINVAL);
249
250     if (frame->width > 0 && frame->height > 0)
251         return get_video_buffer(frame, align);
252     else if (frame->nb_samples > 0 && (frame->channel_layout || frame->channels > 0))
253         return get_audio_buffer(frame, align);
254
255     return AVERROR(EINVAL);
256 }
257
258 static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy)
259 {
260     int ret, i;
261
262     dst->key_frame              = src->key_frame;
263     dst->pict_type              = src->pict_type;
264     dst->sample_aspect_ratio    = src->sample_aspect_ratio;
265     dst->crop_top               = src->crop_top;
266     dst->crop_bottom            = src->crop_bottom;
267     dst->crop_left              = src->crop_left;
268     dst->crop_right             = src->crop_right;
269     dst->pts                    = src->pts;
270     dst->repeat_pict            = src->repeat_pict;
271     dst->interlaced_frame       = src->interlaced_frame;
272     dst->top_field_first        = src->top_field_first;
273     dst->palette_has_changed    = src->palette_has_changed;
274     dst->sample_rate            = src->sample_rate;
275     dst->opaque                 = src->opaque;
276     dst->pkt_dts                = src->pkt_dts;
277     dst->pkt_pos                = src->pkt_pos;
278     dst->pkt_size               = src->pkt_size;
279     dst->pkt_duration           = src->pkt_duration;
280     dst->reordered_opaque       = src->reordered_opaque;
281     dst->quality                = src->quality;
282     dst->best_effort_timestamp  = src->best_effort_timestamp;
283     dst->coded_picture_number   = src->coded_picture_number;
284     dst->display_picture_number = src->display_picture_number;
285     dst->flags                  = src->flags;
286     dst->decode_error_flags     = src->decode_error_flags;
287     dst->color_primaries        = src->color_primaries;
288     dst->color_trc              = src->color_trc;
289     dst->colorspace             = src->colorspace;
290     dst->color_range            = src->color_range;
291     dst->chroma_location        = src->chroma_location;
292
293     av_dict_copy(&dst->metadata, src->metadata, 0);
294
295     for (i = 0; i < src->nb_side_data; i++) {
296         const AVFrameSideData *sd_src = src->side_data[i];
297         AVFrameSideData *sd_dst;
298         if (   sd_src->type == AV_FRAME_DATA_PANSCAN
299             && (src->width != dst->width || src->height != dst->height))
300             continue;
301         if (force_copy) {
302             sd_dst = av_frame_new_side_data(dst, sd_src->type,
303                                             sd_src->size);
304             if (!sd_dst) {
305                 wipe_side_data(dst);
306                 return AVERROR(ENOMEM);
307             }
308             memcpy(sd_dst->data, sd_src->data, sd_src->size);
309         } else {
310             AVBufferRef *ref = av_buffer_ref(sd_src->buf);
311             sd_dst = av_frame_new_side_data_from_buf(dst, sd_src->type, ref);
312             if (!sd_dst) {
313                 av_buffer_unref(&ref);
314                 wipe_side_data(dst);
315                 return AVERROR(ENOMEM);
316             }
317         }
318         av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0);
319     }
320
321     ret = av_buffer_replace(&dst->opaque_ref, src->opaque_ref);
322     ret |= av_buffer_replace(&dst->private_ref, src->private_ref);
323     return ret;
324 }
325
326 int av_frame_ref(AVFrame *dst, const AVFrame *src)
327 {
328     int i, ret = 0;
329
330     av_assert1(dst->width == 0 && dst->height == 0);
331     av_assert1(dst->channels == 0);
332
333     dst->format         = src->format;
334     dst->width          = src->width;
335     dst->height         = src->height;
336     dst->channels       = src->channels;
337     dst->channel_layout = src->channel_layout;
338     dst->nb_samples     = src->nb_samples;
339
340     ret = frame_copy_props(dst, src, 0);
341     if (ret < 0)
342         goto fail;
343
344     /* duplicate the frame data if it's not refcounted */
345     if (!src->buf[0]) {
346         ret = av_frame_get_buffer(dst, 0);
347         if (ret < 0)
348             goto fail;
349
350         ret = av_frame_copy(dst, src);
351         if (ret < 0)
352             goto fail;
353
354         return 0;
355     }
356
357     /* ref the buffers */
358     for (i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
359         if (!src->buf[i])
360             continue;
361         dst->buf[i] = av_buffer_ref(src->buf[i]);
362         if (!dst->buf[i]) {
363             ret = AVERROR(ENOMEM);
364             goto fail;
365         }
366     }
367
368     if (src->extended_buf) {
369         dst->extended_buf = av_mallocz_array(sizeof(*dst->extended_buf),
370                                        src->nb_extended_buf);
371         if (!dst->extended_buf) {
372             ret = AVERROR(ENOMEM);
373             goto fail;
374         }
375         dst->nb_extended_buf = src->nb_extended_buf;
376
377         for (i = 0; i < src->nb_extended_buf; i++) {
378             dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]);
379             if (!dst->extended_buf[i]) {
380                 ret = AVERROR(ENOMEM);
381                 goto fail;
382             }
383         }
384     }
385
386     if (src->hw_frames_ctx) {
387         dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
388         if (!dst->hw_frames_ctx) {
389             ret = AVERROR(ENOMEM);
390             goto fail;
391         }
392     }
393
394     /* duplicate extended data */
395     if (src->extended_data != src->data) {
396         int ch = src->channels;
397
398         if (!ch) {
399             ret = AVERROR(EINVAL);
400             goto fail;
401         }
402         CHECK_CHANNELS_CONSISTENCY(src);
403
404         dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch);
405         if (!dst->extended_data) {
406             ret = AVERROR(ENOMEM);
407             goto fail;
408         }
409         memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch);
410     } else
411         dst->extended_data = dst->data;
412
413     memcpy(dst->data,     src->data,     sizeof(src->data));
414     memcpy(dst->linesize, src->linesize, sizeof(src->linesize));
415
416     return 0;
417
418 fail:
419     av_frame_unref(dst);
420     return ret;
421 }
422
423 AVFrame *av_frame_clone(const AVFrame *src)
424 {
425     AVFrame *ret = av_frame_alloc();
426
427     if (!ret)
428         return NULL;
429
430     if (av_frame_ref(ret, src) < 0)
431         av_frame_free(&ret);
432
433     return ret;
434 }
435
436 void av_frame_unref(AVFrame *frame)
437 {
438     int i;
439
440     if (!frame)
441         return;
442
443     wipe_side_data(frame);
444
445     for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
446         av_buffer_unref(&frame->buf[i]);
447     for (i = 0; i < frame->nb_extended_buf; i++)
448         av_buffer_unref(&frame->extended_buf[i]);
449     av_freep(&frame->extended_buf);
450     av_dict_free(&frame->metadata);
451
452     av_buffer_unref(&frame->hw_frames_ctx);
453
454     av_buffer_unref(&frame->opaque_ref);
455     av_buffer_unref(&frame->private_ref);
456
457     get_frame_defaults(frame);
458 }
459
460 void av_frame_move_ref(AVFrame *dst, AVFrame *src)
461 {
462     av_assert1(dst->width == 0 && dst->height == 0);
463     av_assert1(dst->channels == 0);
464
465     *dst = *src;
466     if (src->extended_data == src->data)
467         dst->extended_data = dst->data;
468     memset(src, 0, sizeof(*src));
469     get_frame_defaults(src);
470 }
471
472 int av_frame_is_writable(AVFrame *frame)
473 {
474     int i, ret = 1;
475
476     /* assume non-refcounted frames are not writable */
477     if (!frame->buf[0])
478         return 0;
479
480     for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
481         if (frame->buf[i])
482             ret &= !!av_buffer_is_writable(frame->buf[i]);
483     for (i = 0; i < frame->nb_extended_buf; i++)
484         ret &= !!av_buffer_is_writable(frame->extended_buf[i]);
485
486     return ret;
487 }
488
489 int av_frame_make_writable(AVFrame *frame)
490 {
491     AVFrame tmp;
492     int ret;
493
494     if (!frame->buf[0])
495         return AVERROR(EINVAL);
496
497     if (av_frame_is_writable(frame))
498         return 0;
499
500     memset(&tmp, 0, sizeof(tmp));
501     tmp.format         = frame->format;
502     tmp.width          = frame->width;
503     tmp.height         = frame->height;
504     tmp.channels       = frame->channels;
505     tmp.channel_layout = frame->channel_layout;
506     tmp.nb_samples     = frame->nb_samples;
507
508     if (frame->hw_frames_ctx)
509         ret = av_hwframe_get_buffer(frame->hw_frames_ctx, &tmp, 0);
510     else
511         ret = av_frame_get_buffer(&tmp, 0);
512     if (ret < 0)
513         return ret;
514
515     ret = av_frame_copy(&tmp, frame);
516     if (ret < 0) {
517         av_frame_unref(&tmp);
518         return ret;
519     }
520
521     ret = av_frame_copy_props(&tmp, frame);
522     if (ret < 0) {
523         av_frame_unref(&tmp);
524         return ret;
525     }
526
527     av_frame_unref(frame);
528
529     *frame = tmp;
530     if (tmp.data == tmp.extended_data)
531         frame->extended_data = frame->data;
532
533     return 0;
534 }
535
536 int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
537 {
538     return frame_copy_props(dst, src, 1);
539 }
540
541 AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane)
542 {
543     uint8_t *data;
544     int planes, i;
545
546     if (frame->nb_samples) {
547         int channels = frame->channels;
548         if (!channels)
549             return NULL;
550         CHECK_CHANNELS_CONSISTENCY(frame);
551         planes = av_sample_fmt_is_planar(frame->format) ? channels : 1;
552     } else
553         planes = 4;
554
555     if (plane < 0 || plane >= planes || !frame->extended_data[plane])
556         return NULL;
557     data = frame->extended_data[plane];
558
559     for (i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) {
560         AVBufferRef *buf = frame->buf[i];
561         if (data >= buf->data && data < buf->data + buf->size)
562             return buf;
563     }
564     for (i = 0; i < frame->nb_extended_buf; i++) {
565         AVBufferRef *buf = frame->extended_buf[i];
566         if (data >= buf->data && data < buf->data + buf->size)
567             return buf;
568     }
569     return NULL;
570 }
571
572 AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
573                                                  enum AVFrameSideDataType type,
574                                                  AVBufferRef *buf)
575 {
576     AVFrameSideData *ret, **tmp;
577
578     if (!buf)
579         return NULL;
580
581     if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1)
582         return NULL;
583
584     tmp = av_realloc(frame->side_data,
585                      (frame->nb_side_data + 1) * sizeof(*frame->side_data));
586     if (!tmp)
587         return NULL;
588     frame->side_data = tmp;
589
590     ret = av_mallocz(sizeof(*ret));
591     if (!ret)
592         return NULL;
593
594     ret->buf = buf;
595     ret->data = ret->buf->data;
596     ret->size = buf->size;
597     ret->type = type;
598
599     frame->side_data[frame->nb_side_data++] = ret;
600
601     return ret;
602 }
603
604 AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
605                                         enum AVFrameSideDataType type,
606                                         size_t size)
607 {
608     AVFrameSideData *ret;
609     AVBufferRef *buf = av_buffer_alloc(size);
610     ret = av_frame_new_side_data_from_buf(frame, type, buf);
611     if (!ret)
612         av_buffer_unref(&buf);
613     return ret;
614 }
615
616 AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
617                                         enum AVFrameSideDataType type)
618 {
619     int i;
620
621     for (i = 0; i < frame->nb_side_data; i++) {
622         if (frame->side_data[i]->type == type)
623             return frame->side_data[i];
624     }
625     return NULL;
626 }
627
628 static int frame_copy_video(AVFrame *dst, const AVFrame *src)
629 {
630     const uint8_t *src_data[4];
631     int i, planes;
632
633     if (dst->width  < src->width ||
634         dst->height < src->height)
635         return AVERROR(EINVAL);
636
637     if (src->hw_frames_ctx || dst->hw_frames_ctx)
638         return av_hwframe_transfer_data(dst, src, 0);
639
640     planes = av_pix_fmt_count_planes(dst->format);
641     for (i = 0; i < planes; i++)
642         if (!dst->data[i] || !src->data[i])
643             return AVERROR(EINVAL);
644
645     memcpy(src_data, src->data, sizeof(src_data));
646     av_image_copy(dst->data, dst->linesize,
647                   src_data, src->linesize,
648                   dst->format, src->width, src->height);
649
650     return 0;
651 }
652
653 static int frame_copy_audio(AVFrame *dst, const AVFrame *src)
654 {
655     int planar   = av_sample_fmt_is_planar(dst->format);
656     int channels = dst->channels;
657     int planes   = planar ? channels : 1;
658     int i;
659
660     if (dst->nb_samples     != src->nb_samples ||
661         dst->channels       != src->channels ||
662         dst->channel_layout != src->channel_layout)
663         return AVERROR(EINVAL);
664
665     CHECK_CHANNELS_CONSISTENCY(src);
666
667     for (i = 0; i < planes; i++)
668         if (!dst->extended_data[i] || !src->extended_data[i])
669             return AVERROR(EINVAL);
670
671     av_samples_copy(dst->extended_data, src->extended_data, 0, 0,
672                     dst->nb_samples, channels, dst->format);
673
674     return 0;
675 }
676
677 int av_frame_copy(AVFrame *dst, const AVFrame *src)
678 {
679     if (dst->format != src->format || dst->format < 0)
680         return AVERROR(EINVAL);
681
682     if (dst->width > 0 && dst->height > 0)
683         return frame_copy_video(dst, src);
684     else if (dst->nb_samples > 0 && dst->channels > 0)
685         return frame_copy_audio(dst, src);
686
687     return AVERROR(EINVAL);
688 }
689
690 void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
691 {
692     int i;
693
694     for (i = frame->nb_side_data - 1; i >= 0; i--) {
695         AVFrameSideData *sd = frame->side_data[i];
696         if (sd->type == type) {
697             free_side_data(&frame->side_data[i]);
698             frame->side_data[i] = frame->side_data[frame->nb_side_data - 1];
699             frame->nb_side_data--;
700         }
701     }
702 }
703
704 const char *av_frame_side_data_name(enum AVFrameSideDataType type)
705 {
706     switch(type) {
707     case AV_FRAME_DATA_PANSCAN:         return "AVPanScan";
708     case AV_FRAME_DATA_A53_CC:          return "ATSC A53 Part 4 Closed Captions";
709     case AV_FRAME_DATA_STEREO3D:        return "Stereo 3D";
710     case AV_FRAME_DATA_MATRIXENCODING:  return "AVMatrixEncoding";
711     case AV_FRAME_DATA_DOWNMIX_INFO:    return "Metadata relevant to a downmix procedure";
712     case AV_FRAME_DATA_REPLAYGAIN:      return "AVReplayGain";
713     case AV_FRAME_DATA_DISPLAYMATRIX:   return "3x3 displaymatrix";
714     case AV_FRAME_DATA_AFD:             return "Active format description";
715     case AV_FRAME_DATA_MOTION_VECTORS:  return "Motion vectors";
716     case AV_FRAME_DATA_SKIP_SAMPLES:    return "Skip samples";
717     case AV_FRAME_DATA_AUDIO_SERVICE_TYPE:          return "Audio service type";
718     case AV_FRAME_DATA_MASTERING_DISPLAY_METADATA:  return "Mastering display metadata";
719     case AV_FRAME_DATA_CONTENT_LIGHT_LEVEL:         return "Content light level metadata";
720     case AV_FRAME_DATA_GOP_TIMECODE:                return "GOP timecode";
721     case AV_FRAME_DATA_S12M_TIMECODE:               return "SMPTE 12-1 timecode";
722     case AV_FRAME_DATA_SPHERICAL:                   return "Spherical Mapping";
723     case AV_FRAME_DATA_ICC_PROFILE:                 return "ICC profile";
724     case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: return "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)";
725     case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest";
726     case AV_FRAME_DATA_VIDEO_ENC_PARAMS:            return "Video encoding parameters";
727     case AV_FRAME_DATA_SEI_UNREGISTERED:            return "H.26[45] User Data Unregistered SEI message";
728     case AV_FRAME_DATA_FILM_GRAIN_PARAMS:           return "Film grain parameters";
729     case AV_FRAME_DATA_DETECTION_BBOXES:            return "Bounding boxes for object detection and classification";
730     }
731     return NULL;
732 }
733
734 static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
735                                  const AVPixFmtDescriptor *desc)
736 {
737     int i, j;
738
739     for (i = 0; frame->data[i]; i++) {
740         const AVComponentDescriptor *comp = NULL;
741         int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
742         int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
743
744         if (desc->flags & AV_PIX_FMT_FLAG_PAL && i == 1) {
745             offsets[i] = 0;
746             break;
747         }
748
749         /* find any component descriptor for this plane */
750         for (j = 0; j < desc->nb_components; j++) {
751             if (desc->comp[j].plane == i) {
752                 comp = &desc->comp[j];
753                 break;
754             }
755         }
756         if (!comp)
757             return AVERROR_BUG;
758
759         offsets[i] = (frame->crop_top  >> shift_y) * frame->linesize[i] +
760                      (frame->crop_left >> shift_x) * comp->step;
761     }
762
763     return 0;
764 }
765
766 int av_frame_apply_cropping(AVFrame *frame, int flags)
767 {
768     const AVPixFmtDescriptor *desc;
769     size_t offsets[4];
770     int i;
771
772     if (!(frame->width > 0 && frame->height > 0))
773         return AVERROR(EINVAL);
774
775     if (frame->crop_left >= INT_MAX - frame->crop_right        ||
776         frame->crop_top  >= INT_MAX - frame->crop_bottom       ||
777         (frame->crop_left + frame->crop_right) >= frame->width ||
778         (frame->crop_top + frame->crop_bottom) >= frame->height)
779         return AVERROR(ERANGE);
780
781     desc = av_pix_fmt_desc_get(frame->format);
782     if (!desc)
783         return AVERROR_BUG;
784
785     /* Apply just the right/bottom cropping for hwaccel formats. Bitstream
786      * formats cannot be easily handled here either (and corresponding decoders
787      * should not export any cropping anyway), so do the same for those as well.
788      * */
789     if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) {
790         frame->width      -= frame->crop_right;
791         frame->height     -= frame->crop_bottom;
792         frame->crop_right  = 0;
793         frame->crop_bottom = 0;
794         return 0;
795     }
796
797     /* calculate the offsets for each plane */
798     calc_cropping_offsets(offsets, frame, desc);
799
800     /* adjust the offsets to avoid breaking alignment */
801     if (!(flags & AV_FRAME_CROP_UNALIGNED)) {
802         int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX;
803         int min_log2_align = INT_MAX;
804
805         for (i = 0; frame->data[i]; i++) {
806             int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX;
807             min_log2_align = FFMIN(log2_align, min_log2_align);
808         }
809
810         /* we assume, and it should always be true, that the data alignment is
811          * related to the cropping alignment by a constant power-of-2 factor */
812         if (log2_crop_align < min_log2_align)
813             return AVERROR_BUG;
814
815         if (min_log2_align < 5) {
816             frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1);
817             calc_cropping_offsets(offsets, frame, desc);
818         }
819     }
820
821     for (i = 0; frame->data[i]; i++)
822         frame->data[i] += offsets[i];
823
824     frame->width      -= (frame->crop_left + frame->crop_right);
825     frame->height     -= (frame->crop_top  + frame->crop_bottom);
826     frame->crop_left   = 0;
827     frame->crop_right  = 0;
828     frame->crop_top    = 0;
829     frame->crop_bottom = 0;
830
831     return 0;
832 }