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