tor-browser

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

av1_parser.c (7026B)


      1 /*
      2 * AV1 parser
      3 *
      4 * Copyright (C) 2018 James Almer <jamrial@gmail.com>
      5 *
      6 * This file is part of FFmpeg.
      7 *
      8 * FFmpeg is free software; you can redistribute it and/or
      9 * modify it under the terms of the GNU Lesser General Public
     10 * License as published by the Free Software Foundation; either
     11 * version 2.1 of the License, or (at your option) any later version.
     12 *
     13 * FFmpeg is distributed in the hope that it will be useful,
     14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16 * Lesser General Public License for more details.
     17 *
     18 * You should have received a copy of the GNU Lesser General Public
     19 * License along with FFmpeg; if not, write to the Free Software
     20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     21 */
     22 
     23 #include "libavutil/avassert.h"
     24 
     25 #include "av1_parse.h"
     26 #include "cbs.h"
     27 #include "cbs_av1.h"
     28 #include "parser.h"
     29 
     30 typedef struct AV1ParseContext {
     31    CodedBitstreamContext *cbc;
     32    CodedBitstreamFragment temporal_unit;
     33    int parsed_extradata;
     34 } AV1ParseContext;
     35 
     36 static const enum AVPixelFormat pix_fmts_8bit[2][2] = {
     37    { AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE },
     38    { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P },
     39 };
     40 static const enum AVPixelFormat pix_fmts_10bit[2][2] = {
     41    { AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE },
     42    { AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10 },
     43 };
     44 static const enum AVPixelFormat pix_fmts_12bit[2][2] = {
     45    { AV_PIX_FMT_YUV444P12, AV_PIX_FMT_NONE },
     46    { AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12 },
     47 };
     48 
     49 static const enum AVPixelFormat pix_fmts_rgb[3] = {
     50    AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
     51 };
     52 
     53 static int av1_parser_parse(AVCodecParserContext *ctx,
     54                            AVCodecContext *avctx,
     55                            const uint8_t **out_data, int *out_size,
     56                            const uint8_t *data, int size)
     57 {
     58    AV1ParseContext *s = ctx->priv_data;
     59    CodedBitstreamFragment *td = &s->temporal_unit;
     60    const CodedBitstreamAV1Context *av1 = s->cbc->priv_data;
     61    const AV1RawSequenceHeader *seq;
     62    const AV1RawColorConfig *color;
     63    int ret;
     64 
     65    *out_data = data;
     66    *out_size = size;
     67 
     68    ctx->key_frame         = -1;
     69    ctx->pict_type         = AV_PICTURE_TYPE_NONE;
     70    ctx->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
     71 
     72    s->cbc->log_ctx = avctx;
     73 
     74    if (avctx->extradata_size && !s->parsed_extradata) {
     75        s->parsed_extradata = 1;
     76 
     77        ret = ff_cbs_read_extradata_from_codec(s->cbc, td, avctx);
     78        if (ret < 0) {
     79            av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata.\n");
     80        }
     81 
     82        ff_cbs_fragment_reset(td);
     83    }
     84 
     85    ret = ff_cbs_read(s->cbc, td, data, size);
     86    if (ret < 0) {
     87        av_log(avctx, AV_LOG_ERROR, "Failed to parse temporal unit.\n");
     88        goto end;
     89    }
     90 
     91    if (!av1->sequence_header) {
     92        av_log(avctx, AV_LOG_ERROR, "No sequence header available\n");
     93        goto end;
     94    }
     95 
     96    seq = av1->sequence_header;
     97    color = &seq->color_config;
     98 
     99    for (int i = 0; i < td->nb_units; i++) {
    100        const CodedBitstreamUnit *unit = &td->units[i];
    101        const AV1RawOBU *obu = unit->content;
    102        const AV1RawFrameHeader *frame;
    103 
    104        if (unit->type == AV1_OBU_FRAME)
    105            frame = &obu->obu.frame.header;
    106        else if (unit->type == AV1_OBU_FRAME_HEADER)
    107            frame = &obu->obu.frame_header;
    108        else
    109            continue;
    110 
    111        if (obu->header.spatial_id > 0)
    112            continue;
    113 
    114        if (!frame->show_frame && !frame->show_existing_frame)
    115            continue;
    116 
    117        ctx->width  = frame->frame_width_minus_1 + 1;
    118        ctx->height = frame->frame_height_minus_1 + 1;
    119 
    120        ctx->key_frame = frame->frame_type == AV1_FRAME_KEY && !frame->show_existing_frame;
    121 
    122        switch (frame->frame_type) {
    123        case AV1_FRAME_KEY:
    124        case AV1_FRAME_INTRA_ONLY:
    125            ctx->pict_type = AV_PICTURE_TYPE_I;
    126            break;
    127        case AV1_FRAME_INTER:
    128            ctx->pict_type = AV_PICTURE_TYPE_P;
    129            break;
    130        case AV1_FRAME_SWITCH:
    131            ctx->pict_type = AV_PICTURE_TYPE_SP;
    132            break;
    133        }
    134        ctx->picture_structure = AV_PICTURE_STRUCTURE_FRAME;
    135    }
    136 
    137    switch (av1->bit_depth) {
    138    case 8:
    139        ctx->format = color->mono_chrome ? AV_PIX_FMT_GRAY8
    140                                         : pix_fmts_8bit [color->subsampling_x][color->subsampling_y];
    141        break;
    142    case 10:
    143        ctx->format = color->mono_chrome ? AV_PIX_FMT_GRAY10
    144                                         : pix_fmts_10bit[color->subsampling_x][color->subsampling_y];
    145        break;
    146    case 12:
    147        ctx->format = color->mono_chrome ? AV_PIX_FMT_GRAY12
    148                                         : pix_fmts_12bit[color->subsampling_x][color->subsampling_y];
    149        break;
    150    }
    151    av_assert2(ctx->format != AV_PIX_FMT_NONE);
    152 
    153    if (!color->subsampling_x && !color->subsampling_y &&
    154        color->matrix_coefficients       == AVCOL_SPC_RGB &&
    155        color->color_primaries           == AVCOL_PRI_BT709 &&
    156        color->transfer_characteristics  == AVCOL_TRC_IEC61966_2_1)
    157        ctx->format = pix_fmts_rgb[color->high_bitdepth + color->twelve_bit];
    158 
    159    avctx->profile = seq->seq_profile;
    160    avctx->level   = seq->seq_level_idx[0];
    161 
    162    avctx->colorspace = (enum AVColorSpace) color->matrix_coefficients;
    163    avctx->color_primaries = (enum AVColorPrimaries) color->color_primaries;
    164    avctx->color_trc = (enum AVColorTransferCharacteristic) color->transfer_characteristics;
    165    avctx->color_range = color->color_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
    166 
    167    if (seq->timing_info_present_flag)
    168        avctx->framerate = ff_av1_framerate(1LL + seq->timing_info.num_ticks_per_picture_minus_1,
    169                                            seq->timing_info.num_units_in_display_tick,
    170                                            seq->timing_info.time_scale);
    171 
    172 end:
    173    ff_cbs_fragment_reset(td);
    174 
    175    s->cbc->log_ctx = NULL;
    176 
    177    return size;
    178 }
    179 
    180 static const CodedBitstreamUnitType decompose_unit_types[] = {
    181    AV1_OBU_TEMPORAL_DELIMITER,
    182    AV1_OBU_SEQUENCE_HEADER,
    183    AV1_OBU_FRAME_HEADER,
    184    AV1_OBU_TILE_GROUP,
    185    AV1_OBU_FRAME,
    186 };
    187 
    188 static av_cold int av1_parser_init(AVCodecParserContext *ctx)
    189 {
    190    AV1ParseContext *s = ctx->priv_data;
    191    int ret;
    192 
    193    ret = ff_cbs_init(&s->cbc, AV_CODEC_ID_AV1, NULL);
    194    if (ret < 0)
    195        return ret;
    196 
    197    s->cbc->decompose_unit_types    = decompose_unit_types;
    198    s->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
    199 
    200    return 0;
    201 }
    202 
    203 static void av1_parser_close(AVCodecParserContext *ctx)
    204 {
    205    AV1ParseContext *s = ctx->priv_data;
    206 
    207    ff_cbs_fragment_free(&s->temporal_unit);
    208    ff_cbs_close(&s->cbc);
    209 }
    210 
    211 const AVCodecParser ff_av1_parser = {
    212    .codec_ids      = { AV_CODEC_ID_AV1 },
    213    .priv_data_size = sizeof(AV1ParseContext),
    214    .parser_init    = av1_parser_init,
    215    .parser_close   = av1_parser_close,
    216    .parser_parse   = av1_parser_parse,
    217 };