1 /*
2 * H.265 video codec.
3 * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
4 *
5 * This file is part of libde265.
6 *
7 * libde265 is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * libde265 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
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with libde265. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "sei.h"
22 #include "util.h"
23 #include "md5.h"
24
25 #include "libde265/sps.h"
26 #include "libde265/image.h"
27 #include "libde265/decctx.h"
28
29 #include <assert.h>
30
31
read_sei_decoded_picture_hash(bitreader * reader,sei_message * sei,const seq_parameter_set * sps)32 static de265_error read_sei_decoded_picture_hash(bitreader* reader, sei_message* sei,
33 const seq_parameter_set* sps)
34 {
35 sei_decoded_picture_hash* seihash = &sei->data.decoded_picture_hash;
36
37 seihash->hash_type = (enum sei_decoded_picture_hash_type)get_bits(reader,8);
38
39 if (sps==NULL) {
40 return DE265_WARNING_SPS_MISSING_CANNOT_DECODE_SEI;
41 }
42
43 int nHashes = sps->chroma_format_idc==0 ? 1 : 3;
44 for (int i=0;i<nHashes;i++) {
45 switch (seihash->hash_type) {
46 case sei_decoded_picture_hash_type_MD5:
47 for (int b=0;b<16;b++) { seihash->md5[i][b] = get_bits(reader,8); }
48 break;
49
50 case sei_decoded_picture_hash_type_CRC:
51 seihash->crc[i] = get_bits(reader,16);
52 break;
53
54 case sei_decoded_picture_hash_type_checksum:
55 seihash->checksum[i] = get_bits(reader,32);
56 break;
57 }
58 }
59
60 return DE265_OK;
61 }
62
63
dump_sei_decoded_picture_hash(const sei_message * sei,const seq_parameter_set * sps)64 static void dump_sei_decoded_picture_hash(const sei_message* sei,
65 const seq_parameter_set* sps)
66 {
67 const sei_decoded_picture_hash* seihash = &sei->data.decoded_picture_hash;
68
69 loginfo(LogSEI," hash_type: ");
70 switch (seihash->hash_type) {
71 case sei_decoded_picture_hash_type_MD5: loginfo(LogSEI,"MD5\n"); break;
72 case sei_decoded_picture_hash_type_CRC: loginfo(LogSEI,"CRC\n"); break;
73 case sei_decoded_picture_hash_type_checksum: loginfo(LogSEI,"checksum\n"); break;
74 }
75
76 int nHashes = sps->chroma_format_idc==0 ? 1 : 3;
77 for (int i=0;i<nHashes;i++) {
78 switch (seihash->hash_type) {
79 case sei_decoded_picture_hash_type_MD5:
80 loginfo(LogSEI," MD5[%d]: %02x", i,seihash->md5[i][0]);
81 for (int b=1;b<16;b++) {
82 loginfo(LogSEI,"*:%02x", seihash->md5[i][b]);
83 }
84 loginfo(LogSEI,"*\n");
85 break;
86
87 case sei_decoded_picture_hash_type_CRC:
88 loginfo(LogSEI," CRC[%d]: %02x\n", i,seihash->crc[i]);
89 break;
90
91 case sei_decoded_picture_hash_type_checksum:
92 loginfo(LogSEI," checksum[%d]: %04x\n", i,seihash->checksum[i]);
93 break;
94 }
95 }
96 }
97
98
99 class raw_hash_data
100 {
101 public:
102 raw_hash_data(int w, int stride);
103 ~raw_hash_data();
104
105 struct data_chunk {
106 const uint8_t* data;
107 int len;
108 };
109
110 data_chunk prepare_8bit(const uint8_t* data,int y);
111 data_chunk prepare_16bit(const uint8_t* data,int y);
112
113 private:
114 int mWidth, mStride;
115
116 uint8_t* mMem;
117 };
118
119
raw_hash_data(int w,int stride)120 raw_hash_data::raw_hash_data(int w, int stride)
121 {
122 mWidth=w;
123 mStride=stride;
124 mMem = NULL;
125 }
126
~raw_hash_data()127 raw_hash_data::~raw_hash_data()
128 {
129 delete[] mMem;
130 }
131
prepare_8bit(const uint8_t * data,int y)132 raw_hash_data::data_chunk raw_hash_data::prepare_8bit(const uint8_t* data,int y)
133 {
134 data_chunk chunk;
135 chunk.data = data+y*mStride;
136 chunk.len = mWidth;
137 return chunk;
138 }
139
prepare_16bit(const uint8_t * data,int y)140 raw_hash_data::data_chunk raw_hash_data::prepare_16bit(const uint8_t* data,int y)
141 {
142 if (mMem == NULL) {
143 mMem = new uint8_t[2*mWidth];
144 }
145
146 const uint16_t* data16 = (uint16_t*)data;
147
148 for (int x=0; x<mWidth; x++) {
149 mMem[2*x+0] = data16[y*mStride+x] & 0xFF;
150 mMem[2*x+1] = data16[y*mStride+x] >> 8;
151 }
152
153 data_chunk chunk;
154 chunk.data = mMem;
155 chunk.len = 2*mWidth;
156 return chunk;
157 }
158
159
compute_checksum_8bit(uint8_t * data,int w,int h,int stride,int bit_depth)160 static uint32_t compute_checksum_8bit(uint8_t* data,int w,int h,int stride, int bit_depth)
161 {
162 uint32_t sum = 0;
163
164 if (bit_depth<=8) {
165 for (int y=0; y<h; y++)
166 for(int x=0; x<w; x++) {
167 uint8_t xorMask = ( x & 0xFF ) ^ ( y & 0xFF ) ^ ( x >> 8 ) ^ ( y >> 8 );
168 sum += data[y*stride + x] ^ xorMask;
169 }
170 }
171 else {
172 for (int y=0; y<h; y++)
173 for(int x=0; x<w; x++) {
174 uint8_t xorMask = ( x & 0xFF ) ^ ( y & 0xFF ) ^ ( x >> 8 ) ^ ( y >> 8 );
175 sum += (data[y*stride + x] & 0xFF) ^ xorMask;
176 sum += (data[y*stride + x] >> 8) ^ xorMask;
177 }
178 }
179
180 return sum & 0xFFFFFFFF;
181 }
182
crc_process_byte(uint16_t crc,uint8_t byte)183 static inline uint16_t crc_process_byte(uint16_t crc, uint8_t byte)
184 {
185 for (int bit=0;bit<8;bit++) {
186 int bitVal = (byte >> (7-bit)) & 1;
187
188 int crcMsb = (crc>>15) & 1;
189 crc = (((crc<<1) + bitVal) & 0xFFFF);
190
191 if (crcMsb) { crc ^= 0x1021; }
192 }
193
194 return crc;
195 }
196
197 /*
198 static uint16_t compute_CRC_8bit_old(const uint8_t* data,int w,int h,int stride)
199 {
200 uint16_t crc = 0xFFFF;
201
202 for (int y=0; y<h; y++)
203 for(int x=0; x<w; x++) {
204 crc = crc_process_byte(crc, data[y*stride+x]);
205 }
206
207 crc = crc_process_byte(crc, 0);
208 crc = crc_process_byte(crc, 0);
209
210 return crc;
211 }
212 */
213
crc_process_byte_parallel(uint16_t crc,uint8_t byte)214 static inline uint16_t crc_process_byte_parallel(uint16_t crc, uint8_t byte)
215 {
216 uint16_t s = byte ^ (crc >> 8);
217 uint16_t t = s ^ (s >> 4);
218
219 return ((crc << 8) ^
220 t ^
221 (t << 5) ^
222 (t << 12)) & 0xFFFF;
223 }
224
compute_CRC_8bit_fast(const uint8_t * data,int w,int h,int stride,int bit_depth)225 static uint32_t compute_CRC_8bit_fast(const uint8_t* data,int w,int h,int stride, int bit_depth)
226 {
227 raw_hash_data raw_data(w,stride);
228
229 uint16_t crc = 0xFFFF;
230
231 crc = crc_process_byte_parallel(crc, 0);
232 crc = crc_process_byte_parallel(crc, 0);
233
234 for (int y=0; y<h; y++) {
235 raw_hash_data::data_chunk chunk;
236
237 if (bit_depth>8)
238 chunk = raw_data.prepare_16bit(data, y);
239 else
240 chunk = raw_data.prepare_8bit(data, y);
241
242 for(int x=0; x<chunk.len; x++) {
243 crc = crc_process_byte_parallel(crc, chunk.data[x]);
244 }
245 }
246
247 return crc;
248 }
249
250
compute_MD5(uint8_t * data,int w,int h,int stride,uint8_t * result,int bit_depth)251 static void compute_MD5(uint8_t* data,int w,int h,int stride, uint8_t* result, int bit_depth)
252 {
253 MD5_CTX md5;
254 MD5_Init(&md5);
255
256 raw_hash_data raw_data(w,stride);
257
258 for (int y=0; y<h; y++) {
259 raw_hash_data::data_chunk chunk;
260
261 if (bit_depth>8)
262 chunk = raw_data.prepare_16bit(data, y);
263 else
264 chunk = raw_data.prepare_8bit(data, y);
265
266 MD5_Update(&md5, (void*)chunk.data, chunk.len);
267 }
268
269 MD5_Final(result, &md5);
270 }
271
272
process_sei_decoded_picture_hash(const sei_message * sei,de265_image * img)273 static de265_error process_sei_decoded_picture_hash(const sei_message* sei, de265_image* img)
274 {
275 const sei_decoded_picture_hash* seihash = &sei->data.decoded_picture_hash;
276
277 /* Do not check SEI on pictures that are not output.
278 Hash may be wrong, because of a broken link (BLA).
279 This happens, for example in conformance stream RAP_B, where a EOS-NAL
280 appears before a CRA (POC=32). */
281 if (img->PicOutputFlag == false) {
282 return DE265_OK;
283 }
284
285 //write_picture(img);
286
287 int nHashes = img->sps.chroma_format_idc==0 ? 1 : 3;
288 for (int i=0;i<nHashes;i++) {
289 uint8_t* data;
290 int w,h,stride;
291
292 w = img->get_width(i);
293 h = img->get_height(i);
294
295 data = img->get_image_plane(i);
296 stride = img->get_image_stride(i);
297
298 switch (seihash->hash_type) {
299 case sei_decoded_picture_hash_type_MD5:
300 {
301 uint8_t md5[16];
302 compute_MD5(data,w,h,stride,md5, img->get_bit_depth(i));
303
304 /*
305 fprintf(stderr,"computed MD5: ");
306 for (int b=0;b<16;b++) {
307 fprintf(stderr,"%02x", md5[b]);
308 }
309 fprintf(stderr,"\n");
310 */
311
312 for (int b=0;b<16;b++) {
313 if (md5[b] != seihash->md5[i][b]) {
314 fprintf(stderr,"SEI decoded picture MD5 mismatch (POC=%d)\n", img->PicOrderCntVal);
315 return DE265_ERROR_CHECKSUM_MISMATCH;
316 }
317 }
318 }
319 break;
320
321 case sei_decoded_picture_hash_type_CRC:
322 {
323 uint16_t crc = compute_CRC_8bit_fast(data,w,h,stride, img->get_bit_depth(i));
324
325 logtrace(LogSEI,"SEI decoded picture hash: %04x <-[%d]-> decoded picture: %04x\n",
326 seihash->crc[i], i, crc);
327
328 if (crc != seihash->crc[i]) {
329 fprintf(stderr,"SEI decoded picture hash: %04x, decoded picture: %04x (POC=%d)\n",
330 seihash->crc[i], crc, img->PicOrderCntVal);
331 return DE265_ERROR_CHECKSUM_MISMATCH;
332 }
333 }
334 break;
335
336 case sei_decoded_picture_hash_type_checksum:
337 {
338 uint32_t chksum = compute_checksum_8bit(data,w,h,stride, img->get_bit_depth(i));
339
340 if (chksum != seihash->checksum[i]) {
341 fprintf(stderr,"SEI decoded picture hash: %04x, decoded picture: %04x (POC=%d)\n",
342 seihash->checksum[i], chksum, img->PicOrderCntVal);
343 return DE265_ERROR_CHECKSUM_MISMATCH;
344 }
345 }
346 break;
347 }
348 }
349
350 loginfo(LogSEI,"decoded picture hash checked: OK\n");
351 //printf("checked picture %d SEI: OK\n", img->PicOrderCntVal);
352
353 return DE265_OK;
354 }
355
356
read_sei(bitreader * reader,sei_message * sei,bool suffix,const seq_parameter_set * sps)357 de265_error read_sei(bitreader* reader, sei_message* sei, bool suffix, const seq_parameter_set* sps)
358 {
359 int payload_type = 0;
360 for (;;)
361 {
362 int byte = get_bits(reader,8);
363 payload_type += byte;
364 if (byte != 0xFF) { break; }
365 }
366
367 //printf("SEI payload: %d\n",payload_type);
368
369 int payload_size = 0;
370 for (;;)
371 {
372 int byte = get_bits(reader,8);
373 payload_size += byte;
374 if (byte != 0xFF) { break; }
375 }
376
377 sei->payload_type = (enum sei_payload_type)payload_type;
378 sei->payload_size = payload_size;
379
380
381 // --- sei message dispatch
382
383 de265_error err = DE265_OK;
384
385 switch (sei->payload_type) {
386 case sei_payload_type_decoded_picture_hash:
387 err = read_sei_decoded_picture_hash(reader,sei,sps);
388 break;
389
390 default:
391 // TODO: unknown SEI messages are ignored
392 break;
393 }
394
395 return err;
396 }
397
dump_sei(const sei_message * sei,const seq_parameter_set * sps)398 void dump_sei(const sei_message* sei, const seq_parameter_set* sps)
399 {
400 loginfo(LogHeaders,"SEI message: %s\n", sei_type_name(sei->payload_type));
401
402 switch (sei->payload_type) {
403 case sei_payload_type_decoded_picture_hash:
404 dump_sei_decoded_picture_hash(sei, sps);
405 break;
406
407 default:
408 // TODO: unknown SEI messages are ignored
409 break;
410 }
411 }
412
413
process_sei(const sei_message * sei,de265_image * img)414 de265_error process_sei(const sei_message* sei, de265_image* img)
415 {
416 de265_error err = DE265_OK;
417
418 switch (sei->payload_type) {
419 case sei_payload_type_decoded_picture_hash:
420 if (img->decctx->param_sei_check_hash) {
421 err = process_sei_decoded_picture_hash(sei, img);
422 if (err==DE265_OK) {
423 //printf("SEI check ok\n");
424 }
425 }
426
427 break;
428
429 default:
430 // TODO: unknown SEI messages are ignored
431 break;
432 }
433
434 return err;
435 }
436
437
sei_type_name(enum sei_payload_type type)438 const char* sei_type_name(enum sei_payload_type type)
439 {
440 switch (type) {
441 case sei_payload_type_buffering_period:
442 return "buffering_period";
443 case sei_payload_type_pic_timing:
444 return "pic_timing";
445 case sei_payload_type_pan_scan_rect:
446 return "pan_scan_rect";
447 case sei_payload_type_filler_payload:
448 return "filler_payload";
449 case sei_payload_type_user_data_registered_itu_t_t35:
450 return "user_data_registered_itu_t_t35";
451 case sei_payload_type_user_data_unregistered:
452 return "user_data_unregistered";
453 case sei_payload_type_recovery_point:
454 return "recovery_point";
455 case sei_payload_type_scene_info:
456 return "scene_info";
457 case sei_payload_type_picture_snapshot:
458 return "picture_snapshot";
459 case sei_payload_type_progressive_refinement_segment_start:
460 return "progressive_refinement_segment_start";
461 case sei_payload_type_progressive_refinement_segment_end:
462 return "progressive_refinement_segment_end";
463 case sei_payload_type_film_grain_characteristics:
464 return "film_grain_characteristics";
465 case sei_payload_type_post_filter_hint:
466 return "post_filter_hint";
467 case sei_payload_type_tone_mapping_info:
468 return "tone_mapping_info";
469 case sei_payload_type_frame_packing_arrangement:
470 return "frame_packing_arrangement";
471 case sei_payload_type_display_orientation:
472 return "display_orientation";
473 case sei_payload_type_structure_of_pictures_info:
474 return "structure_of_pictures_info";
475 case sei_payload_type_active_parameter_sets:
476 return "active_parameter_sets";
477 case sei_payload_type_decoding_unit_info:
478 return "decoding_unit_info";
479 case sei_payload_type_temporal_sub_layer_zero_index:
480 return "temporal_sub_layer_zero_index";
481 case sei_payload_type_decoded_picture_hash:
482 return "decoded_picture_hash";
483 case sei_payload_type_scalable_nesting:
484 return "scalable_nesting";
485 case sei_payload_type_region_refresh_info:
486 return "region_refresh_info";
487 case sei_payload_type_no_display:
488 return "no_display";
489 case sei_payload_type_motion_constrained_tile_sets:
490 return "motion_constrained_tile_sets";
491
492 default:
493 return "unknown SEI message";
494 }
495 }
496