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 #ifndef DE265_IMAGE_H 22 #define DE265_IMAGE_H 23 24 #ifdef HAVE_CONFIG_H 25 #include <config.h> 26 #endif 27 28 #include <assert.h> 29 #include <stdint.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #ifdef HAVE_STDBOOL_H 33 #include <stdbool.h> 34 #endif 35 #include "libde265/de265.h" 36 #include "libde265/en265.h" 37 #include "libde265/sps.h" 38 #include "libde265/pps.h" 39 #include "libde265/motion.h" 40 #include "libde265/threads.h" 41 #include "libde265/slice.h" 42 #include "libde265/nal.h" 43 44 enum PictureState { 45 UnusedForReference, 46 UsedForShortTermReference, 47 UsedForLongTermReference 48 }; 49 50 51 /* TODO: 52 At INTEGRITY_DERIVED_FROM_FAULTY_REFERENCE images, we can check the SEI hash, whether 53 the output image is correct despite the faulty reference, and set the state back to correct. 54 */ 55 #define INTEGRITY_CORRECT 0 56 #define INTEGRITY_UNAVAILABLE_REFERENCE 1 57 #define INTEGRITY_NOT_DECODED 2 58 #define INTEGRITY_DECODING_ERRORS 3 59 #define INTEGRITY_DERIVED_FROM_FAULTY_REFERENCE 4 60 61 #define SEI_HASH_UNCHECKED 0 62 #define SEI_HASH_CORRECT 1 63 #define SEI_HASH_INCORRECT 2 64 65 #define TU_FLAG_NONZERO_COEFF (1<<7) 66 #define TU_FLAG_SPLIT_TRANSFORM_MASK 0x1F 67 68 #define DEBLOCK_FLAG_VERTI (1<<4) 69 #define DEBLOCK_FLAG_HORIZ (1<<5) 70 #define DEBLOCK_PB_EDGE_VERTI (1<<6) 71 #define DEBLOCK_PB_EDGE_HORIZ (1<<7) 72 #define DEBLOCK_BS_MASK 0x03 73 74 75 #define CTB_PROGRESS_NONE 0 76 #define CTB_PROGRESS_PREFILTER 1 77 #define CTB_PROGRESS_DEBLK_V 2 78 #define CTB_PROGRESS_DEBLK_H 3 79 #define CTB_PROGRESS_SAO 4 80 81 class decoder_context; 82 83 template <class DataUnit> class MetaDataArray 84 { 85 public: MetaDataArray()86 MetaDataArray() { data=NULL; data_size=0; log2unitSize=0; width_in_units=0; height_in_units=0; } ~MetaDataArray()87 ~MetaDataArray() { free(data); } 88 alloc(int w,int h,int _log2unitSize)89 LIBDE265_CHECK_RESULT bool alloc(int w,int h, int _log2unitSize) { 90 int size = w*h; 91 92 if (size != data_size) { 93 free(data); 94 data = (DataUnit*)malloc(size * sizeof(DataUnit)); 95 if (data == NULL) { 96 data_size = 0; 97 return false; 98 } 99 data_size = size; 100 } 101 102 width_in_units = w; 103 height_in_units = h; 104 105 log2unitSize = _log2unitSize; 106 107 return data != NULL; 108 } 109 clear()110 void clear() { 111 if (data) memset(data, 0, sizeof(DataUnit) * data_size); 112 } 113 get(int x,int y)114 const DataUnit& get(int x,int y) const { 115 int unitX = x>>log2unitSize; 116 int unitY = y>>log2unitSize; 117 118 assert(unitX >= 0 && unitX < width_in_units); 119 assert(unitY >= 0 && unitY < height_in_units); 120 121 return data[ unitX + unitY*width_in_units ]; 122 } 123 get(int x,int y)124 DataUnit& get(int x,int y) { 125 int unitX = x>>log2unitSize; 126 int unitY = y>>log2unitSize; 127 128 assert(unitX >= 0 && unitX < width_in_units); 129 assert(unitY >= 0 && unitY < height_in_units); 130 131 return data[ unitX + unitY*width_in_units ]; 132 } 133 set(int x,int y,const DataUnit & d)134 void set(int x,int y, const DataUnit& d) { 135 int unitX = x>>log2unitSize; 136 int unitY = y>>log2unitSize; 137 138 assert(unitX >= 0 && unitX < width_in_units); 139 assert(unitY >= 0 && unitY < height_in_units); 140 141 data[ unitX + unitY*width_in_units ] = d; 142 } 143 144 DataUnit& operator[](int idx) { return data[idx]; } 145 const DataUnit& operator[](int idx) const { return data[idx]; } 146 size()147 int size() const { return data_size; } 148 149 // private: 150 DataUnit* data; 151 int data_size; 152 int log2unitSize; 153 int width_in_units; 154 int height_in_units; 155 }; 156 157 #define SET_CB_BLK(x,y,log2BlkWidth, Field,value) \ 158 int cbX = x >> cb_info.log2unitSize; \ 159 int cbY = y >> cb_info.log2unitSize; \ 160 int width = 1 << (log2BlkWidth - cb_info.log2unitSize); \ 161 for (int cby=cbY;cby<cbY+width;cby++) \ 162 for (int cbx=cbX;cbx<cbX+width;cbx++) \ 163 { \ 164 cb_info[ cbx + cby*cb_info.width_in_units ].Field = value; \ 165 } 166 167 #define CLEAR_TB_BLK(x,y,log2BlkWidth) \ 168 int tuX = x >> tu_info.log2unitSize; \ 169 int tuY = y >> tu_info.log2unitSize; \ 170 int width = 1 << (log2BlkWidth - tu_info.log2unitSize); \ 171 for (int tuy=tuY;tuy<tuY+width;tuy++) \ 172 for (int tux=tuX;tux<tuX+width;tux++) \ 173 { \ 174 tu_info[ tux + tuy*tu_info.width_in_units ] = 0; \ 175 } 176 177 178 typedef struct { 179 uint16_t SliceAddrRS; 180 uint16_t SliceHeaderIndex; // index into array to slice header for this CTB 181 182 sao_info saoInfo; 183 bool deblock; // this CTB has to be deblocked 184 185 // The following flag helps to quickly check whether we have to 186 // check all conditions in the SAO filter or whether we can skip them. 187 bool has_pcm_or_cu_transquant_bypass; // pcm or transquant_bypass is used in this CTB 188 } CTB_info; 189 190 191 typedef struct { 192 uint8_t log2CbSize : 3; /* [0;6] (1<<log2CbSize) = 64 193 This is only set in the top-left corner of the CB. 194 The other values should be zero. 195 TODO: in the encoder, we have to clear to zero. 196 Used in deblocking and QP-scale decoding */ 197 uint8_t PartMode : 3; // (enum PartMode) [0;7] set only in top-left of CB 198 // Used for spatial merging candidates in current frame 199 // and for deriving interSplitFlag in decoding. 200 201 uint8_t ctDepth : 2; // [0:3]? (for CTB size 64: 0:64, 1:32, 2:16, 3:8) 202 // Used for decoding/encoding split_cu flag. 203 204 // --- byte boundary --- 205 uint8_t PredMode : 2; // (enum PredMode) [0;2] must be saved for past images 206 // Used in motion decoding. 207 uint8_t pcm_flag : 1; // Stored for intra-prediction / SAO 208 uint8_t cu_transquant_bypass : 1; // Stored for SAO 209 // note: 4 bits left 210 211 // --- byte boundary --- 212 int8_t QP_Y; // Stored for QP prediction 213 214 } CB_ref_info; 215 216 217 typedef struct { 218 MotionVectorSpec mv; // TODO: this can be done in 16x16 grid 219 } PB_ref_info; 220 221 // intraPredMode: Used for determining scanIdx when decoding/encoding coefficients. 222 223 224 225 struct de265_image { 226 de265_image(); 227 ~de265_image(); 228 229 230 de265_error alloc_image(int w,int h, enum de265_chroma c, 231 const seq_parameter_set* sps, 232 bool allocMetadata, 233 decoder_context* dctx, 234 class encoder_context* ectx, 235 de265_PTS pts, void* user_data, 236 bool useCustomAllocFunctions); 237 238 //de265_error alloc_encoder_data(const seq_parameter_set* sps); 239 is_allocatedde265_image240 bool is_allocated() const { return pixels[0] != NULL; } 241 242 void release(); 243 244 void fill_image(int y,int u,int v); 245 de265_error copy_image(const de265_image* src); 246 void copy_lines_from(const de265_image* src, int first, int end); 247 void exchange_pixel_data_with(de265_image&); 248 get_IDde265_image249 uint32_t get_ID() const { return ID; } 250 251 get_image_planede265_image252 /* */ uint8_t* get_image_plane(int cIdx) { return pixels[cIdx]; } get_image_planede265_image253 const uint8_t* get_image_plane(int cIdx) const { return pixels[cIdx]; } 254 255 void set_image_plane(int cIdx, uint8_t* mem, int stride, void *userdata); 256 get_image_plane_at_posde265_image257 uint8_t* get_image_plane_at_pos(int cIdx, int xpos,int ypos) 258 { 259 int stride = get_image_stride(cIdx); 260 return pixels[cIdx] + xpos + ypos*stride; 261 } 262 263 264 /// xpos;ypos in actual plane resolution 265 template <class pixel_t> get_image_plane_at_pos_NEWde265_image266 pixel_t* get_image_plane_at_pos_NEW(int cIdx, int xpos,int ypos) 267 { 268 int stride = get_image_stride(cIdx); 269 return (pixel_t*)(pixels[cIdx] + (xpos + ypos*stride)*sizeof(pixel_t)); 270 } 271 get_image_plane_at_posde265_image272 const uint8_t* get_image_plane_at_pos(int cIdx, int xpos,int ypos) const 273 { 274 int stride = get_image_stride(cIdx); 275 return pixels[cIdx] + xpos + ypos*stride; 276 } 277 get_image_plane_at_pos_any_depthde265_image278 void* get_image_plane_at_pos_any_depth(int cIdx, int xpos,int ypos) 279 { 280 int stride = get_image_stride(cIdx); 281 return pixels[cIdx] + ((xpos + ypos*stride) << bpp_shift[cIdx]); 282 } 283 get_image_plane_at_pos_any_depthde265_image284 const void* get_image_plane_at_pos_any_depth(int cIdx, int xpos,int ypos) const 285 { 286 int stride = get_image_stride(cIdx); 287 return pixels[cIdx] + ((xpos + ypos*stride) << bpp_shift[cIdx]); 288 } 289 290 /* Number of pixels in one row (not number of bytes). 291 */ get_image_stridede265_image292 int get_image_stride(int cIdx) const 293 { 294 if (cIdx==0) return stride; 295 else return chroma_stride; 296 } 297 get_luma_stridede265_image298 int get_luma_stride() const { return stride; } get_chroma_stridede265_image299 int get_chroma_stride() const { return chroma_stride; } 300 301 int get_width (int cIdx=0) const { return cIdx==0 ? width : chroma_width; } 302 int get_height(int cIdx=0) const { return cIdx==0 ? height : chroma_height; } 303 get_chroma_formatde265_image304 enum de265_chroma get_chroma_format() const { return chroma_format; } 305 get_bit_depthde265_image306 int get_bit_depth(int cIdx) const { 307 if (cIdx==0) return sps.BitDepth_Y; 308 else return sps.BitDepth_C; 309 } 310 get_bytes_per_pixelde265_image311 int get_bytes_per_pixel(int cIdx) const { 312 return (get_bit_depth(cIdx)+7)/8; 313 } 314 high_bit_depthde265_image315 bool high_bit_depth(int cIdx) const { 316 return get_bit_depth(cIdx)>8; 317 } 318 can_be_releasedde265_image319 bool can_be_released() const { return PicOutputFlag==false && PicState==UnusedForReference; } 320 321 add_slice_segment_headerde265_image322 void add_slice_segment_header(slice_segment_header* shdr) { 323 shdr->slice_index = slices.size(); 324 slices.push_back(shdr); 325 } 326 327 328 bool available_zscan(int xCurr,int yCurr, int xN,int yN) const; 329 330 bool available_pred_blk(int xC,int yC, int nCbS, 331 int xP, int yP, int nPbW, int nPbH, int partIdx, 332 int xN,int yN) const; 333 334 335 static de265_image_allocation default_image_allocation; 336 printBlkde265_image337 void printBlk(const char* title, int x0,int y0,int blkSize,int cIdx) const { 338 ::printBlk(title, get_image_plane_at_pos(cIdx,x0,y0), 339 blkSize, get_image_stride(cIdx)); 340 } 341 342 private: 343 uint32_t ID; 344 static uint32_t s_next_image_ID; 345 346 uint8_t* pixels[3]; 347 uint8_t bpp_shift[3]; // 0 for 8 bit, 1 for 16 bit 348 349 enum de265_chroma chroma_format; 350 351 int width, height; // size in luma pixels 352 353 int chroma_width, chroma_height; 354 int stride, chroma_stride; 355 356 public: 357 std::vector<slice_segment_header*> slices; 358 359 public: 360 361 // --- conformance cropping window --- 362 363 uint8_t* pixels_confwin[3]; // pointer to pixels in the conformance window 364 365 int width_confwin, height_confwin; 366 int chroma_width_confwin, chroma_height_confwin; 367 368 // --- decoding info --- 369 370 // If PicOutputFlag==false && PicState==UnusedForReference, image buffer is free. 371 372 int picture_order_cnt_lsb; 373 int PicOrderCntVal; 374 enum PictureState PicState; 375 bool PicOutputFlag; 376 377 int32_t removed_at_picture_id; 378 379 video_parameter_set vps; 380 seq_parameter_set sps; // the SPS used for decoding this image 381 pic_parameter_set pps; // the PPS used for decoding this image 382 decoder_context* decctx; 383 class encoder_context* encctx; 384 number_of_ctbsde265_image385 int number_of_ctbs() const { return ctb_info.size(); } 386 387 private: 388 MetaDataArray<CTB_info> ctb_info; 389 MetaDataArray<CB_ref_info> cb_info; 390 MetaDataArray<PB_ref_info> pb_info; 391 MetaDataArray<uint8_t> intraPredMode; 392 MetaDataArray<uint8_t> intraPredModeC; 393 MetaDataArray<uint8_t> tu_info; 394 MetaDataArray<uint8_t> deblk_info; 395 396 public: 397 // --- meta information --- 398 399 de265_PTS pts; 400 void* user_data; 401 void* plane_user_data[3]; // this is logically attached to the pixel data pointers 402 de265_image_allocation image_allocation_functions; // the functions used for memory allocation 403 void (*encoder_image_release_func)(en265_encoder_context*, 404 de265_image*, 405 void* userdata); 406 407 uint8_t integrity; /* Whether an error occured while the image was decoded. 408 When generated, this is initialized to INTEGRITY_CORRECT, 409 and changed on decoding errors. 410 */ 411 bool sei_hash_check_result; 412 413 nal_header nal_hdr; 414 415 // --- multi core --- 416 417 de265_progress_lock* ctb_progress; // ctb_info_size 418 mark_all_CTB_progressde265_image419 void mark_all_CTB_progress(int progress) { 420 for (int i=0;i<ctb_info.data_size;i++) { 421 ctb_progress[i].set_progress(progress); 422 } 423 } 424 425 426 void thread_start(int nThreads); 427 void thread_run(const thread_task*); 428 void thread_blocks(); 429 void thread_unblocks(); 430 /* NOTE: you should not access any data in the thread_task after 431 calling this, as this function may unlock other threads that 432 will push this image to the output queue and free all decoder data. */ 433 void thread_finishes(const thread_task*); 434 435 void wait_for_progress(thread_task* task, int ctbx,int ctby, int progress); 436 void wait_for_progress(thread_task* task, int ctbAddrRS, int progress); 437 438 void wait_for_completion(); // block until image is decoded by background threads 439 bool debug_is_completed() const; num_threads_activede265_image440 int num_threads_active() const { return nThreadsRunning + nThreadsBlocked; } // for debug only 441 442 //private: 443 int nThreadsQueued; 444 int nThreadsRunning; 445 int nThreadsBlocked; 446 int nThreadsFinished; 447 int nThreadsTotal; 448 449 // ALIGNED_8(de265_sync_int tasks_pending); // number of tasks pending to complete decoding 450 de265_mutex mutex; 451 de265_cond finished_cond; 452 453 public: 454 455 /* Clear all CTB/CB/PB decoding data of this image. 456 All CTB's processing states are set to 'unprocessed'. 457 */ 458 void clear_metadata(); 459 460 461 // --- CB metadata access --- 462 set_pred_modede265_image463 void set_pred_mode(int x,int y, int log2BlkWidth, enum PredMode mode) 464 { 465 SET_CB_BLK(x,y,log2BlkWidth, PredMode, mode); 466 } 467 fill_pred_modede265_image468 void fill_pred_mode(enum PredMode mode) 469 { 470 for (int i=0;i<cb_info.data_size;i++) 471 { cb_info[i].PredMode = MODE_INTRA; } 472 } 473 get_pred_modede265_image474 enum PredMode get_pred_mode(int x,int y) const 475 { 476 return (enum PredMode)cb_info.get(x,y).PredMode; 477 } 478 get_cu_skip_flagde265_image479 uint8_t get_cu_skip_flag(int x,int y) const 480 { 481 return get_pred_mode(x,y)==MODE_SKIP; 482 } 483 484 void set_pcm_flag(int x,int y, int log2BlkWidth, uint8_t value=1) 485 { 486 SET_CB_BLK(x,y,log2BlkWidth, pcm_flag, value); 487 488 // TODO: in the encoder, we somewhere have to clear this 489 ctb_info.get(x,y).has_pcm_or_cu_transquant_bypass = true; 490 } 491 get_pcm_flagde265_image492 int get_pcm_flag(int x,int y) const 493 { 494 return cb_info.get(x,y).pcm_flag; 495 } 496 497 void set_cu_transquant_bypass(int x,int y, int log2BlkWidth, uint8_t value=1) 498 { 499 SET_CB_BLK(x,y,log2BlkWidth, cu_transquant_bypass, value); 500 501 // TODO: in the encoder, we somewhere have to clear this 502 ctb_info.get(x,y).has_pcm_or_cu_transquant_bypass = true; 503 } 504 get_cu_transquant_bypassde265_image505 int get_cu_transquant_bypass(int x,int y) const 506 { 507 return cb_info.get(x,y).cu_transquant_bypass; 508 } 509 set_log2CbSizede265_image510 void set_log2CbSize(int x0, int y0, int log2CbSize, bool fill) 511 { 512 // In theory, we could assume that remaining cb_info blocks are initialized to zero. 513 // But in corrupted streams, slices may overlap and set contradicting log2CbSizes. 514 // We also need this for encoding. 515 if (fill) { 516 SET_CB_BLK(x0,y0,log2CbSize, log2CbSize, 0); 517 } 518 519 cb_info.get(x0,y0).log2CbSize = log2CbSize; 520 } 521 get_log2CbSizede265_image522 int get_log2CbSize(int x0, int y0) const 523 { 524 return (enum PredMode)cb_info.get(x0,y0).log2CbSize; 525 } 526 527 // coordinates in CB units get_log2CbSize_cbUnitsde265_image528 int get_log2CbSize_cbUnits(int xCb, int yCb) const 529 { 530 return (enum PredMode)cb_info[ xCb + yCb*cb_info.width_in_units ].log2CbSize; 531 } 532 set_PartModede265_image533 void set_PartMode(int x,int y, enum PartMode mode) 534 { 535 cb_info.get(x,y).PartMode = mode; 536 } 537 get_PartModede265_image538 enum PartMode get_PartMode(int x,int y) const 539 { 540 return (enum PartMode)cb_info.get(x,y).PartMode; 541 } 542 set_ctDepthde265_image543 void set_ctDepth(int x,int y, int log2BlkWidth, int depth) 544 { 545 SET_CB_BLK(x,y,log2BlkWidth, ctDepth, depth); 546 } 547 get_ctDepthde265_image548 int get_ctDepth(int x,int y) const 549 { 550 return cb_info.get(x,y).ctDepth; 551 } 552 set_QPYde265_image553 void set_QPY(int x,int y, int log2BlkWidth, int QP_Y) 554 { 555 SET_CB_BLK (x, y, log2BlkWidth, QP_Y, QP_Y); 556 } 557 get_QPYde265_image558 int get_QPY(int x0,int y0) const 559 { 560 return cb_info.get(x0,y0).QP_Y; 561 } 562 563 // --- TU metadata access --- 564 set_split_transform_flagde265_image565 void set_split_transform_flag(int x0,int y0,int trafoDepth) 566 { 567 tu_info.get(x0,y0) |= (1<<trafoDepth); 568 } 569 clear_split_transform_flagsde265_image570 void clear_split_transform_flags(int x0,int y0,int log2CbSize) 571 { 572 CLEAR_TB_BLK (x0,y0, log2CbSize); 573 } 574 get_split_transform_flagde265_image575 int get_split_transform_flag(int x0,int y0,int trafoDepth) const 576 { 577 return (tu_info.get(x0,y0) & (1<<trafoDepth)); 578 } 579 set_nonzero_coefficientde265_image580 void set_nonzero_coefficient(int x,int y, int log2TrafoSize) 581 { 582 const int tuX = x >> tu_info.log2unitSize; 583 const int tuY = y >> tu_info.log2unitSize; 584 const int width = 1 << (log2TrafoSize - tu_info.log2unitSize); 585 586 for (int tuy=tuY;tuy<tuY+width;tuy++) 587 for (int tux=tuX;tux<tuX+width;tux++) 588 { 589 tu_info[ tux + tuy*tu_info.width_in_units ] |= TU_FLAG_NONZERO_COEFF; 590 } 591 } 592 get_nonzero_coefficientde265_image593 int get_nonzero_coefficient(int x,int y) const 594 { 595 return tu_info.get(x,y) & TU_FLAG_NONZERO_COEFF; 596 } 597 598 599 // --- intraPredMode metadata access --- 600 get_IntraPredModede265_image601 enum IntraPredMode get_IntraPredMode(int x,int y) const 602 { 603 return (enum IntraPredMode)intraPredMode.get(x,y); 604 } 605 get_IntraPredMode_atIndexde265_image606 enum IntraPredMode get_IntraPredMode_atIndex(int idx) const 607 { 608 return (enum IntraPredMode)intraPredMode[idx]; 609 } 610 set_IntraPredModede265_image611 void set_IntraPredMode(int PUidx,int log2blkSize, enum IntraPredMode mode) 612 { 613 int pbSize = 1<<(log2blkSize - intraPredMode.log2unitSize); 614 615 for (int y=0;y<pbSize;y++) 616 for (int x=0;x<pbSize;x++) 617 intraPredMode[PUidx + x + y*intraPredMode.width_in_units] = mode; 618 } 619 set_IntraPredModede265_image620 void set_IntraPredMode(int x0,int y0,int log2blkSize, 621 enum IntraPredMode mode) 622 { 623 int pbSize = 1<<(log2blkSize - intraPredMode.log2unitSize); 624 int PUidx = (x0>>sps.Log2MinPUSize) + (y0>>sps.Log2MinPUSize)*sps.PicWidthInMinPUs; 625 626 for (int y=0;y<pbSize;y++) 627 for (int x=0;x<pbSize;x++) { 628 assert(x<sps.PicWidthInMinPUs); 629 assert(y<sps.PicHeightInMinPUs); 630 631 int idx = PUidx + x + y*intraPredMode.width_in_units; 632 assert(idx<intraPredMode.data_size); 633 intraPredMode[idx] = mode; 634 } 635 } 636 637 get_IntraPredModeCde265_image638 enum IntraPredMode get_IntraPredModeC(int x,int y) const 639 { 640 return (enum IntraPredMode)(intraPredModeC.get(x,y) & 0x3f); 641 } 642 is_IntraPredModeC_Mode4de265_image643 bool is_IntraPredModeC_Mode4(int x,int y) const 644 { 645 return intraPredModeC.get(x,y) & 0x80; 646 } 647 set_IntraPredModeCde265_image648 void set_IntraPredModeC(int x0,int y0,int log2blkSize, enum IntraPredMode mode, 649 bool is_mode4) 650 { 651 uint8_t combinedValue = mode; 652 if (is_mode4) combinedValue |= 0x80; 653 654 int pbSize = 1<<(log2blkSize - intraPredMode.log2unitSize); 655 int PUidx = (x0>>sps.Log2MinPUSize) + (y0>>sps.Log2MinPUSize)*sps.PicWidthInMinPUs; 656 657 for (int y=0;y<pbSize;y++) 658 for (int x=0;x<pbSize;x++) { 659 assert(x<sps.PicWidthInMinPUs); 660 assert(y<sps.PicHeightInMinPUs); 661 662 int idx = PUidx + x + y*intraPredModeC.width_in_units; 663 assert(idx<intraPredModeC.data_size); 664 intraPredModeC[idx] = combinedValue; 665 } 666 } 667 668 669 /* 670 // NOTE: encoder only 671 void set_ChromaIntraPredMode(int x,int y,int log2BlkWidth, enum IntraChromaPredMode mode) 672 { 673 SET_CB_BLK (x, y, log2BlkWidth, intra_chroma_pred_mode, mode); 674 } 675 676 // NOTE: encoder only 677 enum IntraChromaPredMode get_ChromaIntraPredMode(int x,int y) const 678 { 679 return (enum IntraChromaPredMode)(cb_info.get(x,y).intra_chroma_pred_mode); 680 } 681 */ 682 683 // --- CTB metadata access --- 684 685 // address of first CTB in slice set_SliceAddrRSde265_image686 void set_SliceAddrRS(int ctbX, int ctbY, int SliceAddrRS) 687 { 688 int idx = ctbX + ctbY*ctb_info.width_in_units; 689 ctb_info[idx].SliceAddrRS = SliceAddrRS; 690 } 691 get_SliceAddrRSde265_image692 int get_SliceAddrRS(int ctbX, int ctbY) const 693 { 694 return ctb_info[ctbX + ctbY*ctb_info.width_in_units].SliceAddrRS; 695 } 696 get_SliceAddrRS_atCtbRSde265_image697 int get_SliceAddrRS_atCtbRS(int ctbRS) const 698 { 699 return ctb_info[ctbRS].SliceAddrRS; 700 } 701 702 set_SliceHeaderIndexde265_image703 void set_SliceHeaderIndex(int x, int y, int SliceHeaderIndex) 704 { 705 ctb_info.get(x,y).SliceHeaderIndex = SliceHeaderIndex; 706 } 707 get_SliceHeaderIndexde265_image708 int get_SliceHeaderIndex(int x, int y) const 709 { 710 return ctb_info.get(x,y).SliceHeaderIndex; 711 } 712 get_SliceHeaderIndexCtbde265_image713 int get_SliceHeaderIndexCtb(int ctbX, int ctbY) const 714 { 715 return ctb_info[ctbX + ctbY*ctb_info.width_in_units].SliceHeaderIndex; 716 } 717 get_SliceHeaderIndex_atIndexde265_image718 int get_SliceHeaderIndex_atIndex(int ctb) const 719 { 720 return ctb_info[ctb].SliceHeaderIndex; 721 } 722 is_SliceHeader_availablede265_image723 bool is_SliceHeader_available(int x,int y) const 724 { 725 int idx = ctb_info.get(x,y).SliceHeaderIndex; 726 return idx >= 0 && idx < slices.size(); 727 } 728 get_SliceHeaderde265_image729 slice_segment_header* get_SliceHeader(int x, int y) 730 { 731 int idx = get_SliceHeaderIndex(x,y); 732 if (idx >= slices.size()) { return NULL; } 733 return slices[idx]; 734 } 735 get_SliceHeaderCtbde265_image736 slice_segment_header* get_SliceHeaderCtb(int ctbX, int ctbY) 737 { 738 int idx = get_SliceHeaderIndexCtb(ctbX,ctbY); 739 if (idx >= slices.size()) { return NULL; } 740 return slices[idx]; 741 } 742 get_SliceHeaderCtbde265_image743 const slice_segment_header* get_SliceHeaderCtb(int ctbX, int ctbY) const 744 { 745 int idx = get_SliceHeaderIndexCtb(ctbX,ctbY); 746 if (idx >= slices.size()) { return NULL; } 747 return slices[idx]; 748 } 749 set_sao_infode265_image750 void set_sao_info(int ctbX,int ctbY,const sao_info* saoinfo) 751 { 752 sao_info* sao = &ctb_info[ctbX + ctbY*ctb_info.width_in_units].saoInfo; 753 754 memcpy(sao, 755 saoinfo, 756 sizeof(sao_info)); 757 } 758 get_sao_infode265_image759 const sao_info* get_sao_info(int ctbX,int ctbY) const 760 { 761 return &ctb_info[ctbX + ctbY*ctb_info.width_in_units].saoInfo; 762 } 763 764 set_CtbDeblockFlagde265_image765 void set_CtbDeblockFlag(int ctbX, int ctbY, bool flag) 766 { 767 int idx = ctbX + ctbY*ctb_info.width_in_units; 768 ctb_info[idx].deblock = flag; 769 } 770 get_CtbDeblockFlagde265_image771 bool get_CtbDeblockFlag(int ctbX, int ctbY) const 772 { 773 return ctb_info[ctbX + ctbY*ctb_info.width_in_units].deblock; 774 } 775 776 get_CTB_has_pcm_or_cu_transquant_bypassde265_image777 bool get_CTB_has_pcm_or_cu_transquant_bypass(int ctbX,int ctbY) const 778 { 779 int idx = ctbX + ctbY*ctb_info.width_in_units; 780 return ctb_info[idx].has_pcm_or_cu_transquant_bypass; 781 } 782 783 784 785 // --- DEBLK metadata access --- 786 get_deblk_widthde265_image787 int get_deblk_width() const { return deblk_info.width_in_units; } get_deblk_heightde265_image788 int get_deblk_height() const { return deblk_info.height_in_units; } 789 set_deblk_flagsde265_image790 void set_deblk_flags(int x0,int y0, uint8_t flags) 791 { 792 const int xd = x0/4; 793 const int yd = y0/4; 794 795 if (xd<deblk_info.width_in_units && 796 yd<deblk_info.height_in_units) { 797 deblk_info[xd + yd*deblk_info.width_in_units] |= flags; 798 } 799 } 800 get_deblk_flagsde265_image801 uint8_t get_deblk_flags(int x0,int y0) const 802 { 803 const int xd = x0/4; 804 const int yd = y0/4; 805 806 return deblk_info[xd + yd*deblk_info.width_in_units]; 807 } 808 set_deblk_bSde265_image809 void set_deblk_bS(int x0,int y0, uint8_t bS) 810 { 811 uint8_t* data = &deblk_info[x0/4 + y0/4*deblk_info.width_in_units]; 812 *data &= ~DEBLOCK_BS_MASK; 813 *data |= bS; 814 } 815 get_deblk_bSde265_image816 uint8_t get_deblk_bS(int x0,int y0) const 817 { 818 return deblk_info[x0/4 + y0/4*deblk_info.width_in_units] & DEBLOCK_BS_MASK; 819 } 820 821 822 // --- PB metadata access --- 823 get_mv_infode265_image824 const MotionVectorSpec* get_mv_info(int x,int y) const 825 { 826 return &pb_info.get(x,y).mv; 827 } 828 829 void set_mv_info(int x,int y, int nPbW,int nPbH, const MotionVectorSpec& mv); 830 831 // --- value logging --- 832 833 void printBlk(int x0,int y0, int cIdx, int log2BlkSize); 834 }; 835 836 837 #endif 838