1/* 2 * This file is part of FFmpeg. 3 * 4 * FFmpeg is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * FFmpeg is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with FFmpeg; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19static int FUNC(filler_payload) 20 (CodedBitstreamContext *ctx, RWContext *rw, 21 SEIRawFillerPayload *current, SEIMessageState *state) 22{ 23 int err, i; 24 25 HEADER("Filler Payload"); 26 27#ifdef READ 28 current->payload_size = state->payload_size; 29#endif 30 31 for (i = 0; i < current->payload_size; i++) 32 fixed(8, ff_byte, 0xff); 33 34 return 0; 35} 36 37static int FUNC(user_data_registered) 38 (CodedBitstreamContext *ctx, RWContext *rw, 39 SEIRawUserDataRegistered *current, SEIMessageState *state) 40{ 41 int err, i, j; 42 43 HEADER("User Data Registered ITU-T T.35"); 44 45 u(8, itu_t_t35_country_code, 0x00, 0xff); 46 if (current->itu_t_t35_country_code != 0xff) 47 i = 1; 48 else { 49 u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff); 50 i = 2; 51 } 52 53#ifdef READ 54 if (state->payload_size < i) { 55 av_log(ctx->log_ctx, AV_LOG_ERROR, 56 "Invalid SEI user data registered payload.\n"); 57 return AVERROR_INVALIDDATA; 58 } 59 current->data_length = state->payload_size - i; 60#endif 61 62 allocate(current->data, current->data_length); 63 for (j = 0; j < current->data_length; j++) 64 xu(8, itu_t_t35_payload_byte[], current->data[j], 0x00, 0xff, 1, i + j); 65 66 return 0; 67} 68 69static int FUNC(user_data_unregistered) 70 (CodedBitstreamContext *ctx, RWContext *rw, 71 SEIRawUserDataUnregistered *current, SEIMessageState *state) 72{ 73 int err, i; 74 75 HEADER("User Data Unregistered"); 76 77#ifdef READ 78 if (state->payload_size < 16) { 79 av_log(ctx->log_ctx, AV_LOG_ERROR, 80 "Invalid SEI user data unregistered payload.\n"); 81 return AVERROR_INVALIDDATA; 82 } 83 current->data_length = state->payload_size - 16; 84#endif 85 86 for (i = 0; i < 16; i++) 87 us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i); 88 89 allocate(current->data, current->data_length); 90 91 for (i = 0; i < current->data_length; i++) 92 xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1, i); 93 94 return 0; 95} 96 97static int FUNC(mastering_display_colour_volume) 98 (CodedBitstreamContext *ctx, RWContext *rw, 99 SEIRawMasteringDisplayColourVolume *current, SEIMessageState *state) 100{ 101 int err, c; 102 103 HEADER("Mastering Display Colour Volume"); 104 105 for (c = 0; c < 3; c++) { 106 ubs(16, display_primaries_x[c], 1, c); 107 ubs(16, display_primaries_y[c], 1, c); 108 } 109 110 ub(16, white_point_x); 111 ub(16, white_point_y); 112 113 ub(32, max_display_mastering_luminance); 114 ub(32, min_display_mastering_luminance); 115 116 return 0; 117} 118 119static int FUNC(content_light_level_info) 120 (CodedBitstreamContext *ctx, RWContext *rw, 121 SEIRawContentLightLevelInfo *current, SEIMessageState *state) 122{ 123 int err; 124 125 HEADER("Content Light Level Information"); 126 127 ub(16, max_content_light_level); 128 ub(16, max_pic_average_light_level); 129 130 return 0; 131} 132 133static int FUNC(alternative_transfer_characteristics) 134 (CodedBitstreamContext *ctx, RWContext *rw, 135 SEIRawAlternativeTransferCharacteristics *current, 136 SEIMessageState *state) 137{ 138 int err; 139 140 HEADER("Alternative Transfer Characteristics"); 141 142 ub(8, preferred_transfer_characteristics); 143 144 return 0; 145} 146 147static int FUNC(message)(CodedBitstreamContext *ctx, RWContext *rw, 148 SEIRawMessage *current) 149{ 150 const SEIMessageTypeDescriptor *desc; 151 int err, i; 152 153 desc = ff_cbs_sei_find_type(ctx, current->payload_type); 154 if (desc) { 155 SEIMessageState state = { 156 .payload_type = current->payload_type, 157 .payload_size = current->payload_size, 158 .extension_present = current->extension_bit_length > 0, 159 }; 160 int start_position, current_position, bits_written; 161 162#ifdef READ 163 CHECK(ff_cbs_sei_alloc_message_payload(current, desc)); 164#endif 165 166 start_position = bit_position(rw); 167 168 CHECK(desc->READWRITE(ctx, rw, current->payload, &state)); 169 170 current_position = bit_position(rw); 171 bits_written = current_position - start_position; 172 173 if (byte_alignment(rw) || state.extension_present || 174 bits_written < 8 * current->payload_size) { 175 size_t bits_left; 176 177#ifdef READ 178 GetBitContext tmp = *rw; 179 int trailing_bits, trailing_zero_bits; 180 181 bits_left = 8 * current->payload_size - bits_written; 182 if (bits_left > 8) 183 skip_bits_long(&tmp, bits_left - 8); 184 trailing_bits = get_bits(&tmp, FFMIN(bits_left, 8)); 185 if (trailing_bits == 0) { 186 // The trailing bits must contain a bit_equal_to_one, so 187 // they can't all be zero. 188 return AVERROR_INVALIDDATA; 189 } 190 trailing_zero_bits = ff_ctz(trailing_bits); 191 current->extension_bit_length = 192 bits_left - 1 - trailing_zero_bits; 193#endif 194 195 if (current->extension_bit_length > 0) { 196 allocate(current->extension_data, 197 (current->extension_bit_length + 7) / 8); 198 199 bits_left = current->extension_bit_length; 200 for (i = 0; bits_left > 0; i++) { 201 int length = FFMIN(bits_left, 8); 202 xu(length, reserved_payload_extension_data, 203 current->extension_data[i], 204 0, MAX_UINT_BITS(length), 0); 205 bits_left -= length; 206 } 207 } 208 209 fixed(1, bit_equal_to_one, 1); 210 while (byte_alignment(rw)) 211 fixed(1, bit_equal_to_zero, 0); 212 } 213 214#ifdef WRITE 215 current->payload_size = (put_bits_count(rw) - start_position) / 8; 216#endif 217 } else { 218 uint8_t *data; 219 220 allocate(current->payload, current->payload_size); 221 data = current->payload; 222 223 for (i = 0; i < current->payload_size; i++) 224 xu(8, payload_byte[i], data[i], 0, 255, 1, i); 225 } 226 227 return 0; 228} 229 230static int FUNC(message_list)(CodedBitstreamContext *ctx, RWContext *rw, 231 SEIRawMessageList *current, int prefix) 232{ 233 SEIRawMessage *message; 234 int err, k; 235 236#ifdef READ 237 for (k = 0;; k++) { 238 uint32_t payload_type = 0; 239 uint32_t payload_size = 0; 240 uint32_t tmp; 241 GetBitContext payload_gbc; 242 243 while (show_bits(rw, 8) == 0xff) { 244 fixed(8, ff_byte, 0xff); 245 payload_type += 255; 246 } 247 xu(8, last_payload_type_byte, tmp, 0, 254, 0); 248 payload_type += tmp; 249 250 while (show_bits(rw, 8) == 0xff) { 251 fixed(8, ff_byte, 0xff); 252 payload_size += 255; 253 } 254 xu(8, last_payload_size_byte, tmp, 0, 254, 0); 255 payload_size += tmp; 256 257 // There must be space remaining for both the payload and 258 // the trailing bits on the SEI NAL unit. 259 if (payload_size + 1 > get_bits_left(rw) / 8) { 260 av_log(ctx->log_ctx, AV_LOG_ERROR, 261 "Invalid SEI message: payload_size too large " 262 "(%"PRIu32" bytes).\n", payload_size); 263 return AVERROR_INVALIDDATA; 264 } 265 CHECK(init_get_bits(&payload_gbc, rw->buffer, 266 get_bits_count(rw) + 8 * payload_size)); 267 skip_bits_long(&payload_gbc, get_bits_count(rw)); 268 269 CHECK(ff_cbs_sei_list_add(current)); 270 message = ¤t->messages[k]; 271 272 message->payload_type = payload_type; 273 message->payload_size = payload_size; 274 275 CHECK(FUNC(message)(ctx, &payload_gbc, message)); 276 277 skip_bits_long(rw, 8 * payload_size); 278 279 if (!cbs_h2645_read_more_rbsp_data(rw)) 280 break; 281 } 282#else 283 for (k = 0; k < current->nb_messages; k++) { 284 PutBitContext start_state; 285 uint32_t tmp; 286 int trace, i; 287 288 message = ¤t->messages[k]; 289 290 // We write the payload twice in order to find the size. Trace 291 // output is switched off for the first write. 292 trace = ctx->trace_enable; 293 ctx->trace_enable = 0; 294 295 start_state = *rw; 296 for (i = 0; i < 2; i++) { 297 *rw = start_state; 298 299 tmp = message->payload_type; 300 while (tmp >= 255) { 301 fixed(8, ff_byte, 0xff); 302 tmp -= 255; 303 } 304 xu(8, last_payload_type_byte, tmp, 0, 254, 0); 305 306 tmp = message->payload_size; 307 while (tmp >= 255) { 308 fixed(8, ff_byte, 0xff); 309 tmp -= 255; 310 } 311 xu(8, last_payload_size_byte, tmp, 0, 254, 0); 312 313 err = FUNC(message)(ctx, rw, message); 314 ctx->trace_enable = trace; 315 if (err < 0) 316 return err; 317 } 318 } 319#endif 320 321 return 0; 322} 323