xref: /OK3568_Linux_fs/external/mpp/mpp/codec/dec/h265/h265d_refs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *
3  * Copyright 2015 Rockchip Electronics Co. LTD
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /*
19  * @file       h265_refs.c
20  * @brief
21  * @author      csy(csy@rock-chips.com)
22 
23  * @version     1.0.0
24  * @history
25  *   2015.7.15 : Create
26  */
27 
28 #define MODULE_TAG  "H265_PARSER_REF"
29 
30 #include "mpp_compat_impl.h"
31 
32 #include "h265d_parser.h"
33 #include "h265d_api.h"
34 
35 #define HEVC_ALIGN(value, x)   ((value + (x-1)) & (~(x-1)))
36 
mpp_hevc_unref_frame(HEVCContext * s,HEVCFrame * frame,int flags)37 void mpp_hevc_unref_frame(HEVCContext *s, HEVCFrame *frame, int flags)
38 {
39     /* frame->frame can be NULL if context init failed */
40     if (!frame->frame || (frame->slot_index == 0xff))
41         return;
42 
43     frame->flags &= ~flags;
44     if (!frame->flags) {
45         frame->refPicList = NULL;
46         frame->collocated_ref = NULL;
47         if (frame->slot_index <= 0x7f) {
48             h265d_dbg(H265D_DBG_REF, "poc %d clr ref index %d", frame->poc, frame->slot_index);
49             mpp_buf_slot_clr_flag(s->slots, frame->slot_index, SLOT_CODEC_USE);
50         }
51         h265d_dbg(H265D_DBG_REF, "unref_frame poc %d frame->slot_index %d \n", frame->poc, frame->slot_index);
52         frame->poc = INT_MAX;
53         frame->slot_index = 0xff;
54         frame->error_flag = 0;
55     }
56 }
57 
58 
mpp_hevc_clear_refs(HEVCContext * s)59 void mpp_hevc_clear_refs(HEVCContext *s)
60 {
61     RK_U32 i;
62     for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
63         mpp_hevc_unref_frame(s, &s->DPB[i],
64                              HEVC_FRAME_FLAG_SHORT_REF |
65                              HEVC_FRAME_FLAG_LONG_REF);
66     }
67 }
68 
mpp_hevc_flush_dpb(HEVCContext * s)69 void mpp_hevc_flush_dpb(HEVCContext *s)
70 {
71     RK_U32 i;
72     for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
73         mpp_hevc_unref_frame(s, &s->DPB[i], ~0);
74     }
75 }
76 
hor_align_64(RK_U32 val)77 static RK_U32 hor_align_64(RK_U32 val)
78 {
79     return MPP_ALIGN(val, 64);
80 }
81 
alloc_frame(HEVCContext * s)82 static HEVCFrame *alloc_frame(HEVCContext *s)
83 {
84     RK_U32  i;
85     MPP_RET ret = MPP_OK;
86     for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
87         HEVCFrame *frame = &s->DPB[i];
88         if (frame->slot_index != 0xff) {
89             continue;
90         }
91 
92         h265d_dbg(H265D_DBG_GLOBAL, "width = %d height = %d", s->h265dctx->width, s->h265dctx->height);
93         mpp_frame_set_width(frame->frame, s->h265dctx->width);
94         mpp_frame_set_height(frame->frame, s->h265dctx->height);
95         mpp_frame_set_hor_stride(frame->frame,
96                                  (MPP_ALIGN(s->h265dctx->coded_width, 64) * s->h265dctx->nBitDepth) >> 3);
97         mpp_frame_set_ver_stride(frame->frame, s->h265dctx->coded_height);
98         if (s->is_hdr) {
99             s->h265dctx->pix_fmt |= MPP_FRAME_HDR;
100         }
101         mpp_frame_set_fmt(frame->frame, s->h265dctx->pix_fmt);
102 
103         if (MPP_FRAME_FMT_IS_FBC(s->h265dctx->pix_fmt)) {
104             RK_U32 fbc_hdr_stride = MPP_ALIGN(s->h265dctx->width, 64);
105 
106             mpp_slots_set_prop(s->slots, SLOTS_HOR_ALIGN, hor_align_64);
107             mpp_frame_set_offset_x(frame->frame, 0);
108             mpp_frame_set_offset_y(frame->frame, 4);
109 
110             if (*compat_ext_fbc_buf_size)
111                 mpp_frame_set_ver_stride(frame->frame, s->h265dctx->coded_height + 16);
112 
113             if (*compat_ext_fbc_hdr_256_odd)
114                 fbc_hdr_stride = MPP_ALIGN(s->h265dctx->width, 256) | 256;
115 
116             mpp_frame_set_fbc_hdr_stride(frame->frame, fbc_hdr_stride);
117         } else {
118             if ((s->h265dctx->cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) &&
119                 s->h265dctx->width <= 1920 &&  s->h265dctx->height <= 1088)
120                 mpp_frame_set_mode(frame->frame, MPP_FRAME_FLAG_DEINTERLACED);
121         }
122 
123         if (s->h265dctx->cfg->base.enable_thumbnail && s->h265dctx->hw_info->cap_down_scale)
124             mpp_frame_set_thumbnail_en(frame->frame, 1);
125         else
126             mpp_frame_set_thumbnail_en(frame->frame, 0);
127 
128         mpp_frame_set_errinfo(frame->frame, 0);
129         mpp_frame_set_pts(frame->frame, s->pts);
130         mpp_frame_set_poc(frame->frame, s->poc);
131         mpp_frame_set_color_range(frame->frame, s->h265dctx->color_range);
132         mpp_frame_set_color_primaries(frame->frame, s->sps->vui.colour_primaries);
133         if (s->alternative_transfer.present)
134             mpp_frame_set_color_trc(frame->frame,
135                                     s->alternative_transfer.preferred_transfer_characteristics);
136         else
137             mpp_frame_set_color_trc(frame->frame, s->sps->vui.transfer_characteristic);
138         mpp_frame_set_colorspace(frame->frame, s->h265dctx->colorspace);
139         mpp_frame_set_mastering_display(frame->frame, s->mastering_display);
140         mpp_frame_set_content_light(frame->frame, s->content_light);
141         if (s->hdr_dynamic_meta && s->hdr_dynamic) {
142             mpp_frame_set_hdr_dynamic_meta(frame->frame, s->hdr_dynamic_meta);
143             s->hdr_dynamic = 0;
144         }
145         h265d_dbg(H265D_DBG_GLOBAL, "poc %d w_stride %d h_stride %d\n",
146                   s->poc, s->h265dctx->coded_width, s->h265dctx->coded_height);
147         ret = mpp_buf_slot_get_unused(s->slots, &frame->slot_index);
148         mpp_assert(ret == MPP_OK);
149         return frame;
150     }
151     mpp_err( "Error allocating frame, DPB full.\n");
152     return NULL;
153 }
154 
mpp_hevc_set_new_ref(HEVCContext * s,MppFrame * mframe,int poc)155 int mpp_hevc_set_new_ref(HEVCContext *s, MppFrame *mframe, int poc)
156 {
157 
158     HEVCFrame *ref = NULL;
159     RK_U32 i;
160 
161     /* check that this POC doesn't already exist */
162     for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
163         HEVCFrame *frame = &s->DPB[i];
164 
165         if ((frame->slot_index != 0xff) && frame->sequence == s->seq_decode &&
166             frame->poc == poc && !s->nuh_layer_id) {
167             mpp_err( "Duplicate POC in a sequence: %d.\n",
168                      poc);
169             return  MPP_ERR_STREAM;
170         }
171     }
172 
173     ref = alloc_frame(s);
174     if (!ref) {
175         mpp_err( "alloc_frame error\n");
176         return MPP_ERR_NOMEM;
177     }
178 
179     *mframe = ref->frame;
180     s->ref = ref;
181     ref->poc      = poc;
182     h265d_dbg(H265D_DBG_REF, "alloc frame poc %d slot_index %d", poc, ref->slot_index);
183     ref->flags    = HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_SHORT_REF;
184     mpp_buf_slot_set_flag(s->slots, ref->slot_index, SLOT_CODEC_USE);
185     mpp_buf_slot_set_flag(s->slots, ref->slot_index, SLOT_HAL_OUTPUT);
186     s->task->output = ref->slot_index;
187 
188     ref->sequence = s->seq_decode;
189     ref->window   = s->sps->output_window;
190     return 0;
191 }
192 
find_ref_idx(HEVCContext * s,int poc)193 static HEVCFrame *find_ref_idx(HEVCContext *s, int poc)
194 {
195     RK_U32 i;
196     RK_S32 LtMask = (1 << s->sps->log2_max_poc_lsb) - 1;
197 
198     for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
199         HEVCFrame *ref = &s->DPB[i];
200         if ((ref->slot_index != 0xff) && (ref->sequence == s->seq_decode)) {
201             if ((ref->poc & LtMask) == poc)
202                 return ref;
203         }
204     }
205 
206     for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
207         HEVCFrame *ref = &s->DPB[i];
208         if ((ref->slot_index != 0xff) && ref->sequence == s->seq_decode) {
209             if (ref->poc == poc || (ref->poc & LtMask) == poc)
210                 return ref;
211         }
212     }
213     mpp_err("cur_poc %d Could not find ref with POC %d\n", s->poc, poc);
214     return NULL;
215 }
216 
mark_ref(HEVCFrame * frame,int flag)217 static void mark_ref(HEVCFrame *frame, int flag)
218 {
219     frame->flags &= ~(HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF);
220     frame->flags |= flag;
221 }
222 
generate_missing_ref(HEVCContext * s,int poc)223 static HEVCFrame *generate_missing_ref(HEVCContext *s, int poc)
224 {
225     HEVCFrame *frame;
226     h265d_dbg(H265D_DBG_REF, "generate_missing_ref in \n");
227     frame = alloc_frame(s);
228     if (!frame)
229         return NULL;
230     frame->poc      = poc;
231 
232     mpp_frame_set_errinfo(frame->frame, 1);
233     mpp_buf_slot_set_prop(s->slots, frame->slot_index, SLOT_FRAME, frame->frame);
234     mpp_buf_slot_set_flag(s->slots, frame->slot_index, SLOT_CODEC_READY);
235     mpp_buf_slot_set_flag(s->slots, frame->slot_index, SLOT_CODEC_USE);
236     h265d_dbg(H265D_DBG_REF, "generate_missing_ref frame poc %d slot_index %d", poc, frame->slot_index);
237     frame->sequence = s->seq_decode;
238     frame->flags    = 0;
239     return frame;
240 }
241 
242 /* add a reference with the given poc to the list and mark it as used in DPB */
add_candidate_ref(HEVCContext * s,RefPicList * list,int poc,int ref_flag,RK_U32 cur_used)243 static int add_candidate_ref(HEVCContext *s, RefPicList *list,
244                              int poc, int ref_flag, RK_U32 cur_used)
245 {
246     HEVCFrame *ref = find_ref_idx(s, poc);
247 
248     if (!ref) {
249         ref = generate_missing_ref(s, poc);
250         if (!ref)
251             return MPP_ERR_NOMEM;
252 
253         ref->error_flag = 1;
254     }
255 
256     list->list[list->nb_refs] = ref->poc;
257     list->ref[list->nb_refs]  = ref;
258     list->nb_refs++;
259     if (ref_flag) {
260         h265d_dbg(H265D_DBG_REF, "set ref poc = %d ref->slot_index %d", ref->poc, ref->slot_index);
261         mpp_buf_slot_set_flag(s->slots, ref->slot_index, SLOT_CODEC_USE);
262     }
263     mark_ref(ref, ref_flag);
264     if (ref->error_flag && cur_used) {
265         s->miss_ref_flag = 1;
266     }
267     return 0;
268 }
269 
mpp_hevc_frame_rps(HEVCContext * s)270 RK_S32 mpp_hevc_frame_rps(HEVCContext *s)
271 {
272 
273     const ShortTermRPS *short_rps = s->sh.short_term_rps;
274     const LongTermRPS  *long_rps  = &s->sh.long_term_rps;
275     RefPicList               *rps = s->rps;
276     RK_S32  ret;
277     RK_U32  i;
278 
279     if (!short_rps) {
280         rps[0].nb_refs = rps[1].nb_refs = 0;
281         return 0;
282     }
283 
284     /* clear the reference flags on all frames except the current one */
285     for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
286         HEVCFrame *frame = &s->DPB[i];
287         mark_ref(frame, 0);
288     }
289 
290     for (i = 0; i < NB_RPS_TYPE; i++)
291         rps[i].nb_refs = 0;
292 
293     /* add the short refs */
294     for (i = 0; short_rps && (RK_S32)i < short_rps->num_delta_pocs; i++) {
295         int poc = s->poc + short_rps->delta_poc[i];
296         int list;
297 
298         if (!short_rps->used[i])
299             list = ST_FOLL;
300         else if (i < short_rps->num_negative_pics)
301             list = ST_CURR_BEF;
302         else
303             list = ST_CURR_AFT;
304 
305         ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_SHORT_REF, ST_FOLL != list);
306         if (ret < 0)
307             return ret;
308     }
309 
310     /* add the long refs */
311     for (i = 0; long_rps && i < long_rps->nb_refs; i++) {
312         int poc  = long_rps->poc[i];
313         int list = long_rps->used[i] ? LT_CURR : LT_FOLL;
314 
315         ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_LONG_REF, LT_FOLL != list);
316         if (ret < 0)
317             return ret;
318     }
319     /* release any frames that are now unused */
320     for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
321         mpp_hevc_unref_frame(s, &s->DPB[i], 0);
322     }
323     /*
324      * flush for CRA frame if there has frame poc > cur poc in dpb.
325      */
326     if (IS_CRA(s)) {
327         for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
328             HEVCFrame *ref = &s->DPB[i];
329 
330             if ((ref->slot_index != 0xff) && (ref->poc > s->poc)) {
331                 h265d_flush(s->h265dctx);
332                 break;
333             }
334         }
335     }
336 
337     return 0;
338 }
339 
mpp_hevc_compute_poc(HEVCContext * s,int poc_lsb)340 int mpp_hevc_compute_poc(HEVCContext *s, int poc_lsb)
341 {
342     RK_S32 max_poc_lsb  = 1 << s->sps->log2_max_poc_lsb;
343     RK_S32 prev_poc_lsb = s->pocTid0 % max_poc_lsb;
344     RK_S32 prev_poc_msb = s->pocTid0 - prev_poc_lsb;
345     RK_S32 poc_msb;
346 
347     if (poc_lsb < prev_poc_lsb && prev_poc_lsb - poc_lsb >= max_poc_lsb / 2)
348         poc_msb = prev_poc_msb + max_poc_lsb;
349     else if (poc_lsb > prev_poc_lsb && poc_lsb - prev_poc_lsb > max_poc_lsb / 2)
350         poc_msb = prev_poc_msb - max_poc_lsb;
351     else
352         poc_msb = prev_poc_msb;
353 
354     // For BLA picture types, POCmsb is set to 0.
355     if (s->nal_unit_type == NAL_BLA_W_LP   ||
356         s->nal_unit_type == NAL_BLA_W_RADL ||
357         s->nal_unit_type == NAL_BLA_N_LP)
358         poc_msb = 0;
359 
360     return poc_msb + poc_lsb;
361 }
362 
mpp_hevc_frame_nb_refs(HEVCContext * s)363 int mpp_hevc_frame_nb_refs(HEVCContext *s)
364 {
365     RK_S32 ret = 0;
366     RK_S32 i;
367     const ShortTermRPS *rps = s->sh.short_term_rps;
368     LongTermRPS *long_rps   = &s->sh.long_term_rps;
369 
370     if (s->sh.slice_type == I_SLICE) {
371         return 0;
372     }
373     if (rps) {
374         for (i = 0; (RK_U32)i < rps->num_negative_pics; i++)
375             ret += !!rps->used[i];
376         for (; i < rps->num_delta_pocs; i++)
377             ret += !!rps->used[i];
378     }
379 
380     if (long_rps) {
381         for (i = 0; i < long_rps->nb_refs; i++)
382             ret += !!long_rps->used[i];
383     }
384     return ret;
385 }
386 
387