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 #include <memory>
33 #ifdef HAVE_STDBOOL_H
34 #include <stdbool.h>
35 #endif
36 
37 #include "libde265/de265.h"
38 #include "libde265/sps.h"
39 #include "libde265/pps.h"
40 #include "libde265/motion.h"
41 #include "libde265/threads.h"
42 #include "libde265/slice.h"
43 #include "libde265/nal.h"
44 
45 struct en265_encoder_context;
46 
47 enum PictureState {
48   UnusedForReference,
49   UsedForShortTermReference,
50   UsedForLongTermReference
51 };
52 
53 
54 /* TODO:
55    At INTEGRITY_DERIVED_FROM_FAULTY_REFERENCE images, we can check the SEI hash, whether
56    the output image is correct despite the faulty reference, and set the state back to correct.
57 */
58 #define INTEGRITY_CORRECT 0
59 #define INTEGRITY_UNAVAILABLE_REFERENCE 1
60 #define INTEGRITY_NOT_DECODED 2
61 #define INTEGRITY_DECODING_ERRORS 3
62 #define INTEGRITY_DERIVED_FROM_FAULTY_REFERENCE 4
63 
64 #define SEI_HASH_UNCHECKED 0
65 #define SEI_HASH_CORRECT   1
66 #define SEI_HASH_INCORRECT 2
67 
68 #define TU_FLAG_NONZERO_COEFF  (1<<7)
69 #define TU_FLAG_SPLIT_TRANSFORM_MASK  0x1F
70 
71 #define DEBLOCK_FLAG_VERTI (1<<4)
72 #define DEBLOCK_FLAG_HORIZ (1<<5)
73 #define DEBLOCK_PB_EDGE_VERTI (1<<6)
74 #define DEBLOCK_PB_EDGE_HORIZ (1<<7)
75 #define DEBLOCK_BS_MASK     0x03
76 
77 
78 #define CTB_PROGRESS_NONE      0
79 #define CTB_PROGRESS_PREFILTER 1
80 #define CTB_PROGRESS_DEBLK_V   2
81 #define CTB_PROGRESS_DEBLK_H   3
82 #define CTB_PROGRESS_SAO       4
83 
84 class decoder_context;
85 
86 template <class DataUnit> class MetaDataArray
87 {
88  public:
MetaDataArray()89   MetaDataArray() { data=NULL; data_size=0; log2unitSize=0; width_in_units=0; height_in_units=0; }
~MetaDataArray()90   ~MetaDataArray() { free(data); }
91 
alloc(int w,int h,int _log2unitSize)92   LIBDE265_CHECK_RESULT bool alloc(int w,int h, int _log2unitSize) {
93     int size = w*h;
94 
95     if (size != data_size) {
96       free(data);
97       data = (DataUnit*)malloc(size * sizeof(DataUnit));
98       if (data == NULL) {
99         data_size = 0;
100         return false;
101       }
102       data_size = size;
103     }
104 
105     width_in_units = w;
106     height_in_units = h;
107 
108     log2unitSize = _log2unitSize;
109 
110     return data != NULL;
111   }
112 
clear()113   void clear() {
114     if (data) memset(data, 0, sizeof(DataUnit) * data_size);
115   }
116 
get(int x,int y)117   const DataUnit& get(int x,int y) const {
118     int unitX = x>>log2unitSize;
119     int unitY = y>>log2unitSize;
120 
121     assert(unitX >= 0 && unitX < width_in_units);
122     assert(unitY >= 0 && unitY < height_in_units);
123 
124     return data[ unitX + unitY*width_in_units ];
125   }
126 
get(int x,int y)127   DataUnit& get(int x,int y) {
128     int unitX = x>>log2unitSize;
129     int unitY = y>>log2unitSize;
130 
131     assert(unitX >= 0 && unitX < width_in_units);
132     assert(unitY >= 0 && unitY < height_in_units);
133 
134     return data[ unitX + unitY*width_in_units ];
135   }
136 
set(int x,int y,const DataUnit & d)137   void set(int x,int y, const DataUnit& d) {
138     int unitX = x>>log2unitSize;
139     int unitY = y>>log2unitSize;
140 
141     assert(unitX >= 0 && unitX < width_in_units);
142     assert(unitY >= 0 && unitY < height_in_units);
143 
144     data[ unitX + unitY*width_in_units ] = d;
145   }
146 
147   DataUnit& operator[](int idx) { return data[idx]; }
148   const DataUnit& operator[](int idx) const { return data[idx]; }
149 
size()150   int size() const { return data_size; }
151 
152   // private:
153   DataUnit* data;
154   int data_size;
155   int log2unitSize;
156   int width_in_units;
157   int height_in_units;
158 };
159 
160 #define SET_CB_BLK(x,y,log2BlkWidth,  Field,value)              \
161   int cbX = x >> cb_info.log2unitSize; \
162   int cbY = y >> cb_info.log2unitSize; \
163   int width = 1 << (log2BlkWidth - cb_info.log2unitSize);           \
164   for (int cby=cbY;cby<cbY+width;cby++)                             \
165     for (int cbx=cbX;cbx<cbX+width;cbx++)                           \
166       {                                                             \
167         cb_info[ cbx + cby*cb_info.width_in_units ].Field = value;  \
168       }
169 
170 #define CLEAR_TB_BLK(x,y,log2BlkWidth)              \
171   int tuX = x >> tu_info.log2unitSize; \
172   int tuY = y >> tu_info.log2unitSize; \
173   int width = 1 << (log2BlkWidth - tu_info.log2unitSize);           \
174   for (int tuy=tuY;tuy<tuY+width;tuy++)                             \
175     for (int tux=tuX;tux<tuX+width;tux++)                           \
176       {                                                             \
177         tu_info[ tux + tuy*tu_info.width_in_units ] = 0;  \
178       }
179 
180 
181 typedef struct {
182   uint16_t SliceAddrRS;
183   uint16_t SliceHeaderIndex; // index into array to slice header for this CTB
184 
185   sao_info saoInfo;
186   bool     deblock;         // this CTB has to be deblocked
187 
188   // The following flag helps to quickly check whether we have to
189   // check all conditions in the SAO filter or whether we can skip them.
190   bool     has_pcm_or_cu_transquant_bypass; // pcm or transquant_bypass is used in this CTB
191 } CTB_info;
192 
193 
194 typedef struct {
195   uint8_t log2CbSize : 3;   /* [0;6] (1<<log2CbSize) = 64
196                                This is only set in the top-left corner of the CB.
197                                The other values should be zero.
198                                TODO: in the encoder, we have to clear to zero.
199                                Used in deblocking and QP-scale decoding */
200   uint8_t PartMode : 3;     // (enum PartMode)  [0;7] set only in top-left of CB
201                             // Used for spatial merging candidates in current frame
202                             // and for deriving interSplitFlag in decoding.
203 
204   uint8_t ctDepth : 2;      // [0:3]? (for CTB size 64: 0:64, 1:32, 2:16, 3:8)
205                             // Used for decoding/encoding split_cu flag.
206 
207   // --- byte boundary ---
208   uint8_t PredMode : 2;     // (enum PredMode)  [0;2] must be saved for past images
209                             // Used in motion decoding.
210   uint8_t pcm_flag : 1;     // Stored for intra-prediction / SAO
211   uint8_t cu_transquant_bypass : 1; // Stored for SAO
212   // note: 4 bits left
213 
214   // --- byte boundary ---
215   int8_t  QP_Y;  // Stored for QP prediction
216 
217 } CB_ref_info;
218 
219 
220 
221 
222 struct de265_image {
223   de265_image();
224   ~de265_image();
225 
226 
227   de265_error alloc_image(int w,int h, enum de265_chroma c,
228                           std::shared_ptr<const seq_parameter_set> sps,
229                           bool allocMetadata,
230                           decoder_context* dctx,
231                           //class encoder_context* ectx,
232                           de265_PTS pts, void* user_data,
233                           bool useCustomAllocFunctions);
234 
235   //de265_error alloc_encoder_data(const seq_parameter_set* sps);
236 
is_allocatedde265_image237   bool is_allocated() const { return pixels[0] != NULL; }
238 
239   void release();
240 
set_headersde265_image241   void set_headers(std::shared_ptr<video_parameter_set> _vps,
242                    std::shared_ptr<seq_parameter_set>   _sps,
243                    std::shared_ptr<pic_parameter_set>   _pps) {
244     vps = _vps;
245     sps = _sps;
246     pps = _pps;
247   }
248 
249   void fill_image(int y,int u,int v);
250   de265_error copy_image(const de265_image* src);
251   void copy_lines_from(const de265_image* src, int first, int end);
252   void exchange_pixel_data_with(de265_image&);
253 
get_IDde265_image254   uint32_t get_ID() const { return ID; }
255 
256 
get_image_planede265_image257   /* */ uint8_t* get_image_plane(int cIdx)       { return pixels[cIdx]; }
get_image_planede265_image258   const uint8_t* get_image_plane(int cIdx) const { return pixels[cIdx]; }
259 
260   void set_image_plane(int cIdx, uint8_t* mem, int stride, void *userdata);
261 
get_image_plane_at_posde265_image262   uint8_t* get_image_plane_at_pos(int cIdx, int xpos,int ypos)
263   {
264     int stride = get_image_stride(cIdx);
265     return pixels[cIdx] + xpos + ypos*stride;
266   }
267 
268 
269   /// xpos;ypos in actual plane resolution
270   template <class pixel_t>
get_image_plane_at_pos_NEWde265_image271   pixel_t* get_image_plane_at_pos_NEW(int cIdx, int xpos,int ypos)
272   {
273     int stride = get_image_stride(cIdx);
274     return (pixel_t*)(pixels[cIdx] + (xpos + ypos*stride)*sizeof(pixel_t));
275   }
276 
get_image_plane_at_posde265_image277   const uint8_t* get_image_plane_at_pos(int cIdx, int xpos,int ypos) const
278   {
279     int stride = get_image_stride(cIdx);
280     return pixels[cIdx] + xpos + ypos*stride;
281   }
282 
get_image_plane_at_pos_any_depthde265_image283   void* get_image_plane_at_pos_any_depth(int cIdx, int xpos,int ypos)
284   {
285     int stride = get_image_stride(cIdx);
286     return pixels[cIdx] + ((xpos + ypos*stride) << bpp_shift[cIdx]);
287   }
288 
get_image_plane_at_pos_any_depthde265_image289   const void* get_image_plane_at_pos_any_depth(int cIdx, int xpos,int ypos) const
290   {
291     int stride = get_image_stride(cIdx);
292     return pixels[cIdx] + ((xpos + ypos*stride) << bpp_shift[cIdx]);
293   }
294 
295   /* Number of pixels in one row (not number of bytes).
296    */
get_image_stridede265_image297   int get_image_stride(int cIdx) const
298   {
299     if (cIdx==0) return stride;
300     else         return chroma_stride;
301   }
302 
get_luma_stridede265_image303   int get_luma_stride() const { return stride; }
get_chroma_stridede265_image304   int get_chroma_stride() const { return chroma_stride; }
305 
306   int get_width (int cIdx=0) const { return cIdx==0 ? width  : chroma_width;  }
307   int get_height(int cIdx=0) const { return cIdx==0 ? height : chroma_height; }
308 
get_chroma_formatde265_image309   enum de265_chroma get_chroma_format() const { return chroma_format; }
310 
get_bit_depthde265_image311   int get_bit_depth(int cIdx) const {
312     if (cIdx==0) return sps->BitDepth_Y;
313     else         return sps->BitDepth_C;
314   }
315 
get_bytes_per_pixelde265_image316   int get_bytes_per_pixel(int cIdx) const {
317     return (get_bit_depth(cIdx)+7)/8;
318   }
319 
high_bit_depthde265_image320   bool high_bit_depth(int cIdx) const {
321     return get_bit_depth(cIdx)>8;
322   }
323 
can_be_releasedde265_image324   bool can_be_released() const { return PicOutputFlag==false && PicState==UnusedForReference; }
325 
326 
add_slice_segment_headerde265_image327   void add_slice_segment_header(slice_segment_header* shdr) {
328     shdr->slice_index = slices.size();
329     slices.push_back(shdr);
330   }
331 
332 
333   bool available_zscan(int xCurr,int yCurr, int xN,int yN) const;
334 
335   bool available_pred_blk(int xC,int yC, int nCbS,
336                           int xP, int yP, int nPbW, int nPbH, int partIdx,
337                           int xN,int yN) const;
338 
339 
340   static de265_image_allocation default_image_allocation;
341 
printBlkde265_image342   void printBlk(const char* title, int x0,int y0,int blkSize,int cIdx) const {
343     ::printBlk(title, get_image_plane_at_pos(cIdx,x0,y0),
344                blkSize, get_image_stride(cIdx));
345   }
346 
347 private:
348   uint32_t ID;
349   static uint32_t s_next_image_ID;
350 
351   uint8_t* pixels[3];
352   uint8_t  bpp_shift[3];  // 0 for 8 bit, 1 for 16 bit
353 
354   enum de265_chroma chroma_format;
355 
356   int width, height;  // size in luma pixels
357 
358   int chroma_width, chroma_height;
359   int stride, chroma_stride;
360 
361 public:
362   uint8_t BitDepth_Y, BitDepth_C;
363   uint8_t SubWidthC, SubHeightC;
364   std::vector<slice_segment_header*> slices;
365 
366 public:
367 
368   // --- conformance cropping window ---
369 
370   uint8_t* pixels_confwin[3];   // pointer to pixels in the conformance window
371 
372   int width_confwin, height_confwin;
373   int chroma_width_confwin, chroma_height_confwin;
374 
375   // --- decoding info ---
376 
377   // If PicOutputFlag==false && PicState==UnusedForReference, image buffer is free.
378 
379   int  picture_order_cnt_lsb;
380   int  PicOrderCntVal;
381   enum PictureState PicState;
382   bool PicOutputFlag;
383 
384   int32_t removed_at_picture_id;
385 
get_vpsde265_image386   const video_parameter_set& get_vps() const { return *vps; }
get_spsde265_image387   const seq_parameter_set& get_sps() const { return *sps; }
get_ppsde265_image388   const pic_parameter_set& get_pps() const { return *pps; }
389 
has_vpsde265_image390   bool has_vps() const { return (bool)vps; }
has_spsde265_image391   bool has_sps() const { return (bool)sps; }
has_ppsde265_image392   bool has_pps() const { return (bool)pps; }
393 
get_shared_spsde265_image394   std::shared_ptr<const seq_parameter_set> get_shared_sps() { return sps; }
395 
396   //std::shared_ptr<const seq_parameter_set> get_shared_sps() const { return sps; }
397   //std::shared_ptr<const pic_parameter_set> get_shared_pps() const { return pps; }
398 
399   decoder_context*    decctx;
400   //class encoder_context*    encctx;
401 
number_of_ctbsde265_image402   int number_of_ctbs() const { return ctb_info.size(); }
403 
404 private:
405   // The image also keeps a reference to VPS/SPS/PPS, because when decoding is delayed,
406   // the currently active parameter sets in the decctx might already have been replaced
407   // with new parameters.
408   std::shared_ptr<const video_parameter_set> vps;
409   std::shared_ptr<const seq_parameter_set>   sps;  // the SPS used for decoding this image
410   std::shared_ptr<const pic_parameter_set>   pps;  // the PPS used for decoding this image
411 
412   MetaDataArray<CTB_info>    ctb_info;
413   MetaDataArray<CB_ref_info> cb_info;
414   MetaDataArray<PBMotion>    pb_info;
415   MetaDataArray<uint8_t>     intraPredMode;
416   MetaDataArray<uint8_t>     intraPredModeC;
417   MetaDataArray<uint8_t>     tu_info;
418   MetaDataArray<uint8_t>     deblk_info;
419 
420 public:
421   // --- meta information ---
422 
423   de265_PTS pts;
424   void*     user_data;
425   void*     plane_user_data[3];  // this is logically attached to the pixel data pointers
426   de265_image_allocation image_allocation_functions; // the functions used for memory allocation
427 
428   /*
429   void (*encoder_image_release_func)(en265_encoder_context*,
430                                      de265_image*,
431                                      void* userdata);
432   */
433 
434   uint8_t integrity; /* Whether an error occured while the image was decoded.
435                         When generated, this is initialized to INTEGRITY_CORRECT,
436                         and changed on decoding errors.
437                       */
438   bool sei_hash_check_result;
439 
440   nal_header nal_hdr;
441 
442   // --- multi core ---
443 
444   de265_progress_lock* ctb_progress; // ctb_info_size
445 
mark_all_CTB_progressde265_image446   void mark_all_CTB_progress(int progress) {
447     for (int i=0;i<ctb_info.data_size;i++) {
448       ctb_progress[i].set_progress(progress);
449     }
450   }
451 
452 
453   void thread_start(int nThreads);
454   void thread_run(const thread_task*);
455   void thread_blocks();
456   void thread_unblocks();
457   /* NOTE: you should not access any data in the thread_task after
458      calling this, as this function may unlock other threads that
459      will push this image to the output queue and free all decoder data. */
460   void thread_finishes(const thread_task*);
461 
462   void wait_for_progress(thread_task* task, int ctbx,int ctby, int progress);
463   void wait_for_progress(thread_task* task, int ctbAddrRS, int progress);
464 
465   void wait_for_completion();  // block until image is decoded by background threads
466   bool debug_is_completed() const;
num_threads_activede265_image467   int  num_threads_active() const { return nThreadsRunning + nThreadsBlocked; } // for debug only
468 
469   //private:
470   int   nThreadsQueued;
471   int   nThreadsRunning;
472   int   nThreadsBlocked;
473   int   nThreadsFinished;
474   int   nThreadsTotal;
475 
476   // ALIGNED_8(de265_sync_int tasks_pending); // number of tasks pending to complete decoding
477   de265_mutex mutex;
478   de265_cond  finished_cond;
479 
480 public:
481 
482   /* Clear all CTB/CB/PB decoding data of this image.
483      All CTB's processing states are set to 'unprocessed'.
484   */
485   void clear_metadata();
486 
487 
488   // --- CB metadata access ---
489 
set_pred_modede265_image490   void set_pred_mode(int x,int y, int log2BlkWidth, enum PredMode mode)
491   {
492     SET_CB_BLK(x,y,log2BlkWidth, PredMode, mode);
493   }
494 
fill_pred_modede265_image495   void fill_pred_mode(enum PredMode mode)
496   {
497     for (int i=0;i<cb_info.data_size;i++)
498       { cb_info[i].PredMode = MODE_INTRA; }
499   }
500 
get_pred_modede265_image501   enum PredMode get_pred_mode(int x,int y) const
502   {
503     return (enum PredMode)cb_info.get(x,y).PredMode;
504   }
505 
get_cu_skip_flagde265_image506   uint8_t get_cu_skip_flag(int x,int y) const
507   {
508     return get_pred_mode(x,y)==MODE_SKIP;
509   }
510 
511   void set_pcm_flag(int x,int y, int log2BlkWidth, uint8_t value=1)
512   {
513     SET_CB_BLK(x,y,log2BlkWidth, pcm_flag, value);
514 
515     // TODO: in the encoder, we somewhere have to clear this
516     ctb_info.get(x,y).has_pcm_or_cu_transquant_bypass = true;
517   }
518 
get_pcm_flagde265_image519   int  get_pcm_flag(int x,int y) const
520   {
521     return cb_info.get(x,y).pcm_flag;
522   }
523 
524   void set_cu_transquant_bypass(int x,int y, int log2BlkWidth, uint8_t value=1)
525   {
526     SET_CB_BLK(x,y,log2BlkWidth, cu_transquant_bypass, value);
527 
528     // TODO: in the encoder, we somewhere have to clear this
529     ctb_info.get(x,y).has_pcm_or_cu_transquant_bypass = true;
530   }
531 
get_cu_transquant_bypassde265_image532   int  get_cu_transquant_bypass(int x,int y) const
533   {
534     return cb_info.get(x,y).cu_transquant_bypass;
535   }
536 
set_log2CbSizede265_image537   void set_log2CbSize(int x0, int y0, int log2CbSize, bool fill)
538   {
539     // In theory, we could assume that remaining cb_info blocks are initialized to zero.
540     // But in corrupted streams, slices may overlap and set contradicting log2CbSizes.
541     // We also need this for encoding.
542     if (fill) {
543       SET_CB_BLK(x0,y0,log2CbSize, log2CbSize, 0);
544     }
545 
546     cb_info.get(x0,y0).log2CbSize = log2CbSize;
547   }
548 
get_log2CbSizede265_image549   int  get_log2CbSize(int x0, int y0) const
550   {
551     return (enum PredMode)cb_info.get(x0,y0).log2CbSize;
552   }
553 
554   // coordinates in CB units
get_log2CbSize_cbUnitsde265_image555   int  get_log2CbSize_cbUnits(int xCb, int yCb) const
556   {
557     return (enum PredMode)cb_info[ xCb + yCb*cb_info.width_in_units ].log2CbSize;
558   }
559 
set_PartModede265_image560   void set_PartMode(int x,int y, enum PartMode mode)
561   {
562     cb_info.get(x,y).PartMode = mode;
563   }
564 
get_PartModede265_image565   enum PartMode get_PartMode(int x,int y) const
566   {
567     return (enum PartMode)cb_info.get(x,y).PartMode;
568   }
569 
set_ctDepthde265_image570   void set_ctDepth(int x,int y, int log2BlkWidth, int depth)
571   {
572     SET_CB_BLK(x,y,log2BlkWidth, ctDepth, depth);
573   }
574 
get_ctDepthde265_image575   int get_ctDepth(int x,int y) const
576   {
577     return cb_info.get(x,y).ctDepth;
578   }
579 
set_QPYde265_image580   void set_QPY(int x,int y, int log2BlkWidth, int QP_Y)
581   {
582     SET_CB_BLK (x, y, log2BlkWidth, QP_Y, QP_Y);
583   }
584 
get_QPYde265_image585   int  get_QPY(int x0,int y0) const
586   {
587     return cb_info.get(x0,y0).QP_Y;
588   }
589 
590   // --- TU metadata access ---
591 
set_split_transform_flagde265_image592   void set_split_transform_flag(int x0,int y0,int trafoDepth)
593   {
594     tu_info.get(x0,y0) |= (1<<trafoDepth);
595   }
596 
clear_split_transform_flagsde265_image597   void clear_split_transform_flags(int x0,int y0,int log2CbSize)
598   {
599     CLEAR_TB_BLK (x0,y0, log2CbSize);
600   }
601 
get_split_transform_flagde265_image602   int  get_split_transform_flag(int x0,int y0,int trafoDepth) const
603   {
604     return (tu_info.get(x0,y0) & (1<<trafoDepth));
605   }
606 
set_nonzero_coefficientde265_image607   void set_nonzero_coefficient(int x,int y, int log2TrafoSize)
608   {
609     const int tuX = x >> tu_info.log2unitSize;
610     const int tuY = y >> tu_info.log2unitSize;
611     const int width = 1 << (log2TrafoSize - tu_info.log2unitSize);
612 
613     for (int tuy=tuY;tuy<tuY+width;tuy++)
614       for (int tux=tuX;tux<tuX+width;tux++)
615         {
616           tu_info[ tux + tuy*tu_info.width_in_units ] |= TU_FLAG_NONZERO_COEFF;
617         }
618   }
619 
get_nonzero_coefficientde265_image620   int  get_nonzero_coefficient(int x,int y) const
621   {
622     return tu_info.get(x,y) & TU_FLAG_NONZERO_COEFF;
623   }
624 
625 
626   // --- intraPredMode metadata access ---
627 
get_IntraPredModede265_image628   enum IntraPredMode get_IntraPredMode(int x,int y) const
629   {
630     return (enum IntraPredMode)intraPredMode.get(x,y);
631   }
632 
get_IntraPredMode_atIndexde265_image633   enum IntraPredMode get_IntraPredMode_atIndex(int idx) const
634   {
635     return (enum IntraPredMode)intraPredMode[idx];
636   }
637 
set_IntraPredModede265_image638   void set_IntraPredMode(int PUidx,int log2blkSize, enum IntraPredMode mode)
639   {
640     int pbSize = 1<<(log2blkSize - intraPredMode.log2unitSize);
641 
642     for (int y=0;y<pbSize;y++)
643       for (int x=0;x<pbSize;x++)
644         intraPredMode[PUidx + x + y*intraPredMode.width_in_units] = mode;
645   }
646 
set_IntraPredModede265_image647   void set_IntraPredMode(int x0,int y0,int log2blkSize,
648                          enum IntraPredMode mode)
649   {
650     int pbSize = 1<<(log2blkSize - intraPredMode.log2unitSize);
651     int PUidx  = (x0>>sps->Log2MinPUSize) + (y0>>sps->Log2MinPUSize)*sps->PicWidthInMinPUs;
652 
653     for (int y=0;y<pbSize;y++)
654       for (int x=0;x<pbSize;x++) {
655         assert(x < sps->PicWidthInMinPUs);
656         assert(y < sps->PicHeightInMinPUs);
657 
658         int idx = PUidx + x + y*intraPredMode.width_in_units;
659         assert(idx<intraPredMode.data_size);
660         intraPredMode[idx] = mode;
661       }
662   }
663 
664 
get_IntraPredModeCde265_image665   enum IntraPredMode get_IntraPredModeC(int x,int y) const
666   {
667     return (enum IntraPredMode)(intraPredModeC.get(x,y) & 0x3f);
668   }
669 
is_IntraPredModeC_Mode4de265_image670   bool is_IntraPredModeC_Mode4(int x,int y) const
671   {
672     return intraPredModeC.get(x,y) & 0x80;
673   }
674 
set_IntraPredModeCde265_image675   void set_IntraPredModeC(int x0,int y0,int log2blkSize, enum IntraPredMode mode,
676                           bool is_mode4)
677   {
678     uint8_t combinedValue = mode;
679     if (is_mode4) combinedValue |= 0x80;
680 
681     int pbSize = 1<<(log2blkSize - intraPredMode.log2unitSize);
682     int PUidx  = (x0>>sps->Log2MinPUSize) + (y0>>sps->Log2MinPUSize)*sps->PicWidthInMinPUs;
683 
684     for (int y=0;y<pbSize;y++)
685       for (int x=0;x<pbSize;x++) {
686         assert(x<sps->PicWidthInMinPUs);
687         assert(y<sps->PicHeightInMinPUs);
688 
689         int idx = PUidx + x + y*intraPredModeC.width_in_units;
690         assert(idx<intraPredModeC.data_size);
691         intraPredModeC[idx] = combinedValue;
692       }
693   }
694 
695 
696   /*
697   // NOTE: encoder only
698   void set_ChromaIntraPredMode(int x,int y,int log2BlkWidth, enum IntraChromaPredMode mode)
699   {
700     SET_CB_BLK (x, y, log2BlkWidth, intra_chroma_pred_mode, mode);
701   }
702 
703   // NOTE: encoder only
704   enum IntraChromaPredMode get_ChromaIntraPredMode(int x,int y) const
705   {
706     return (enum IntraChromaPredMode)(cb_info.get(x,y).intra_chroma_pred_mode);
707   }
708   */
709 
710   // --- CTB metadata access ---
711 
712   // address of first CTB in slice
set_SliceAddrRSde265_image713   void set_SliceAddrRS(int ctbX, int ctbY, int SliceAddrRS)
714   {
715     int idx = ctbX + ctbY*ctb_info.width_in_units;
716     ctb_info[idx].SliceAddrRS = SliceAddrRS;
717   }
718 
get_SliceAddrRSde265_image719   int  get_SliceAddrRS(int ctbX, int ctbY) const
720   {
721     return ctb_info[ctbX + ctbY*ctb_info.width_in_units].SliceAddrRS;
722   }
723 
get_SliceAddrRS_atCtbRSde265_image724   int  get_SliceAddrRS_atCtbRS(int ctbRS) const
725   {
726     return ctb_info[ctbRS].SliceAddrRS;
727   }
728 
729 
set_SliceHeaderIndexde265_image730   void set_SliceHeaderIndex(int x, int y, int SliceHeaderIndex)
731   {
732     ctb_info.get(x,y).SliceHeaderIndex = SliceHeaderIndex;
733   }
734 
get_SliceHeaderIndexde265_image735   int  get_SliceHeaderIndex(int x, int y) const
736   {
737     return ctb_info.get(x,y).SliceHeaderIndex;
738   }
739 
get_SliceHeaderIndexCtbde265_image740   int  get_SliceHeaderIndexCtb(int ctbX, int ctbY) const
741   {
742     return ctb_info[ctbX + ctbY*ctb_info.width_in_units].SliceHeaderIndex;
743   }
744 
get_SliceHeaderIndex_atIndexde265_image745   int  get_SliceHeaderIndex_atIndex(int ctb) const
746   {
747     return ctb_info[ctb].SliceHeaderIndex;
748   }
749 
is_SliceHeader_availablede265_image750   bool is_SliceHeader_available(int x,int y) const
751   {
752     int idx = ctb_info.get(x,y).SliceHeaderIndex;
753     return idx >= 0 && idx < slices.size();
754   }
755 
get_SliceHeaderde265_image756   slice_segment_header* get_SliceHeader(int x, int y)
757   {
758     int idx = get_SliceHeaderIndex(x,y);
759     if (idx >= slices.size()) { return NULL; }
760     return slices[idx];
761   }
762 
get_SliceHeaderCtbde265_image763   slice_segment_header* get_SliceHeaderCtb(int ctbX, int ctbY)
764   {
765     int idx = get_SliceHeaderIndexCtb(ctbX,ctbY);
766     if (idx >= slices.size()) { return NULL; }
767     return slices[idx];
768   }
769 
get_SliceHeaderCtbde265_image770   const slice_segment_header* get_SliceHeaderCtb(int ctbX, int ctbY) const
771   {
772     int idx = get_SliceHeaderIndexCtb(ctbX,ctbY);
773     if (idx >= slices.size()) { return NULL; }
774     return slices[idx];
775   }
776 
set_sao_infode265_image777   void set_sao_info(int ctbX,int ctbY,const sao_info* saoinfo)
778   {
779     sao_info* sao = &ctb_info[ctbX + ctbY*ctb_info.width_in_units].saoInfo;
780 
781     memcpy(sao,
782            saoinfo,
783            sizeof(sao_info));
784   }
785 
get_sao_infode265_image786   const sao_info* get_sao_info(int ctbX,int ctbY) const
787   {
788     return &ctb_info[ctbX + ctbY*ctb_info.width_in_units].saoInfo;
789   }
790 
791 
set_CtbDeblockFlagde265_image792   void set_CtbDeblockFlag(int ctbX, int ctbY, bool flag)
793   {
794     int idx = ctbX + ctbY*ctb_info.width_in_units;
795     ctb_info[idx].deblock = flag;
796   }
797 
get_CtbDeblockFlagde265_image798   bool get_CtbDeblockFlag(int ctbX, int ctbY) const
799   {
800     return ctb_info[ctbX + ctbY*ctb_info.width_in_units].deblock;
801   }
802 
803 
get_CTB_has_pcm_or_cu_transquant_bypassde265_image804   bool get_CTB_has_pcm_or_cu_transquant_bypass(int ctbX,int ctbY) const
805   {
806     int idx = ctbX + ctbY*ctb_info.width_in_units;
807     return ctb_info[idx].has_pcm_or_cu_transquant_bypass;
808   }
809 
810 
811 
812   // --- DEBLK metadata access ---
813 
get_deblk_widthde265_image814   int  get_deblk_width()  const { return deblk_info.width_in_units; }
get_deblk_heightde265_image815   int  get_deblk_height() const { return deblk_info.height_in_units; }
816 
set_deblk_flagsde265_image817   void    set_deblk_flags(int x0,int y0, uint8_t flags)
818   {
819     const int xd = x0/4;
820     const int yd = y0/4;
821 
822     if (xd<deblk_info.width_in_units &&
823         yd<deblk_info.height_in_units) {
824       deblk_info[xd + yd*deblk_info.width_in_units] |= flags;
825     }
826   }
827 
get_deblk_flagsde265_image828   uint8_t get_deblk_flags(int x0,int y0) const
829   {
830     const int xd = x0/4;
831     const int yd = y0/4;
832 
833     return deblk_info[xd + yd*deblk_info.width_in_units];
834   }
835 
set_deblk_bSde265_image836   void    set_deblk_bS(int x0,int y0, uint8_t bS)
837   {
838     uint8_t* data = &deblk_info[x0/4 + y0/4*deblk_info.width_in_units];
839     *data &= ~DEBLOCK_BS_MASK;
840     *data |= bS;
841   }
842 
get_deblk_bSde265_image843   uint8_t get_deblk_bS(int x0,int y0) const
844   {
845     return deblk_info[x0/4 + y0/4*deblk_info.width_in_units] & DEBLOCK_BS_MASK;
846   }
847 
848 
849   // --- PB metadata access ---
850 
get_mv_infode265_image851   const PBMotion& get_mv_info(int x,int y) const
852   {
853     return pb_info.get(x,y);
854   }
855 
856   void set_mv_info(int x,int y, int nPbW,int nPbH, const PBMotion& mv);
857 
858   // --- value logging ---
859 
860   void printBlk(int x0,int y0, int cIdx, int log2BlkSize);
861 };
862 
863 
864 #endif
865