1/* 2 * AVS2-P2/IEEE1857.4 video parser. 3 * Copyright (c) 2018 Huiwen Ren <hwrenx@gmail.com> 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "libavutil/avutil.h" 23#include "avs2.h" 24#include "get_bits.h" 25#include "parser.h" 26 27static int avs2_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) 28{ 29 int pic_found = pc->frame_start_found; 30 uint32_t state = pc->state; 31 int cur = 0; 32 33 if (!pic_found) { 34 for (; cur < buf_size; ++cur) { 35 state = (state << 8) | buf[cur]; 36 if ((state & 0xFFFFFF00) == 0x100 && AVS2_ISPIC(buf[cur])) { 37 cur++; 38 pic_found = 1; 39 break; 40 } 41 } 42 } 43 44 if (pic_found) { 45 if (!buf_size) 46 return END_NOT_FOUND; 47 for (; cur < buf_size; cur++) { 48 state = (state << 8) | buf[cur]; 49 if ((state & 0xFFFFFF00) == 0x100 && AVS2_ISUNIT(buf[cur])) { 50 pc->frame_start_found = 0; 51 pc->state = -1; 52 return cur - 3; 53 } 54 } 55 } 56 57 pc->frame_start_found = pic_found; 58 pc->state = state; 59 60 return END_NOT_FOUND; 61} 62 63static void parse_avs2_seq_header(AVCodecParserContext *s, const uint8_t *buf, 64 int buf_size, AVCodecContext *avctx) 65{ 66 GetBitContext gb; 67 int profile, level; 68 int width, height; 69 int chroma, sample_precision, encoding_precision = 1; 70 // sample_precision and encoding_precision is 3 bits 71 static const uint8_t precision[8] = { 0, 8, 10 }; 72 unsigned aspect_ratio; 73 unsigned frame_rate_code; 74 int low_delay; 75 // update buf_size_min if parse more deeper 76 const int buf_size_min = 15; 77 78 if (buf_size < buf_size_min) 79 return; 80 81 init_get_bits8(&gb, buf, buf_size_min); 82 83 s->key_frame = 1; 84 s->pict_type = AV_PICTURE_TYPE_I; 85 86 profile = get_bits(&gb, 8); 87 level = get_bits(&gb, 8); 88 89 // progressive_sequence u(1) 90 // field_coded_sequence u(1) 91 skip_bits(&gb, 2); 92 93 width = get_bits(&gb, 14); 94 height = get_bits(&gb, 14); 95 96 chroma = get_bits(&gb, 2); 97 sample_precision = get_bits(&gb, 3); 98 if (profile == AVS2_PROFILE_MAIN10) 99 encoding_precision = get_bits(&gb, 3); 100 101 aspect_ratio = get_bits(&gb, 4); 102 frame_rate_code = get_bits(&gb, 4); 103 104 // bit_rate_lower u(18) 105 // marker_bit f(1) 106 // bit_rate_upper u(12) 107 skip_bits(&gb, 31); 108 109 low_delay = get_bits(&gb, 1); 110 111 s->width = width; 112 s->height = height; 113 s->coded_width = FFALIGN(width, 8); 114 s->coded_height = FFALIGN(height, 8); 115 avctx->framerate.num = avctx->time_base.den = 116 ff_avs2_frame_rate_tab[frame_rate_code].num; 117 avctx->framerate.den = avctx->time_base.num = 118 ff_avs2_frame_rate_tab[frame_rate_code].den; 119 avctx->has_b_frames = FFMAX(avctx->has_b_frames, !low_delay); 120 121 av_log(avctx, AV_LOG_DEBUG, 122 "AVS2 parse seq HDR: profile %x, level %x, " 123 "width %d, height %d, " 124 "chroma %d, sample_precision %d bits, encoding_precision %d bits, " 125 "aspect_ratio 0x%x, framerate %d/%d, low_delay %d\n", 126 profile, level, 127 width, height, 128 chroma, precision[sample_precision], precision[encoding_precision], 129 aspect_ratio, avctx->framerate.num, avctx->framerate.den, low_delay); 130} 131 132static void parse_avs2_units(AVCodecParserContext *s, const uint8_t *buf, 133 int buf_size, AVCodecContext *avctx) 134{ 135 if (buf_size < 5) 136 return; 137 138 if (!(buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1)) 139 return; 140 141 switch (buf[3]) { 142 case AVS2_SEQ_START_CODE: 143 parse_avs2_seq_header(s, buf + 4, buf_size - 4, avctx); 144 return; 145 case AVS2_INTRA_PIC_START_CODE: 146 s->key_frame = 1; 147 s->pict_type = AV_PICTURE_TYPE_I; 148 return; 149 case AVS2_INTER_PIC_START_CODE: 150 s->key_frame = 0; 151 if (buf_size > 9) { 152 int pic_code_type = buf[8] & 0x3; 153 if (pic_code_type == 1) 154 s->pict_type = AV_PICTURE_TYPE_P; 155 else if (pic_code_type == 3) 156 s->pict_type = AV_PICTURE_TYPE_S; 157 else 158 s->pict_type = AV_PICTURE_TYPE_B; 159 } 160 return; 161 } 162} 163 164static int avs2_parse(AVCodecParserContext *s, AVCodecContext *avctx, 165 const uint8_t **poutbuf, int *poutbuf_size, 166 const uint8_t *buf, int buf_size) 167{ 168 ParseContext *pc = s->priv_data; 169 int next; 170 171 if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { 172 next = buf_size; 173 } else { 174 next = avs2_find_frame_end(pc, buf, buf_size); 175 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { 176 *poutbuf = NULL; 177 *poutbuf_size = 0; 178 return buf_size; 179 } 180 } 181 182 parse_avs2_units(s, buf, buf_size, avctx); 183 184 *poutbuf = buf; 185 *poutbuf_size = buf_size; 186 187 return next; 188} 189 190const AVCodecParser ff_avs2_parser = { 191 .codec_ids = { AV_CODEC_ID_AVS2 }, 192 .priv_data_size = sizeof(ParseContext), 193 .parser_parse = avs2_parse, 194 .parser_close = ff_parse_close, 195}; 196