Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2017, Alliance for Open Media. All rights reserved |
| 3 | * |
| 4 | * This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | * was not distributed with this source code in the LICENSE file, you can |
| 7 | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | * Media Patent License 1.0 was not distributed with this source code in the |
| 9 | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| 10 | */ |
| 11 | |
| 12 | #include <assert.h> |
| 13 | |
| 14 | #include "./aom_config.h" |
| 15 | |
| 16 | #include "aom/aom_codec.h" |
| 17 | #include "aom_dsp/bitreader_buffer.h" |
| 18 | #include "aom_ports/mem_ops.h" |
| 19 | |
| 20 | #include "av1/common/common.h" |
| 21 | #include "av1/decoder/decoder.h" |
| 22 | #include "av1/decoder/decodeframe.h" |
Tom Finegan | 04450b1 | 2018-03-19 18:12:28 -0700 | [diff] [blame] | 23 | #include "av1/decoder/obu.h" |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 24 | |
Tom Finegan | 9540d59 | 2018-02-06 10:04:31 -0800 | [diff] [blame] | 25 | // Picture prediction structures (0-12 are predefined) in scalability metadata. |
Soo-Chul Han | f858986 | 2018-01-24 03:13:14 +0000 | [diff] [blame] | 26 | typedef enum { |
| 27 | SCALABILITY_L1T2 = 0, |
| 28 | SCALABILITY_L1T3 = 1, |
| 29 | SCALABILITY_L2T1 = 2, |
| 30 | SCALABILITY_L2T2 = 3, |
| 31 | SCALABILITY_L2T3 = 4, |
| 32 | SCALABILITY_S2T1 = 5, |
| 33 | SCALABILITY_S2T2 = 6, |
| 34 | SCALABILITY_S2T3 = 7, |
| 35 | SCALABILITY_L2T2h = 8, |
| 36 | SCALABILITY_L2T3h = 9, |
| 37 | SCALABILITY_S2T1h = 10, |
| 38 | SCALABILITY_S2T2h = 11, |
| 39 | SCALABILITY_S2T3h = 12, |
| 40 | SCALABILITY_SS = 13 |
| 41 | } SCALABILITY_STRUCTURES; |
Soo-Chul Han | f858986 | 2018-01-24 03:13:14 +0000 | [diff] [blame] | 42 | |
Tom Finegan | 13ee28c | 2018-02-26 19:37:41 -0800 | [diff] [blame] | 43 | int get_obu_type(uint8_t obu_header, OBU_TYPE *obu_type) { |
| 44 | if (!obu_type) return -1; |
| 45 | *obu_type = (OBU_TYPE)((obu_header >> 3) & 0xF); |
| 46 | switch (*obu_type) { |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 47 | case OBU_SEQUENCE_HEADER: |
| 48 | case OBU_TEMPORAL_DELIMITER: |
| 49 | case OBU_FRAME_HEADER: |
Tom Finegan | f927381 | 2018-03-14 09:49:45 -0700 | [diff] [blame] | 50 | case OBU_REDUNDANT_FRAME_HEADER: |
Tom Finegan | f927381 | 2018-03-14 09:49:45 -0700 | [diff] [blame] | 51 | case OBU_FRAME: |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 52 | case OBU_TILE_GROUP: |
| 53 | case OBU_METADATA: |
Tom Finegan | 13ee28c | 2018-02-26 19:37:41 -0800 | [diff] [blame] | 54 | case OBU_PADDING: break; |
| 55 | default: return -1; |
| 56 | } |
| 57 | return 0; |
| 58 | } |
| 59 | |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 60 | // Returns 1 when OBU type is valid, and 0 otherwise. |
| 61 | static int valid_obu_type(int obu_type) { |
| 62 | int valid_type = 0; |
| 63 | switch (obu_type) { |
| 64 | case OBU_SEQUENCE_HEADER: |
| 65 | case OBU_TEMPORAL_DELIMITER: |
| 66 | case OBU_FRAME_HEADER: |
Tom Finegan | f927381 | 2018-03-14 09:49:45 -0700 | [diff] [blame] | 67 | case OBU_REDUNDANT_FRAME_HEADER: |
Vignesh Venkatasubramanian | b2ce34e | 2018-03-05 16:57:40 -0800 | [diff] [blame] | 68 | case OBU_FRAME: |
Tom Finegan | f927381 | 2018-03-14 09:49:45 -0700 | [diff] [blame] | 69 | case OBU_TILE_GROUP: |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 70 | case OBU_METADATA: |
| 71 | case OBU_PADDING: valid_type = 1; break; |
| 72 | default: break; |
| 73 | } |
| 74 | return valid_type; |
| 75 | } |
| 76 | |
Vignesh Venkatasubramanian | 2faf53d | 2018-03-14 11:25:50 -0700 | [diff] [blame] | 77 | // Parses OBU header and stores values in 'header'. |
| 78 | static aom_codec_err_t read_obu_header(struct aom_read_bit_buffer *rb, |
Soo-Chul Han | 29c46fb | 2018-03-23 16:02:00 -0400 | [diff] [blame] | 79 | int is_annexb, ObuHeader *header) { |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 80 | if (!rb || !header) return AOM_CODEC_INVALID_PARAM; |
| 81 | |
| 82 | header->size = 1; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 83 | |
| 84 | // first bit is obu_forbidden_bit (0) according to R19 |
| 85 | aom_rb_read_bit(rb); |
| 86 | |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 87 | header->type = (OBU_TYPE)aom_rb_read_literal(rb, 4); |
| 88 | |
| 89 | if (!valid_obu_type(header->type)) return AOM_CODEC_CORRUPT_FRAME; |
| 90 | |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 91 | header->has_extension = aom_rb_read_bit(rb); |
Tom Finegan | 04450b1 | 2018-03-19 18:12:28 -0700 | [diff] [blame] | 92 | header->has_length_field = aom_rb_read_bit(rb); |
Soo-Chul Han | 29c46fb | 2018-03-23 16:02:00 -0400 | [diff] [blame] | 93 | |
| 94 | if (!header->has_length_field && !is_annexb) { |
| 95 | // section 5 obu streams must have length field set. |
Vignesh Venkatasubramanian | 2faf53d | 2018-03-14 11:25:50 -0700 | [diff] [blame] | 96 | return AOM_CODEC_UNSUP_BITSTREAM; |
| 97 | } |
Tom Finegan | 5427be1 | 2018-03-14 18:45:39 -0700 | [diff] [blame] | 98 | |
Vignesh Venkatasubramanian | 726f795 | 2018-03-08 15:03:35 -0800 | [diff] [blame] | 99 | aom_rb_read_bit(rb); // reserved |
Vignesh Venkatasubramanian | 726f795 | 2018-03-08 15:03:35 -0800 | [diff] [blame] | 100 | |
Tom Finegan | 04450b1 | 2018-03-19 18:12:28 -0700 | [diff] [blame] | 101 | const ptrdiff_t bit_buffer_byte_length = rb->bit_buffer_end - rb->bit_buffer; |
| 102 | if (header->has_extension && bit_buffer_byte_length > 1) { |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 103 | header->size += 1; |
| 104 | header->temporal_layer_id = aom_rb_read_literal(rb, 3); |
| 105 | header->enhancement_layer_id = aom_rb_read_literal(rb, 2); |
| 106 | aom_rb_read_literal(rb, 3); // reserved |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 107 | } |
| 108 | |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 109 | return AOM_CODEC_OK; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 110 | } |
| 111 | |
Tom Finegan | 04450b1 | 2018-03-19 18:12:28 -0700 | [diff] [blame] | 112 | aom_codec_err_t aom_read_obu_header(uint8_t *buffer, size_t buffer_length, |
Soo-Chul Han | 29c46fb | 2018-03-23 16:02:00 -0400 | [diff] [blame] | 113 | size_t *consumed, ObuHeader *header, |
| 114 | int is_annexb) { |
Tom Finegan | 04450b1 | 2018-03-19 18:12:28 -0700 | [diff] [blame] | 115 | if (buffer_length < 1 || !consumed || !header) return AOM_CODEC_INVALID_PARAM; |
| 116 | |
| 117 | // TODO(tomfinegan): Set the error handler here and throughout this file, and |
| 118 | // confirm parsing work done via aom_read_bit_buffer is successful. |
| 119 | struct aom_read_bit_buffer rb = { buffer, buffer + buffer_length, 0, NULL, |
| 120 | NULL }; |
Soo-Chul Han | 29c46fb | 2018-03-23 16:02:00 -0400 | [diff] [blame] | 121 | aom_codec_err_t parse_result = read_obu_header(&rb, is_annexb, header); |
Tom Finegan | 04450b1 | 2018-03-19 18:12:28 -0700 | [diff] [blame] | 122 | if (parse_result == AOM_CODEC_OK) *consumed = header->size; |
| 123 | return parse_result; |
| 124 | } |
| 125 | |
Soo-Chul Han | 79a501a | 2018-03-19 15:24:40 -0400 | [diff] [blame] | 126 | static int is_obu_in_current_operating_point(AV1Decoder *pbi, |
| 127 | ObuHeader obu_header) { |
| 128 | if (!pbi->current_operating_point) { |
| 129 | return 1; |
| 130 | } |
| 131 | |
| 132 | if ((pbi->current_operating_point >> obu_header.temporal_layer_id) & 0x1 && |
| 133 | (pbi->current_operating_point >> (obu_header.enhancement_layer_id + 8)) & |
| 134 | 0x1) { |
| 135 | return 1; |
| 136 | } |
| 137 | return 0; |
| 138 | } |
Soo-Chul Han | 79a501a | 2018-03-19 15:24:40 -0400 | [diff] [blame] | 139 | |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 140 | static uint32_t read_temporal_delimiter_obu() { return 0; } |
| 141 | |
| 142 | static uint32_t read_sequence_header_obu(AV1Decoder *pbi, |
| 143 | struct aom_read_bit_buffer *rb) { |
| 144 | AV1_COMMON *const cm = &pbi->common; |
| 145 | uint32_t saved_bit_offset = rb->bit_offset; |
| 146 | |
| 147 | cm->profile = av1_read_profile(rb); |
Soo-Chul Han | 79a501a | 2018-03-19 15:24:40 -0400 | [diff] [blame] | 148 | |
Debargha Mukherjee | 5d6e3fb | 2018-04-03 13:05:54 -0700 | [diff] [blame] | 149 | SequenceHeader *seq_params = &cm->seq_params; |
| 150 | |
| 151 | // Still picture or not |
| 152 | seq_params->still_picture = aom_rb_read_bit(rb); |
Debargha Mukherjee | c6f24c2 | 2018-04-07 08:43:08 -0700 | [diff] [blame] | 153 | seq_params->reduced_still_picture_hdr = aom_rb_read_bit(rb); |
| 154 | // Video must have reduced_still_picture_hdr = 0 |
| 155 | if (!cm->seq_params.still_picture && |
| 156 | cm->seq_params.reduced_still_picture_hdr) { |
| 157 | return AOM_CODEC_UNSUP_BITSTREAM; |
| 158 | } |
Debargha Mukherjee | 5d6e3fb | 2018-04-03 13:05:54 -0700 | [diff] [blame] | 159 | |
Debargha Mukherjee | c6f24c2 | 2018-04-07 08:43:08 -0700 | [diff] [blame] | 160 | if (seq_params->reduced_still_picture_hdr) { |
| 161 | pbi->common.enhancement_layers_cnt = 1; |
| 162 | seq_params->operating_point_idc[0] = 0; |
Debargha Mukherjee | acd41f9 | 2018-04-11 07:58:34 -0700 | [diff] [blame^] | 163 | seq_params->level[0] = aom_rb_read_literal(rb, LEVEL_BITS); |
Debargha Mukherjee | c6f24c2 | 2018-04-07 08:43:08 -0700 | [diff] [blame] | 164 | seq_params->decoder_rate_model_param_present_flag[0] = 0; |
| 165 | } else { |
Debargha Mukherjee | 112c582 | 2018-04-09 09:42:29 -0700 | [diff] [blame] | 166 | uint8_t operating_points_minus1_cnt = |
| 167 | aom_rb_read_literal(rb, OP_POINTS_MINUS1_BITS); |
Debargha Mukherjee | c6f24c2 | 2018-04-07 08:43:08 -0700 | [diff] [blame] | 168 | pbi->common.enhancement_layers_cnt = operating_points_minus1_cnt + 1; |
| 169 | for (int i = 0; i < operating_points_minus1_cnt + 1; i++) { |
Debargha Mukherjee | 112c582 | 2018-04-09 09:42:29 -0700 | [diff] [blame] | 170 | seq_params->operating_point_idc[i] = |
| 171 | aom_rb_read_literal(rb, OP_POINTS_IDC_BITS); |
| 172 | seq_params->level[i] = aom_rb_read_literal(rb, LEVEL_BITS); |
Andrey Norkin | 795ba87 | 2018-03-06 13:24:14 -0800 | [diff] [blame] | 173 | #if !CONFIG_BUFFER_MODEL |
Debargha Mukherjee | c6f24c2 | 2018-04-07 08:43:08 -0700 | [diff] [blame] | 174 | seq_params->decoder_rate_model_param_present_flag[i] = |
| 175 | aom_rb_read_literal(rb, 1); |
| 176 | if (seq_params->decoder_rate_model_param_present_flag[i]) { |
| 177 | seq_params->decode_to_display_rate_ratio[i] = |
| 178 | aom_rb_read_literal(rb, 12); |
| 179 | seq_params->initial_display_delay[i] = aom_rb_read_literal(rb, 24); |
| 180 | seq_params->extra_frame_buffers[i] = aom_rb_read_literal(rb, 4); |
| 181 | } |
Andrey Norkin | 795ba87 | 2018-03-06 13:24:14 -0800 | [diff] [blame] | 182 | #endif |
Soo-Chul Han | 79a501a | 2018-03-19 15:24:40 -0400 | [diff] [blame] | 183 | } |
| 184 | } |
| 185 | // This decoder supports all levels. Choose the first operating point |
| 186 | pbi->current_operating_point = seq_params->operating_point_idc[0]; |
Soo-Chul Han | f858986 | 2018-01-24 03:13:14 +0000 | [diff] [blame] | 187 | |
Thomas Davies | 0cbcf79 | 2018-03-15 14:10:02 +0000 | [diff] [blame] | 188 | read_sequence_header(cm, rb); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 189 | |
| 190 | av1_read_bitdepth_colorspace_sampling(cm, rb, pbi->allow_lowbitdepth); |
| 191 | |
Andrey Norkin | 795ba87 | 2018-03-06 13:24:14 -0800 | [diff] [blame] | 192 | #if !CONFIG_BUFFER_MODEL |
Debargha Mukherjee | c6f24c2 | 2018-04-07 08:43:08 -0700 | [diff] [blame] | 193 | if (!seq_params->reduced_still_picture_hdr) |
| 194 | av1_read_timing_info_header(cm, rb); |
| 195 | else |
| 196 | cm->timing_info_present = 0; |
Andrey Norkin | 795ba87 | 2018-03-06 13:24:14 -0800 | [diff] [blame] | 197 | #else |
| 198 | if (!seq_params->reduced_still_picture_hdr) |
| 199 | cm->timing_info_present = aom_rb_read_bit(rb); // timing info present flag |
| 200 | else |
| 201 | cm->timing_info_present = 0; |
| 202 | |
| 203 | if (cm->timing_info_present) { |
| 204 | av1_read_timing_info_header(cm, rb); |
| 205 | |
| 206 | cm->decoder_model_info_present_flag = aom_rb_read_bit(rb); |
| 207 | if (cm->decoder_model_info_present_flag) |
| 208 | av1_read_decoder_model_info(cm, rb); |
| 209 | } |
| 210 | int operating_points_decoder_model_present = aom_rb_read_bit(rb); |
| 211 | if (operating_points_decoder_model_present) { |
| 212 | cm->operating_points_decoder_model_cnt = aom_rb_read_literal(rb, 5) + 1; |
| 213 | } else { |
| 214 | cm->operating_points_decoder_model_cnt = 0; |
| 215 | } |
| 216 | for (int op_num = 0; op_num < cm->operating_points_decoder_model_cnt; |
| 217 | ++op_num) { |
| 218 | cm->op_params[op_num].decoder_model_operating_point_idc = |
| 219 | aom_rb_read_literal(rb, 12); |
| 220 | cm->op_params[op_num].display_model_param_present_flag = |
| 221 | aom_rb_read_bit(rb); |
| 222 | if (cm->op_params[op_num].display_model_param_present_flag) { |
| 223 | cm->op_params[op_num].initial_display_delay = |
| 224 | aom_rb_read_literal(rb, 4) + 1; |
| 225 | if (cm->op_params[op_num].initial_display_delay > 10) |
| 226 | aom_internal_error( |
| 227 | &cm->error, AOM_CODEC_UNSUP_BITSTREAM, |
| 228 | "AV1 does not support more than 10 decoded frames delay"); |
| 229 | } |
| 230 | if (cm->decoder_model_info_present_flag) { |
| 231 | cm->op_params[op_num].decoder_model_param_present_flag = |
| 232 | aom_rb_read_bit(rb); |
| 233 | if (cm->op_params[op_num].decoder_model_param_present_flag) |
| 234 | av1_read_op_parameters_info(cm, rb, op_num); |
| 235 | } |
| 236 | } |
| 237 | #endif |
Andrey Norkin | 28e9ce2 | 2018-01-08 10:11:21 -0800 | [diff] [blame] | 238 | |
Andrey Norkin | 6f1c2f7 | 2018-01-15 20:08:52 -0800 | [diff] [blame] | 239 | cm->film_grain_params_present = aom_rb_read_bit(rb); |
Andrey Norkin | 6f1c2f7 | 2018-01-15 20:08:52 -0800 | [diff] [blame] | 240 | |
Jingning Han | 53995e1 | 2018-03-23 08:02:57 -0700 | [diff] [blame] | 241 | av1_check_trailing_bits(pbi, rb); |
Jingning Han | 8a59bd5 | 2018-03-22 21:30:31 -0700 | [diff] [blame] | 242 | |
David Barker | 3a7b5c2 | 2018-03-21 12:06:16 +0000 | [diff] [blame] | 243 | pbi->sequence_header_ready = 1; |
Hui Su | 224cf96 | 2018-03-11 12:28:10 -0700 | [diff] [blame] | 244 | |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 245 | return ((rb->bit_offset - saved_bit_offset + 7) >> 3); |
| 246 | } |
| 247 | |
Cyril Concolato | 2dab275 | 2018-02-26 14:25:47 -0800 | [diff] [blame] | 248 | static uint32_t read_frame_header_obu(AV1Decoder *pbi, |
Cyril Concolato | 2dab275 | 2018-02-26 14:25:47 -0800 | [diff] [blame] | 249 | struct aom_read_bit_buffer *rb, |
Cyril Concolato | 2dab275 | 2018-02-26 14:25:47 -0800 | [diff] [blame] | 250 | const uint8_t *data, |
Vignesh Venkatasubramanian | bd7b0e3 | 2018-04-10 11:31:59 -0700 | [diff] [blame] | 251 | const uint8_t **p_data_end, |
| 252 | int trailing_bits_present) { |
| 253 | av1_decode_frame_headers_and_setup(pbi, rb, data, p_data_end, |
| 254 | trailing_bits_present); |
Yunqing Wang | e7142e1 | 2018-01-17 11:20:12 -0800 | [diff] [blame] | 255 | return (uint32_t)(pbi->uncomp_hdr_size); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 256 | } |
| 257 | |
Vignesh Venkatasubramanian | 386d9c3 | 2018-04-10 12:39:02 -0700 | [diff] [blame] | 258 | static int32_t read_tile_group_header(AV1Decoder *pbi, |
| 259 | struct aom_read_bit_buffer *rb, |
| 260 | int *startTile, int *endTile, |
| 261 | int tile_start_implicit) { |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 262 | AV1_COMMON *const cm = &pbi->common; |
| 263 | uint32_t saved_bit_offset = rb->bit_offset; |
Vignesh Venkatasubramanian | 2a06b41 | 2018-03-01 15:18:06 -0800 | [diff] [blame] | 264 | int tile_start_and_end_present_flag = 0; |
| 265 | const int num_tiles = pbi->common.tile_rows * pbi->common.tile_cols; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 266 | |
Vignesh Venkatasubramanian | 2a06b41 | 2018-03-01 15:18:06 -0800 | [diff] [blame] | 267 | if (!pbi->common.large_scale_tile && num_tiles > 1) { |
| 268 | tile_start_and_end_present_flag = aom_rb_read_bit(rb); |
| 269 | } |
| 270 | if (pbi->common.large_scale_tile || num_tiles == 1 || |
| 271 | !tile_start_and_end_present_flag) { |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 272 | *startTile = 0; |
Vignesh Venkatasubramanian | 2a06b41 | 2018-03-01 15:18:06 -0800 | [diff] [blame] | 273 | *endTile = num_tiles - 1; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 274 | return ((rb->bit_offset - saved_bit_offset + 7) >> 3); |
| 275 | } |
Vignesh Venkatasubramanian | 386d9c3 | 2018-04-10 12:39:02 -0700 | [diff] [blame] | 276 | if (tile_start_implicit && tile_start_and_end_present_flag) { |
| 277 | return -1; |
| 278 | } |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 279 | *startTile = aom_rb_read_literal(rb, cm->log2_tile_rows + cm->log2_tile_cols); |
| 280 | *endTile = aom_rb_read_literal(rb, cm->log2_tile_rows + cm->log2_tile_cols); |
| 281 | |
| 282 | return ((rb->bit_offset - saved_bit_offset + 7) >> 3); |
| 283 | } |
| 284 | |
Vignesh Venkatasubramanian | 386d9c3 | 2018-04-10 12:39:02 -0700 | [diff] [blame] | 285 | static uint32_t read_one_tile_group_obu( |
| 286 | AV1Decoder *pbi, struct aom_read_bit_buffer *rb, int is_first_tg, |
| 287 | const uint8_t *data, const uint8_t *data_end, const uint8_t **p_data_end, |
| 288 | int *is_last_tg, int tile_start_implicit) { |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 289 | AV1_COMMON *const cm = &pbi->common; |
| 290 | int startTile, endTile; |
Vignesh Venkatasubramanian | 386d9c3 | 2018-04-10 12:39:02 -0700 | [diff] [blame] | 291 | int32_t header_size, tg_payload_size; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 292 | |
Vignesh Venkatasubramanian | 386d9c3 | 2018-04-10 12:39:02 -0700 | [diff] [blame] | 293 | header_size = read_tile_group_header(pbi, rb, &startTile, &endTile, |
| 294 | tile_start_implicit); |
| 295 | if (header_size == -1) return 0; |
Hui Su | a94c775 | 2018-03-12 11:43:41 -0700 | [diff] [blame] | 296 | if (startTile > endTile) return header_size; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 297 | data += header_size; |
| 298 | av1_decode_tg_tiles_and_wrapup(pbi, data, data_end, p_data_end, startTile, |
| 299 | endTile, is_first_tg); |
Frank Bossen | ebcf3e5 | 2018-03-27 12:19:20 -0400 | [diff] [blame] | 300 | |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 301 | tg_payload_size = (uint32_t)(*p_data_end - data); |
| 302 | |
| 303 | // TODO(shan): For now, assume all tile groups received in order |
| 304 | *is_last_tg = endTile == cm->tile_rows * cm->tile_cols - 1; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 305 | return header_size + tg_payload_size; |
| 306 | } |
| 307 | |
| 308 | static void read_metadata_private_data(const uint8_t *data, size_t sz) { |
| 309 | for (size_t i = 0; i < sz; i++) { |
| 310 | mem_get_le16(data); |
| 311 | data += 2; |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | static void read_metadata_hdr_cll(const uint8_t *data) { |
| 316 | mem_get_le16(data); |
| 317 | mem_get_le16(data + 2); |
| 318 | } |
| 319 | |
| 320 | static void read_metadata_hdr_mdcv(const uint8_t *data) { |
| 321 | for (int i = 0; i < 3; i++) { |
| 322 | mem_get_le16(data); |
| 323 | data += 2; |
| 324 | mem_get_le16(data); |
| 325 | data += 2; |
| 326 | } |
| 327 | |
| 328 | mem_get_le16(data); |
| 329 | data += 2; |
| 330 | mem_get_le16(data); |
| 331 | data += 2; |
| 332 | mem_get_le16(data); |
| 333 | data += 2; |
| 334 | mem_get_le16(data); |
| 335 | } |
| 336 | |
Soo-Chul Han | f858986 | 2018-01-24 03:13:14 +0000 | [diff] [blame] | 337 | static void scalability_structure(struct aom_read_bit_buffer *rb) { |
| 338 | int enhancement_layers_cnt = aom_rb_read_literal(rb, 2); |
| 339 | int enhancement_layer_dimensions_present_flag = aom_rb_read_literal(rb, 1); |
| 340 | int enhancement_layer_description_present_flag = aom_rb_read_literal(rb, 1); |
| 341 | int temporal_group_description_flag = aom_rb_read_literal(rb, 1); |
| 342 | aom_rb_read_literal(rb, 3); // reserved |
| 343 | |
| 344 | if (enhancement_layer_dimensions_present_flag) { |
| 345 | int i; |
| 346 | for (i = 0; i < enhancement_layers_cnt + 1; i++) { |
| 347 | aom_rb_read_literal(rb, 16); |
| 348 | aom_rb_read_literal(rb, 16); |
| 349 | } |
| 350 | } |
| 351 | if (enhancement_layer_description_present_flag) { |
| 352 | int i; |
| 353 | for (i = 0; i < enhancement_layers_cnt + 1; i++) { |
| 354 | aom_rb_read_literal(rb, 8); |
| 355 | } |
| 356 | } |
| 357 | if (temporal_group_description_flag) { |
| 358 | int i, j, temporal_group_size; |
| 359 | temporal_group_size = aom_rb_read_literal(rb, 8); |
| 360 | for (i = 0; i < temporal_group_size; i++) { |
| 361 | aom_rb_read_literal(rb, 3); |
| 362 | aom_rb_read_literal(rb, 1); |
| 363 | int temporal_group_ref_cnt = aom_rb_read_literal(rb, 2); |
| 364 | aom_rb_read_literal(rb, 2); |
| 365 | for (j = 0; j < temporal_group_ref_cnt; j++) { |
| 366 | aom_rb_read_literal(rb, 8); |
| 367 | } |
| 368 | } |
| 369 | } |
| 370 | } |
| 371 | |
| 372 | static void read_metadata_scalability(const uint8_t *data, size_t sz) { |
| 373 | struct aom_read_bit_buffer rb = { data, data + sz, 0, NULL, NULL }; |
| 374 | int scalability_mode_idc = aom_rb_read_literal(&rb, 8); |
| 375 | if (scalability_mode_idc == SCALABILITY_SS) { |
| 376 | scalability_structure(&rb); |
| 377 | } |
| 378 | } |
Soo-Chul Han | f858986 | 2018-01-24 03:13:14 +0000 | [diff] [blame] | 379 | |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 380 | static size_t read_metadata(const uint8_t *data, size_t sz) { |
Hui Su | c3b42aa | 2018-03-12 10:20:39 -0700 | [diff] [blame] | 381 | if (sz < 2) return sz; // Invalid data size. |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 382 | const OBU_METADATA_TYPE metadata_type = (OBU_METADATA_TYPE)mem_get_le16(data); |
| 383 | |
| 384 | if (metadata_type == OBU_METADATA_TYPE_PRIVATE_DATA) { |
| 385 | read_metadata_private_data(data + 2, sz - 2); |
| 386 | } else if (metadata_type == OBU_METADATA_TYPE_HDR_CLL) { |
| 387 | read_metadata_hdr_cll(data + 2); |
| 388 | } else if (metadata_type == OBU_METADATA_TYPE_HDR_MDCV) { |
| 389 | read_metadata_hdr_mdcv(data + 2); |
Soo-Chul Han | f858986 | 2018-01-24 03:13:14 +0000 | [diff] [blame] | 390 | } else if (metadata_type == OBU_METADATA_TYPE_SCALABILITY) { |
| 391 | read_metadata_scalability(data + 2, sz - 2); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 392 | } |
| 393 | |
| 394 | return sz; |
| 395 | } |
| 396 | |
Vignesh Venkatasubramanian | ea0257d | 2018-02-28 14:43:34 -0800 | [diff] [blame] | 397 | static aom_codec_err_t read_obu_size(const uint8_t *data, |
| 398 | size_t bytes_available, |
| 399 | size_t *const obu_size, |
| 400 | size_t *const length_field_size) { |
| 401 | uint64_t u_obu_size = 0; |
| 402 | if (aom_uleb_decode(data, bytes_available, &u_obu_size, length_field_size) != |
| 403 | 0) { |
| 404 | return AOM_CODEC_CORRUPT_FRAME; |
| 405 | } |
| 406 | |
| 407 | *obu_size = (size_t)u_obu_size; |
| 408 | return AOM_CODEC_OK; |
| 409 | } |
Vignesh Venkatasubramanian | ea0257d | 2018-02-28 14:43:34 -0800 | [diff] [blame] | 410 | |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 411 | void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data, |
| 412 | const uint8_t *data_end, |
| 413 | const uint8_t **p_data_end) { |
| 414 | AV1_COMMON *const cm = &pbi->common; |
| 415 | int frame_decoding_finished = 0; |
| 416 | int is_first_tg_obu_received = 1; |
| 417 | int frame_header_received = 0; |
| 418 | int frame_header_size = 0; |
Yaowu Xu | 5018f6a | 2018-03-01 16:21:03 -0800 | [diff] [blame] | 419 | int seq_header_received = 0; |
| 420 | size_t seq_header_size = 0; |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 421 | ObuHeader obu_header; |
| 422 | memset(&obu_header, 0, sizeof(obu_header)); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 423 | |
Hui Su | b4d6b1c | 2018-01-08 13:43:12 -0800 | [diff] [blame] | 424 | if (data_end < data) { |
| 425 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 426 | return; |
| 427 | } |
| 428 | |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 429 | // decode frame as a series of OBUs |
| 430 | while (!frame_decoding_finished && !cm->error.error_code) { |
| 431 | struct aom_read_bit_buffer rb; |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 432 | size_t payload_size = 0; |
| 433 | size_t decoded_payload_size = 0; |
Vignesh Venkatasubramanian | b2ce34e | 2018-03-05 16:57:40 -0800 | [diff] [blame] | 434 | size_t obu_payload_offset = 0; |
Tom Finegan | f2d40f6 | 2018-02-01 11:52:49 -0800 | [diff] [blame] | 435 | const size_t bytes_available = data_end - data; |
| 436 | |
| 437 | if (bytes_available < 1) { |
| 438 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 439 | return; |
| 440 | } |
Tom Finegan | 41150ad | 2018-01-23 11:42:55 -0800 | [diff] [blame] | 441 | |
Vignesh Venkatasubramanian | 6198ebc | 2018-03-02 12:47:33 -0800 | [diff] [blame] | 442 | size_t length_field_size = 0; |
Soo-Chul Han | 29c46fb | 2018-03-23 16:02:00 -0400 | [diff] [blame] | 443 | size_t obu_size = 0; |
| 444 | if (cm->is_annexb) { |
| 445 | if (read_obu_size(data, bytes_available, &obu_size, &length_field_size) != |
| 446 | AOM_CODEC_OK) { |
| 447 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 448 | return; |
| 449 | } |
| 450 | } |
Hui Su | 9c84d42 | 2018-03-11 15:48:09 -0700 | [diff] [blame] | 451 | if (data_end < data + length_field_size) { |
| 452 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 453 | return; |
| 454 | } |
Tom Finegan | f2d40f6 | 2018-02-01 11:52:49 -0800 | [diff] [blame] | 455 | av1_init_read_bit_buffer(pbi, &rb, data + length_field_size, data_end); |
| 456 | |
Soo-Chul Han | 29c46fb | 2018-03-23 16:02:00 -0400 | [diff] [blame] | 457 | const aom_codec_err_t status = |
| 458 | read_obu_header(&rb, cm->is_annexb, &obu_header); |
Vignesh Venkatasubramanian | 2faf53d | 2018-03-14 11:25:50 -0700 | [diff] [blame] | 459 | if (status != AOM_CODEC_OK) { |
| 460 | cm->error.error_code = status; |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 461 | return; |
| 462 | } |
| 463 | |
Soo-Chul Han | 29c46fb | 2018-03-23 16:02:00 -0400 | [diff] [blame] | 464 | if (!cm->is_annexb) { |
Hui Su | 5c9751e | 2018-04-06 14:08:22 -0700 | [diff] [blame] | 465 | if (data_end < data + obu_header.size) { |
| 466 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 467 | return; |
| 468 | } |
Soo-Chul Han | 29c46fb | 2018-03-23 16:02:00 -0400 | [diff] [blame] | 469 | if (read_obu_size(data + obu_header.size, |
| 470 | bytes_available - obu_header.size, &payload_size, |
| 471 | &length_field_size) != AOM_CODEC_OK) { |
| 472 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 473 | return; |
| 474 | } |
| 475 | av1_init_read_bit_buffer( |
| 476 | pbi, &rb, data + length_field_size + obu_header.size, data_end); |
| 477 | } else { |
| 478 | payload_size = obu_size - obu_header.size; |
Vignesh Venkatasubramanian | ea0257d | 2018-02-28 14:43:34 -0800 | [diff] [blame] | 479 | } |
Soo-Chul Han | f858986 | 2018-01-24 03:13:14 +0000 | [diff] [blame] | 480 | |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 481 | data += length_field_size + obu_header.size; |
Hui Su | b4d6b1c | 2018-01-08 13:43:12 -0800 | [diff] [blame] | 482 | if (data_end < data) { |
| 483 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 484 | return; |
| 485 | } |
Soo-Chul Han | f858986 | 2018-01-24 03:13:14 +0000 | [diff] [blame] | 486 | |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 487 | cm->temporal_layer_id = obu_header.temporal_layer_id; |
| 488 | cm->enhancement_layer_id = obu_header.enhancement_layer_id; |
Soo-Chul Han | f858986 | 2018-01-24 03:13:14 +0000 | [diff] [blame] | 489 | |
Tom Finegan | e4e2d09 | 2018-03-01 22:21:23 -0800 | [diff] [blame] | 490 | switch (obu_header.type) { |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 491 | case OBU_TEMPORAL_DELIMITER: |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 492 | decoded_payload_size = read_temporal_delimiter_obu(); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 493 | break; |
| 494 | case OBU_SEQUENCE_HEADER: |
Yaowu Xu | 5018f6a | 2018-03-01 16:21:03 -0800 | [diff] [blame] | 495 | if (!seq_header_received) { |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 496 | decoded_payload_size = read_sequence_header_obu(pbi, &rb); |
| 497 | seq_header_size = decoded_payload_size; |
Yaowu Xu | 5018f6a | 2018-03-01 16:21:03 -0800 | [diff] [blame] | 498 | seq_header_received = 1; |
| 499 | } else { |
| 500 | // Seeing another sequence header, skip as all sequence headers |
| 501 | // are requred to be identical. |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 502 | if (payload_size != seq_header_size) { |
Yaowu Xu | 5018f6a | 2018-03-01 16:21:03 -0800 | [diff] [blame] | 503 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 504 | return; |
| 505 | } |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 506 | decoded_payload_size = seq_header_size; |
Yaowu Xu | 5018f6a | 2018-03-01 16:21:03 -0800 | [diff] [blame] | 507 | } |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 508 | break; |
Tom Finegan | 542aa32 | 2018-03-14 18:03:17 -0700 | [diff] [blame] | 509 | case OBU_FRAME_HEADER: |
Tom Finegan | f927381 | 2018-03-14 09:49:45 -0700 | [diff] [blame] | 510 | case OBU_REDUNDANT_FRAME_HEADER: |
Tom Finegan | 542aa32 | 2018-03-14 18:03:17 -0700 | [diff] [blame] | 511 | case OBU_FRAME: |
Soo-Chul Han | 79a501a | 2018-03-19 15:24:40 -0400 | [diff] [blame] | 512 | // don't decode obu if it's not in current operating mode |
| 513 | if (!is_obu_in_current_operating_point(pbi, obu_header)) { |
| 514 | decoded_payload_size = payload_size; |
| 515 | break; |
| 516 | } |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 517 | // Only decode first frame header received |
| 518 | if (!frame_header_received) { |
Cyril Concolato | 2dab275 | 2018-02-26 14:25:47 -0800 | [diff] [blame] | 519 | av1_init_read_bit_buffer(pbi, &rb, data, data_end); |
Vignesh Venkatasubramanian | bd7b0e3 | 2018-04-10 11:31:59 -0700 | [diff] [blame] | 520 | frame_header_size = read_frame_header_obu( |
| 521 | pbi, &rb, data, p_data_end, obu_header.type != OBU_FRAME); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 522 | frame_header_received = 1; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 523 | } |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 524 | decoded_payload_size = frame_header_size; |
Vignesh Venkatasubramanian | b2ce34e | 2018-03-05 16:57:40 -0800 | [diff] [blame] | 525 | if (cm->show_existing_frame) { |
| 526 | frame_decoding_finished = 1; |
| 527 | break; |
| 528 | } |
David Barker | 163f0f0 | 2018-03-20 16:23:33 +0000 | [diff] [blame] | 529 | if (obu_header.type != OBU_FRAME) break; |
Vignesh Venkatasubramanian | b2ce34e | 2018-03-05 16:57:40 -0800 | [diff] [blame] | 530 | obu_payload_offset = frame_header_size; |
| 531 | AOM_FALLTHROUGH_INTENDED; // fall through to read tile group. |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 532 | case OBU_TILE_GROUP: |
Yaowu Xu | cc7b448 | 2018-02-28 07:03:01 -0800 | [diff] [blame] | 533 | if (!frame_header_received) { |
| 534 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 535 | return; |
| 536 | } |
Hui Su | 9c84d42 | 2018-03-11 15:48:09 -0700 | [diff] [blame] | 537 | if (data_end < data + obu_payload_offset || |
| 538 | data_end < data + payload_size) { |
| 539 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 540 | return; |
| 541 | } |
Soo-Chul Han | 79a501a | 2018-03-19 15:24:40 -0400 | [diff] [blame] | 542 | // don't decode obu if it's not in current operating mode |
| 543 | if (!is_obu_in_current_operating_point(pbi, obu_header)) { |
| 544 | decoded_payload_size = payload_size; |
| 545 | break; |
| 546 | } |
Vignesh Venkatasubramanian | b2ce34e | 2018-03-05 16:57:40 -0800 | [diff] [blame] | 547 | decoded_payload_size += read_one_tile_group_obu( |
| 548 | pbi, &rb, is_first_tg_obu_received, data + obu_payload_offset, |
Vignesh Venkatasubramanian | 386d9c3 | 2018-04-10 12:39:02 -0700 | [diff] [blame] | 549 | data + payload_size, p_data_end, &frame_decoding_finished, |
| 550 | obu_header.type == OBU_FRAME); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 551 | is_first_tg_obu_received = 0; |
| 552 | break; |
| 553 | case OBU_METADATA: |
Soo-Chul Han | 79a501a | 2018-03-19 15:24:40 -0400 | [diff] [blame] | 554 | // don't decode obu if it's not in current operating mode |
| 555 | if (!is_obu_in_current_operating_point(pbi, obu_header)) { |
| 556 | decoded_payload_size = payload_size; |
| 557 | break; |
| 558 | } |
Hui Su | 5c9751e | 2018-04-06 14:08:22 -0700 | [diff] [blame] | 559 | if (data_end < data + payload_size) { |
| 560 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 561 | return; |
| 562 | } |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 563 | decoded_payload_size = read_metadata(data, payload_size); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 564 | break; |
Yaowu Xu | 993f7be | 2018-02-28 08:54:36 -0800 | [diff] [blame] | 565 | case OBU_PADDING: |
| 566 | default: |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 567 | // Skip unrecognized OBUs |
| 568 | decoded_payload_size = payload_size; |
Yaowu Xu | 993f7be | 2018-02-28 08:54:36 -0800 | [diff] [blame] | 569 | break; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 570 | } |
Tom Finegan | f2d40f6 | 2018-02-01 11:52:49 -0800 | [diff] [blame] | 571 | |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 572 | // Check that the signalled OBU size matches the actual amount of data read |
David Barker | cbba79c | 2018-03-28 14:29:38 +0100 | [diff] [blame] | 573 | if (decoded_payload_size > payload_size) { |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 574 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 575 | return; |
| 576 | } |
| 577 | |
Hui Su | 5c9751e | 2018-04-06 14:08:22 -0700 | [diff] [blame] | 578 | if (data_end < data + payload_size) { |
| 579 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 580 | return; |
| 581 | } |
| 582 | |
David Barker | cbba79c | 2018-03-28 14:29:38 +0100 | [diff] [blame] | 583 | // If there are extra padding bytes, they should all be zero |
| 584 | while (decoded_payload_size < payload_size) { |
| 585 | uint8_t padding_byte = data[decoded_payload_size++]; |
| 586 | if (padding_byte != 0) { |
| 587 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 588 | return; |
| 589 | } |
| 590 | } |
| 591 | |
David Barker | 3bb1f2a | 2017-10-09 14:57:17 +0100 | [diff] [blame] | 592 | data += payload_size; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 593 | } |
| 594 | } |