tor-browser

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

picture.c (12847B)


      1 /*
      2 * Copyright © 2018, VideoLAN and dav1d authors
      3 * Copyright © 2018, Two Orioles, LLC
      4 * All rights reserved.
      5 *
      6 * Redistribution and use in source and binary forms, with or without
      7 * modification, are permitted provided that the following conditions are met:
      8 *
      9 * 1. Redistributions of source code must retain the above copyright notice, this
     10 *    list of conditions and the following disclaimer.
     11 *
     12 * 2. Redistributions in binary form must reproduce the above copyright notice,
     13 *    this list of conditions and the following disclaimer in the documentation
     14 *    and/or other materials provided with the distribution.
     15 *
     16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 */
     27 
     28 #include "config.h"
     29 
     30 #include <errno.h>
     31 #include <stdint.h>
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 
     36 #include "common/intops.h"
     37 #include "common/validate.h"
     38 
     39 #include "src/internal.h"
     40 #include "src/log.h"
     41 #include "src/picture.h"
     42 #include "src/ref.h"
     43 #include "src/thread.h"
     44 #include "src/thread_task.h"
     45 
     46 int dav1d_default_picture_alloc(Dav1dPicture *const p, void *const cookie) {
     47    assert(sizeof(Dav1dMemPoolBuffer) <= DAV1D_PICTURE_ALIGNMENT);
     48    const int hbd = p->p.bpc > 8;
     49    const int aligned_w = (p->p.w + 127) & ~127;
     50    const int aligned_h = (p->p.h + 127) & ~127;
     51    const int has_chroma = p->p.layout != DAV1D_PIXEL_LAYOUT_I400;
     52    const int ss_ver = p->p.layout == DAV1D_PIXEL_LAYOUT_I420;
     53    const int ss_hor = p->p.layout != DAV1D_PIXEL_LAYOUT_I444;
     54    ptrdiff_t y_stride = aligned_w << hbd;
     55    ptrdiff_t uv_stride = has_chroma ? y_stride >> ss_hor : 0;
     56    /* Due to how mapping of addresses to sets works in most L1 and L2 cache
     57     * implementations, strides of multiples of certain power-of-two numbers
     58     * may cause multiple rows of the same superblock to map to the same set,
     59     * causing evictions of previous rows resulting in a reduction in cache
     60     * hit rate. Avoid that by slightly padding the stride when necessary. */
     61    if (!(y_stride & 1023))
     62        y_stride += DAV1D_PICTURE_ALIGNMENT;
     63    if (!(uv_stride & 1023) && has_chroma)
     64        uv_stride += DAV1D_PICTURE_ALIGNMENT;
     65    p->stride[0] = y_stride;
     66    p->stride[1] = uv_stride;
     67    const size_t y_sz = y_stride * aligned_h;
     68    const size_t uv_sz = uv_stride * (aligned_h >> ss_ver);
     69    const size_t pic_size = y_sz + 2 * uv_sz;
     70 
     71    Dav1dMemPoolBuffer *const buf = dav1d_mem_pool_pop(cookie, pic_size +
     72                                                       DAV1D_PICTURE_ALIGNMENT -
     73                                                       sizeof(Dav1dMemPoolBuffer));
     74    if (!buf) return DAV1D_ERR(ENOMEM);
     75    p->allocator_data = buf;
     76 
     77    uint8_t *const data = buf->data;
     78    p->data[0] = data;
     79    p->data[1] = has_chroma ? data + y_sz : NULL;
     80    p->data[2] = has_chroma ? data + y_sz + uv_sz : NULL;
     81 
     82    return 0;
     83 }
     84 
     85 void dav1d_default_picture_release(Dav1dPicture *const p, void *const cookie) {
     86    dav1d_mem_pool_push(cookie, p->allocator_data);
     87 }
     88 
     89 struct pic_ctx_context {
     90    Dav1dPicAllocator allocator;
     91    Dav1dPicture pic;
     92    Dav1dRef ref;
     93    void *extra_data[];
     94 };
     95 
     96 static void free_buffer(const uint8_t *const data, void *const user_data) {
     97    Dav1dMemPoolBuffer *buf = (Dav1dMemPoolBuffer *)data;
     98    struct pic_ctx_context *pic_ctx = buf->data;
     99 
    100    pic_ctx->allocator.release_picture_callback(&pic_ctx->pic,
    101                                                pic_ctx->allocator.cookie);
    102    dav1d_mem_pool_push(user_data, buf);
    103 }
    104 
    105 void dav1d_picture_free_itut_t35(const uint8_t *const data, void *const user_data) {
    106    struct itut_t35_ctx_context *itut_t35_ctx = user_data;
    107 
    108    for (size_t i = 0; i < itut_t35_ctx->n_itut_t35; i++)
    109        dav1d_free(itut_t35_ctx->itut_t35[i].payload);
    110    dav1d_free(itut_t35_ctx->itut_t35);
    111    dav1d_free(itut_t35_ctx);
    112 }
    113 
    114 static int picture_alloc(Dav1dContext *const c,
    115                         Dav1dPicture *const p,
    116                         const int w, const int h,
    117                         Dav1dSequenceHeader *const seq_hdr, Dav1dRef *const seq_hdr_ref,
    118                         Dav1dFrameHeader *const frame_hdr, Dav1dRef *const frame_hdr_ref,
    119                         const int bpc,
    120                         const Dav1dDataProps *const props,
    121                         Dav1dPicAllocator *const p_allocator,
    122                         void **const extra_ptr)
    123 {
    124    if (p->data[0]) {
    125        dav1d_log(c, "Picture already allocated!\n");
    126        return -1;
    127    }
    128    assert(bpc > 0 && bpc <= 16);
    129 
    130    size_t extra = c->n_fc > 1 ? sizeof(atomic_int) * 2 : 0;
    131    Dav1dMemPoolBuffer *buf = dav1d_mem_pool_pop(c->pic_ctx_pool,
    132                                                 extra + sizeof(struct pic_ctx_context));
    133    if (buf == NULL)
    134        return DAV1D_ERR(ENOMEM);
    135 
    136    struct pic_ctx_context *pic_ctx = buf->data;
    137 
    138    p->p.w = w;
    139    p->p.h = h;
    140    p->seq_hdr = seq_hdr;
    141    p->frame_hdr = frame_hdr;
    142    p->p.layout = seq_hdr->layout;
    143    p->p.bpc = bpc;
    144    dav1d_data_props_set_defaults(&p->m);
    145    const int res = p_allocator->alloc_picture_callback(p, p_allocator->cookie);
    146    if (res < 0) {
    147        dav1d_mem_pool_push(c->pic_ctx_pool, buf);
    148        return res;
    149    }
    150 
    151    pic_ctx->allocator = *p_allocator;
    152    pic_ctx->pic = *p;
    153    p->ref = dav1d_ref_init(&pic_ctx->ref, buf, free_buffer, c->pic_ctx_pool, 0);
    154 
    155    p->seq_hdr_ref = seq_hdr_ref;
    156    if (seq_hdr_ref) dav1d_ref_inc(seq_hdr_ref);
    157 
    158    p->frame_hdr_ref = frame_hdr_ref;
    159    if (frame_hdr_ref) dav1d_ref_inc(frame_hdr_ref);
    160 
    161    if (extra && extra_ptr)
    162        *extra_ptr = &pic_ctx->extra_data;
    163 
    164    return 0;
    165 }
    166 
    167 void dav1d_picture_copy_props(Dav1dPicture *const p,
    168                              Dav1dContentLightLevel *const content_light, Dav1dRef *const content_light_ref,
    169                              Dav1dMasteringDisplay *const mastering_display, Dav1dRef *const mastering_display_ref,
    170                              Dav1dITUTT35 *const itut_t35, Dav1dRef *itut_t35_ref, size_t n_itut_t35,
    171                              const Dav1dDataProps *const props)
    172 {
    173    dav1d_data_props_copy(&p->m, props);
    174 
    175    dav1d_ref_dec(&p->content_light_ref);
    176    p->content_light_ref = content_light_ref;
    177    p->content_light = content_light;
    178    if (content_light_ref) dav1d_ref_inc(content_light_ref);
    179 
    180    dav1d_ref_dec(&p->mastering_display_ref);
    181    p->mastering_display_ref = mastering_display_ref;
    182    p->mastering_display = mastering_display;
    183    if (mastering_display_ref) dav1d_ref_inc(mastering_display_ref);
    184 
    185    dav1d_ref_dec(&p->itut_t35_ref);
    186    p->itut_t35_ref = itut_t35_ref;
    187    p->itut_t35 = itut_t35;
    188    p->n_itut_t35 = n_itut_t35;
    189    if (itut_t35_ref) dav1d_ref_inc(itut_t35_ref);
    190 }
    191 
    192 int dav1d_thread_picture_alloc(Dav1dContext *const c, Dav1dFrameContext *const f,
    193                               const int bpc)
    194 {
    195    Dav1dThreadPicture *const p = &f->sr_cur;
    196 
    197    const int res = picture_alloc(c, &p->p, f->frame_hdr->width[1], f->frame_hdr->height,
    198                                  f->seq_hdr, f->seq_hdr_ref,
    199                                  f->frame_hdr, f->frame_hdr_ref,
    200                                  bpc, &f->tile[0].data.m, &c->allocator,
    201                                  (void **) &p->progress);
    202    if (res) return res;
    203 
    204    // Don't clear these flags from c->frame_flags if the frame is not going to be output.
    205    // This way they will be added to the next visible frame too.
    206    const int flags_mask = ((f->frame_hdr->show_frame || c->output_invisible_frames) &&
    207                            c->max_spatial_id == f->frame_hdr->spatial_id)
    208                           ? 0 : (PICTURE_FLAG_NEW_SEQUENCE | PICTURE_FLAG_NEW_OP_PARAMS_INFO);
    209    p->flags = c->frame_flags;
    210    c->frame_flags &= flags_mask;
    211 
    212    p->visible = f->frame_hdr->show_frame;
    213    p->showable = f->frame_hdr->showable_frame;
    214 
    215    if (p->visible) {
    216        // Only add HDR10+ and T35 metadata when show frame flag is enabled
    217        dav1d_picture_copy_props(&p->p, c->content_light, c->content_light_ref,
    218                                 c->mastering_display, c->mastering_display_ref,
    219                                 c->itut_t35, c->itut_t35_ref, c->n_itut_t35,
    220                                 &f->tile[0].data.m);
    221 
    222        // Must be removed from the context after being attached to the frame
    223        dav1d_ref_dec(&c->itut_t35_ref);
    224        c->itut_t35 = NULL;
    225        c->n_itut_t35 = 0;
    226    } else {
    227        dav1d_data_props_copy(&p->p.m, &f->tile[0].data.m);
    228    }
    229 
    230    if (c->n_fc > 1) {
    231        atomic_init(&p->progress[0], 0);
    232        atomic_init(&p->progress[1], 0);
    233    }
    234    return res;
    235 }
    236 
    237 int dav1d_picture_alloc_copy(Dav1dContext *const c, Dav1dPicture *const dst, const int w,
    238                             const Dav1dPicture *const src)
    239 {
    240    Dav1dMemPoolBuffer *const buf = (Dav1dMemPoolBuffer *)src->ref->const_data;
    241    struct pic_ctx_context *const pic_ctx = buf->data;
    242    const int res = picture_alloc(c, dst, w, src->p.h,
    243                                  src->seq_hdr, src->seq_hdr_ref,
    244                                  src->frame_hdr, src->frame_hdr_ref,
    245                                  src->p.bpc, &src->m, &pic_ctx->allocator,
    246                                  NULL);
    247    if (res) return res;
    248 
    249    dav1d_picture_copy_props(dst, src->content_light, src->content_light_ref,
    250                             src->mastering_display, src->mastering_display_ref,
    251                             src->itut_t35, src->itut_t35_ref, src->n_itut_t35,
    252                             &src->m);
    253 
    254    return 0;
    255 }
    256 
    257 void dav1d_picture_ref(Dav1dPicture *const dst, const Dav1dPicture *const src) {
    258    assert(dst != NULL);
    259    assert(dst->data[0] == NULL);
    260    assert(src != NULL);
    261 
    262    if (src->ref) {
    263        assert(src->data[0] != NULL);
    264        dav1d_ref_inc(src->ref);
    265    }
    266    if (src->frame_hdr_ref) dav1d_ref_inc(src->frame_hdr_ref);
    267    if (src->seq_hdr_ref) dav1d_ref_inc(src->seq_hdr_ref);
    268    if (src->m.user_data.ref) dav1d_ref_inc(src->m.user_data.ref);
    269    if (src->content_light_ref) dav1d_ref_inc(src->content_light_ref);
    270    if (src->mastering_display_ref) dav1d_ref_inc(src->mastering_display_ref);
    271    if (src->itut_t35_ref) dav1d_ref_inc(src->itut_t35_ref);
    272    *dst = *src;
    273 }
    274 
    275 void dav1d_picture_move_ref(Dav1dPicture *const dst, Dav1dPicture *const src) {
    276    assert(dst != NULL);
    277    assert(dst->data[0] == NULL);
    278    assert(src != NULL);
    279 
    280    if (src->ref)
    281        assert(src->data[0] != NULL);
    282 
    283    *dst = *src;
    284    memset(src, 0, sizeof(*src));
    285 }
    286 
    287 void dav1d_thread_picture_ref(Dav1dThreadPicture *const dst,
    288                              const Dav1dThreadPicture *const src)
    289 {
    290    dav1d_picture_ref(&dst->p, &src->p);
    291    dst->visible = src->visible;
    292    dst->showable = src->showable;
    293    dst->progress = src->progress;
    294    dst->flags = src->flags;
    295 }
    296 
    297 void dav1d_thread_picture_move_ref(Dav1dThreadPicture *const dst,
    298                                   Dav1dThreadPicture *const src)
    299 {
    300    dav1d_picture_move_ref(&dst->p, &src->p);
    301    dst->visible = src->visible;
    302    dst->showable = src->showable;
    303    dst->progress = src->progress;
    304    dst->flags = src->flags;
    305    memset(src, 0, sizeof(*src));
    306 }
    307 
    308 void dav1d_picture_unref_internal(Dav1dPicture *const p) {
    309    validate_input(p != NULL);
    310 
    311    if (p->ref) {
    312        validate_input(p->data[0] != NULL);
    313        dav1d_ref_dec(&p->ref);
    314    }
    315    dav1d_ref_dec(&p->seq_hdr_ref);
    316    dav1d_ref_dec(&p->frame_hdr_ref);
    317    dav1d_ref_dec(&p->m.user_data.ref);
    318    dav1d_ref_dec(&p->content_light_ref);
    319    dav1d_ref_dec(&p->mastering_display_ref);
    320    dav1d_ref_dec(&p->itut_t35_ref);
    321    memset(p, 0, sizeof(*p));
    322    dav1d_data_props_set_defaults(&p->m);
    323 }
    324 
    325 void dav1d_thread_picture_unref(Dav1dThreadPicture *const p) {
    326    dav1d_picture_unref_internal(&p->p);
    327 
    328    p->progress = NULL;
    329 }
    330 
    331 enum Dav1dEventFlags dav1d_picture_get_event_flags(const Dav1dThreadPicture *const p) {
    332    if (!p->flags)
    333        return 0;
    334 
    335    enum Dav1dEventFlags flags = 0;
    336    if (p->flags & PICTURE_FLAG_NEW_SEQUENCE)
    337       flags |= DAV1D_EVENT_FLAG_NEW_SEQUENCE;
    338    if (p->flags & PICTURE_FLAG_NEW_OP_PARAMS_INFO)
    339       flags |= DAV1D_EVENT_FLAG_NEW_OP_PARAMS_INFO;
    340 
    341    return flags;
    342 }