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" |
| 23 | |
| 24 | static OBU_TYPE read_obu_header(struct aom_read_bit_buffer *rb, |
Tom Finegan | 8695e98 | 2018-01-23 21:59:24 +0000 | [diff] [blame] | 25 | size_t *header_size) { |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 26 | *header_size = 1; |
| 27 | |
| 28 | // first bit is obu_forbidden_bit (0) according to R19 |
| 29 | aom_rb_read_bit(rb); |
| 30 | |
| 31 | const OBU_TYPE obu_type = (OBU_TYPE)aom_rb_read_literal(rb, 4); |
| 32 | aom_rb_read_literal(rb, 2); // reserved |
| 33 | const int obu_extension_flag = aom_rb_read_bit(rb); |
| 34 | if (obu_extension_flag) { |
| 35 | *header_size += 1; |
| 36 | aom_rb_read_literal(rb, 3); // temporal_id |
| 37 | aom_rb_read_literal(rb, 2); |
| 38 | aom_rb_read_literal(rb, 2); |
| 39 | aom_rb_read_literal(rb, 1); // reserved |
| 40 | } |
| 41 | |
| 42 | return obu_type; |
| 43 | } |
| 44 | |
| 45 | static uint32_t read_temporal_delimiter_obu() { return 0; } |
| 46 | |
| 47 | static uint32_t read_sequence_header_obu(AV1Decoder *pbi, |
| 48 | struct aom_read_bit_buffer *rb) { |
| 49 | AV1_COMMON *const cm = &pbi->common; |
| 50 | uint32_t saved_bit_offset = rb->bit_offset; |
| 51 | |
| 52 | cm->profile = av1_read_profile(rb); |
| 53 | aom_rb_read_literal(rb, 4); // level |
| 54 | |
| 55 | read_sequence_header(&cm->seq_params, rb); |
| 56 | |
| 57 | av1_read_bitdepth_colorspace_sampling(cm, rb, pbi->allow_lowbitdepth); |
| 58 | |
Andrey Norkin | 28e9ce2 | 2018-01-08 10:11:21 -0800 | [diff] [blame] | 59 | #if CONFIG_TIMING_INFO_IN_SEQ_HEADERS |
| 60 | av1_read_timing_info_header(cm, rb); |
| 61 | #endif |
| 62 | |
Andrey Norkin | 6f1c2f7 | 2018-01-15 20:08:52 -0800 | [diff] [blame^] | 63 | #if CONFIG_FILM_GRAIN |
| 64 | cm->film_grain_params_present = aom_rb_read_bit(rb); |
| 65 | #endif |
| 66 | |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 67 | return ((rb->bit_offset - saved_bit_offset + 7) >> 3); |
| 68 | } |
| 69 | |
| 70 | static uint32_t read_frame_header_obu(AV1Decoder *pbi, const uint8_t *data, |
| 71 | const uint8_t *data_end, |
| 72 | const uint8_t **p_data_end) { |
Yunqing Wang | e7142e1 | 2018-01-17 11:20:12 -0800 | [diff] [blame] | 73 | av1_decode_frame_headers_and_setup(pbi, data, data_end, p_data_end); |
| 74 | return (uint32_t)(pbi->uncomp_hdr_size); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 75 | } |
| 76 | |
| 77 | static uint32_t read_tile_group_header(AV1Decoder *pbi, |
| 78 | struct aom_read_bit_buffer *rb, |
| 79 | int *startTile, int *endTile) { |
| 80 | AV1_COMMON *const cm = &pbi->common; |
| 81 | uint32_t saved_bit_offset = rb->bit_offset; |
| 82 | |
| 83 | #if CONFIG_EXT_TILE |
| 84 | if (pbi->common.large_scale_tile) { |
| 85 | *startTile = 0; |
| 86 | *endTile = pbi->common.tile_rows * pbi->common.tile_cols - 1; |
| 87 | return ((rb->bit_offset - saved_bit_offset + 7) >> 3); |
| 88 | } |
| 89 | #endif |
| 90 | |
| 91 | *startTile = aom_rb_read_literal(rb, cm->log2_tile_rows + cm->log2_tile_cols); |
| 92 | *endTile = aom_rb_read_literal(rb, cm->log2_tile_rows + cm->log2_tile_cols); |
| 93 | |
| 94 | return ((rb->bit_offset - saved_bit_offset + 7) >> 3); |
| 95 | } |
| 96 | |
| 97 | static uint32_t read_one_tile_group_obu(AV1Decoder *pbi, |
| 98 | struct aom_read_bit_buffer *rb, |
| 99 | int is_first_tg, const uint8_t *data, |
| 100 | const uint8_t *data_end, |
| 101 | const uint8_t **p_data_end, |
| 102 | int *is_last_tg) { |
| 103 | AV1_COMMON *const cm = &pbi->common; |
| 104 | int startTile, endTile; |
| 105 | uint32_t header_size, tg_payload_size; |
| 106 | |
| 107 | header_size = read_tile_group_header(pbi, rb, &startTile, &endTile); |
| 108 | data += header_size; |
| 109 | av1_decode_tg_tiles_and_wrapup(pbi, data, data_end, p_data_end, startTile, |
| 110 | endTile, is_first_tg); |
| 111 | tg_payload_size = (uint32_t)(*p_data_end - data); |
| 112 | |
| 113 | // TODO(shan): For now, assume all tile groups received in order |
| 114 | *is_last_tg = endTile == cm->tile_rows * cm->tile_cols - 1; |
| 115 | |
| 116 | return header_size + tg_payload_size; |
| 117 | } |
| 118 | |
| 119 | static void read_metadata_private_data(const uint8_t *data, size_t sz) { |
| 120 | for (size_t i = 0; i < sz; i++) { |
| 121 | mem_get_le16(data); |
| 122 | data += 2; |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | static void read_metadata_hdr_cll(const uint8_t *data) { |
| 127 | mem_get_le16(data); |
| 128 | mem_get_le16(data + 2); |
| 129 | } |
| 130 | |
| 131 | static void read_metadata_hdr_mdcv(const uint8_t *data) { |
| 132 | for (int i = 0; i < 3; i++) { |
| 133 | mem_get_le16(data); |
| 134 | data += 2; |
| 135 | mem_get_le16(data); |
| 136 | data += 2; |
| 137 | } |
| 138 | |
| 139 | mem_get_le16(data); |
| 140 | data += 2; |
| 141 | mem_get_le16(data); |
| 142 | data += 2; |
| 143 | mem_get_le16(data); |
| 144 | data += 2; |
| 145 | mem_get_le16(data); |
| 146 | } |
| 147 | |
| 148 | static size_t read_metadata(const uint8_t *data, size_t sz) { |
| 149 | assert(sz >= 2); |
| 150 | const OBU_METADATA_TYPE metadata_type = (OBU_METADATA_TYPE)mem_get_le16(data); |
| 151 | |
| 152 | if (metadata_type == OBU_METADATA_TYPE_PRIVATE_DATA) { |
| 153 | read_metadata_private_data(data + 2, sz - 2); |
| 154 | } else if (metadata_type == OBU_METADATA_TYPE_HDR_CLL) { |
| 155 | read_metadata_hdr_cll(data + 2); |
| 156 | } else if (metadata_type == OBU_METADATA_TYPE_HDR_MDCV) { |
| 157 | read_metadata_hdr_mdcv(data + 2); |
| 158 | } |
| 159 | |
| 160 | return sz; |
| 161 | } |
| 162 | |
| 163 | void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data, |
| 164 | const uint8_t *data_end, |
| 165 | const uint8_t **p_data_end) { |
| 166 | AV1_COMMON *const cm = &pbi->common; |
| 167 | int frame_decoding_finished = 0; |
| 168 | int is_first_tg_obu_received = 1; |
| 169 | int frame_header_received = 0; |
| 170 | int frame_header_size = 0; |
| 171 | |
Hui Su | b4d6b1c | 2018-01-08 13:43:12 -0800 | [diff] [blame] | 172 | if (data_end < data) { |
| 173 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 174 | return; |
| 175 | } |
| 176 | |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 177 | // decode frame as a series of OBUs |
| 178 | while (!frame_decoding_finished && !cm->error.error_code) { |
| 179 | struct aom_read_bit_buffer rb; |
| 180 | size_t obu_header_size, obu_payload_size = 0; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 181 | av1_init_read_bit_buffer(pbi, &rb, data + PRE_OBU_SIZE_BYTES, data_end); |
Tom Finegan | 41150ad | 2018-01-23 11:42:55 -0800 | [diff] [blame] | 182 | |
| 183 | #if CONFIG_OBU_SIZING |
| 184 | // OBUs are preceded by an unsigned leb128 coded unsigned integer padded to |
| 185 | // PRE_OBU_SIZE_BYTES bytes. |
| 186 | uint32_t u_obu_size = 0; |
| 187 | aom_uleb_decode(data, PRE_OBU_SIZE_BYTES, &u_obu_size); |
| 188 | const size_t obu_size = (size_t)u_obu_size; |
| 189 | #else |
Tom Finegan | ff86395 | 2017-12-22 11:41:14 -0800 | [diff] [blame] | 190 | // every obu is preceded by PRE_OBU_SIZE_BYTES-byte size of obu (obu header |
| 191 | // + payload size) |
| 192 | // The obu size is only needed for tile group OBUs |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 193 | const size_t obu_size = mem_get_le32(data); |
Tom Finegan | 41150ad | 2018-01-23 11:42:55 -0800 | [diff] [blame] | 194 | #endif // CONFIG_OBU_SIZING |
| 195 | |
Tom Finegan | 8695e98 | 2018-01-23 21:59:24 +0000 | [diff] [blame] | 196 | const OBU_TYPE obu_type = read_obu_header(&rb, &obu_header_size); |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 197 | data += (PRE_OBU_SIZE_BYTES + obu_header_size); |
Hui Su | b4d6b1c | 2018-01-08 13:43:12 -0800 | [diff] [blame] | 198 | if (data_end < data) { |
| 199 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 200 | return; |
| 201 | } |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 202 | switch (obu_type) { |
| 203 | case OBU_TEMPORAL_DELIMITER: |
| 204 | obu_payload_size = read_temporal_delimiter_obu(); |
| 205 | break; |
| 206 | case OBU_SEQUENCE_HEADER: |
| 207 | obu_payload_size = read_sequence_header_obu(pbi, &rb); |
| 208 | break; |
| 209 | case OBU_FRAME_HEADER: |
| 210 | // Only decode first frame header received |
| 211 | if (!frame_header_received) { |
Yaowu Xu | 96fa757 | 2017-12-26 20:51:41 -0800 | [diff] [blame] | 212 | frame_header_size = |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 213 | read_frame_header_obu(pbi, data, data_end, p_data_end); |
| 214 | frame_header_received = 1; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 215 | } |
Yaowu Xu | 96fa757 | 2017-12-26 20:51:41 -0800 | [diff] [blame] | 216 | obu_payload_size = frame_header_size; |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 217 | if (cm->show_existing_frame) frame_decoding_finished = 1; |
| 218 | break; |
| 219 | case OBU_TILE_GROUP: |
| 220 | obu_payload_size = |
| 221 | read_one_tile_group_obu(pbi, &rb, is_first_tg_obu_received, data, |
| 222 | data + obu_size - obu_header_size, |
| 223 | p_data_end, &frame_decoding_finished); |
| 224 | is_first_tg_obu_received = 0; |
| 225 | break; |
| 226 | case OBU_METADATA: |
| 227 | obu_payload_size = read_metadata(data, obu_size); |
| 228 | break; |
| 229 | default: break; |
| 230 | } |
| 231 | data += obu_payload_size; |
Hui Su | b4d6b1c | 2018-01-08 13:43:12 -0800 | [diff] [blame] | 232 | if (data_end < data) { |
| 233 | cm->error.error_code = AOM_CODEC_CORRUPT_FRAME; |
| 234 | return; |
| 235 | } |
Sebastien Alaiwan | e9644be | 2017-12-19 18:20:12 +0100 | [diff] [blame] | 236 | } |
| 237 | } |