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 MppFrameFormat fmt = s->h265dctx->cfg->base.out_fmt & (~MPP_FRAME_FMT_MASK);
87
88 for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
89 HEVCFrame *frame = &s->DPB[i];
90 if (frame->slot_index != 0xff) {
91 continue;
92 }
93
94 h265d_dbg(H265D_DBG_GLOBAL, "width = %d height = %d", s->h265dctx->width, s->h265dctx->height);
95 mpp_frame_set_width(frame->frame, s->h265dctx->width);
96 mpp_frame_set_height(frame->frame, s->h265dctx->height);
97 mpp_frame_set_hor_stride(frame->frame,
98 (MPP_ALIGN(s->h265dctx->coded_width, 64) * s->h265dctx->nBitDepth) >> 3);
99 mpp_frame_set_ver_stride(frame->frame, s->h265dctx->coded_height);
100 s->h265dctx->pix_fmt &= MPP_FRAME_FMT_MASK;
101 if (s->is_hdr) {
102 s->h265dctx->pix_fmt |= MPP_FRAME_HDR;
103 }
104 s->h265dctx->pix_fmt |= fmt;
105 mpp_frame_set_fmt(frame->frame, s->h265dctx->pix_fmt);
106
107 if (MPP_FRAME_FMT_IS_FBC(s->h265dctx->pix_fmt)) {
108 RK_U32 fbc_hdr_stride = MPP_ALIGN(s->h265dctx->width, 64);
109
110 mpp_slots_set_prop(s->slots, SLOTS_HOR_ALIGN, hor_align_64);
111 mpp_frame_set_offset_x(frame->frame, 0);
112 mpp_frame_set_offset_y(frame->frame, 4);
113
114 if (*compat_ext_fbc_buf_size)
115 mpp_frame_set_ver_stride(frame->frame, s->h265dctx->coded_height + 16);
116
117 if (*compat_ext_fbc_hdr_256_odd)
118 fbc_hdr_stride = MPP_ALIGN(s->h265dctx->width, 256) | 256;
119
120 mpp_frame_set_fbc_hdr_stride(frame->frame, fbc_hdr_stride);
121 } else if (MPP_FRAME_FMT_IS_TILE(s->h265dctx->pix_fmt)) {
122 /* nothing todo */
123 } else {
124 if ((s->h265dctx->cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) &&
125 s->h265dctx->width <= 1920 && s->h265dctx->height <= 1088)
126 mpp_frame_set_mode(frame->frame, MPP_FRAME_FLAG_DEINTERLACED);
127 }
128
129 if (s->h265dctx->cfg->base.enable_thumbnail && s->h265dctx->hw_info->cap_down_scale)
130 mpp_frame_set_thumbnail_en(frame->frame, s->h265dctx->cfg->base.enable_thumbnail);
131 else
132 mpp_frame_set_thumbnail_en(frame->frame, 0);
133
134 mpp_frame_set_errinfo(frame->frame, 0);
135 mpp_frame_set_discard(frame->frame, 0);
136 mpp_frame_set_pts(frame->frame, s->pts);
137 mpp_frame_set_dts(frame->frame, s->dts);
138 mpp_frame_set_poc(frame->frame, s->poc);
139 mpp_frame_set_color_range(frame->frame, s->h265dctx->color_range);
140 mpp_frame_set_color_primaries(frame->frame, s->sps->vui.colour_primaries);
141 if (s->alternative_transfer.present)
142 mpp_frame_set_color_trc(frame->frame,
143 s->alternative_transfer.preferred_transfer_characteristics);
144 else
145 mpp_frame_set_color_trc(frame->frame, s->sps->vui.transfer_characteristic);
146 mpp_frame_set_colorspace(frame->frame, s->h265dctx->colorspace);
147 mpp_frame_set_mastering_display(frame->frame, s->mastering_display);
148 mpp_frame_set_content_light(frame->frame, s->content_light);
149
150 h265d_dbg(H265D_DBG_GLOBAL, "poc %d w_stride %d h_stride %d\n",
151 s->poc, s->h265dctx->coded_width, s->h265dctx->coded_height);
152 ret = mpp_buf_slot_get_unused(s->slots, &frame->slot_index);
153 mpp_assert(ret == MPP_OK);
154 return frame;
155 }
156 mpp_err( "Error allocating frame, DPB full.\n");
157 return NULL;
158 }
159
mpp_hevc_set_new_ref(HEVCContext * s,MppFrame * mframe,int poc)160 int mpp_hevc_set_new_ref(HEVCContext *s, MppFrame *mframe, int poc)
161 {
162
163 HEVCFrame *ref = NULL;
164 RK_U32 i;
165
166 /* check that this POC doesn't already exist */
167 for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
168 HEVCFrame *frame = &s->DPB[i];
169
170 if ((frame->slot_index != 0xff) && frame->sequence == s->seq_decode &&
171 frame->poc == poc && !s->nuh_layer_id) {
172 mpp_err( "Duplicate POC in a sequence: %d.\n",
173 poc);
174 return MPP_ERR_STREAM;
175 }
176 }
177
178 ref = alloc_frame(s);
179 if (!ref) {
180 mpp_err( "alloc_frame error\n");
181 return MPP_ERR_NOMEM;
182 }
183 // set hdr dynamic meta
184 if (s->hdr_dynamic_meta && s->hdr_dynamic) {
185 mpp_frame_set_hdr_dynamic_meta(ref->frame, s->hdr_dynamic_meta);
186 s->hdr_dynamic = 0;
187 }
188
189 *mframe = ref->frame;
190 s->ref = ref;
191 ref->poc = poc;
192 h265d_dbg(H265D_DBG_REF, "alloc frame poc %d slot_index %d", poc, ref->slot_index);
193 ref->flags = HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_SHORT_REF;
194 mpp_buf_slot_set_flag(s->slots, ref->slot_index, SLOT_CODEC_USE);
195 mpp_buf_slot_set_flag(s->slots, ref->slot_index, SLOT_HAL_OUTPUT);
196 s->task->output = ref->slot_index;
197
198 ref->sequence = s->seq_decode;
199 ref->window = s->sps->output_window;
200 return 0;
201 }
202
find_ref_idx(HEVCContext * s,int poc)203 static HEVCFrame *find_ref_idx(HEVCContext *s, int poc)
204 {
205 RK_U32 i;
206 RK_S32 LtMask = (1 << s->sps->log2_max_poc_lsb) - 1;
207
208 for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
209 HEVCFrame *ref = &s->DPB[i];
210 if ((ref->slot_index != 0xff) && (ref->sequence == s->seq_decode)) {
211 if ((ref->poc & LtMask) == poc)
212 return ref;
213 }
214 }
215
216 for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
217 HEVCFrame *ref = &s->DPB[i];
218 if ((ref->slot_index != 0xff) && ref->sequence == s->seq_decode) {
219 if (ref->poc == poc || (ref->poc & LtMask) == poc)
220 return ref;
221 }
222 }
223 mpp_err("cur_poc %d Could not find ref with POC %d\n", s->poc, poc);
224 return NULL;
225 }
226
mark_ref(HEVCFrame * frame,int flag)227 static void mark_ref(HEVCFrame *frame, int flag)
228 {
229 frame->flags &= ~(HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF);
230 frame->flags |= flag;
231 }
232
generate_missing_ref(HEVCContext * s,int poc)233 static HEVCFrame *generate_missing_ref(HEVCContext *s, int poc)
234 {
235 HEVCFrame *frame;
236 h265d_dbg(H265D_DBG_REF, "generate_missing_ref in \n");
237 frame = alloc_frame(s);
238 if (!frame)
239 return NULL;
240 frame->poc = poc;
241
242 mpp_frame_set_errinfo(frame->frame, 1);
243 mpp_buf_slot_set_prop(s->slots, frame->slot_index, SLOT_FRAME, frame->frame);
244 mpp_buf_slot_set_flag(s->slots, frame->slot_index, SLOT_CODEC_READY);
245 mpp_buf_slot_set_flag(s->slots, frame->slot_index, SLOT_CODEC_USE);
246 mpp_frame_set_poc(frame->frame, poc);
247 h265d_dbg(H265D_DBG_REF, "generate_missing_ref frame poc %d slot_index %d", poc, frame->slot_index);
248 frame->sequence = s->seq_decode;
249 frame->flags = 0;
250 return frame;
251 }
252
253 /* 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)254 static int add_candidate_ref(HEVCContext *s, RefPicList *list,
255 int poc, int ref_flag, RK_U32 cur_used)
256 {
257 HEVCFrame *ref = find_ref_idx(s, poc);
258
259 if (!ref) {
260 ref = generate_missing_ref(s, poc);
261 if (!ref)
262 return MPP_ERR_NOMEM;
263
264 ref->error_flag = 1;
265 }
266
267 list->list[list->nb_refs] = ref->poc;
268 list->ref[list->nb_refs] = ref;
269 list->nb_refs++;
270 if (ref_flag) {
271 h265d_dbg(H265D_DBG_REF, "set ref poc = %d ref->slot_index %d", ref->poc, ref->slot_index);
272 mpp_buf_slot_set_flag(s->slots, ref->slot_index, SLOT_CODEC_USE);
273 }
274 mark_ref(ref, ref_flag);
275 if (ref->error_flag && cur_used) {
276 s->miss_ref_flag = 1;
277 }
278 return 0;
279 }
280
mpp_hevc_frame_rps(HEVCContext * s)281 RK_S32 mpp_hevc_frame_rps(HEVCContext *s)
282 {
283
284 const ShortTermRPS *short_rps = s->sh.short_term_rps;
285 const LongTermRPS *long_rps = &s->sh.long_term_rps;
286 RefPicList *rps = s->rps;
287 RK_S32 ret;
288 RK_U32 i;
289
290 if (!short_rps) {
291 rps[0].nb_refs = rps[1].nb_refs = 0;
292 return 0;
293 }
294
295 /* clear the reference flags on all frames except the current one */
296 for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
297 HEVCFrame *frame = &s->DPB[i];
298 mark_ref(frame, 0);
299 }
300
301 for (i = 0; i < NB_RPS_TYPE; i++)
302 rps[i].nb_refs = 0;
303
304 /* add the short refs */
305 for (i = 0; short_rps && (RK_S32)i < short_rps->num_delta_pocs; i++) {
306 int poc = s->poc + short_rps->delta_poc[i];
307 int list;
308
309 if (!short_rps->used[i])
310 list = ST_FOLL;
311 else if (i < short_rps->num_negative_pics)
312 list = ST_CURR_BEF;
313 else
314 list = ST_CURR_AFT;
315
316 ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_SHORT_REF, ST_FOLL != list);
317 if (ret < 0)
318 return ret;
319 }
320
321 /* add the long refs */
322 for (i = 0; long_rps && i < long_rps->nb_refs; i++) {
323 int poc = long_rps->poc[i];
324 int list = long_rps->used[i] ? LT_CURR : LT_FOLL;
325
326 ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_LONG_REF, LT_FOLL != list);
327 if (ret < 0)
328 return ret;
329 }
330 /* release any frames that are now unused */
331 for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
332 mpp_hevc_unref_frame(s, &s->DPB[i], 0);
333 }
334 /*
335 * flush for CRA frame if there has frame poc > cur poc in dpb.
336 */
337 if (IS_CRA(s)) {
338 for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) {
339 HEVCFrame *ref = &s->DPB[i];
340
341 if ((ref->slot_index != 0xff) && (ref->poc > s->poc)) {
342 h265d_flush(s->h265dctx);
343 break;
344 }
345 }
346 }
347
348 return 0;
349 }
350
mpp_hevc_compute_poc(HEVCContext * s,int poc_lsb)351 int mpp_hevc_compute_poc(HEVCContext *s, int poc_lsb)
352 {
353 RK_S32 max_poc_lsb = 1 << s->sps->log2_max_poc_lsb;
354 RK_S32 prev_poc_lsb = s->pocTid0 % max_poc_lsb;
355 RK_S32 prev_poc_msb = s->pocTid0 - prev_poc_lsb;
356 RK_S32 poc_msb;
357
358 if (poc_lsb < prev_poc_lsb && prev_poc_lsb - poc_lsb >= max_poc_lsb / 2)
359 poc_msb = prev_poc_msb + max_poc_lsb;
360 else if (poc_lsb > prev_poc_lsb && poc_lsb - prev_poc_lsb > max_poc_lsb / 2)
361 poc_msb = prev_poc_msb - max_poc_lsb;
362 else
363 poc_msb = prev_poc_msb;
364
365 // For BLA picture types, POCmsb is set to 0.
366 if (s->nal_unit_type == NAL_BLA_W_LP ||
367 s->nal_unit_type == NAL_BLA_W_RADL ||
368 s->nal_unit_type == NAL_BLA_N_LP)
369 poc_msb = 0;
370
371 return poc_msb + poc_lsb;
372 }
373
mpp_hevc_frame_nb_refs(HEVCContext * s)374 int mpp_hevc_frame_nb_refs(HEVCContext *s)
375 {
376 RK_S32 ret = 0;
377 RK_S32 i;
378 const ShortTermRPS *rps = s->sh.short_term_rps;
379 LongTermRPS *long_rps = &s->sh.long_term_rps;
380
381 if (s->sh.slice_type == I_SLICE) {
382 return 0;
383 }
384 if (rps) {
385 for (i = 0; (RK_U32)i < rps->num_negative_pics; i++)
386 ret += !!rps->used[i];
387 for (; i < rps->num_delta_pocs; i++)
388 ret += !!rps->used[i];
389 }
390
391 if (long_rps) {
392 for (i = 0; i < long_rps->nb_refs; i++)
393 ret += !!long_rps->used[i];
394 }
395 return ret;
396 }
397
398