tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

frame.c (37241B)


      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 "cpu.h"
     24 #include "dict.h"
     25 #include "frame.h"
     26 #include "imgutils.h"
     27 #include "mem.h"
     28 #include "samplefmt.h"
     29 #include "hwcontext.h"
     30 
     31 static const AVSideDataDescriptor sd_props[] = {
     32    [AV_FRAME_DATA_PANSCAN]                     = { "AVPanScan",                                    AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
     33    [AV_FRAME_DATA_A53_CC]                      = { "ATSC A53 Part 4 Closed Captions" },
     34    [AV_FRAME_DATA_MATRIXENCODING]              = { "AVMatrixEncoding" },
     35    [AV_FRAME_DATA_DOWNMIX_INFO]                = { "Metadata relevant to a downmix procedure" },
     36    [AV_FRAME_DATA_AFD]                         = { "Active format description" },
     37    [AV_FRAME_DATA_MOTION_VECTORS]              = { "Motion vectors",                               AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
     38    [AV_FRAME_DATA_SKIP_SAMPLES]                = { "Skip samples" },
     39    [AV_FRAME_DATA_GOP_TIMECODE]                = { "GOP timecode" },
     40    [AV_FRAME_DATA_S12M_TIMECODE]               = { "SMPTE 12-1 timecode" },
     41    [AV_FRAME_DATA_DYNAMIC_HDR_PLUS]            = { "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)",   AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
     42    [AV_FRAME_DATA_DYNAMIC_HDR_VIVID]           = { "HDR Dynamic Metadata CUVA 005.1 2021 (Vivid)", AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
     43    [AV_FRAME_DATA_REGIONS_OF_INTEREST]         = { "Regions Of Interest",                          AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
     44    [AV_FRAME_DATA_VIDEO_ENC_PARAMS]            = { "Video encoding parameters" },
     45    [AV_FRAME_DATA_FILM_GRAIN_PARAMS]           = { "Film grain parameters" },
     46    [AV_FRAME_DATA_DETECTION_BBOXES]            = { "Bounding boxes for object detection and classification", AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
     47    [AV_FRAME_DATA_DOVI_RPU_BUFFER]             = { "Dolby Vision RPU Data",                        AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
     48    [AV_FRAME_DATA_DOVI_METADATA]               = { "Dolby Vision Metadata",                        AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
     49    [AV_FRAME_DATA_LCEVC]                       = { "LCEVC NAL data",                               AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
     50    [AV_FRAME_DATA_VIEW_ID]                     = { "View ID" },
     51    [AV_FRAME_DATA_STEREO3D]                    = { "Stereo 3D",                                    AV_SIDE_DATA_PROP_GLOBAL },
     52    [AV_FRAME_DATA_REPLAYGAIN]                  = { "AVReplayGain",                                 AV_SIDE_DATA_PROP_GLOBAL },
     53    [AV_FRAME_DATA_DISPLAYMATRIX]               = { "3x3 displaymatrix",                            AV_SIDE_DATA_PROP_GLOBAL },
     54    [AV_FRAME_DATA_AUDIO_SERVICE_TYPE]          = { "Audio service type",                           AV_SIDE_DATA_PROP_GLOBAL },
     55    [AV_FRAME_DATA_MASTERING_DISPLAY_METADATA]  = { "Mastering display metadata",                   AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
     56    [AV_FRAME_DATA_CONTENT_LIGHT_LEVEL]         = { "Content light level metadata",                 AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
     57    [AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT] = { "Ambient viewing environment",                  AV_SIDE_DATA_PROP_GLOBAL },
     58    [AV_FRAME_DATA_SPHERICAL]                   = { "Spherical Mapping",                            AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
     59    [AV_FRAME_DATA_ICC_PROFILE]                 = { "ICC profile",                                  AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_COLOR_DEPENDENT },
     60    [AV_FRAME_DATA_SEI_UNREGISTERED]            = { "H.26[45] User Data Unregistered SEI message",  AV_SIDE_DATA_PROP_MULTI },
     61    [AV_FRAME_DATA_VIDEO_HINT]                  = { "Encoding video hint",                          AV_SIDE_DATA_PROP_SIZE_DEPENDENT },
     62 };
     63 
     64 static void get_frame_defaults(AVFrame *frame)
     65 {
     66    memset(frame, 0, sizeof(*frame));
     67 
     68    frame->pts                   =
     69    frame->pkt_dts               = AV_NOPTS_VALUE;
     70    frame->best_effort_timestamp = AV_NOPTS_VALUE;
     71    frame->duration            = 0;
     72 #if FF_API_FRAME_PKT
     73 FF_DISABLE_DEPRECATION_WARNINGS
     74    frame->pkt_pos             = -1;
     75    frame->pkt_size            = -1;
     76 FF_ENABLE_DEPRECATION_WARNINGS
     77 #endif
     78    frame->time_base           = (AVRational){ 0, 1 };
     79    frame->sample_aspect_ratio = (AVRational){ 0, 1 };
     80    frame->format              = -1; /* unknown */
     81    frame->extended_data       = frame->data;
     82    frame->color_primaries     = AVCOL_PRI_UNSPECIFIED;
     83    frame->color_trc           = AVCOL_TRC_UNSPECIFIED;
     84    frame->colorspace          = AVCOL_SPC_UNSPECIFIED;
     85    frame->color_range         = AVCOL_RANGE_UNSPECIFIED;
     86    frame->chroma_location     = AVCHROMA_LOC_UNSPECIFIED;
     87    frame->flags               = 0;
     88 }
     89 
     90 static void free_side_data(AVFrameSideData **ptr_sd)
     91 {
     92    AVFrameSideData *sd = *ptr_sd;
     93 
     94    av_buffer_unref(&sd->buf);
     95    av_dict_free(&sd->metadata);
     96    av_freep(ptr_sd);
     97 }
     98 
     99 static void wipe_side_data(AVFrameSideData ***sd, int *nb_side_data)
    100 {
    101    for (int i = 0; i < *nb_side_data; i++) {
    102        free_side_data(&((*sd)[i]));
    103    }
    104    *nb_side_data = 0;
    105 
    106    av_freep(sd);
    107 }
    108 
    109 static void frame_side_data_wipe(AVFrame *frame)
    110 {
    111    wipe_side_data(&frame->side_data, &frame->nb_side_data);
    112 }
    113 
    114 void av_frame_side_data_free(AVFrameSideData ***sd, int *nb_sd)
    115 {
    116    wipe_side_data(sd, nb_sd);
    117 }
    118 
    119 static void remove_side_data(AVFrameSideData ***sd, int *nb_side_data,
    120                             const enum AVFrameSideDataType type)
    121 {
    122    for (int i = *nb_side_data - 1; i >= 0; i--) {
    123        AVFrameSideData *entry = ((*sd)[i]);
    124        if (entry->type != type)
    125            continue;
    126 
    127        free_side_data(&entry);
    128 
    129        ((*sd)[i]) = ((*sd)[*nb_side_data - 1]);
    130        (*nb_side_data)--;
    131    }
    132 }
    133 
    134 static void remove_side_data_by_entry(AVFrameSideData ***sd, int *nb_sd,
    135                                      const AVFrameSideData *target)
    136 {
    137    for (int i = *nb_sd - 1; i >= 0; i--) {
    138        AVFrameSideData *entry = ((*sd)[i]);
    139        if (entry != target)
    140            continue;
    141 
    142        free_side_data(&entry);
    143 
    144        ((*sd)[i]) = ((*sd)[*nb_sd - 1]);
    145        (*nb_sd)--;
    146 
    147        return;
    148    }
    149 }
    150 
    151 AVFrame *av_frame_alloc(void)
    152 {
    153    AVFrame *frame = av_malloc(sizeof(*frame));
    154 
    155    if (!frame)
    156        return NULL;
    157 
    158    get_frame_defaults(frame);
    159 
    160    return frame;
    161 }
    162 
    163 void av_frame_free(AVFrame **frame)
    164 {
    165    if (!frame || !*frame)
    166        return;
    167 
    168    av_frame_unref(*frame);
    169    av_freep(frame);
    170 }
    171 
    172 #define ALIGN (HAVE_SIMD_ALIGN_64 ? 64 : 32)
    173 
    174 static int get_video_buffer(AVFrame *frame, int align)
    175 {
    176    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
    177    int ret, padded_height;
    178    int plane_padding;
    179    ptrdiff_t linesizes[4];
    180    size_t total_size, sizes[4];
    181 
    182    if (!desc)
    183        return AVERROR(EINVAL);
    184 
    185    if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0)
    186        return ret;
    187 
    188    if (align <= 0)
    189        align = ALIGN;
    190    plane_padding = FFMAX(ALIGN, align);
    191 
    192    if (!frame->linesize[0]) {
    193        for (int i = 1; i <= align; i += i) {
    194            ret = av_image_fill_linesizes(frame->linesize, frame->format,
    195                                          FFALIGN(frame->width, i));
    196            if (ret < 0)
    197                return ret;
    198            if (!(frame->linesize[0] & (align-1)))
    199                break;
    200        }
    201 
    202        for (int i = 0; i < 4 && frame->linesize[i]; i++)
    203            frame->linesize[i] = FFALIGN(frame->linesize[i], align);
    204    }
    205 
    206    for (int i = 0; i < 4; i++)
    207        linesizes[i] = frame->linesize[i];
    208 
    209    padded_height = FFALIGN(frame->height, 32);
    210    if ((ret = av_image_fill_plane_sizes(sizes, frame->format,
    211                                         padded_height, linesizes)) < 0)
    212        return ret;
    213 
    214    total_size = 4 * plane_padding + 4 * align;
    215    for (int i = 0; i < 4; i++) {
    216        if (sizes[i] > SIZE_MAX - total_size)
    217            return AVERROR(EINVAL);
    218        total_size += sizes[i];
    219    }
    220 
    221    frame->buf[0] = av_buffer_alloc(total_size);
    222    if (!frame->buf[0]) {
    223        ret = AVERROR(ENOMEM);
    224        goto fail;
    225    }
    226 
    227    if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height,
    228                                      frame->buf[0]->data, frame->linesize)) < 0)
    229        goto fail;
    230 
    231    for (int i = 1; i < 4; i++) {
    232        if (frame->data[i])
    233            frame->data[i] += i * plane_padding;
    234        frame->data[i] = (uint8_t *)FFALIGN((uintptr_t)frame->data[i], align);
    235    }
    236 
    237    frame->extended_data = frame->data;
    238 
    239    return 0;
    240 fail:
    241    av_frame_unref(frame);
    242    return ret;
    243 }
    244 
    245 static int get_audio_buffer(AVFrame *frame, int align)
    246 {
    247    int planar   = av_sample_fmt_is_planar(frame->format);
    248    int channels, planes;
    249    size_t size;
    250    int ret;
    251 
    252    channels = frame->ch_layout.nb_channels;
    253    planes   = planar ? channels : 1;
    254    if (!frame->linesize[0]) {
    255        ret = av_samples_get_buffer_size(&frame->linesize[0], channels,
    256                                         frame->nb_samples, frame->format,
    257                                         align);
    258        if (ret < 0)
    259            return ret;
    260    }
    261 
    262    if (align <= 0)
    263        align = ALIGN;
    264 
    265    if (planes > AV_NUM_DATA_POINTERS) {
    266        frame->extended_data = av_calloc(planes,
    267                                          sizeof(*frame->extended_data));
    268        frame->extended_buf  = av_calloc(planes - AV_NUM_DATA_POINTERS,
    269                                          sizeof(*frame->extended_buf));
    270        if (!frame->extended_data || !frame->extended_buf) {
    271            av_freep(&frame->extended_data);
    272            av_freep(&frame->extended_buf);
    273            return AVERROR(ENOMEM);
    274        }
    275        frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS;
    276    } else
    277        frame->extended_data = frame->data;
    278 
    279    if (frame->linesize[0] > SIZE_MAX - align)
    280        return AVERROR(EINVAL);
    281    size = frame->linesize[0] + (size_t)align;
    282 
    283    for (int i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
    284        frame->buf[i] = av_buffer_alloc(size);
    285        if (!frame->buf[i]) {
    286            av_frame_unref(frame);
    287            return AVERROR(ENOMEM);
    288        }
    289        frame->extended_data[i] = frame->data[i] =
    290            (uint8_t *)FFALIGN((uintptr_t)frame->buf[i]->data, align);
    291    }
    292    for (int i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) {
    293        frame->extended_buf[i] = av_buffer_alloc(size);
    294        if (!frame->extended_buf[i]) {
    295            av_frame_unref(frame);
    296            return AVERROR(ENOMEM);
    297        }
    298        frame->extended_data[i + AV_NUM_DATA_POINTERS] =
    299            (uint8_t *)FFALIGN((uintptr_t)frame->extended_buf[i]->data, align);
    300    }
    301    return 0;
    302 
    303 }
    304 
    305 int av_frame_get_buffer(AVFrame *frame, int align)
    306 {
    307    if (frame->format < 0)
    308        return AVERROR(EINVAL);
    309 
    310    if (frame->width > 0 && frame->height > 0)
    311        return get_video_buffer(frame, align);
    312    else if (frame->nb_samples > 0 &&
    313             (av_channel_layout_check(&frame->ch_layout)))
    314        return get_audio_buffer(frame, align);
    315 
    316    return AVERROR(EINVAL);
    317 }
    318 
    319 static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy)
    320 {
    321    int ret;
    322 
    323 #if FF_API_FRAME_KEY
    324 FF_DISABLE_DEPRECATION_WARNINGS
    325    dst->key_frame              = src->key_frame;
    326 FF_ENABLE_DEPRECATION_WARNINGS
    327 #endif
    328    dst->pict_type              = src->pict_type;
    329    dst->sample_aspect_ratio    = src->sample_aspect_ratio;
    330    dst->crop_top               = src->crop_top;
    331    dst->crop_bottom            = src->crop_bottom;
    332    dst->crop_left              = src->crop_left;
    333    dst->crop_right             = src->crop_right;
    334    dst->pts                    = src->pts;
    335    dst->duration               = src->duration;
    336    dst->repeat_pict            = src->repeat_pict;
    337 #if FF_API_INTERLACED_FRAME
    338 FF_DISABLE_DEPRECATION_WARNINGS
    339    dst->interlaced_frame       = src->interlaced_frame;
    340    dst->top_field_first        = src->top_field_first;
    341 FF_ENABLE_DEPRECATION_WARNINGS
    342 #endif
    343 #if FF_API_PALETTE_HAS_CHANGED
    344 FF_DISABLE_DEPRECATION_WARNINGS
    345    dst->palette_has_changed    = src->palette_has_changed;
    346 FF_ENABLE_DEPRECATION_WARNINGS
    347 #endif
    348    dst->sample_rate            = src->sample_rate;
    349    dst->opaque                 = src->opaque;
    350    dst->pkt_dts                = src->pkt_dts;
    351 #if FF_API_FRAME_PKT
    352 FF_DISABLE_DEPRECATION_WARNINGS
    353    dst->pkt_pos                = src->pkt_pos;
    354    dst->pkt_size               = src->pkt_size;
    355 FF_ENABLE_DEPRECATION_WARNINGS
    356 #endif
    357    dst->time_base              = src->time_base;
    358    dst->quality                = src->quality;
    359    dst->best_effort_timestamp  = src->best_effort_timestamp;
    360    dst->flags                  = src->flags;
    361    dst->decode_error_flags     = src->decode_error_flags;
    362    dst->color_primaries        = src->color_primaries;
    363    dst->color_trc              = src->color_trc;
    364    dst->colorspace             = src->colorspace;
    365    dst->color_range            = src->color_range;
    366    dst->chroma_location        = src->chroma_location;
    367 
    368    av_dict_copy(&dst->metadata, src->metadata, 0);
    369 
    370    for (int i = 0; i < src->nb_side_data; i++) {
    371        const AVFrameSideData *sd_src = src->side_data[i];
    372        AVFrameSideData *sd_dst;
    373        if (   sd_src->type == AV_FRAME_DATA_PANSCAN
    374            && (src->width != dst->width || src->height != dst->height))
    375            continue;
    376        if (force_copy) {
    377            sd_dst = av_frame_new_side_data(dst, sd_src->type,
    378                                            sd_src->size);
    379            if (!sd_dst) {
    380                frame_side_data_wipe(dst);
    381                return AVERROR(ENOMEM);
    382            }
    383            memcpy(sd_dst->data, sd_src->data, sd_src->size);
    384        } else {
    385            AVBufferRef *ref = av_buffer_ref(sd_src->buf);
    386            sd_dst = av_frame_new_side_data_from_buf(dst, sd_src->type, ref);
    387            if (!sd_dst) {
    388                av_buffer_unref(&ref);
    389                frame_side_data_wipe(dst);
    390                return AVERROR(ENOMEM);
    391            }
    392        }
    393        av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0);
    394    }
    395 
    396    ret = av_buffer_replace(&dst->opaque_ref, src->opaque_ref);
    397    ret |= av_buffer_replace(&dst->private_ref, src->private_ref);
    398    return ret;
    399 }
    400 
    401 int av_frame_ref(AVFrame *dst, const AVFrame *src)
    402 {
    403    int ret = 0;
    404 
    405    av_assert1(dst->width == 0 && dst->height == 0);
    406    av_assert1(dst->ch_layout.nb_channels == 0 &&
    407               dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC);
    408 
    409    dst->format         = src->format;
    410    dst->width          = src->width;
    411    dst->height         = src->height;
    412    dst->nb_samples     = src->nb_samples;
    413 
    414    ret = frame_copy_props(dst, src, 0);
    415    if (ret < 0)
    416        goto fail;
    417 
    418    ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
    419    if (ret < 0)
    420        goto fail;
    421 
    422    /* duplicate the frame data if it's not refcounted */
    423    if (!src->buf[0]) {
    424        ret = av_frame_get_buffer(dst, 0);
    425        if (ret < 0)
    426            goto fail;
    427 
    428        ret = av_frame_copy(dst, src);
    429        if (ret < 0)
    430            goto fail;
    431 
    432        return 0;
    433    }
    434 
    435    /* ref the buffers */
    436    for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
    437        if (!src->buf[i])
    438            continue;
    439        dst->buf[i] = av_buffer_ref(src->buf[i]);
    440        if (!dst->buf[i]) {
    441            ret = AVERROR(ENOMEM);
    442            goto fail;
    443        }
    444    }
    445 
    446    if (src->extended_buf) {
    447        dst->extended_buf = av_calloc(src->nb_extended_buf,
    448                                      sizeof(*dst->extended_buf));
    449        if (!dst->extended_buf) {
    450            ret = AVERROR(ENOMEM);
    451            goto fail;
    452        }
    453        dst->nb_extended_buf = src->nb_extended_buf;
    454 
    455        for (int i = 0; i < src->nb_extended_buf; i++) {
    456            dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]);
    457            if (!dst->extended_buf[i]) {
    458                ret = AVERROR(ENOMEM);
    459                goto fail;
    460            }
    461        }
    462    }
    463 
    464    if (src->hw_frames_ctx) {
    465        dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
    466        if (!dst->hw_frames_ctx) {
    467            ret = AVERROR(ENOMEM);
    468            goto fail;
    469        }
    470    }
    471 
    472    /* duplicate extended data */
    473    if (src->extended_data != src->data) {
    474        int ch = dst->ch_layout.nb_channels;
    475 
    476        if (!ch) {
    477            ret = AVERROR(EINVAL);
    478            goto fail;
    479        }
    480 
    481        dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch);
    482        if (!dst->extended_data) {
    483            ret = AVERROR(ENOMEM);
    484            goto fail;
    485        }
    486        memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch);
    487    } else
    488        dst->extended_data = dst->data;
    489 
    490    memcpy(dst->data,     src->data,     sizeof(src->data));
    491    memcpy(dst->linesize, src->linesize, sizeof(src->linesize));
    492 
    493    return 0;
    494 
    495 fail:
    496    av_frame_unref(dst);
    497    return ret;
    498 }
    499 
    500 int av_frame_replace(AVFrame *dst, const AVFrame *src)
    501 {
    502    int ret = 0;
    503 
    504    if (dst == src)
    505        return AVERROR(EINVAL);
    506 
    507    if (!src->buf[0]) {
    508        av_frame_unref(dst);
    509 
    510        /* duplicate the frame data if it's not refcounted */
    511        if (   src->data[0] || src->data[1]
    512            || src->data[2] || src->data[3])
    513            return av_frame_ref(dst, src);
    514 
    515        ret = frame_copy_props(dst, src, 0);
    516        if (ret < 0)
    517            goto fail;
    518    }
    519 
    520    dst->format         = src->format;
    521    dst->width          = src->width;
    522    dst->height         = src->height;
    523    dst->nb_samples     = src->nb_samples;
    524 
    525    ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
    526    if (ret < 0)
    527        goto fail;
    528 
    529    frame_side_data_wipe(dst);
    530    av_dict_free(&dst->metadata);
    531    ret = frame_copy_props(dst, src, 0);
    532    if (ret < 0)
    533        goto fail;
    534 
    535    /* replace the buffers */
    536    for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
    537        ret = av_buffer_replace(&dst->buf[i], src->buf[i]);
    538        if (ret < 0)
    539            goto fail;
    540    }
    541 
    542    if (src->extended_buf) {
    543        if (dst->nb_extended_buf != src->nb_extended_buf) {
    544            int nb_extended_buf = FFMIN(dst->nb_extended_buf, src->nb_extended_buf);
    545            void *tmp;
    546 
    547            for (int i = nb_extended_buf; i < dst->nb_extended_buf; i++)
    548                av_buffer_unref(&dst->extended_buf[i]);
    549 
    550            tmp = av_realloc_array(dst->extended_buf, sizeof(*dst->extended_buf),
    551                                   src->nb_extended_buf);
    552            if (!tmp) {
    553                ret = AVERROR(ENOMEM);
    554                goto fail;
    555            }
    556            dst->extended_buf = tmp;
    557            dst->nb_extended_buf = src->nb_extended_buf;
    558 
    559            memset(&dst->extended_buf[nb_extended_buf], 0,
    560                   (src->nb_extended_buf - nb_extended_buf) * sizeof(*dst->extended_buf));
    561        }
    562 
    563        for (int i = 0; i < src->nb_extended_buf; i++) {
    564            ret = av_buffer_replace(&dst->extended_buf[i], src->extended_buf[i]);
    565            if (ret < 0)
    566                goto fail;
    567        }
    568    } else if (dst->extended_buf) {
    569        for (int i = 0; i < dst->nb_extended_buf; i++)
    570            av_buffer_unref(&dst->extended_buf[i]);
    571        av_freep(&dst->extended_buf);
    572    }
    573 
    574    ret = av_buffer_replace(&dst->hw_frames_ctx, src->hw_frames_ctx);
    575    if (ret < 0)
    576        goto fail;
    577 
    578    if (dst->extended_data != dst->data)
    579        av_freep(&dst->extended_data);
    580 
    581    if (src->extended_data != src->data) {
    582        int ch = dst->ch_layout.nb_channels;
    583 
    584        if (!ch) {
    585            ret = AVERROR(EINVAL);
    586            goto fail;
    587        }
    588 
    589        if (ch > SIZE_MAX / sizeof(*dst->extended_data))
    590            goto fail;
    591 
    592        dst->extended_data = av_memdup(src->extended_data, sizeof(*dst->extended_data) * ch);
    593        if (!dst->extended_data) {
    594            ret = AVERROR(ENOMEM);
    595            goto fail;
    596        }
    597    } else
    598        dst->extended_data = dst->data;
    599 
    600    memcpy(dst->data,     src->data,     sizeof(src->data));
    601    memcpy(dst->linesize, src->linesize, sizeof(src->linesize));
    602 
    603    return 0;
    604 
    605 fail:
    606    av_frame_unref(dst);
    607    return ret;
    608 }
    609 
    610 AVFrame *av_frame_clone(const AVFrame *src)
    611 {
    612    AVFrame *ret = av_frame_alloc();
    613 
    614    if (!ret)
    615        return NULL;
    616 
    617    if (av_frame_ref(ret, src) < 0)
    618        av_frame_free(&ret);
    619 
    620    return ret;
    621 }
    622 
    623 void av_frame_unref(AVFrame *frame)
    624 {
    625    if (!frame)
    626        return;
    627 
    628    frame_side_data_wipe(frame);
    629 
    630    for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
    631        av_buffer_unref(&frame->buf[i]);
    632    for (int i = 0; i < frame->nb_extended_buf; i++)
    633        av_buffer_unref(&frame->extended_buf[i]);
    634    av_freep(&frame->extended_buf);
    635    av_dict_free(&frame->metadata);
    636 
    637    av_buffer_unref(&frame->hw_frames_ctx);
    638 
    639    av_buffer_unref(&frame->opaque_ref);
    640    av_buffer_unref(&frame->private_ref);
    641 
    642    if (frame->extended_data != frame->data)
    643        av_freep(&frame->extended_data);
    644 
    645    av_channel_layout_uninit(&frame->ch_layout);
    646 
    647    get_frame_defaults(frame);
    648 }
    649 
    650 void av_frame_move_ref(AVFrame *dst, AVFrame *src)
    651 {
    652    av_assert1(dst->width == 0 && dst->height == 0);
    653    av_assert1(dst->ch_layout.nb_channels == 0 &&
    654               dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC);
    655 
    656    *dst = *src;
    657    if (src->extended_data == src->data)
    658        dst->extended_data = dst->data;
    659    get_frame_defaults(src);
    660 }
    661 
    662 int av_frame_is_writable(AVFrame *frame)
    663 {
    664    int ret = 1;
    665 
    666    /* assume non-refcounted frames are not writable */
    667    if (!frame->buf[0])
    668        return 0;
    669 
    670    for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
    671        if (frame->buf[i])
    672            ret &= !!av_buffer_is_writable(frame->buf[i]);
    673    for (int i = 0; i < frame->nb_extended_buf; i++)
    674        ret &= !!av_buffer_is_writable(frame->extended_buf[i]);
    675 
    676    return ret;
    677 }
    678 
    679 int av_frame_make_writable(AVFrame *frame)
    680 {
    681    AVFrame tmp;
    682    int ret;
    683 
    684    if (av_frame_is_writable(frame))
    685        return 0;
    686 
    687    memset(&tmp, 0, sizeof(tmp));
    688    tmp.format         = frame->format;
    689    tmp.width          = frame->width;
    690    tmp.height         = frame->height;
    691    tmp.nb_samples     = frame->nb_samples;
    692    ret = av_channel_layout_copy(&tmp.ch_layout, &frame->ch_layout);
    693    if (ret < 0) {
    694        av_frame_unref(&tmp);
    695        return ret;
    696    }
    697 
    698    if (frame->hw_frames_ctx)
    699        ret = av_hwframe_get_buffer(frame->hw_frames_ctx, &tmp, 0);
    700    else
    701        ret = av_frame_get_buffer(&tmp, 0);
    702    if (ret < 0)
    703        return ret;
    704 
    705    ret = av_frame_copy(&tmp, frame);
    706    if (ret < 0) {
    707        av_frame_unref(&tmp);
    708        return ret;
    709    }
    710 
    711    ret = av_frame_copy_props(&tmp, frame);
    712    if (ret < 0) {
    713        av_frame_unref(&tmp);
    714        return ret;
    715    }
    716 
    717    av_frame_unref(frame);
    718 
    719    *frame = tmp;
    720    if (tmp.data == tmp.extended_data)
    721        frame->extended_data = frame->data;
    722 
    723    return 0;
    724 }
    725 
    726 int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
    727 {
    728    return frame_copy_props(dst, src, 1);
    729 }
    730 
    731 AVBufferRef *av_frame_get_plane_buffer(const AVFrame *frame, int plane)
    732 {
    733    uint8_t *data;
    734    int planes;
    735 
    736    if (frame->nb_samples) {
    737        int channels = frame->ch_layout.nb_channels;
    738        if (!channels)
    739            return NULL;
    740        planes = av_sample_fmt_is_planar(frame->format) ? channels : 1;
    741    } else
    742        planes = 4;
    743 
    744    if (plane < 0 || plane >= planes || !frame->extended_data[plane])
    745        return NULL;
    746    data = frame->extended_data[plane];
    747 
    748    for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) {
    749        AVBufferRef *buf = frame->buf[i];
    750        if (data >= buf->data && data < buf->data + buf->size)
    751            return buf;
    752    }
    753    for (int i = 0; i < frame->nb_extended_buf; i++) {
    754        AVBufferRef *buf = frame->extended_buf[i];
    755        if (data >= buf->data && data < buf->data + buf->size)
    756            return buf;
    757    }
    758    return NULL;
    759 }
    760 
    761 static AVFrameSideData *add_side_data_from_buf_ext(AVFrameSideData ***sd,
    762                                                   int *nb_sd,
    763                                                   enum AVFrameSideDataType type,
    764                                                   AVBufferRef *buf, uint8_t *data,
    765                                                   size_t size)
    766 {
    767    AVFrameSideData *ret, **tmp;
    768 
    769    // *nb_sd + 1 needs to fit into an int and a size_t.
    770    if ((unsigned)*nb_sd >= FFMIN(INT_MAX, SIZE_MAX))
    771        return NULL;
    772 
    773    tmp = av_realloc_array(*sd, sizeof(**sd), *nb_sd + 1);
    774    if (!tmp)
    775        return NULL;
    776    *sd = tmp;
    777 
    778    ret = av_mallocz(sizeof(*ret));
    779    if (!ret)
    780        return NULL;
    781 
    782    ret->buf = buf;
    783    ret->data = data;
    784    ret->size = size;
    785    ret->type = type;
    786 
    787    (*sd)[(*nb_sd)++] = ret;
    788 
    789    return ret;
    790 }
    791 
    792 static AVFrameSideData *add_side_data_from_buf(AVFrameSideData ***sd,
    793                                               int *nb_sd,
    794                                               enum AVFrameSideDataType type,
    795                                               AVBufferRef *buf)
    796 {
    797    if (!buf)
    798        return NULL;
    799 
    800    return add_side_data_from_buf_ext(sd, nb_sd, type, buf, buf->data, buf->size);
    801 }
    802 
    803 AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
    804                                                 enum AVFrameSideDataType type,
    805                                                 AVBufferRef *buf)
    806 {
    807    return
    808        add_side_data_from_buf(
    809            &frame->side_data, &frame->nb_side_data, type, buf);
    810 }
    811 
    812 AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
    813                                        enum AVFrameSideDataType type,
    814                                        size_t size)
    815 {
    816    AVFrameSideData *ret;
    817    AVBufferRef *buf = av_buffer_alloc(size);
    818    ret = av_frame_new_side_data_from_buf(frame, type, buf);
    819    if (!ret)
    820        av_buffer_unref(&buf);
    821    return ret;
    822 }
    823 
    824 static AVFrameSideData *replace_side_data_from_buf(AVFrameSideData *dst,
    825                                                   AVBufferRef *buf, int flags)
    826 {
    827    if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
    828        return NULL;
    829 
    830    av_dict_free(&dst->metadata);
    831    av_buffer_unref(&dst->buf);
    832    dst->buf  = buf;
    833    dst->data = buf->data;
    834    dst->size = buf->size;
    835    return dst;
    836 }
    837 
    838 AVFrameSideData *av_frame_side_data_new(AVFrameSideData ***sd, int *nb_sd,
    839                                        enum AVFrameSideDataType type,
    840                                        size_t size, unsigned int flags)
    841 {
    842    const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
    843    AVBufferRef     *buf = av_buffer_alloc(size);
    844    AVFrameSideData *ret = NULL;
    845 
    846    if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
    847        remove_side_data(sd, nb_sd, type);
    848    if ((!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) &&
    849        (ret = (AVFrameSideData *)av_frame_side_data_get(*sd, *nb_sd, type))) {
    850        ret = replace_side_data_from_buf(ret, buf, flags);
    851        if (!ret)
    852            av_buffer_unref(&buf);
    853        return ret;
    854    }
    855 
    856    ret = add_side_data_from_buf(sd, nb_sd, type, buf);
    857    if (!ret)
    858        av_buffer_unref(&buf);
    859 
    860    return ret;
    861 }
    862 
    863 AVFrameSideData *av_frame_side_data_add(AVFrameSideData ***sd, int *nb_sd,
    864                                        enum AVFrameSideDataType type,
    865                                        AVBufferRef **pbuf, unsigned int flags)
    866 {
    867    const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
    868    AVFrameSideData *sd_dst  = NULL;
    869    AVBufferRef *buf = *pbuf;
    870 
    871    if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
    872        remove_side_data(sd, nb_sd, type);
    873    if ((!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) &&
    874        (sd_dst = (AVFrameSideData *)av_frame_side_data_get(*sd, *nb_sd, type))) {
    875        sd_dst = replace_side_data_from_buf(sd_dst, buf, flags);
    876        if (sd_dst)
    877            *pbuf = NULL;
    878        return sd_dst;
    879    }
    880 
    881    sd_dst = add_side_data_from_buf(sd, nb_sd, type, buf);
    882    if (!sd_dst)
    883        return NULL;
    884 
    885    *pbuf = NULL;
    886    return sd_dst;
    887 }
    888 
    889 int av_frame_side_data_clone(AVFrameSideData ***sd, int *nb_sd,
    890                             const AVFrameSideData *src, unsigned int flags)
    891 {
    892    const AVSideDataDescriptor *desc;
    893    AVBufferRef     *buf    = NULL;
    894    AVFrameSideData *sd_dst = NULL;
    895    int              ret    = AVERROR_BUG;
    896 
    897    if (!sd || !src || !nb_sd || (*nb_sd && !*sd))
    898        return AVERROR(EINVAL);
    899 
    900    desc = av_frame_side_data_desc(src->type);
    901    if (flags & AV_FRAME_SIDE_DATA_FLAG_UNIQUE)
    902        remove_side_data(sd, nb_sd, src->type);
    903    if ((!desc || !(desc->props & AV_SIDE_DATA_PROP_MULTI)) &&
    904        (sd_dst = (AVFrameSideData *)av_frame_side_data_get(*sd, *nb_sd, src->type))) {
    905        AVDictionary *dict = NULL;
    906 
    907        if (!(flags & AV_FRAME_SIDE_DATA_FLAG_REPLACE))
    908            return AVERROR(EEXIST);
    909 
    910        ret = av_dict_copy(&dict, src->metadata, 0);
    911        if (ret < 0)
    912            return ret;
    913 
    914        ret = av_buffer_replace(&sd_dst->buf, src->buf);
    915        if (ret < 0) {
    916            av_dict_free(&dict);
    917            return ret;
    918        }
    919 
    920        av_dict_free(&sd_dst->metadata);
    921        sd_dst->metadata = dict;
    922        sd_dst->data     = src->data;
    923        sd_dst->size     = src->size;
    924        return 0;
    925    }
    926 
    927    buf = av_buffer_ref(src->buf);
    928    if (!buf)
    929        return AVERROR(ENOMEM);
    930 
    931    sd_dst = add_side_data_from_buf_ext(sd, nb_sd, src->type, buf,
    932                                        src->data, src->size);
    933    if (!sd_dst) {
    934        av_buffer_unref(&buf);
    935        return AVERROR(ENOMEM);
    936    }
    937 
    938    ret = av_dict_copy(&sd_dst->metadata, src->metadata, 0);
    939    if (ret < 0) {
    940        remove_side_data_by_entry(sd, nb_sd, sd_dst);
    941        return ret;
    942    }
    943 
    944    return 0;
    945 }
    946 
    947 const AVFrameSideData *av_frame_side_data_get_c(const AVFrameSideData * const *sd,
    948                                                const int nb_sd,
    949                                                enum AVFrameSideDataType type)
    950 {
    951    for (int i = 0; i < nb_sd; i++) {
    952        if (sd[i]->type == type)
    953            return sd[i];
    954    }
    955    return NULL;
    956 }
    957 
    958 void av_frame_side_data_remove(AVFrameSideData ***sd, int *nb_sd,
    959                               enum AVFrameSideDataType type)
    960 {
    961    remove_side_data(sd, nb_sd, type);
    962 }
    963 
    964 void av_frame_side_data_remove_by_props(AVFrameSideData ***sd, int *nb_sd,
    965                                        int props)
    966 {
    967    for (int i = *nb_sd - 1; i >= 0; i--) {
    968        AVFrameSideData *entry = ((*sd)[i]);
    969        const AVSideDataDescriptor *desc = av_frame_side_data_desc(entry->type);
    970        if (!desc || !(desc->props & props))
    971            continue;
    972 
    973        free_side_data(&entry);
    974 
    975        ((*sd)[i]) = ((*sd)[*nb_sd - 1]);
    976        (*nb_sd)--;
    977    }
    978 }
    979 
    980 AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
    981                                        enum AVFrameSideDataType type)
    982 {
    983    return (AVFrameSideData *)av_frame_side_data_get(
    984        frame->side_data, frame->nb_side_data,
    985        type
    986    );
    987 }
    988 
    989 static int frame_copy_video(AVFrame *dst, const AVFrame *src)
    990 {
    991    int planes;
    992 
    993    if (dst->width  < src->width ||
    994        dst->height < src->height)
    995        return AVERROR(EINVAL);
    996 
    997    if (src->hw_frames_ctx || dst->hw_frames_ctx)
    998        return av_hwframe_transfer_data(dst, src, 0);
    999 
   1000    planes = av_pix_fmt_count_planes(dst->format);
   1001    for (int i = 0; i < planes; i++)
   1002        if (!dst->data[i] || !src->data[i])
   1003            return AVERROR(EINVAL);
   1004 
   1005    av_image_copy2(dst->data, dst->linesize,
   1006                   src->data, src->linesize,
   1007                   dst->format, src->width, src->height);
   1008 
   1009    return 0;
   1010 }
   1011 
   1012 static int frame_copy_audio(AVFrame *dst, const AVFrame *src)
   1013 {
   1014    int planar   = av_sample_fmt_is_planar(dst->format);
   1015    int channels = dst->ch_layout.nb_channels;
   1016    int planes   = planar ? channels : 1;
   1017 
   1018    if (dst->nb_samples != src->nb_samples ||
   1019        av_channel_layout_compare(&dst->ch_layout, &src->ch_layout))
   1020        return AVERROR(EINVAL);
   1021 
   1022    for (int i = 0; i < planes; i++)
   1023        if (!dst->extended_data[i] || !src->extended_data[i])
   1024            return AVERROR(EINVAL);
   1025 
   1026    av_samples_copy(dst->extended_data, src->extended_data, 0, 0,
   1027                    dst->nb_samples, channels, dst->format);
   1028 
   1029    return 0;
   1030 }
   1031 
   1032 int av_frame_copy(AVFrame *dst, const AVFrame *src)
   1033 {
   1034    if (dst->format != src->format || dst->format < 0)
   1035        return AVERROR(EINVAL);
   1036 
   1037    if (dst->width > 0 && dst->height > 0)
   1038        return frame_copy_video(dst, src);
   1039    else if (dst->nb_samples > 0 &&
   1040             (av_channel_layout_check(&dst->ch_layout)))
   1041        return frame_copy_audio(dst, src);
   1042 
   1043    return AVERROR(EINVAL);
   1044 }
   1045 
   1046 void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
   1047 {
   1048    remove_side_data(&frame->side_data, &frame->nb_side_data, type);
   1049 }
   1050 
   1051 const AVSideDataDescriptor *av_frame_side_data_desc(enum AVFrameSideDataType type)
   1052 {
   1053    unsigned t = type;
   1054    if (t < FF_ARRAY_ELEMS(sd_props) && sd_props[t].name)
   1055        return &sd_props[t];
   1056    return NULL;
   1057 }
   1058 
   1059 const char *av_frame_side_data_name(enum AVFrameSideDataType type)
   1060 {
   1061    const AVSideDataDescriptor *desc = av_frame_side_data_desc(type);
   1062    return desc ? desc->name : NULL;
   1063 }
   1064 
   1065 static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
   1066                                 const AVPixFmtDescriptor *desc)
   1067 {
   1068    for (int i = 0; frame->data[i]; i++) {
   1069        const AVComponentDescriptor *comp = NULL;
   1070        int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
   1071        int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
   1072 
   1073        if (desc->flags & AV_PIX_FMT_FLAG_PAL && i == 1) {
   1074            offsets[i] = 0;
   1075            break;
   1076        }
   1077 
   1078        /* find any component descriptor for this plane */
   1079        for (int j = 0; j < desc->nb_components; j++) {
   1080            if (desc->comp[j].plane == i) {
   1081                comp = &desc->comp[j];
   1082                break;
   1083            }
   1084        }
   1085        if (!comp)
   1086            return AVERROR_BUG;
   1087 
   1088        offsets[i] = (frame->crop_top  >> shift_y) * frame->linesize[i] +
   1089                     (frame->crop_left >> shift_x) * comp->step;
   1090    }
   1091 
   1092    return 0;
   1093 }
   1094 
   1095 int av_frame_apply_cropping(AVFrame *frame, int flags)
   1096 {
   1097    const AVPixFmtDescriptor *desc;
   1098    size_t offsets[4];
   1099 
   1100    if (!(frame->width > 0 && frame->height > 0))
   1101        return AVERROR(EINVAL);
   1102 
   1103    if (frame->crop_left >= INT_MAX - frame->crop_right        ||
   1104        frame->crop_top  >= INT_MAX - frame->crop_bottom       ||
   1105        (frame->crop_left + frame->crop_right) >= frame->width ||
   1106        (frame->crop_top + frame->crop_bottom) >= frame->height)
   1107        return AVERROR(ERANGE);
   1108 
   1109    desc = av_pix_fmt_desc_get(frame->format);
   1110    if (!desc)
   1111        return AVERROR_BUG;
   1112 
   1113    /* Apply just the right/bottom cropping for hwaccel formats. Bitstream
   1114     * formats cannot be easily handled here either (and corresponding decoders
   1115     * should not export any cropping anyway), so do the same for those as well.
   1116     * */
   1117    if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) {
   1118        frame->width      -= frame->crop_right;
   1119        frame->height     -= frame->crop_bottom;
   1120        frame->crop_right  = 0;
   1121        frame->crop_bottom = 0;
   1122        return 0;
   1123    }
   1124 
   1125    /* calculate the offsets for each plane */
   1126    calc_cropping_offsets(offsets, frame, desc);
   1127 
   1128    /* adjust the offsets to avoid breaking alignment */
   1129    if (!(flags & AV_FRAME_CROP_UNALIGNED)) {
   1130        int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX;
   1131        int min_log2_align = INT_MAX;
   1132 
   1133        for (int i = 0; frame->data[i]; i++) {
   1134            int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX;
   1135            min_log2_align = FFMIN(log2_align, min_log2_align);
   1136        }
   1137 
   1138        /* we assume, and it should always be true, that the data alignment is
   1139         * related to the cropping alignment by a constant power-of-2 factor */
   1140        if (log2_crop_align < min_log2_align)
   1141            return AVERROR_BUG;
   1142 
   1143        if (min_log2_align < 5 && log2_crop_align != INT_MAX) {
   1144            frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1);
   1145            calc_cropping_offsets(offsets, frame, desc);
   1146        }
   1147    }
   1148 
   1149    for (int i = 0; frame->data[i]; i++)
   1150        frame->data[i] += offsets[i];
   1151 
   1152    frame->width      -= (frame->crop_left + frame->crop_right);
   1153    frame->height     -= (frame->crop_top  + frame->crop_bottom);
   1154    frame->crop_left   = 0;
   1155    frame->crop_right  = 0;
   1156    frame->crop_top    = 0;
   1157    frame->crop_bottom = 0;
   1158 
   1159    return 0;
   1160 }