/src/libhevc/decoder/ihevcd_decode.c
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore |
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 | | ******************************************************************************* |
20 | | * @file |
21 | | * ihevcd_decode.c |
22 | | * |
23 | | * @brief |
24 | | * Contains codecs main decode function |
25 | | * |
26 | | * @author |
27 | | * Harish |
28 | | * |
29 | | * @par List of Functions: |
30 | | * - fill_outargs() |
31 | | * - ihevcd_decode |
32 | | * @remarks |
33 | | * None |
34 | | * |
35 | | ******************************************************************************* |
36 | | */ |
37 | | /*****************************************************************************/ |
38 | | /* File Includes */ |
39 | | /*****************************************************************************/ |
40 | | #include <stdio.h> |
41 | | #include <stddef.h> |
42 | | #include <stdlib.h> |
43 | | #include <string.h> |
44 | | #include <assert.h> |
45 | | |
46 | | #include "ihevc_typedefs.h" |
47 | | #include "iv.h" |
48 | | #include "ivd.h" |
49 | | #include "ihevcd_cxa.h" |
50 | | #include "ithread.h" |
51 | | |
52 | | #include "ihevc_defs.h" |
53 | | #include "ihevc_debug.h" |
54 | | #include "ihevc_structs.h" |
55 | | #include "ihevc_macros.h" |
56 | | #include "ihevc_platform_macros.h" |
57 | | #include "ihevc_cabac_tables.h" |
58 | | #include "ihevc_disp_mgr.h" |
59 | | #include "ihevc_buf_mgr.h" |
60 | | #include "ihevc_dpb_mgr.h" |
61 | | #include "ihevc_error.h" |
62 | | |
63 | | #include "ihevcd_defs.h" |
64 | | #include "ihevcd_function_selector.h" |
65 | | #include "ihevcd_structs.h" |
66 | | #include "ihevcd_error.h" |
67 | | #include "ihevcd_nal.h" |
68 | | #include "ihevcd_bitstream.h" |
69 | | #include "ihevcd_fmt_conv.h" |
70 | | #include "ihevcd_job_queue.h" |
71 | | #include "ihevcd_debug.h" |
72 | | #include "ihevcd_parse_slice.h" |
73 | | #include "ihevcd_process_slice.h" |
74 | | #include "ihevcd_ittiam_logo.h" |
75 | | #include "ihevcd_profile.h" |
76 | | |
77 | | #define NUM_FRAMES_LIMIT_ENABLED 0 |
78 | | |
79 | | #if NUM_FRAMES_LIMIT_ENABLED |
80 | | #define NUM_FRAMES_LIMIT 10000 |
81 | | #else |
82 | 62.4k | #define NUM_FRAMES_LIMIT 0x7FFFFFFF |
83 | | #endif |
84 | | |
85 | | IHEVCD_ERROR_T ihevcd_check_out_buf_size(codec_t *ps_codec); |
86 | | IHEVCD_ERROR_T ihevcd_fmt_conv(codec_t *ps_codec, |
87 | | process_ctxt_t *ps_proc, |
88 | | UWORD8 *pu1_y_dst, |
89 | | UWORD8 *pu1_u_dst, |
90 | | UWORD8 *pu1_v_dst, |
91 | | WORD32 cur_row, |
92 | | WORD32 num_rows); |
93 | | WORD32 ihevcd_init(codec_t *ps_codec); |
94 | | |
95 | | WORD32 ihevcd_allocate_dynamic_bufs(codec_t *ps_codec); |
96 | | WORD32 ihevcd_free_dynamic_bufs(codec_t *ps_codec); |
97 | | /*****************************************************************************/ |
98 | | /* Function Prototypes */ |
99 | | /*****************************************************************************/ |
100 | | |
101 | | |
102 | | /** |
103 | | ******************************************************************************* |
104 | | * |
105 | | * @brief Fills output arguments for decode process |
106 | | * |
107 | | * @par Description |
108 | | * Fills elements in the output structure based on the current state |
109 | | * |
110 | | * @param[in] ps_codec |
111 | | * Codec context |
112 | | * |
113 | | * @param[in] ps_dec_ip |
114 | | * Pointer to input structure |
115 | | * |
116 | | * @param[in] ps_dec_op |
117 | | * Pointer to output structure |
118 | | * |
119 | | * @returns none |
120 | | * |
121 | | * @remarks |
122 | | * |
123 | | ******************************************************************************* |
124 | | */ |
125 | | static UWORD32 ihevcd_map_error(IHEVCD_ERROR_T e_error) |
126 | 62.4k | { |
127 | 62.4k | UWORD32 error_code = 0; |
128 | 62.4k | error_code = e_error; |
129 | 62.4k | switch(error_code) |
130 | 62.4k | { |
131 | 47.7k | case IHEVCD_SUCCESS : |
132 | 47.7k | break; |
133 | 0 | case IHEVCD_INIT_NOT_DONE: |
134 | 0 | case IHEVCD_LEVEL_UNSUPPORTED: |
135 | 0 | case IHEVCD_NUM_REF_UNSUPPORTED: |
136 | 0 | case IHEVCD_NUM_REORDER_UNSUPPORTED: |
137 | 0 | case IHEVCD_NUM_EXTRA_DISP_UNSUPPORTED: |
138 | 0 | case IHEVCD_INSUFFICIENT_MEM_MVBANK: |
139 | 0 | case IHEVCD_INSUFFICIENT_MEM_PICBUF: |
140 | 595 | case IHEVCD_UNSUPPORTED_CHROMA_FMT_IDC: |
141 | 802 | case IHEVCD_UNSUPPORTED_BIT_DEPTH: |
142 | 802 | case IVD_MEM_ALLOC_FAILED: |
143 | 1.06k | case IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED: |
144 | 1.06k | error_code |= 1 << IVD_FATALERROR; |
145 | 1.06k | break; |
146 | 0 | case IHEVCD_INVALID_DISP_STRD: |
147 | 0 | case IHEVCD_CXA_VERS_BUF_INSUFFICIENT: |
148 | 0 | case IHEVCD_UNSUPPORTED_VPS_ID: |
149 | 2.73k | case IHEVCD_UNSUPPORTED_SPS_ID: |
150 | 3.03k | case IHEVCD_UNSUPPORTED_PPS_ID: |
151 | 3.03k | case IHEVCD_BUF_MGR_ERROR: |
152 | 3.03k | case IHEVCD_NO_FREE_MVBANK: |
153 | 3.03k | case IHEVCD_NO_FREE_PICBUF: |
154 | 3.03k | case IHEVCD_SLICE_IN_HEADER_MODE: |
155 | 3.03k | case IHEVCD_END_OF_SEQUENCE: |
156 | 3.03k | break; |
157 | 10.5k | default: |
158 | 10.5k | break; |
159 | 62.4k | } |
160 | 62.4k | return error_code; |
161 | 62.4k | } |
162 | | /** |
163 | | ******************************************************************************* |
164 | | * |
165 | | * @brief Fills output arguments for decode process |
166 | | * |
167 | | * @par Description |
168 | | * Fills elements in the output structure based on the current state |
169 | | * |
170 | | * @param[in] ps_codec |
171 | | * Codec context |
172 | | * |
173 | | * @param[in] ps_dec_ip |
174 | | * Pointer to input structure |
175 | | * |
176 | | * @param[in] ps_dec_op |
177 | | * Pointer to output structure |
178 | | * |
179 | | * @returns none |
180 | | * |
181 | | * @remarks |
182 | | * |
183 | | ******************************************************************************* |
184 | | */ |
185 | | static void ihevcd_fill_outargs(codec_t *ps_codec, |
186 | | void *pv_api_ip, |
187 | | void *pv_api_op) |
188 | 62.4k | { |
189 | | |
190 | 62.4k | ihevcd_cxa_video_decode_ip_t *ps_hevcd_dec_ip; |
191 | 62.4k | ihevcd_cxa_video_decode_op_t *ps_hevcd_dec_op; |
192 | 62.4k | ivd_video_decode_ip_t *ps_dec_ip; |
193 | 62.4k | ivd_video_decode_op_t *ps_dec_op; |
194 | | |
195 | 62.4k | ps_hevcd_dec_ip = (ihevcd_cxa_video_decode_ip_t *)pv_api_ip; |
196 | 62.4k | ps_hevcd_dec_op = (ihevcd_cxa_video_decode_op_t *)pv_api_op; |
197 | 62.4k | ps_dec_ip = &ps_hevcd_dec_ip->s_ivd_video_decode_ip_t; |
198 | 62.4k | ps_dec_op = &ps_hevcd_dec_op->s_ivd_video_decode_op_t; |
199 | | |
200 | 62.4k | ps_dec_op->u4_error_code = ihevcd_map_error((IHEVCD_ERROR_T)ps_codec->i4_error_code); |
201 | 62.4k | ps_dec_op->u4_num_bytes_consumed = ps_dec_ip->u4_num_Bytes |
202 | 62.4k | - ps_codec->i4_bytes_remaining; |
203 | 62.4k | if(ps_codec->i4_sps_done) |
204 | 28.7k | { |
205 | 28.7k | ps_dec_op->u4_pic_wd = ps_codec->i4_disp_wd; |
206 | 28.7k | ps_dec_op->u4_pic_ht = ps_codec->i4_disp_ht; |
207 | 28.7k | } |
208 | 33.6k | else |
209 | 33.6k | { |
210 | 33.6k | ps_dec_op->u4_pic_wd = 0; |
211 | 33.6k | ps_dec_op->u4_pic_ht = 0; |
212 | 33.6k | } |
213 | | |
214 | 62.4k | ps_dec_op->e_pic_type = ps_codec->e_dec_pic_type; |
215 | 62.4k | ps_dec_op->u4_frame_decoded_flag = ps_codec->i4_pic_present; |
216 | 62.4k | ps_dec_op->u4_new_seq = 0; |
217 | | |
218 | 62.4k | ps_dec_op->u4_output_present = 0; |
219 | 62.4k | ps_dec_op->u4_progressive_frame_flag = 1; |
220 | 62.4k | ps_dec_op->i4_display_index = -1; |
221 | 62.4k | ps_dec_op->i4_reorder_depth = -1; |
222 | 62.4k | if(ps_codec->i4_sps_done) |
223 | 28.7k | { |
224 | 28.7k | sps_t *ps_sps = (ps_codec->s_parse.ps_sps_base + ps_codec->i4_sps_id); |
225 | 28.7k | profile_tier_lvl_info_t *ps_ptl; |
226 | 28.7k | ps_ptl = &ps_sps->s_ptl; |
227 | 28.7k | if((0 == ps_ptl->s_ptl_gen.i1_general_progressive_source_flag) && |
228 | 17.2k | (1 == ps_ptl->s_ptl_gen.i1_general_interlaced_source_flag)) |
229 | 1.03k | { |
230 | 1.03k | ps_dec_op->u4_progressive_frame_flag = 0; |
231 | 1.03k | } |
232 | 28.7k | ps_dec_op->i4_reorder_depth = |
233 | 28.7k | ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1]; |
234 | 28.7k | } |
235 | | |
236 | 62.4k | ps_dec_op->u4_is_ref_flag = 1; |
237 | 62.4k | ps_dec_op->e_output_format = ps_codec->e_chroma_fmt; |
238 | 62.4k | ps_dec_op->u4_is_ref_flag = 1; |
239 | | |
240 | 62.4k | ps_dec_op->e4_fld_type = IV_FLD_TYPE_DEFAULT; |
241 | 62.4k | ps_dec_op->u4_ts = (UWORD32)(-1); |
242 | 62.4k | ps_dec_op->u4_disp_buf_id = ps_codec->i4_disp_buf_id; |
243 | 62.4k | if(ps_codec->i4_flush_mode) |
244 | 149 | { |
245 | 149 | ps_dec_op->u4_num_bytes_consumed = 0; |
246 | | /*In the case of flush ,since no frame is decoded set pic type as invalid*/ |
247 | 149 | ps_dec_op->u4_is_ref_flag = 0; |
248 | 149 | ps_dec_op->e_pic_type = IV_NA_FRAME; |
249 | 149 | ps_dec_op->u4_frame_decoded_flag = 0; |
250 | | |
251 | 149 | } |
252 | | /* If there is a display buffer */ |
253 | 62.4k | if(ps_codec->ps_disp_buf) |
254 | 9.46k | { |
255 | 9.46k | pic_buf_t *ps_disp_buf = ps_codec->ps_disp_buf; |
256 | 9.46k | #ifndef DISABLE_SEI |
257 | 9.46k | sei_params_t *ps_sei = &ps_disp_buf->s_sei_params; |
258 | | |
259 | 9.46k | if(ps_sei->i1_sei_parameters_present_flag && |
260 | 184 | ps_sei->i1_pic_timing_params_present_flag) |
261 | 78 | { |
262 | 78 | UWORD32 u4_pic_struct; |
263 | 78 | u4_pic_struct = ps_sei->s_pic_timing_sei_params.u4_pic_struct; |
264 | 78 | switch(u4_pic_struct) |
265 | 78 | { |
266 | 16 | case 1: |
267 | 16 | ps_dec_op->e4_fld_type = IV_TOP_FLD; |
268 | 16 | ps_dec_op->u4_progressive_frame_flag = 0; |
269 | 16 | break; |
270 | 0 | case 2: |
271 | 0 | ps_dec_op->e4_fld_type = IV_BOT_FLD; |
272 | 0 | ps_dec_op->u4_progressive_frame_flag = 0; |
273 | 0 | break; |
274 | 62 | case 0: |
275 | 62 | default: |
276 | 62 | ps_dec_op->e4_fld_type = IV_FLD_TYPE_DEFAULT; |
277 | 62 | ps_dec_op->u4_progressive_frame_flag = 1; |
278 | 62 | break; |
279 | 78 | } |
280 | 78 | } |
281 | 9.46k | #endif |
282 | 9.46k | ps_dec_op->i4_display_index = ps_disp_buf->i4_abs_poc; |
283 | 9.46k | ps_dec_op->u4_output_present = 1; |
284 | 9.46k | ps_dec_op->u4_ts = ps_disp_buf->u4_ts; |
285 | 9.46k | if((ps_codec->i4_flush_mode == 0) && (ps_codec->s_parse.i4_end_of_frame == 0)) |
286 | 0 | ps_dec_op->u4_output_present = 0; |
287 | 9.46k | ps_dec_op->s_disp_frm_buf.u4_y_wd = ps_codec->i4_disp_wd; |
288 | 9.46k | ps_dec_op->s_disp_frm_buf.u4_y_ht = ps_codec->i4_disp_ht; |
289 | | |
290 | 9.46k | if(ps_codec->i4_share_disp_buf) |
291 | 0 | { |
292 | 0 | ps_dec_op->s_disp_frm_buf.pv_y_buf = ps_disp_buf->pu1_luma; |
293 | 0 | if(ps_codec->e_chroma_fmt != IV_YUV_420P) |
294 | 0 | { |
295 | 0 | ps_dec_op->s_disp_frm_buf.pv_u_buf = ps_disp_buf->pu1_chroma; |
296 | 0 | ps_dec_op->s_disp_frm_buf.pv_v_buf = NULL; |
297 | 0 | } |
298 | 0 | else |
299 | 0 | { |
300 | 0 | WORD32 i; |
301 | 0 | UWORD8 *pu1_u_dst = NULL, *pu1_v_dst = NULL; |
302 | 0 | for(i = 0; i < ps_codec->i4_share_disp_buf_cnt; i++) |
303 | 0 | { |
304 | 0 | WORD32 diff = ps_disp_buf->pu1_luma - ps_codec->s_disp_buffer[i].pu1_bufs[0]; |
305 | 0 | if(diff == (ps_codec->i4_strd * PAD_TOP + PAD_LEFT)) |
306 | 0 | { |
307 | 0 | pu1_u_dst = ps_codec->s_disp_buffer[i].pu1_bufs[1]; |
308 | 0 | pu1_u_dst += (ps_codec->i4_strd * PAD_TOP) / 4 + (PAD_LEFT / 2); |
309 | |
|
310 | 0 | pu1_v_dst = ps_codec->s_disp_buffer[i].pu1_bufs[2]; |
311 | 0 | pu1_v_dst += (ps_codec->i4_strd * PAD_TOP) / 4 + (PAD_LEFT / 2); |
312 | 0 | break; |
313 | 0 | } |
314 | 0 | } |
315 | 0 | ps_dec_op->s_disp_frm_buf.pv_u_buf = pu1_u_dst; |
316 | 0 | ps_dec_op->s_disp_frm_buf.pv_v_buf = pu1_v_dst; |
317 | 0 | } |
318 | 0 | ps_dec_op->s_disp_frm_buf.u4_y_strd = ps_codec->i4_strd; |
319 | 0 | } |
320 | 9.46k | else |
321 | 9.46k | { |
322 | 9.46k | ps_dec_op->s_disp_frm_buf.pv_y_buf = |
323 | 9.46k | ps_dec_ip->s_out_buffer.pu1_bufs[0]; |
324 | 9.46k | ps_dec_op->s_disp_frm_buf.pv_u_buf = |
325 | 9.46k | ps_dec_ip->s_out_buffer.pu1_bufs[1]; |
326 | 9.46k | ps_dec_op->s_disp_frm_buf.pv_v_buf = |
327 | 9.46k | ps_dec_ip->s_out_buffer.pu1_bufs[2]; |
328 | 9.46k | ps_dec_op->s_disp_frm_buf.u4_y_strd = ps_codec->i4_disp_strd; |
329 | 9.46k | } |
330 | | |
331 | 9.46k | if((IV_YUV_420SP_VU == ps_codec->e_chroma_fmt) |
332 | 7.86k | || (IV_YUV_420SP_UV == ps_codec->e_chroma_fmt)) |
333 | 4.03k | { |
334 | 4.03k | ps_dec_op->s_disp_frm_buf.u4_u_strd = |
335 | 4.03k | ps_dec_op->s_disp_frm_buf.u4_y_strd; |
336 | 4.03k | ps_dec_op->s_disp_frm_buf.u4_v_strd = 0; |
337 | 4.03k | ps_dec_op->s_disp_frm_buf.u4_u_wd = |
338 | 4.03k | ps_dec_op->s_disp_frm_buf.u4_y_wd; |
339 | 4.03k | ps_dec_op->s_disp_frm_buf.u4_v_wd = 0; |
340 | 4.03k | ps_dec_op->s_disp_frm_buf.u4_u_ht = |
341 | 4.03k | ps_dec_op->s_disp_frm_buf.u4_y_ht / 2; |
342 | 4.03k | ps_dec_op->s_disp_frm_buf.u4_v_ht = 0; |
343 | 4.03k | } |
344 | 5.42k | else if(IV_YUV_420P == ps_codec->e_chroma_fmt) |
345 | 2.99k | { |
346 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_u_strd = |
347 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_y_strd / 2; |
348 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_v_strd = |
349 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_y_strd / 2; |
350 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_u_wd = |
351 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_y_wd / 2; |
352 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_v_wd = |
353 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_y_wd / 2; |
354 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_u_ht = |
355 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_y_ht / 2; |
356 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_v_ht = |
357 | 2.99k | ps_dec_op->s_disp_frm_buf.u4_y_ht / 2; |
358 | 2.99k | } |
359 | 2.43k | else if(IV_YUV_444P == ps_codec->e_chroma_fmt) |
360 | 0 | { |
361 | 0 | ps_dec_op->s_disp_frm_buf.u4_u_strd = ps_dec_op->s_disp_frm_buf.u4_y_strd; |
362 | 0 | ps_dec_op->s_disp_frm_buf.u4_v_strd = ps_dec_op->s_disp_frm_buf.u4_y_strd; |
363 | 0 | ps_dec_op->s_disp_frm_buf.u4_u_wd = ps_dec_op->s_disp_frm_buf.u4_y_wd; |
364 | 0 | ps_dec_op->s_disp_frm_buf.u4_v_wd = ps_dec_op->s_disp_frm_buf.u4_y_wd; |
365 | 0 | ps_dec_op->s_disp_frm_buf.u4_u_ht = ps_dec_op->s_disp_frm_buf.u4_y_ht; |
366 | 0 | ps_dec_op->s_disp_frm_buf.u4_v_ht = ps_dec_op->s_disp_frm_buf.u4_y_ht; |
367 | 0 | } |
368 | 2.43k | else if(IV_GRAY == ps_codec->e_chroma_fmt) |
369 | 2.43k | { |
370 | 2.43k | ps_dec_op->s_disp_frm_buf.u4_u_strd = 0; |
371 | 2.43k | ps_dec_op->s_disp_frm_buf.u4_v_strd = 0; |
372 | 2.43k | ps_dec_op->s_disp_frm_buf.u4_u_wd = 0; |
373 | 2.43k | ps_dec_op->s_disp_frm_buf.u4_v_wd = 0; |
374 | 2.43k | ps_dec_op->s_disp_frm_buf.u4_u_ht = 0; |
375 | 2.43k | ps_dec_op->s_disp_frm_buf.u4_v_ht = 0; |
376 | 2.43k | } |
377 | | |
378 | 9.46k | } |
379 | 52.9k | else if(ps_codec->i4_flush_mode) |
380 | 149 | { |
381 | 149 | ps_dec_op->u4_error_code = IHEVCD_END_OF_SEQUENCE; |
382 | | /* Come out of flush mode */ |
383 | 149 | ps_codec->i4_flush_mode = 0; |
384 | 149 | } |
385 | | |
386 | 62.4k | if(ps_codec->u1_enable_cu_info && ps_dec_op->u4_output_present) |
387 | 0 | { |
388 | 0 | WORD32 info_map_dst_strd = ALIGN8(ps_codec->i4_wd) >> 3; |
389 | 0 | WORD32 info_map_src_strd = ALIGN64(ps_codec->i4_wd) >> 3; |
390 | 0 | WORD32 info_map_ht = ALIGN8(ps_codec->i4_ht); |
391 | 0 | UWORD32 info_map_size = (ALIGN8(ps_codec->i4_wd) * info_map_ht) >> 6; |
392 | 0 | WORD32 vert_8x8; |
393 | 0 | UWORD8 *pu1_out_qp_map, *pu1_qp_map; |
394 | 0 | UWORD8 *pu1_out_blk_type_map, *pu1_type_map; |
395 | |
|
396 | 0 | if(ps_hevcd_dec_ip->pu1_8x8_blk_qp_map) |
397 | 0 | { |
398 | 0 | ps_hevcd_dec_op->pu1_8x8_blk_qp_map = ps_hevcd_dec_ip->pu1_8x8_blk_qp_map; |
399 | 0 | ps_hevcd_dec_op->u4_8x8_blk_qp_map_size = info_map_size; |
400 | |
|
401 | 0 | pu1_out_qp_map = ps_hevcd_dec_op->pu1_8x8_blk_qp_map; |
402 | 0 | pu1_qp_map = ps_codec->as_buf_id_info_map[ps_codec->i4_disp_buf_id].pu1_qp_map; |
403 | 0 | for(vert_8x8 = 0; vert_8x8 < info_map_ht; vert_8x8++) |
404 | 0 | { |
405 | 0 | memcpy(pu1_out_qp_map, pu1_qp_map, info_map_dst_strd); |
406 | 0 | pu1_out_qp_map += info_map_dst_strd; |
407 | 0 | pu1_qp_map += info_map_src_strd; |
408 | 0 | } |
409 | 0 | } |
410 | |
|
411 | 0 | if(ps_hevcd_dec_ip->pu1_8x8_blk_type_map) |
412 | 0 | { |
413 | 0 | ps_hevcd_dec_op->pu1_8x8_blk_type_map = ps_hevcd_dec_ip->pu1_8x8_blk_type_map; |
414 | 0 | ps_hevcd_dec_op->u4_8x8_blk_type_map_size = info_map_size; |
415 | |
|
416 | 0 | pu1_out_blk_type_map = ps_hevcd_dec_op->pu1_8x8_blk_type_map; |
417 | 0 | pu1_type_map = |
418 | 0 | ps_codec->as_buf_id_info_map[ps_codec->i4_disp_buf_id].pu1_cu_type_map; |
419 | 0 | for(vert_8x8 = 0; vert_8x8 < info_map_ht; vert_8x8++) |
420 | 0 | { |
421 | 0 | memcpy(pu1_out_blk_type_map, pu1_type_map, info_map_dst_strd); |
422 | 0 | pu1_out_blk_type_map += info_map_dst_strd; |
423 | 0 | pu1_type_map += info_map_src_strd; |
424 | 0 | } |
425 | 0 | } |
426 | 0 | } |
427 | 62.4k | } |
428 | | |
429 | | /** |
430 | | ******************************************************************************* |
431 | | * |
432 | | * @brief |
433 | | * Codec process call |
434 | | * |
435 | | * @par Description: |
436 | | * Codec process call Tests for few error checks Handle flush and decode |
437 | | * header related code Parse bitstream for start codes For each NAL unit |
438 | | * call decode NAL function Once a complete frame is decoded (in frame |
439 | | * decode mode) Fill output arguments and return |
440 | | * |
441 | | * @param[in] ps_codec_obj |
442 | | * Pointer to codec object at API level |
443 | | * |
444 | | * @param[in] pv_api_ip |
445 | | * Pointer to input argument structure |
446 | | * |
447 | | * @param[in] pv_api_op |
448 | | * Pointer to output argument structure |
449 | | * |
450 | | * @returns Status |
451 | | * |
452 | | * @remarks |
453 | | * |
454 | | * |
455 | | ******************************************************************************* |
456 | | */ |
457 | | WORD32 ihevcd_decode(iv_obj_t *ps_codec_obj, void *pv_api_ip, void *pv_api_op) |
458 | 62.4k | { |
459 | 62.4k | WORD32 ret = IV_SUCCESS; |
460 | 62.4k | codec_t *ps_codec = (codec_t *)(ps_codec_obj->pv_codec_handle); |
461 | 62.4k | ihevcd_cxa_video_decode_ip_t s_hevcd_dec_ip = {}; |
462 | 62.4k | ihevcd_cxa_video_decode_ip_t *ps_hevcd_dec_ip; |
463 | 62.4k | ihevcd_cxa_video_decode_op_t *ps_hevcd_dec_op; |
464 | 62.4k | ivd_video_decode_ip_t *ps_dec_ip; |
465 | 62.4k | ivd_video_decode_op_t *ps_dec_op; |
466 | | |
467 | 62.4k | WORD32 proc_idx = 0; |
468 | 62.4k | WORD32 prev_proc_idx = 0; |
469 | | |
470 | | /* Initialize error code */ |
471 | 62.4k | ps_codec->i4_error_code = 0; |
472 | | /* Initialize bytes remaining */ |
473 | 62.4k | ps_codec->i4_bytes_remaining = 0; |
474 | | |
475 | 62.4k | ps_dec_ip = (ivd_video_decode_ip_t *)pv_api_ip; |
476 | 62.4k | memcpy(&s_hevcd_dec_ip, ps_dec_ip, ps_dec_ip->u4_size); |
477 | 62.4k | s_hevcd_dec_ip.s_ivd_video_decode_ip_t.u4_size = sizeof(ihevcd_cxa_video_decode_ip_t); |
478 | | |
479 | 62.4k | ps_hevcd_dec_ip = &s_hevcd_dec_ip; |
480 | 62.4k | ps_dec_ip = &ps_hevcd_dec_ip->s_ivd_video_decode_ip_t; |
481 | | |
482 | 62.4k | ps_hevcd_dec_op = (ihevcd_cxa_video_decode_op_t *)pv_api_op; |
483 | 62.4k | ps_dec_op = &ps_hevcd_dec_op->s_ivd_video_decode_op_t; |
484 | | |
485 | 62.4k | { |
486 | 62.4k | UWORD32 u4_size = ps_dec_op->u4_size; |
487 | 62.4k | memset(ps_hevcd_dec_op, 0, u4_size); |
488 | 62.4k | ps_dec_op->u4_size = u4_size; //Restore size field |
489 | 62.4k | } |
490 | 62.4k | if(ps_codec->i4_init_done != 1) |
491 | 0 | { |
492 | 0 | ps_dec_op->u4_error_code |= 1 << IVD_FATALERROR; |
493 | 0 | ps_dec_op->u4_error_code |= IHEVCD_INIT_NOT_DONE; |
494 | 0 | return IV_FAIL; |
495 | 0 | } |
496 | | |
497 | 62.4k | if(ps_codec->u4_pic_cnt >= NUM_FRAMES_LIMIT) |
498 | 0 | { |
499 | 0 | ps_dec_op->u4_error_code |= 1 << IVD_FATALERROR; |
500 | 0 | ps_dec_op->u4_error_code |= IHEVCD_NUM_FRAMES_LIMIT_REACHED; |
501 | 0 | return IV_FAIL; |
502 | 0 | } |
503 | | |
504 | 62.4k | if(ps_codec->u1_enable_cu_info && ps_codec->i4_sps_done) |
505 | 0 | { |
506 | 0 | UWORD32 blk_qp_map_size = ps_hevcd_dec_ip->u4_8x8_blk_qp_map_size; |
507 | 0 | UWORD32 blk_type_map_size = ps_hevcd_dec_ip->u4_8x8_blk_type_map_size; |
508 | 0 | UWORD32 blk_8x8_map_size = (ALIGN8(ps_codec->i4_wd) * ALIGN8(ps_codec->i4_ht)) >> 6; |
509 | |
|
510 | 0 | if ((ps_hevcd_dec_ip->pu1_8x8_blk_qp_map && blk_qp_map_size < blk_8x8_map_size) || |
511 | 0 | (ps_hevcd_dec_ip->pu1_8x8_blk_type_map && blk_type_map_size < blk_8x8_map_size)) |
512 | 0 | { |
513 | 0 | ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; |
514 | 0 | ps_dec_op->u4_error_code |= IHEVCD_INSUFFICIENT_METADATA_BUFFER; |
515 | 0 | return IV_FAIL; |
516 | 0 | } |
517 | 0 | } |
518 | | |
519 | | /* If reset flag is set, flush the existing buffers */ |
520 | 62.4k | if(ps_codec->i4_reset_flag) |
521 | 149 | { |
522 | 149 | ps_codec->i4_flush_mode = 1; |
523 | 149 | } |
524 | | |
525 | | /*Data memory barries instruction,so that bitstream write by the application is complete*/ |
526 | | //arm_dsb(); |
527 | | /* In case the decoder is not in flush mode check for input buffer validity */ |
528 | 62.4k | if(0 == ps_codec->i4_flush_mode) |
529 | 62.2k | { |
530 | 62.2k | if(ps_dec_ip->pv_stream_buffer == NULL) |
531 | 0 | { |
532 | 0 | ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; |
533 | 0 | ps_dec_op->u4_error_code |= IVD_DEC_FRM_BS_BUF_NULL; |
534 | 0 | return IV_FAIL; |
535 | 0 | } |
536 | 62.2k | if(ps_dec_ip->u4_num_Bytes <= MIN_START_CODE_LEN) |
537 | 6 | { |
538 | 6 | if((WORD32)ps_dec_ip->u4_num_Bytes > 0) |
539 | 6 | ps_dec_op->u4_num_bytes_consumed = ps_dec_ip->u4_num_Bytes; |
540 | 0 | else |
541 | 0 | ps_dec_op->u4_num_bytes_consumed = 0; |
542 | | |
543 | 6 | ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; |
544 | 6 | ps_dec_op->u4_error_code |= IVD_DEC_NUMBYTES_INV; |
545 | 6 | return IV_FAIL; |
546 | | |
547 | 6 | } |
548 | 62.2k | } |
549 | | |
550 | | #ifdef APPLY_CONCEALMENT |
551 | | { |
552 | | WORD32 num_mbs; |
553 | | |
554 | | num_mbs = (ps_codec->i4_wd * ps_codec->i4_ht + 255) >> 8; |
555 | | /* Reset MB Count at the beginning of every process call */ |
556 | | ps_codec->mb_count = 0; |
557 | | memset(ps_codec->mb_map, 0, ((num_mbs + 7) >> 3)); |
558 | | } |
559 | | #endif |
560 | | |
561 | 62.4k | if(0 == ps_codec->i4_share_disp_buf && ps_codec->i4_header_mode == 0) |
562 | 33.3k | { |
563 | 33.3k | UWORD32 i; |
564 | 33.3k | if((ps_dec_ip->s_out_buffer.u4_num_bufs <= 0) || |
565 | 33.3k | (ps_dec_ip->s_out_buffer.u4_num_bufs > IVD_VIDDEC_MAX_IO_BUFFERS)) |
566 | 0 | { |
567 | 0 | ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; |
568 | 0 | ps_dec_op->u4_error_code |= IVD_DISP_FRM_ZERO_OP_BUFS; |
569 | 0 | return IV_FAIL; |
570 | 0 | } |
571 | | |
572 | 104k | for(i = 0; i < ps_dec_ip->s_out_buffer.u4_num_bufs; i++) |
573 | 70.7k | { |
574 | 70.7k | if(ps_dec_ip->s_out_buffer.pu1_bufs[i] == NULL) |
575 | 0 | { |
576 | 0 | ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; |
577 | 0 | ps_dec_op->u4_error_code |= IVD_DISP_FRM_OP_BUF_NULL; |
578 | 0 | return IV_FAIL; |
579 | 0 | } |
580 | | |
581 | 70.7k | if(ps_dec_ip->s_out_buffer.u4_min_out_buf_size[i] == 0) |
582 | 0 | { |
583 | 0 | ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; |
584 | 0 | ps_dec_op->u4_error_code |= IVD_DISP_FRM_ZERO_OP_BUF_SIZE; |
585 | 0 | return IV_FAIL; |
586 | 0 | } |
587 | 70.7k | } |
588 | 33.3k | } |
589 | | |
590 | 62.4k | ps_codec->ps_out_buffer = &ps_dec_ip->s_out_buffer; |
591 | 62.4k | ps_codec->u4_ts = ps_dec_ip->u4_ts; |
592 | 62.4k | if(ps_codec->i4_flush_mode) |
593 | 149 | { |
594 | | |
595 | 149 | ps_dec_op->u4_pic_wd = ps_codec->i4_disp_wd; |
596 | 149 | ps_dec_op->u4_pic_ht = ps_codec->i4_disp_ht; |
597 | | |
598 | 149 | ps_dec_op->u4_new_seq = 0; |
599 | | |
600 | 149 | ps_codec->ps_disp_buf = (pic_buf_t *)ihevc_disp_mgr_get( |
601 | 149 | (disp_mgr_t *)ps_codec->pv_disp_buf_mgr, &ps_codec->i4_disp_buf_id); |
602 | | /* In case of non-shared mode, then convert/copy the frame to output buffer */ |
603 | | /* Only if the codec is in non-shared mode or in shared mode but needs 420P output */ |
604 | 149 | if((ps_codec->ps_disp_buf) |
605 | 0 | && ((0 == ps_codec->i4_share_disp_buf) |
606 | 0 | || (IV_YUV_420P |
607 | 0 | == ps_codec->e_chroma_fmt))) |
608 | 0 | { |
609 | |
|
610 | 0 | process_ctxt_t *ps_proc = &ps_codec->as_process[prev_proc_idx]; |
611 | 0 | if(0 == ps_proc->i4_init_done) |
612 | 0 | { |
613 | 0 | ihevcd_init_proc_ctxt(ps_proc, 0); |
614 | 0 | } |
615 | | |
616 | | /* Output buffer check */ |
617 | 0 | ret = ihevcd_check_out_buf_size(ps_codec); |
618 | 0 | RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret); |
619 | | |
620 | | /* Set remaining number of rows to be processed */ |
621 | 0 | ret = ihevcd_fmt_conv(ps_codec, &ps_codec->as_process[prev_proc_idx], |
622 | 0 | ps_dec_ip->s_out_buffer.pu1_bufs[0], |
623 | 0 | ps_dec_ip->s_out_buffer.pu1_bufs[1], |
624 | 0 | ps_dec_ip->s_out_buffer.pu1_bufs[2], 0, |
625 | 0 | ps_codec->i4_disp_ht); |
626 | |
|
627 | 0 | ihevc_buf_mgr_release((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, |
628 | 0 | ps_codec->i4_disp_buf_id, BUF_MGR_DISP); |
629 | 0 | } |
630 | | |
631 | 149 | ihevcd_fill_outargs(ps_codec, ps_hevcd_dec_ip, ps_hevcd_dec_op); |
632 | | |
633 | 149 | if(1 == ps_dec_op->u4_output_present) |
634 | 0 | { |
635 | 0 | WORD32 xpos = ps_codec->i4_disp_wd - 32 - LOGO_WD; |
636 | 0 | WORD32 ypos = ps_codec->i4_disp_ht - 32 - LOGO_HT; |
637 | |
|
638 | 0 | if(ypos < 0) |
639 | 0 | ypos = 0; |
640 | |
|
641 | 0 | if(xpos < 0) |
642 | 0 | xpos = 0; |
643 | |
|
644 | 0 | INSERT_LOGO(ps_dec_ip->s_out_buffer.pu1_bufs[0], |
645 | 0 | ps_dec_ip->s_out_buffer.pu1_bufs[1], |
646 | 0 | ps_dec_ip->s_out_buffer.pu1_bufs[2], ps_codec->i4_disp_strd, |
647 | 0 | xpos, |
648 | 0 | ypos, |
649 | 0 | ps_codec->e_chroma_fmt, |
650 | 0 | ps_codec->i4_disp_wd, |
651 | 0 | ps_codec->i4_disp_ht); |
652 | 0 | } |
653 | | |
654 | | |
655 | 149 | if(NULL == ps_codec->ps_disp_buf) |
656 | 149 | { |
657 | | /* If in flush mode and there are no more buffers to flush, |
658 | | * check for the reset flag and reset the decoder */ |
659 | 149 | if(ps_codec->i4_reset_flag) |
660 | 149 | { |
661 | 149 | ihevcd_init(ps_codec); |
662 | 149 | } |
663 | 149 | return (IV_FAIL); |
664 | 149 | } |
665 | | |
666 | 0 | return (IV_SUCCESS); |
667 | | |
668 | 149 | } |
669 | | /* In case of shared mode, check if there is a free buffer for reconstruction */ |
670 | 62.2k | if((0 == ps_codec->i4_header_mode) && (1 == ps_codec->i4_share_disp_buf)) |
671 | 0 | { |
672 | 0 | WORD32 buf_status; |
673 | 0 | buf_status = 1; |
674 | 0 | if(ps_codec->pv_pic_buf_mgr) |
675 | 0 | buf_status = ihevc_buf_mgr_check_free((buf_mgr_t *)ps_codec->pv_pic_buf_mgr); |
676 | | |
677 | | /* If there is no free buffer, then return with an error code */ |
678 | 0 | if(0 == buf_status) |
679 | 0 | { |
680 | 0 | ps_dec_op->u4_error_code = IVD_DEC_REF_BUF_NULL; |
681 | 0 | ps_dec_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM); |
682 | 0 | return IV_FAIL; |
683 | 0 | } |
684 | 0 | } |
685 | 62.2k | ps_codec->i4_bytes_remaining = ps_dec_ip->u4_num_Bytes; |
686 | 62.2k | ps_codec->pu1_inp_bitsbuf = (UWORD8 *)ps_dec_ip->pv_stream_buffer; |
687 | 62.2k | ps_codec->s_parse.i4_end_of_frame = 0; |
688 | | |
689 | 62.2k | ps_codec->i4_pic_present = 0; |
690 | 62.2k | ps_codec->i4_slice_error = 0; |
691 | 62.2k | ps_codec->ps_disp_buf = NULL; |
692 | | |
693 | 62.2k | if(ps_codec->i4_num_cores > 1) |
694 | 29.8k | { |
695 | 29.8k | ithread_set_affinity(0); |
696 | 29.8k | } |
697 | 137k | while(MIN_START_CODE_LEN < ps_codec->i4_bytes_remaining) |
698 | 136k | { |
699 | 136k | WORD32 nal_len; |
700 | 136k | WORD32 nal_ofst; |
701 | 136k | WORD32 bits_len; |
702 | | |
703 | 136k | if(ps_codec->i4_slice_error) |
704 | 2.09k | { |
705 | 2.09k | slice_header_t *ps_slice_hdr_next = ps_codec->s_parse.ps_slice_hdr_base + (ps_codec->s_parse.i4_cur_slice_idx & (MAX_SLICE_HDR_CNT - 1)); |
706 | 2.09k | WORD32 next_slice_addr = ps_slice_hdr_next->i2_ctb_x + |
707 | 2.09k | ps_slice_hdr_next->i2_ctb_y * ps_codec->s_parse.ps_sps->i2_pic_wd_in_ctb; |
708 | 2.09k | if(ps_codec->s_parse.i4_next_ctb_indx == next_slice_addr) |
709 | 0 | ps_codec->i4_slice_error = 0; |
710 | 2.09k | } |
711 | | |
712 | 136k | if(ps_codec->pu1_bitsbuf_dynamic) |
713 | 10.7k | { |
714 | 10.7k | ps_codec->pu1_bitsbuf = ps_codec->pu1_bitsbuf_dynamic; |
715 | 10.7k | ps_codec->u4_bitsbuf_size = ps_codec->u4_bitsbuf_size_dynamic; |
716 | 10.7k | } |
717 | 126k | else |
718 | 126k | { |
719 | 126k | ps_codec->pu1_bitsbuf = ps_codec->pu1_bitsbuf_static; |
720 | 126k | ps_codec->u4_bitsbuf_size = ps_codec->u4_bitsbuf_size_static; |
721 | 126k | } |
722 | | |
723 | 136k | nal_ofst = ihevcd_nal_search_start_code(ps_codec->pu1_inp_bitsbuf, |
724 | 136k | ps_codec->i4_bytes_remaining); |
725 | | /* If there is no start code found, consume the data and break */ |
726 | 136k | if(nal_ofst == ps_codec->i4_bytes_remaining) |
727 | 28 | { |
728 | 28 | ps_codec->pu1_inp_bitsbuf += nal_ofst; |
729 | 28 | ps_codec->i4_bytes_remaining -= nal_ofst; |
730 | 28 | break; |
731 | 28 | } |
732 | | |
733 | 136k | ps_codec->i4_nal_ofst = nal_ofst; |
734 | 136k | { |
735 | 136k | WORD32 bytes_remaining = ps_codec->i4_bytes_remaining - nal_ofst; |
736 | | |
737 | 136k | bytes_remaining = MIN((UWORD32)bytes_remaining, ps_codec->u4_bitsbuf_size); |
738 | 136k | ihevcd_nal_remv_emuln_bytes(ps_codec->pu1_inp_bitsbuf + nal_ofst, |
739 | 136k | ps_codec->pu1_bitsbuf, |
740 | 136k | bytes_remaining, |
741 | 136k | &nal_len, &bits_len); |
742 | | |
743 | | /* Decoder may read upto 8 extra bytes at the end of frame */ |
744 | | /* These are not used, but still set them to zero to avoid uninitialized reads */ |
745 | 136k | if(bits_len < (WORD32)(ps_codec->u4_bitsbuf_size - 8)) |
746 | 136k | { |
747 | 136k | memset(ps_codec->pu1_bitsbuf + bits_len, 0, 2 * sizeof(UWORD32)); |
748 | 136k | } |
749 | 136k | } |
750 | | /* This may be used to update the offsets for tiles and entropy sync row offsets */ |
751 | 136k | ps_codec->i4_num_emln_bytes = nal_len - bits_len; |
752 | 136k | ps_codec->i4_nal_len = nal_len; |
753 | | |
754 | 136k | ihevcd_bits_init(&ps_codec->s_parse.s_bitstrm, ps_codec->pu1_bitsbuf, |
755 | 136k | bits_len); |
756 | | |
757 | 136k | ret = ihevcd_nal_unit(ps_codec); |
758 | | |
759 | | /* If the frame is incomplete and |
760 | | * the bytes remaining is zero or a header is received, |
761 | | * complete the frame treating it to be in error */ |
762 | 136k | if(ps_codec->i4_pic_present && |
763 | 31.4k | (ps_codec->s_parse.i4_next_ctb_indx != ps_codec->s_parse.ps_sps->i4_pic_size_in_ctb)) |
764 | 21.9k | { |
765 | 21.9k | if((ps_codec->i4_bytes_remaining - (nal_len + nal_ofst) <= MIN_START_CODE_LEN) || |
766 | 21.6k | (ps_codec->i4_header_in_slice_mode)) |
767 | 1.51k | { |
768 | 1.51k | slice_header_t *ps_slice_hdr_next; |
769 | | |
770 | 1.51k | ps_codec->s_parse.i4_cur_slice_idx--; |
771 | 1.51k | if(ps_codec->s_parse.i4_cur_slice_idx < 0) |
772 | 0 | ps_codec->s_parse.i4_cur_slice_idx = 0; |
773 | | |
774 | 1.51k | ps_slice_hdr_next = ps_codec->s_parse.ps_slice_hdr_base + ((ps_codec->s_parse.i4_cur_slice_idx + 1) & (MAX_SLICE_HDR_CNT - 1)); |
775 | 1.51k | ps_slice_hdr_next->i2_ctb_x = 0; |
776 | 1.51k | ps_slice_hdr_next->i2_ctb_y = ps_codec->s_parse.ps_sps->i2_pic_ht_in_ctb; |
777 | 1.51k | ps_codec->i4_slice_error = 1; |
778 | 1.51k | continue; |
779 | 1.51k | } |
780 | 21.9k | } |
781 | | |
782 | 135k | if(IHEVCD_IGNORE_SLICE == ret) |
783 | 16.5k | { |
784 | 16.5k | ps_codec->pu1_inp_bitsbuf += (nal_ofst + nal_len); |
785 | 16.5k | ps_codec->i4_bytes_remaining -= (nal_ofst + nal_len); |
786 | | |
787 | 16.5k | continue; |
788 | 16.5k | } |
789 | | |
790 | 118k | if(IVD_RES_CHANGED == ret) |
791 | 1.53k | { |
792 | 1.53k | break; |
793 | 1.53k | } |
794 | | |
795 | | /* Update bytes remaining and bytes consumed and input bitstream pointer */ |
796 | | /* Do not consume the NAL in the following cases */ |
797 | | /* Slice header reached during header decode mode */ |
798 | | /* TODO: Next picture's slice reached */ |
799 | 117k | if(ret != IHEVCD_SLICE_IN_HEADER_MODE) |
800 | 92.3k | { |
801 | 92.3k | if((0 == ps_codec->i4_slice_error) || |
802 | 38 | (ps_codec->i4_bytes_remaining - (nal_len + nal_ofst) <= MIN_START_CODE_LEN)) |
803 | 92.2k | { |
804 | 92.2k | ps_codec->pu1_inp_bitsbuf += (nal_ofst + nal_len); |
805 | 92.2k | ps_codec->i4_bytes_remaining -= (nal_ofst + nal_len); |
806 | 92.2k | } |
807 | 92.3k | if(ret != IHEVCD_SUCCESS) |
808 | 26.0k | break; |
809 | | |
810 | 66.2k | if(ps_codec->s_parse.i4_end_of_frame) |
811 | 9.52k | break; |
812 | 66.2k | } |
813 | 24.9k | else |
814 | 24.9k | { |
815 | 24.9k | ret = IHEVCD_SUCCESS; |
816 | 24.9k | break; |
817 | 24.9k | } |
818 | | |
819 | | /* Allocate dynamic bitstream buffer once SPS is decoded */ |
820 | 56.7k | if((ps_codec->u4_allocate_dynamic_done == 0) && ps_codec->i4_sps_done) |
821 | 2.26k | { |
822 | 2.26k | WORD32 ret; |
823 | 2.26k | ret = ihevcd_allocate_dynamic_bufs(ps_codec); |
824 | 2.26k | if(ret != IV_SUCCESS) |
825 | 0 | { |
826 | | /* Free any dynamic buffers that are allocated */ |
827 | 0 | ihevcd_free_dynamic_bufs(ps_codec); |
828 | 0 | ps_codec->i4_error_code = IVD_MEM_ALLOC_FAILED; |
829 | 0 | ps_dec_op->u4_error_code = 1 << IVD_FATALERROR; |
830 | 0 | ps_dec_op->u4_error_code |= IVD_MEM_ALLOC_FAILED; |
831 | |
|
832 | 0 | return IV_FAIL; |
833 | 0 | } |
834 | 2.26k | } |
835 | | |
836 | 56.7k | BREAK_AFTER_SLICE_NAL(); |
837 | 56.7k | } |
838 | | |
839 | 62.2k | if(1 == ps_codec->i4_pic_present && 0 == ps_codec->s_parse.i4_end_of_frame) |
840 | 1.40k | { |
841 | 1.40k | slice_header_t *ps_slice_hdr_next; |
842 | 1.40k | ps_codec->i4_slice_error = 1; |
843 | 1.40k | ps_codec->s_parse.i4_cur_slice_idx--; |
844 | 1.40k | if(ps_codec->s_parse.i4_cur_slice_idx < 0) |
845 | 0 | ps_codec->s_parse.i4_cur_slice_idx = 0; |
846 | | |
847 | 1.40k | ps_slice_hdr_next = ps_codec->s_parse.ps_slice_hdr_base + ((ps_codec->s_parse.i4_cur_slice_idx + 1) & (MAX_SLICE_HDR_CNT - 1)); |
848 | 1.40k | ps_slice_hdr_next->i2_ctb_x = -1; |
849 | 1.40k | ps_slice_hdr_next->i2_ctb_y = -1; |
850 | | |
851 | 1.40k | ihevcd_parse_slice_data(ps_codec); |
852 | 1.40k | ASSERT(ps_codec->s_parse.i4_end_of_frame != 0); |
853 | 1.40k | } |
854 | | |
855 | 62.2k | if(1 == ps_codec->i4_pic_present) |
856 | 10.9k | { |
857 | 10.9k | WORD32 i; |
858 | 10.9k | sps_t *ps_sps = ps_codec->s_parse.ps_sps; |
859 | 10.9k | ps_codec->i4_first_pic_done = 1; |
860 | | |
861 | | /*TODO temporary fix: end_of_frame is checked before adding format conversion to job queue */ |
862 | 10.9k | if(ps_codec->i4_num_cores > 1 && ps_codec->s_parse.i4_end_of_frame) |
863 | 4.95k | { |
864 | | |
865 | | /* Add job queue for format conversion / frame copy for each ctb row */ |
866 | | /* Only if the codec is in non-shared mode or in shared mode but needs 420P output */ |
867 | 4.95k | process_ctxt_t *ps_proc; |
868 | | |
869 | | /* i4_num_cores - 1 contexts are currently being used by other threads */ |
870 | 4.95k | ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1]; |
871 | | |
872 | 4.95k | if((ps_codec->ps_disp_buf) && |
873 | 4.20k | ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt))) |
874 | 4.20k | { |
875 | | /* If format conversion jobs were not issued in pic_init() add them here */ |
876 | 4.20k | if((0 == ps_codec->u4_enable_fmt_conv_ahead) || |
877 | 0 | (ps_codec->i4_disp_buf_id == ps_proc->i4_cur_pic_buf_id)) |
878 | 43.8k | for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++) |
879 | 39.6k | { |
880 | 39.6k | proc_job_t s_job; |
881 | 39.6k | IHEVCD_ERROR_T ret; |
882 | 39.6k | s_job.i4_cmd = CMD_FMTCONV; |
883 | 39.6k | s_job.i2_ctb_cnt = 0; |
884 | 39.6k | s_job.i2_ctb_x = 0; |
885 | 39.6k | s_job.i2_ctb_y = i; |
886 | 39.6k | s_job.i2_slice_idx = 0; |
887 | 39.6k | s_job.i4_tu_coeff_data_ofst = 0; |
888 | 39.6k | ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq, |
889 | 39.6k | &s_job, sizeof(proc_job_t), 1); |
890 | 39.6k | if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS) |
891 | 0 | return (WORD32)ret; |
892 | 39.6k | } |
893 | 4.20k | } |
894 | | /* Reached end of frame : Signal terminate */ |
895 | | /* The terminate flag is checked only after all the jobs are dequeued */ |
896 | 4.95k | ret = ihevcd_jobq_terminate((jobq_t *)ps_codec->s_parse.pv_proc_jobq); |
897 | | |
898 | 33.4k | while(1) |
899 | 33.4k | { |
900 | 33.4k | IHEVCD_ERROR_T ret; |
901 | 33.4k | proc_job_t s_job; |
902 | 33.4k | process_ctxt_t *ps_proc; |
903 | | |
904 | | /* i4_num_cores - 1 contexts are currently being used by other threads */ |
905 | 33.4k | ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1]; |
906 | | |
907 | 33.4k | ret = ihevcd_jobq_dequeue((jobq_t *)ps_proc->pv_proc_jobq, &s_job, |
908 | 33.4k | sizeof(proc_job_t), 1); |
909 | 33.4k | if((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret) |
910 | 4.95k | break; |
911 | | |
912 | 28.4k | ps_proc->i4_ctb_cnt = s_job.i2_ctb_cnt; |
913 | 28.4k | ps_proc->i4_ctb_x = s_job.i2_ctb_x; |
914 | 28.4k | ps_proc->i4_ctb_y = s_job.i2_ctb_y; |
915 | 28.4k | ps_proc->i4_cur_slice_idx = s_job.i2_slice_idx; |
916 | | |
917 | 28.4k | if(CMD_PROCESS == s_job.i4_cmd) |
918 | 14.4k | { |
919 | 14.4k | ihevcd_init_proc_ctxt(ps_proc, s_job.i4_tu_coeff_data_ofst); |
920 | | |
921 | 14.4k | ihevcd_process(ps_proc); |
922 | 14.4k | } |
923 | 13.9k | else if(CMD_FMTCONV == s_job.i4_cmd) |
924 | 13.9k | { |
925 | 13.9k | sps_t *ps_sps = ps_codec->s_parse.ps_sps; |
926 | 13.9k | WORD32 num_rows = 1 << ps_sps->i1_log2_ctb_size; |
927 | 13.9k | if(0 == ps_proc->i4_init_done) |
928 | 442 | { |
929 | 442 | ihevcd_init_proc_ctxt(ps_proc, 0); |
930 | 442 | } |
931 | | |
932 | 13.9k | num_rows = MIN(num_rows, (ps_codec->i4_disp_ht - (s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size))); |
933 | 13.9k | if(num_rows < 0) |
934 | 0 | num_rows = 0; |
935 | | |
936 | 13.9k | ihevcd_fmt_conv(ps_codec, ps_proc, |
937 | 13.9k | ps_dec_ip->s_out_buffer.pu1_bufs[0], |
938 | 13.9k | ps_dec_ip->s_out_buffer.pu1_bufs[1], |
939 | 13.9k | ps_dec_ip->s_out_buffer.pu1_bufs[2], |
940 | 13.9k | s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size, |
941 | 13.9k | num_rows); |
942 | 13.9k | } |
943 | 28.4k | } |
944 | 4.95k | } |
945 | | /* In case of non-shared mode and while running in single core mode, then convert/copy the frame to output buffer */ |
946 | | /* Only if the codec is in non-shared mode or in shared mode but needs 420P output */ |
947 | 5.96k | else if((ps_codec->ps_disp_buf) && ((0 == ps_codec->i4_share_disp_buf) || |
948 | 0 | (IV_YUV_420P == ps_codec->e_chroma_fmt)) && |
949 | 5.26k | (ps_codec->s_parse.i4_end_of_frame)) |
950 | 5.26k | { |
951 | 5.26k | process_ctxt_t *ps_proc = &ps_codec->as_process[proc_idx]; |
952 | | /* Set remaining number of rows to be processed */ |
953 | 5.26k | ps_codec->s_fmt_conv.i4_num_rows = ps_codec->i4_disp_ht |
954 | 5.26k | - ps_codec->s_fmt_conv.i4_cur_row; |
955 | 5.26k | if(0 == ps_proc->i4_init_done) |
956 | 0 | { |
957 | 0 | ihevcd_init_proc_ctxt(ps_proc, 0); |
958 | 0 | } |
959 | | |
960 | 5.26k | if(ps_codec->s_fmt_conv.i4_num_rows < 0) |
961 | 0 | ps_codec->s_fmt_conv.i4_num_rows = 0; |
962 | | |
963 | 5.26k | ret = ihevcd_fmt_conv(ps_codec, ps_proc, |
964 | 5.26k | ps_dec_ip->s_out_buffer.pu1_bufs[0], |
965 | 5.26k | ps_dec_ip->s_out_buffer.pu1_bufs[1], |
966 | 5.26k | ps_dec_ip->s_out_buffer.pu1_bufs[2], |
967 | 5.26k | ps_codec->s_fmt_conv.i4_cur_row, |
968 | 5.26k | ps_codec->s_fmt_conv.i4_num_rows); |
969 | 5.26k | ps_codec->s_fmt_conv.i4_cur_row += ps_codec->s_fmt_conv.i4_num_rows; |
970 | | |
971 | 5.26k | } |
972 | | |
973 | | |
974 | 10.9k | DEBUG_DUMP_MV_MAP(ps_codec); |
975 | | |
976 | | /* Mark MV Buf as needed for reference */ |
977 | 10.9k | ihevc_buf_mgr_set_status((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, |
978 | 10.9k | ps_codec->as_process[proc_idx].i4_cur_mv_bank_buf_id, |
979 | 10.9k | BUF_MGR_REF); |
980 | | |
981 | | /* Mark pic buf as needed for reference */ |
982 | 10.9k | ihevc_buf_mgr_set_status((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, |
983 | 10.9k | ps_codec->as_process[proc_idx].i4_cur_pic_buf_id, |
984 | 10.9k | BUF_MGR_REF); |
985 | | |
986 | | /* Mark pic buf as needed for display */ |
987 | 10.9k | ihevc_buf_mgr_set_status((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, |
988 | 10.9k | ps_codec->as_process[proc_idx].i4_cur_pic_buf_id, |
989 | 10.9k | BUF_MGR_DISP); |
990 | | |
991 | | /* Insert the current picture as short term reference */ |
992 | 10.9k | ihevc_dpb_mgr_insert_ref((dpb_mgr_t *)ps_codec->pv_dpb_mgr, |
993 | 10.9k | ps_codec->as_process[proc_idx].ps_cur_pic, |
994 | 10.9k | ps_codec->as_process[proc_idx].i4_cur_pic_buf_id); |
995 | | |
996 | | /* If a frame was displayed (in non-shared mode), then release it from display manager */ |
997 | 10.9k | if((0 == ps_codec->i4_share_disp_buf) && (ps_codec->ps_disp_buf)) |
998 | 9.46k | ihevc_buf_mgr_release((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, |
999 | 9.46k | ps_codec->i4_disp_buf_id, BUF_MGR_DISP); |
1000 | | |
1001 | | /* Wait for threads */ |
1002 | 21.1k | for(i = 0; i < (ps_codec->i4_num_cores - 1); i++) |
1003 | 10.2k | { |
1004 | 10.2k | if(ps_codec->ai4_process_thread_created[i]) |
1005 | 10.2k | { |
1006 | 10.2k | if(ps_codec->i4_threads_active) |
1007 | 10.2k | { |
1008 | 10.2k | ret = ithread_mutex_lock(ps_codec->apv_proc_done_mutex[i]); |
1009 | 10.2k | RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret); |
1010 | | |
1011 | 13.6k | while(!ps_codec->ai4_process_done[i]) |
1012 | 3.43k | { |
1013 | 3.43k | ithread_cond_wait(ps_codec->apv_proc_done_condition[i], |
1014 | 3.43k | ps_codec->apv_proc_done_mutex[i]); |
1015 | 3.43k | } |
1016 | 10.2k | ps_codec->ai4_process_done[i] = 0; |
1017 | 10.2k | ret = ithread_mutex_unlock(ps_codec->apv_proc_done_mutex[i]); |
1018 | 10.2k | RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret); |
1019 | 10.2k | } |
1020 | 0 | else |
1021 | 0 | { |
1022 | 0 | ithread_join(ps_codec->apv_process_thread_handle[i], NULL); |
1023 | 0 | ps_codec->ai4_process_thread_created[i] = 0; |
1024 | 0 | } |
1025 | 10.2k | } |
1026 | 10.2k | } |
1027 | | |
1028 | 10.9k | DEBUG_VALIDATE_PADDED_REGION(&ps_codec->as_process[proc_idx]); |
1029 | 10.9k | if(ps_codec->u4_pic_cnt > 0) |
1030 | 9.32k | { |
1031 | 9.32k | DEBUG_DUMP_PIC_PU(ps_codec); |
1032 | 9.32k | } |
1033 | 10.9k | DEBUG_DUMP_PIC_BUFFERS(ps_codec); |
1034 | | |
1035 | | /* Increment the number of pictures decoded */ |
1036 | 10.9k | ps_codec->u4_pic_cnt++; |
1037 | 10.9k | } |
1038 | 62.2k | ihevcd_fill_outargs(ps_codec, ps_hevcd_dec_ip, ps_hevcd_dec_op); |
1039 | | |
1040 | 62.2k | if(1 == ps_dec_op->u4_output_present) |
1041 | 9.46k | { |
1042 | 9.46k | WORD32 xpos = ps_codec->i4_disp_wd - 32 - LOGO_WD; |
1043 | 9.46k | WORD32 ypos = ps_codec->i4_disp_ht - 32 - LOGO_HT; |
1044 | | |
1045 | 9.46k | if(ypos < 0) |
1046 | 1.42k | ypos = 0; |
1047 | | |
1048 | 9.46k | if(xpos < 0) |
1049 | 1.92k | xpos = 0; |
1050 | | |
1051 | 9.46k | INSERT_LOGO(ps_dec_ip->s_out_buffer.pu1_bufs[0], |
1052 | 9.46k | ps_dec_ip->s_out_buffer.pu1_bufs[1], |
1053 | 9.46k | ps_dec_ip->s_out_buffer.pu1_bufs[2], ps_codec->i4_disp_strd, |
1054 | 9.46k | xpos, |
1055 | 9.46k | ypos, |
1056 | 9.46k | ps_codec->e_chroma_fmt, |
1057 | 9.46k | ps_codec->i4_disp_wd, |
1058 | 9.46k | ps_codec->i4_disp_ht); |
1059 | 9.46k | } |
1060 | | |
1061 | | |
1062 | 62.2k | return ret; |
1063 | 62.2k | } |
1064 | | |