/work/svt-av1/Source/Lib/Codec/packetization_process.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright(c) 2019 Intel Corporation |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 2 Clause License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license. |
10 | | */ |
11 | | #include <stdlib.h> |
12 | | |
13 | | #include "enc_handle.h" |
14 | | #include "packetization_process.h" |
15 | | #include "ec_results.h" |
16 | | #include "sequence_control_set.h" |
17 | | #include "pcs.h" |
18 | | #include "entropy_coding.h" |
19 | | #include "rc_tasks.h" |
20 | | #include "svt_time.h" |
21 | | #include "md_process.h" |
22 | | #include "pic_demux_results.h" |
23 | | #include "svt_log.h" |
24 | | #include "EbSvtAv1ErrorCodes.h" |
25 | | #include "pd_results.h" |
26 | | #include "restoration.h" // RDCOST_DBL |
27 | | #include "rc_process.h" |
28 | | #include "enc_mode_config.h" |
29 | | |
30 | 0 | #define RDCOST_DBL_WITH_NATIVE_BD_DIST(RM, R, D, BD) RDCOST_DBL((RM), (R), (double)((D) >> (2 * (BD - 8)))) |
31 | | |
32 | | /************************************** |
33 | | * Context |
34 | | **************************************/ |
35 | | typedef struct PacketizationContext { |
36 | | EbDctor dctor; |
37 | | EbFifo* entropy_coding_input_fifo_ptr; |
38 | | EbFifo* rate_control_tasks_output_fifo_ptr; |
39 | | EbFifo* picture_decision_results_output_fifo_ptr; // to motion estimation process |
40 | | EbFifo* picture_demux_fifo_ptr; // to picture manager process |
41 | | #if DETAILED_FRAME_OUTPUT |
42 | | uint64_t dpb_disp_order[8], dpb_dec_order[8]; |
43 | | #endif |
44 | | uint64_t tot_shown_frames; |
45 | | uint64_t disp_order_continuity_count; |
46 | | } PacketizationContext; |
47 | | |
48 | | void free_temporal_filtering_buffer(PictureControlSet* pcs); |
49 | | void svt_aom_recon_output(PictureControlSet* pcs, SequenceControlSet* scs); |
50 | | void svt_aom_init_resize_picture(SequenceControlSet* scs, PictureParentControlSet* pcs); |
51 | | void pad_ref_and_set_flags(PictureControlSet* pcs, SequenceControlSet* scs); |
52 | | void svt_aom_update_rc_counts(PictureParentControlSet* ppcs); |
53 | | EbErrorType svt_aom_ssim_calculations(PictureControlSet* pcs, SequenceControlSet* scs, bool free_memory); |
54 | | |
55 | 474 | static void packetization_context_dctor(EbPtr p) { |
56 | 474 | EbThreadContext* thread_ctx = (EbThreadContext*)p; |
57 | 474 | PacketizationContext* obj = (PacketizationContext*)thread_ctx->priv; |
58 | 474 | EB_FREE_ARRAY(obj); |
59 | 474 | } |
60 | | |
61 | | EbErrorType svt_aom_packetization_context_ctor(EbThreadContext* thread_ctx, const EbEncHandle* enc_handle_ptr, |
62 | 474 | int rate_control_index, int demux_index, int me_port_index) { |
63 | 474 | PacketizationContext* context_ptr; |
64 | 474 | EB_CALLOC_ARRAY(context_ptr, 1); |
65 | 474 | thread_ctx->priv = context_ptr; |
66 | 474 | thread_ctx->dctor = packetization_context_dctor; |
67 | | |
68 | 474 | context_ptr->dctor = packetization_context_dctor; |
69 | 474 | context_ptr->entropy_coding_input_fifo_ptr = svt_system_resource_get_consumer_fifo( |
70 | 474 | enc_handle_ptr->entropy_coding_results_resource_ptr, 0); |
71 | 474 | context_ptr->rate_control_tasks_output_fifo_ptr = svt_system_resource_get_producer_fifo( |
72 | 474 | enc_handle_ptr->rate_control_tasks_resource_ptr, rate_control_index); |
73 | 474 | context_ptr->picture_demux_fifo_ptr = svt_system_resource_get_producer_fifo( |
74 | 474 | enc_handle_ptr->picture_demux_results_resource_ptr, demux_index); |
75 | 474 | context_ptr->picture_decision_results_output_fifo_ptr = svt_system_resource_get_producer_fifo( |
76 | 474 | enc_handle_ptr->picture_decision_results_resource_ptr, me_port_index); |
77 | | |
78 | 474 | return EB_ErrorNone; |
79 | 474 | } |
80 | | |
81 | 3.31k | static inline int get_reorder_queue_pos(const EncodeContext* enc_ctx, int delta) { |
82 | 3.31k | return (enc_ctx->packetization_reorder_queue_head_index + delta) % enc_ctx->packetization_reorder_queue_size; |
83 | 3.31k | } |
84 | | |
85 | 2.84k | static inline PacketizationReorderEntry* get_reorder_queue_entry(const EncodeContext* enc_ctx, int delta) { |
86 | 2.84k | int pos = get_reorder_queue_pos(enc_ctx, delta); |
87 | 2.84k | return enc_ctx->packetization_reorder_queue[pos]; |
88 | 2.84k | } |
89 | | |
90 | 948 | static uint32_t count_frames_in_next_tu(const EncodeContext* enc_ctx, uint32_t* data_size) { |
91 | 948 | uint32_t i = 0; |
92 | 948 | *data_size = 0; |
93 | 948 | do { |
94 | 948 | const PacketizationReorderEntry* queue_entry_ptr = get_reorder_queue_entry(enc_ctx, i); |
95 | 948 | const EbObjectWrapper* wrapper = queue_entry_ptr->output_stream_wrapper_ptr; |
96 | | // not a completed td |
97 | 948 | if (!wrapper) { |
98 | 474 | return 0; |
99 | 474 | } |
100 | | |
101 | 474 | const EbBufferHeaderType* output_stream_ptr = (EbBufferHeaderType*)wrapper->object_ptr; |
102 | 474 | *data_size += output_stream_ptr->n_filled_len; |
103 | | |
104 | 474 | i++; |
105 | | //we have a td when we got a displable frame |
106 | 474 | if (queue_entry_ptr->show_frame) { |
107 | 474 | break; |
108 | 474 | } |
109 | 0 | if (output_stream_ptr->flags & EB_BUFFERFLAG_EOS) { |
110 | 0 | break; |
111 | 0 | } |
112 | |
|
113 | 0 | } while (i < enc_ctx->packetization_reorder_queue_size); |
114 | 474 | return i; |
115 | 948 | } |
116 | | |
117 | 0 | static int pts_descend(const void* pa, const void* pb) { |
118 | 0 | EbObjectWrapper* a = *(EbObjectWrapper**)pa; |
119 | 0 | EbObjectWrapper* b = *(EbObjectWrapper**)pb; |
120 | 0 | EbBufferHeaderType* ba = (EbBufferHeaderType*)(a->object_ptr); |
121 | 0 | EbBufferHeaderType* bb = (EbBufferHeaderType*)(b->object_ptr); |
122 | 0 | return (int)(bb->pts - ba->pts); |
123 | 0 | } |
124 | | |
125 | 0 | static void push_undisplayed_frame(EncodeContext* enc_ctx, EbObjectWrapper* wrapper) { |
126 | 0 | if (enc_ctx->picture_decision_undisplayed_queue_count >= UNDISP_QUEUE_SIZE) { |
127 | 0 | SVT_ERROR("bug, too many frames in undisplayed queue"); |
128 | 0 | return; |
129 | 0 | } |
130 | 0 | uint32_t count = enc_ctx->picture_decision_undisplayed_queue_count; |
131 | 0 | enc_ctx->picture_decision_undisplayed_queue[count++] = wrapper; |
132 | 0 | enc_ctx->picture_decision_undisplayed_queue_count = count; |
133 | 0 | } |
134 | | |
135 | 0 | static EbObjectWrapper* pop_undisplayed_frame(EncodeContext* enc_ctx) { |
136 | 0 | uint32_t count = enc_ctx->picture_decision_undisplayed_queue_count; |
137 | 0 | if (!count) { |
138 | 0 | SVT_ERROR("bug, no frame in undisplayed queue"); |
139 | 0 | return NULL; |
140 | 0 | } |
141 | 0 | count--; |
142 | 0 | EbObjectWrapper* ret = enc_ctx->picture_decision_undisplayed_queue[count]; |
143 | 0 | enc_ctx->picture_decision_undisplayed_queue_count = count; |
144 | 0 | return ret; |
145 | 0 | } |
146 | | |
147 | 0 | static void sort_undisplayed_frame(EncodeContext* enc_ctx) { |
148 | 0 | qsort(&enc_ctx->picture_decision_undisplayed_queue[0], |
149 | 0 | enc_ctx->picture_decision_undisplayed_queue_count, |
150 | 0 | sizeof(EbObjectWrapper*), |
151 | 0 | pts_descend); |
152 | 0 | } |
153 | | |
154 | | #if DETAILED_FRAME_OUTPUT |
155 | | static void print_detailed_frame_info(PacketizationContext* context_ptr, |
156 | | const PacketizationReorderEntry* queue_entry_ptr) { |
157 | | int32_t i; |
158 | | uint8_t showTab[] = {'H', 'V'}; |
159 | | |
160 | | //Countinuity count check of visible frames |
161 | | if (queue_entry_ptr->show_frame) { |
162 | | if (context_ptr->disp_order_continuity_count == queue_entry_ptr->poc) { |
163 | | context_ptr->disp_order_continuity_count++; |
164 | | } else { |
165 | | SVT_ERROR("disp_order_continuity_count Error1 POC:%i\n", (int32_t)queue_entry_ptr->poc); |
166 | | exit(0); |
167 | | } |
168 | | } |
169 | | |
170 | | if (queue_entry_ptr->has_show_existing) { |
171 | | if (context_ptr->disp_order_continuity_count == |
172 | | context_ptr->dpb_disp_order[queue_entry_ptr->show_existing_frame]) { |
173 | | context_ptr->disp_order_continuity_count++; |
174 | | } else { |
175 | | SVT_ERROR("disp_order_continuity_count Error2 POC:%i\n", (int32_t)queue_entry_ptr->poc); |
176 | | exit(0); |
177 | | } |
178 | | } |
179 | | |
180 | | //update total number of shown frames |
181 | | if (queue_entry_ptr->show_frame) { |
182 | | context_ptr->tot_shown_frames++; |
183 | | } |
184 | | if (queue_entry_ptr->has_show_existing) { |
185 | | context_ptr->tot_shown_frames++; |
186 | | } |
187 | | |
188 | | //implement the GOP here - Serial dec order |
189 | | if (queue_entry_ptr->frame_type == KEY_FRAME) { |
190 | | //reset the DPB on a Key frame |
191 | | for (i = 0; i < 8; i++) { |
192 | | context_ptr->dpb_dec_order[i] = queue_entry_ptr->picture_number; |
193 | | context_ptr->dpb_disp_order[i] = queue_entry_ptr->poc; |
194 | | } |
195 | | SVT_LOG("%i %i %c ****KEY***** %i frames\n", |
196 | | (int32_t)queue_entry_ptr->picture_number, |
197 | | (int32_t)queue_entry_ptr->poc, |
198 | | showTab[queue_entry_ptr->show_frame], |
199 | | (int32_t)context_ptr->tot_shown_frames); |
200 | | } else { |
201 | | int32_t LASTrefIdx = queue_entry_ptr->av1_ref_signal.ref_dpb_index[0]; |
202 | | int32_t BWDrefIdx = queue_entry_ptr->av1_ref_signal.ref_dpb_index[4]; |
203 | | |
204 | | if (queue_entry_ptr->frame_type == INTER_FRAME) { |
205 | | if (queue_entry_ptr->has_show_existing) { |
206 | | SVT_LOG("%i (%i %i) %i (%i %i) %c showEx: %i %i frames\n", |
207 | | (int32_t)queue_entry_ptr->picture_number, |
208 | | (int32_t)context_ptr->dpb_dec_order[LASTrefIdx], |
209 | | (int32_t)context_ptr->dpb_dec_order[BWDrefIdx], |
210 | | (int32_t)queue_entry_ptr->poc, |
211 | | (int32_t)context_ptr->dpb_disp_order[LASTrefIdx], |
212 | | (int32_t)context_ptr->dpb_disp_order[BWDrefIdx], |
213 | | showTab[queue_entry_ptr->show_frame], |
214 | | (int32_t)context_ptr->dpb_disp_order[queue_entry_ptr->show_existing_frame], |
215 | | (int32_t)context_ptr->tot_shown_frames); |
216 | | } else { |
217 | | SVT_LOG("%i (%i %i) %i (%i %i) %c %i frames\n", |
218 | | (int32_t)queue_entry_ptr->picture_number, |
219 | | (int32_t)context_ptr->dpb_dec_order[LASTrefIdx], |
220 | | (int32_t)context_ptr->dpb_dec_order[BWDrefIdx], |
221 | | (int32_t)queue_entry_ptr->poc, |
222 | | (int32_t)context_ptr->dpb_disp_order[LASTrefIdx], |
223 | | (int32_t)context_ptr->dpb_disp_order[BWDrefIdx], |
224 | | showTab[queue_entry_ptr->show_frame], |
225 | | (int32_t)context_ptr->tot_shown_frames); |
226 | | } |
227 | | |
228 | | if (queue_entry_ptr->ref_poc_list0 != context_ptr->dpb_disp_order[LASTrefIdx]) { |
229 | | SVT_LOG("L0 MISMATCH POC:%i\n", (int32_t)queue_entry_ptr->poc); |
230 | | exit(0); |
231 | | } |
232 | | |
233 | | for (int rr = 0; rr < 7; rr++) { |
234 | | uint8_t dpb_spot = queue_entry_ptr->av1_ref_signal.ref_dpb_index[rr]; |
235 | | |
236 | | if (queue_entry_ptr->ref_poc_array[rr] != context_ptr->dpb_disp_order[dpb_spot]) { |
237 | | SVT_LOG("REF_POC MISMATCH POC:%i ref:%i\n", (int32_t)queue_entry_ptr->poc, rr); |
238 | | } |
239 | | } |
240 | | } else { |
241 | | if (queue_entry_ptr->has_show_existing) { |
242 | | SVT_LOG("%i %i %c showEx: %i ----INTRA---- %i frames \n", |
243 | | (int32_t)queue_entry_ptr->picture_number, |
244 | | (int32_t)queue_entry_ptr->poc, |
245 | | showTab[queue_entry_ptr->show_frame], |
246 | | (int32_t)context_ptr->dpb_disp_order[queue_entry_ptr->show_existing_frame], |
247 | | (int32_t)context_ptr->tot_shown_frames); |
248 | | } else { |
249 | | SVT_LOG("%i %i %c ----INTRA---- %i frames\n", |
250 | | (int32_t)queue_entry_ptr->picture_number, |
251 | | (int32_t)queue_entry_ptr->poc, |
252 | | (int32_t)showTab[queue_entry_ptr->show_frame], |
253 | | (int32_t)context_ptr->tot_shown_frames); |
254 | | } |
255 | | } |
256 | | |
257 | | //Update the DPB |
258 | | for (i = 0; i < 8; i++) { |
259 | | if ((queue_entry_ptr->av1_ref_signal.refresh_frame_mask >> i) & 1) { |
260 | | context_ptr->dpb_dec_order[i] = queue_entry_ptr->picture_number; |
261 | | context_ptr->dpb_disp_order[i] = queue_entry_ptr->poc; |
262 | | } |
263 | | } |
264 | | } |
265 | | } |
266 | | #endif |
267 | | |
268 | 474 | static void collect_frames_info(PacketizationContext* context_ptr, const EncodeContext* enc_ctx, int frames) { |
269 | 948 | for (int i = 0; i < frames; i++) { |
270 | 474 | PacketizationReorderEntry* queue_entry_ptr = get_reorder_queue_entry(enc_ctx, i); |
271 | 474 | EbBufferHeaderType* output_stream_ptr = (EbBufferHeaderType*) |
272 | 474 | queue_entry_ptr->output_stream_wrapper_ptr->object_ptr; |
273 | | #if DETAILED_FRAME_OUTPUT |
274 | | print_detailed_frame_info(context_ptr, queue_entry_ptr); |
275 | | #else |
276 | 474 | (void)context_ptr; |
277 | | |
278 | 474 | #endif |
279 | | // Calculate frame latency in milliseconds |
280 | 474 | uint64_t finish_time_seconds = 0; |
281 | 474 | uint64_t finish_time_u_seconds = 0; |
282 | 474 | svt_av1_get_time(&finish_time_seconds, &finish_time_u_seconds); |
283 | | |
284 | 474 | output_stream_ptr->n_tick_count = (uint32_t)svt_av1_compute_overall_elapsed_time_ms( |
285 | 474 | queue_entry_ptr->start_time_seconds, |
286 | 474 | queue_entry_ptr->start_time_u_seconds, |
287 | 474 | finish_time_seconds, |
288 | 474 | finish_time_u_seconds); |
289 | 474 | output_stream_ptr->p_app_private = (EbBufferHeaderType*)NULL; |
290 | 474 | if (queue_entry_ptr->is_alt_ref) { |
291 | 0 | output_stream_ptr->flags |= (uint32_t)EB_BUFFERFLAG_IS_ALT_REF; |
292 | 0 | } |
293 | 474 | } |
294 | 474 | } |
295 | | |
296 | 1.42k | #define TD_SIZE 2 |
297 | | |
298 | | // a tu start with a td, + 0 more not displable frame, + 1 display frame |
299 | | static EbErrorType encode_tu(EncodeContext* enc_ctx, int frames, uint32_t total_bytes, |
300 | 474 | EbBufferHeaderType* output_stream_ptr) { |
301 | 474 | total_bytes += TD_SIZE; |
302 | 474 | if (total_bytes > output_stream_ptr->n_alloc_len) { |
303 | 0 | uint8_t* pbuff; |
304 | 0 | EB_MALLOC(pbuff, total_bytes); |
305 | 0 | if (!pbuff) { |
306 | 0 | SVT_ERROR("failed to allocate more memory in encode_tu"); |
307 | 0 | return EB_ErrorInsufficientResources; |
308 | 0 | } |
309 | 0 | svt_memcpy(pbuff, |
310 | 0 | output_stream_ptr->p_buffer, |
311 | 0 | output_stream_ptr->n_alloc_len > total_bytes ? total_bytes : output_stream_ptr->n_alloc_len); |
312 | 0 | EB_FREE(output_stream_ptr->p_buffer); |
313 | 0 | output_stream_ptr->p_buffer = pbuff; |
314 | 0 | output_stream_ptr->n_alloc_len = total_bytes; |
315 | 0 | } |
316 | 474 | uint8_t* dst = output_stream_ptr->p_buffer + total_bytes; |
317 | | // we use last frame's output_stream_ptr to hold entire tu, so we need copy backward. |
318 | 948 | for (int i = frames - 1; i >= 0; i--) { |
319 | 474 | PacketizationReorderEntry* queue_entry_ptr = get_reorder_queue_entry(enc_ctx, i); |
320 | 474 | EbObjectWrapper* wrapper = queue_entry_ptr->output_stream_wrapper_ptr; |
321 | 474 | EbBufferHeaderType* src_stream_ptr = (EbBufferHeaderType*)wrapper->object_ptr; |
322 | 474 | uint32_t size = src_stream_ptr->n_filled_len; |
323 | 474 | dst -= size; |
324 | 474 | memmove(dst, src_stream_ptr->p_buffer, size); |
325 | | // 1. The last frame is a displayable frame, others are undisplayed. |
326 | | // 2. We do not push alt ref frame since the overlay frame will carry the pts. |
327 | | // 3. Release alt ref stream buffer here for it will not be sent out |
328 | 474 | if (i != frames - 1 && !queue_entry_ptr->is_alt_ref) { |
329 | 0 | push_undisplayed_frame(enc_ctx, wrapper); |
330 | 474 | } else if (queue_entry_ptr->is_alt_ref) { |
331 | 0 | EB_FREE(src_stream_ptr->p_buffer); |
332 | 0 | svt_release_object(wrapper); |
333 | 0 | } |
334 | 474 | } |
335 | 474 | if (frames > 1) { |
336 | 0 | sort_undisplayed_frame(enc_ctx); |
337 | 0 | } |
338 | 474 | dst -= TD_SIZE; |
339 | 474 | svt_aom_encode_td_av1(dst); |
340 | 474 | output_stream_ptr->n_filled_len = total_bytes; |
341 | 474 | output_stream_ptr->flags |= EB_BUFFERFLAG_HAS_TD; |
342 | 474 | return EB_ErrorNone; |
343 | 474 | } |
344 | | |
345 | | static EbErrorType copy_data_from_bitstream(EncodeContext* enc_ctx, Bitstream* bitstream_ptr, |
346 | 474 | EbBufferHeaderType* output_stream_ptr) { |
347 | 474 | EbErrorType return_error = EB_ErrorNone; |
348 | 474 | int size = svt_aom_bitstream_get_bytes_count(bitstream_ptr); |
349 | | |
350 | 474 | CHECK_REPORT_ERROR((size + output_stream_ptr->n_filled_len < output_stream_ptr->n_alloc_len), |
351 | 474 | enc_ctx->app_callback_ptr, |
352 | 474 | EB_ENC_EC_ERROR2); |
353 | | |
354 | 474 | void* dest = output_stream_ptr->p_buffer + output_stream_ptr->n_filled_len; |
355 | 474 | svt_aom_bitstream_copy(bitstream_ptr, dest, size); |
356 | 474 | output_stream_ptr->n_filled_len += size; |
357 | | |
358 | 474 | return return_error; |
359 | 474 | } |
360 | | |
361 | | static void encode_show_existing(EncodeContext* enc_ctx, PacketizationReorderEntry* queue_entry_ptr, |
362 | 0 | EbBufferHeaderType* output_stream_ptr) { |
363 | 0 | uint8_t* dst = output_stream_ptr->p_buffer; |
364 | |
|
365 | 0 | svt_aom_encode_td_av1(dst); |
366 | 0 | output_stream_ptr->n_filled_len = TD_SIZE; |
367 | |
|
368 | 0 | copy_data_from_bitstream(enc_ctx, queue_entry_ptr->bitstream_ptr, output_stream_ptr); |
369 | |
|
370 | 0 | output_stream_ptr->flags |= (EB_BUFFERFLAG_SHOW_EXT | EB_BUFFERFLAG_HAS_TD); |
371 | 0 | } |
372 | | |
373 | 474 | static void release_frames(EncodeContext* enc_ctx, int frames) { |
374 | 948 | for (int i = 0; i < frames; i++) { |
375 | 474 | PacketizationReorderEntry* queue_entry_ptr = get_reorder_queue_entry(enc_ctx, i); |
376 | | // Reset the Reorder Queue Entry |
377 | 474 | queue_entry_ptr->picture_number += enc_ctx->packetization_reorder_queue_size; |
378 | 474 | queue_entry_ptr->output_stream_wrapper_ptr = (EbObjectWrapper*)NULL; |
379 | 474 | } |
380 | 474 | enc_ctx->packetization_reorder_queue_head_index = get_reorder_queue_pos(enc_ctx, frames); |
381 | 474 | } |
382 | | |
383 | | // Release the pd_dpb and ref_pic_list at the end of the sequence |
384 | 474 | void release_references_eos(SequenceControlSet* scs) { |
385 | 474 | EncodeContext* enc_ctx = scs->enc_ctx; |
386 | | // At the end of the sequence release all the refs (needed for MacOS CI tests) |
387 | 474 | svt_block_on_mutex(enc_ctx->pd_dpb_mutex); |
388 | 4.26k | for (uint8_t i = 0; i < REF_FRAMES; i++) { |
389 | | // Get the current entry at that spot in the DPB |
390 | 3.79k | PaReferenceEntry* input_entry = enc_ctx->pd_dpb[i]; |
391 | | |
392 | | // If DPB entry is occupied, release the current entry |
393 | 3.79k | if (input_entry->is_valid) { |
394 | | // Release the entry at that DPB spot |
395 | | // Release the nominal live_count value |
396 | 3.79k | svt_release_object(input_entry->input_object_ptr); |
397 | | |
398 | 3.79k | if (input_entry->y8b_wrapper) { |
399 | | //y8b needs to get decremented at the same time of pa ref |
400 | 3.79k | svt_release_object(input_entry->y8b_wrapper); |
401 | 3.79k | } |
402 | | |
403 | 3.79k | input_entry->input_object_ptr = (EbObjectWrapper*)NULL; |
404 | 3.79k | input_entry->is_valid = false; |
405 | 3.79k | } |
406 | 3.79k | } |
407 | 474 | svt_release_mutex(enc_ctx->pd_dpb_mutex); |
408 | | |
409 | 474 | svt_block_on_mutex(enc_ctx->ref_pic_list_mutex); |
410 | 474 | ReferenceQueueEntry* ref_entry = NULL; |
411 | 1.42k | for (uint32_t i = 0; i < enc_ctx->ref_pic_list_length; i++) { |
412 | 948 | ref_entry = enc_ctx->ref_pic_list[i]; |
413 | 948 | if (ref_entry->is_valid && ref_entry->reference_object_ptr) { |
414 | | // Remove the entry & release the reference if there are no remaining references |
415 | | // Release the nominal live_count value |
416 | 0 | svt_release_object(ref_entry->reference_object_ptr); |
417 | 0 | ref_entry->reference_object_ptr = (EbObjectWrapper*)NULL; |
418 | 0 | ref_entry->reference_available = false; |
419 | 0 | ref_entry->is_ref = false; |
420 | 0 | ref_entry->is_valid = false; |
421 | 0 | ref_entry->frame_context_updated = false; |
422 | 0 | ref_entry->feedback_arrived = false; |
423 | 0 | if (scs->ref_buffer_available_semaphore) { |
424 | 0 | svt_post_semaphore(scs->ref_buffer_available_semaphore); |
425 | 0 | } |
426 | 0 | } |
427 | 948 | } |
428 | 474 | svt_release_mutex(enc_ctx->ref_pic_list_mutex); |
429 | 474 | } |
430 | | |
431 | 0 | inline static void clear_eos_flag(EbBufferHeaderType* output_stream_ptr) { |
432 | 0 | output_stream_ptr->flags &= ~EB_BUFFERFLAG_EOS; |
433 | 0 | } |
434 | | |
435 | 0 | inline static void set_eos_flag(EbBufferHeaderType* output_stream_ptr) { |
436 | 0 | output_stream_ptr->flags |= EB_BUFFERFLAG_EOS; |
437 | 0 | } |
438 | | |
439 | | /* Wrapper function to capture the return of EB_MALLOC */ |
440 | 474 | static inline EbErrorType malloc_p_buffer(EbBufferHeaderType* output_stream_ptr) { |
441 | 474 | EB_MALLOC(output_stream_ptr->p_buffer, output_stream_ptr->n_alloc_len); |
442 | 474 | return EB_ErrorNone; |
443 | 474 | } |
444 | | |
445 | | void update_firstpass_stats(PictureParentControlSet* pcs, const int frame_number, const double ts_duration, |
446 | | StatStruct* stat_struct); |
447 | | void svt_av1_end_first_pass(PictureParentControlSet* pcs); |
448 | | |
449 | | /* Realloc when bitstream pointer size is not enough to write data of size sz */ |
450 | 0 | static EbErrorType realloc_output_bitstream(Bitstream* bitstream_ptr, uint32_t sz) { |
451 | 0 | if (bitstream_ptr && sz > 0) { |
452 | 0 | OutputBitstreamUnit* output_bitstream_ptr = bitstream_ptr->output_bitstream_ptr; |
453 | 0 | if (output_bitstream_ptr) { |
454 | 0 | output_bitstream_ptr->size = sz; |
455 | 0 | EB_REALLOC_ARRAY(output_bitstream_ptr->buffer_begin_av1, output_bitstream_ptr->size); |
456 | 0 | output_bitstream_ptr->buffer_av1 = output_bitstream_ptr->buffer_begin_av1; |
457 | 0 | } |
458 | 0 | } |
459 | 0 | return EB_ErrorNone; |
460 | 0 | } |
461 | | |
462 | 948 | EbErrorType svt_aom_packetization_kernel_iter(void* context) { |
463 | | // Context |
464 | 948 | PacketizationContext* context_ptr = (PacketizationContext*)context; |
465 | | |
466 | | // Input |
467 | 948 | EbObjectWrapper* entropy_coding_results_wrapper_ptr; |
468 | | |
469 | | // Output |
470 | 948 | EbObjectWrapper* rate_control_tasks_wrapper_ptr; |
471 | 948 | EbObjectWrapper* picture_manager_results_wrapper_ptr; |
472 | | |
473 | | // Get EntropyCoding Results |
474 | 948 | EB_GET_FULL_OBJECT(context_ptr->entropy_coding_input_fifo_ptr, &entropy_coding_results_wrapper_ptr); |
475 | | |
476 | 474 | EntropyCodingResults* entropy_coding_results_ptr = (EntropyCodingResults*) |
477 | 474 | entropy_coding_results_wrapper_ptr->object_ptr; |
478 | 474 | PictureControlSet* pcs = (PictureControlSet*)entropy_coding_results_ptr->pcs_wrapper->object_ptr; |
479 | 474 | SequenceControlSet* scs = pcs->scs; |
480 | 474 | EncodeContext* enc_ctx = scs->enc_ctx; |
481 | 474 | FrameHeader* frm_hdr = &pcs->ppcs->frm_hdr; |
482 | 474 | Av1Common* const cm = pcs->ppcs->av1_cm; |
483 | 474 | uint16_t tile_cnt = cm->tiles_info.tile_rows * cm->tiles_info.tile_cols; |
484 | 474 | PictureParentControlSet* ppcs = (PictureParentControlSet*)pcs->ppcs; |
485 | | |
486 | 474 | if (ppcs->superres_total_recode_loop > 0 && ppcs->superres_recode_loop < ppcs->superres_total_recode_loop) { |
487 | | // Reset the Bitstream before writing to it |
488 | 0 | svt_aom_bitstream_reset(pcs->bitstream_ptr); |
489 | 0 | svt_aom_write_frame_header_av1(pcs->bitstream_ptr, scs, pcs, 0); |
490 | 0 | int64_t bits = (int64_t)svt_aom_bitstream_get_bytes_count(pcs->bitstream_ptr) << 3; |
491 | 0 | int64_t rate = bits << 5; // To match scale. |
492 | 0 | svt_aom_bitstream_reset(pcs->bitstream_ptr); |
493 | 0 | int64_t sse = ppcs->luma_sse; |
494 | 0 | EbBitDepth bit_depth = pcs->hbd_md ? EB_TEN_BIT : EB_EIGHT_BIT; |
495 | 0 | uint8_t qindex = ppcs->frm_hdr.quantization_params.base_q_idx; |
496 | 0 | int32_t rdmult = svt_aom_compute_rd_mult(pcs, qindex, qindex, bit_depth); |
497 | |
|
498 | 0 | double rdcost = RDCOST_DBL_WITH_NATIVE_BD_DIST(rdmult, rate, sse, scs->static_config.encoder_bit_depth); |
499 | |
|
500 | | #if DEBUG_SUPERRES_RECODE |
501 | | printf( |
502 | | "\n####### %s - frame %d, loop %d/%d, denom %d, rate %I64d, sse %I64d, rdcost " |
503 | | "%.2f, qindex %d, rdmult %d\n", |
504 | | __FUNCTION__, |
505 | | (int)ppcs->picture_number, |
506 | | ppcs->superres_recode_loop, |
507 | | ppcs->superres_total_recode_loop, |
508 | | ppcs->superres_denom, |
509 | | rate, |
510 | | sse, |
511 | | rdcost, |
512 | | qindex, |
513 | | rdmult); |
514 | | #endif |
515 | |
|
516 | 0 | assert(ppcs->superres_total_recode_loop <= SCALE_NUMERATOR + 1); |
517 | 0 | ppcs->superres_rdcost[ppcs->superres_recode_loop] = rdcost; |
518 | 0 | ++ppcs->superres_recode_loop; |
519 | |
|
520 | 0 | if (ppcs->superres_recode_loop <= ppcs->superres_total_recode_loop) { |
521 | 0 | bool do_recode = false; |
522 | 0 | if (ppcs->superres_recode_loop == ppcs->superres_total_recode_loop) { |
523 | | // compare rdcosts to determine whether need to recode again |
524 | | // rdcost is the smaller the better |
525 | 0 | int best_index = 0; |
526 | 0 | for (int i = 1; i < ppcs->superres_total_recode_loop; ++i) { |
527 | 0 | double rdcost1 = ppcs->superres_rdcost[best_index]; |
528 | 0 | double rdcost2 = ppcs->superres_rdcost[i]; |
529 | 0 | if (rdcost2 < rdcost1) { |
530 | 0 | best_index = i; |
531 | 0 | } |
532 | 0 | } |
533 | |
|
534 | 0 | if (best_index != ppcs->superres_total_recode_loop - 1) { |
535 | 0 | do_recode = true; |
536 | 0 | ppcs->superres_denom = ppcs->superres_denom_array[best_index]; |
537 | | #if DEBUG_SUPERRES_RECODE |
538 | | printf("\n####### %s - frame %d, extra loop, pick denom %d\n", |
539 | | __FUNCTION__, |
540 | | (int)ppcs->picture_number, |
541 | | ppcs->superres_denom); |
542 | | #endif |
543 | 0 | } |
544 | 0 | } else { |
545 | 0 | do_recode = true; |
546 | 0 | } |
547 | |
|
548 | 0 | if (do_recode) { |
549 | 0 | svt_aom_init_resize_picture(scs, ppcs); |
550 | | |
551 | | // reset gm based on super-res on/off |
552 | 0 | bool super_res_off = ppcs->frame_superres_enabled == false && |
553 | 0 | scs->static_config.resize_mode == RESIZE_NONE; |
554 | 0 | svt_aom_set_gm_controls(ppcs, svt_aom_derive_gm_level(ppcs, super_res_off)); |
555 | | // Initialize Segments as picture decision process |
556 | 0 | ppcs->me_segments_completion_count = 0; |
557 | 0 | ppcs->me_processed_b64_count = 0; |
558 | |
|
559 | 0 | if (ppcs->ref_pic_wrapper != NULL) { |
560 | | // update mi_rows and mi_cols for the reference pic wrapper (used in mfmv |
561 | | // for other pictures) |
562 | 0 | EbReferenceObject* ref_object = ppcs->ref_pic_wrapper->object_ptr; |
563 | 0 | svt_reference_object_reset(ref_object, scs); |
564 | 0 | } |
565 | | #if DEBUG_SUPERRES_RECODE |
566 | | printf("\n%s - send superres recode task to open loop ME. Frame %d, denom %d\n", |
567 | | __FUNCTION__, |
568 | | (int)ppcs->picture_number, |
569 | | ppcs->superres_denom); |
570 | | #endif |
571 | |
|
572 | 0 | for (uint32_t segment_index = 0; segment_index < ppcs->me_segments_total_count; ++segment_index) { |
573 | | // Get Empty Results Object |
574 | 0 | EbObjectWrapper* out_results_wrapper; |
575 | 0 | svt_get_empty_object(context_ptr->picture_decision_results_output_fifo_ptr, &out_results_wrapper); |
576 | |
|
577 | 0 | PictureDecisionResults* out_results = (PictureDecisionResults*)out_results_wrapper->object_ptr; |
578 | 0 | out_results->pcs_wrapper = ppcs->p_pcs_wrapper_ptr; |
579 | 0 | out_results->segment_index = segment_index; |
580 | 0 | out_results->task_type = TASK_SUPERRES_RE_ME; |
581 | | // Post the Full Results Object |
582 | 0 | svt_post_full_object(out_results_wrapper); |
583 | 0 | } |
584 | | |
585 | | // Release the Entropy Coding Result |
586 | 0 | svt_release_object(entropy_coding_results_wrapper_ptr); |
587 | 0 | return EB_ErrorNone; |
588 | 0 | } |
589 | 0 | } |
590 | 0 | } |
591 | | |
592 | 474 | if (ppcs->superres_total_recode_loop > 0) { |
593 | | // Release pa_ref_objs |
594 | | // Delayed call from Initial Rate Control process / Source Based Operations process |
595 | 0 | if (ppcs->tpl_ctrls.enable) { |
596 | 0 | if (ppcs->temporal_layer_index == 0) { |
597 | 0 | for (uint32_t i = 0; i < ppcs->tpl_group_size; i++) { |
598 | 0 | if (svt_aom_is_incomp_mg_frame(ppcs->tpl_group[i])) { |
599 | 0 | if (ppcs->tpl_group[i]->ext_mg_id == ppcs->ext_mg_id + 1) { |
600 | 0 | svt_aom_release_pa_reference_objects(scs, ppcs->tpl_group[i]); |
601 | 0 | } |
602 | 0 | } else { |
603 | 0 | if (ppcs->tpl_group[i]->ext_mg_id == ppcs->ext_mg_id) { |
604 | 0 | svt_aom_release_pa_reference_objects(scs, ppcs->tpl_group[i]); |
605 | 0 | } |
606 | 0 | } |
607 | 0 | } |
608 | 0 | } |
609 | 0 | } else { |
610 | 0 | svt_aom_release_pa_reference_objects(scs, ppcs); |
611 | 0 | } |
612 | | |
613 | | // Delayed call from Rate Control process for multiple coding loop frames |
614 | 0 | if (scs->static_config.rate_control_mode) { |
615 | 0 | svt_aom_update_rc_counts(ppcs); |
616 | 0 | } |
617 | | |
618 | | // Release pa me ptr. For non-superres-recode, it's released in svt_aom_mode_decision_kernel |
619 | 0 | assert(pcs->ppcs->me_data_wrapper != NULL); |
620 | 0 | assert(pcs->ppcs->pa_me_data != NULL); |
621 | 0 | svt_release_object(pcs->ppcs->me_data_wrapper); |
622 | 0 | pcs->ppcs->me_data_wrapper = NULL; |
623 | 0 | pcs->ppcs->pa_me_data = NULL; |
624 | | |
625 | | // Delayed call from Rest process |
626 | 0 | { |
627 | 0 | if (pcs->ppcs->compute_ssim) { |
628 | | // memory is freed in the svt_aom_ssim_calculations call |
629 | 0 | svt_aom_ssim_calculations(pcs, scs, true); |
630 | 0 | } else { |
631 | | // free memory used by psnr_calculations |
632 | 0 | free_temporal_filtering_buffer(pcs); |
633 | 0 | } |
634 | |
|
635 | 0 | if (scs->static_config.recon_enabled) { |
636 | 0 | svt_aom_recon_output(pcs, scs); |
637 | 0 | } |
638 | |
|
639 | 0 | if (ppcs->is_ref) { |
640 | 0 | EbObjectWrapper* picture_demux_results_wrapper_ptr; |
641 | 0 | PictureDemuxResults* picture_demux_results_rtr; |
642 | | |
643 | | // Get Empty PicMgr Results |
644 | 0 | svt_get_empty_object(context_ptr->picture_demux_fifo_ptr, &picture_demux_results_wrapper_ptr); |
645 | |
|
646 | 0 | picture_demux_results_rtr = (PictureDemuxResults*)picture_demux_results_wrapper_ptr->object_ptr; |
647 | 0 | picture_demux_results_rtr->ref_pic_wrapper = ppcs->ref_pic_wrapper; |
648 | 0 | picture_demux_results_rtr->scs = ppcs->scs; |
649 | 0 | picture_demux_results_rtr->picture_number = ppcs->picture_number; |
650 | 0 | picture_demux_results_rtr->picture_type = EB_PIC_REFERENCE; |
651 | | |
652 | | // Post Reference Picture |
653 | 0 | svt_post_full_object(picture_demux_results_wrapper_ptr); |
654 | 0 | } |
655 | 0 | } |
656 | | |
657 | | // Delayed call from Entropy Coding process |
658 | 0 | { |
659 | | // Release the reference Pictures from both lists |
660 | 0 | for (REF_FRAME_MINUS1 ref = LAST; ref < ALT + 1; ref++) { |
661 | 0 | const uint8_t list_idx = get_list_idx(ref + 1); |
662 | 0 | const uint8_t ref_idx = get_ref_frame_idx(ref + 1); |
663 | 0 | if (pcs->ref_pic_ptr_array[list_idx][ref_idx] != NULL) { |
664 | 0 | svt_release_object(pcs->ref_pic_ptr_array[list_idx][ref_idx]); |
665 | 0 | } |
666 | 0 | } |
667 | | |
668 | | //free palette data |
669 | 0 | if (pcs->tile_tok[0][0]) { |
670 | 0 | EB_FREE_ARRAY(pcs->tile_tok[0][0]); |
671 | 0 | } |
672 | 0 | } |
673 | 474 | } else if (!(pcs->ppcs->compute_psnr || pcs->ppcs->compute_ssim)) { |
674 | 474 | free_temporal_filtering_buffer(pcs); |
675 | 474 | } |
676 | | //**************************************************** |
677 | | // Input Entropy Results into Reordering Queue |
678 | | //**************************************************** |
679 | | // get a new entry spot |
680 | 474 | int32_t queue_entry_index = pcs->ppcs->decode_order % enc_ctx->packetization_reorder_queue_size; |
681 | 474 | PacketizationReorderEntry* queue_entry_ptr = enc_ctx->packetization_reorder_queue[queue_entry_index]; |
682 | 474 | queue_entry_ptr->start_time_seconds = pcs->ppcs->start_time_seconds; |
683 | 474 | queue_entry_ptr->start_time_u_seconds = pcs->ppcs->start_time_u_seconds; |
684 | 474 | queue_entry_ptr->is_alt_ref = pcs->ppcs->is_alt_ref; |
685 | 474 | svt_get_empty_object(scs->enc_ctx->stream_output_fifo_ptr, &pcs->ppcs->output_stream_wrapper_ptr); |
686 | 474 | EbObjectWrapper* output_stream_wrapper_ptr = pcs->ppcs->output_stream_wrapper_ptr; |
687 | 474 | EbBufferHeaderType* output_stream_ptr = (EbBufferHeaderType*)output_stream_wrapper_ptr->object_ptr; |
688 | | |
689 | 474 | if (frm_hdr->frame_type == KEY_FRAME) { |
690 | 474 | if (scs->static_config.mastering_display.max_luma) { |
691 | 0 | svt_add_metadata(pcs->ppcs->input_ptr, |
692 | 0 | EB_AV1_METADATA_TYPE_HDR_MDCV, |
693 | 0 | (const uint8_t*)&scs->static_config.mastering_display, |
694 | 0 | sizeof(scs->static_config.mastering_display)); |
695 | 0 | } |
696 | 474 | if (scs->static_config.content_light_level.max_cll) { |
697 | 0 | svt_add_metadata(pcs->ppcs->input_ptr, |
698 | 0 | EB_AV1_METADATA_TYPE_HDR_CLL, |
699 | 0 | (const uint8_t*)&scs->static_config.content_light_level, |
700 | 0 | sizeof(scs->static_config.content_light_level)); |
701 | 0 | } |
702 | 474 | } |
703 | | |
704 | 474 | output_stream_ptr->flags = 0; |
705 | 474 | output_stream_ptr->n_filled_len = 0; |
706 | 474 | output_stream_ptr->pts = pcs->ppcs->input_ptr->pts; |
707 | | // we output one temporal unit a time, so dts alwasy equals to pts. |
708 | 474 | output_stream_ptr->dts = output_stream_ptr->pts; |
709 | 474 | if (pcs->ppcs->idr_flag) { |
710 | 474 | output_stream_ptr->pic_type = EB_AV1_KEY_PICTURE; |
711 | 474 | } else if (pcs->slice_type == I_SLICE) { |
712 | 0 | output_stream_ptr->pic_type = EB_AV1_INTRA_ONLY_PICTURE; |
713 | 0 | } else if (pcs->ppcs->is_ref) { |
714 | 0 | output_stream_ptr->pic_type = EB_AV1_INTER_PICTURE; |
715 | 0 | } else { |
716 | 0 | output_stream_ptr->pic_type = EB_AV1_NON_REF_PICTURE; |
717 | 0 | } |
718 | 474 | output_stream_ptr->p_app_private = pcs->ppcs->input_ptr->p_app_private; |
719 | 474 | output_stream_ptr->temporal_layer_index = pcs->ppcs->temporal_layer_index; |
720 | 474 | output_stream_ptr->qp = pcs->ppcs->picture_qp; |
721 | 474 | output_stream_ptr->avg_qp = pcs->ppcs->avg_qp; |
722 | 474 | if (pcs->ppcs->compute_psnr) { |
723 | 0 | output_stream_ptr->luma_sse = pcs->ppcs->luma_sse; |
724 | 0 | output_stream_ptr->cr_sse = pcs->ppcs->cr_sse; |
725 | 0 | output_stream_ptr->cb_sse = pcs->ppcs->cb_sse; |
726 | 474 | } else { |
727 | 474 | output_stream_ptr->luma_sse = 0; |
728 | 474 | output_stream_ptr->cr_sse = 0; |
729 | 474 | output_stream_ptr->cb_sse = 0; |
730 | 474 | } |
731 | 474 | if (pcs->ppcs->compute_ssim) { |
732 | 0 | output_stream_ptr->luma_ssim = pcs->ppcs->luma_ssim; |
733 | 0 | output_stream_ptr->cr_ssim = pcs->ppcs->cr_ssim; |
734 | 0 | output_stream_ptr->cb_ssim = pcs->ppcs->cb_ssim; |
735 | 474 | } else { |
736 | 474 | output_stream_ptr->luma_ssim = 0; |
737 | 474 | output_stream_ptr->cr_ssim = 0; |
738 | 474 | output_stream_ptr->cb_ssim = 0; |
739 | 474 | } |
740 | | |
741 | | // Get Empty Rate Control Input Tasks |
742 | 474 | svt_get_empty_object(context_ptr->rate_control_tasks_output_fifo_ptr, &rate_control_tasks_wrapper_ptr); |
743 | 474 | RateControlTasks* rc_tasks = (RateControlTasks*)rate_control_tasks_wrapper_ptr->object_ptr; |
744 | 474 | rc_tasks->pcs_wrapper = pcs->ppcs_wrapper; |
745 | 474 | rc_tasks->task_type = RC_PACKETIZATION_FEEDBACK_RESULT; |
746 | 474 | if (scs->enable_dec_order || (pcs->ppcs->is_ref == true && pcs->ppcs->ref_pic_wrapper)) { |
747 | 0 | if (pcs->ppcs->is_ref == true && |
748 | | // Force each frame to update their data so future frames can use it, |
749 | | // even if the current frame did not use it. This enables REF frames to |
750 | | // have the feature off, while NREF frames can have it on. Used for |
751 | | // multi-threading. |
752 | 0 | pcs->ppcs->ref_pic_wrapper) { |
753 | 0 | for (uint16_t tile_idx = 0; tile_idx < tile_cnt; tile_idx++) { |
754 | 0 | svt_av1_reset_cdf_symbol_counters(pcs->ec_info[tile_idx]->ec->fc); |
755 | 0 | ((EbReferenceObject*)pcs->ppcs->ref_pic_wrapper->object_ptr)->frame_context = |
756 | 0 | (*pcs->ec_info[tile_idx]->ec->fc); |
757 | 0 | } |
758 | 0 | } |
759 | | // Get Empty Results Object |
760 | 0 | svt_get_empty_object(context_ptr->picture_demux_fifo_ptr, &picture_manager_results_wrapper_ptr); |
761 | |
|
762 | 0 | PictureDemuxResults* picture_manager_results_ptr = (PictureDemuxResults*) |
763 | 0 | picture_manager_results_wrapper_ptr->object_ptr; |
764 | 0 | picture_manager_results_ptr->picture_number = pcs->picture_number; |
765 | 0 | picture_manager_results_ptr->picture_type = EB_PIC_FEEDBACK; |
766 | 0 | picture_manager_results_ptr->decode_order = pcs->ppcs->decode_order; |
767 | 0 | picture_manager_results_ptr->scs = pcs->scs; |
768 | 0 | } |
769 | | // Reset the Bitstream before writing to it |
770 | 474 | svt_aom_bitstream_reset(pcs->bitstream_ptr); |
771 | | |
772 | 474 | size_t metadata_sz = 0; |
773 | | |
774 | | // Code the SPS |
775 | 474 | if (frm_hdr->frame_type == KEY_FRAME) { |
776 | 474 | svt_aom_encode_sps_av1(pcs->bitstream_ptr, scs); |
777 | | // Add CLL and MDCV meta when frame is keyframe and SPS is written |
778 | 474 | svt_aom_write_metadata_av1(pcs->bitstream_ptr, pcs->ppcs->input_ptr->metadata, EB_AV1_METADATA_TYPE_HDR_CLL); |
779 | 474 | svt_aom_write_metadata_av1(pcs->bitstream_ptr, pcs->ppcs->input_ptr->metadata, EB_AV1_METADATA_TYPE_HDR_MDCV); |
780 | 474 | } |
781 | | |
782 | 474 | if (frm_hdr->show_frame) { |
783 | | // Add HDR10+ dynamic metadata when show frame flag is enabled |
784 | 474 | svt_aom_write_metadata_av1(pcs->bitstream_ptr, pcs->ppcs->input_ptr->metadata, EB_AV1_METADATA_TYPE_ITUT_T35); |
785 | 474 | svt_metadata_array_free(&pcs->ppcs->input_ptr->metadata); |
786 | 474 | } else { |
787 | | // Copy metadata pointer to the queue entry related to current frame number |
788 | 0 | uint64_t current_picture_number = pcs->picture_number; |
789 | | // TODO: Shouldn't entry be indexed based on decode order, not picture number |
790 | 0 | PacketizationReorderEntry* temp_entry = |
791 | 0 | enc_ctx->packetization_reorder_queue[current_picture_number % enc_ctx->packetization_reorder_queue_size]; |
792 | 0 | temp_entry->metadata = pcs->ppcs->input_ptr->metadata; |
793 | 0 | pcs->ppcs->input_ptr->metadata = NULL; |
794 | 0 | metadata_sz = svt_metadata_size(temp_entry->metadata, EB_AV1_METADATA_TYPE_ITUT_T35); |
795 | 0 | } |
796 | | |
797 | 474 | svt_aom_write_frame_header_av1(pcs->bitstream_ptr, scs, pcs, 0); |
798 | | |
799 | 474 | output_stream_ptr->n_alloc_len = (uint32_t)(svt_aom_bitstream_get_bytes_count(pcs->bitstream_ptr) + TD_SIZE + |
800 | 474 | metadata_sz); |
801 | 474 | malloc_p_buffer(output_stream_ptr); |
802 | | |
803 | 474 | assert(output_stream_ptr->p_buffer != NULL && "bit-stream memory allocation failure"); |
804 | | |
805 | 474 | copy_data_from_bitstream(enc_ctx, pcs->bitstream_ptr, output_stream_ptr); |
806 | | |
807 | 474 | if (pcs->ppcs->has_show_existing) { |
808 | 0 | uint64_t next_picture_number = pcs->picture_number + 1; |
809 | | // TODO: Shouldn't entry be indexed based on decode order, not picture number |
810 | 0 | PacketizationReorderEntry* temp_entry = |
811 | 0 | enc_ctx->packetization_reorder_queue[next_picture_number % enc_ctx->packetization_reorder_queue_size]; |
812 | | // Check if the temporal entry has metadata |
813 | 0 | if (temp_entry->metadata) { |
814 | | // Get bitstream from queue entry |
815 | 0 | Bitstream* bitstream_ptr = queue_entry_ptr->bitstream_ptr; |
816 | 0 | size_t current_metadata_sz = svt_metadata_size(temp_entry->metadata, EB_AV1_METADATA_TYPE_ITUT_T35); |
817 | | // 16 bytes for frame header |
818 | 0 | realloc_output_bitstream(bitstream_ptr, (uint32_t)(current_metadata_sz + 16)); |
819 | 0 | } |
820 | | // Reset the Bitstream before writing to it |
821 | 0 | svt_aom_bitstream_reset(queue_entry_ptr->bitstream_ptr); |
822 | 0 | svt_aom_write_metadata_av1(queue_entry_ptr->bitstream_ptr, temp_entry->metadata, EB_AV1_METADATA_TYPE_ITUT_T35); |
823 | 0 | svt_aom_write_frame_header_av1(queue_entry_ptr->bitstream_ptr, scs, pcs, 1); |
824 | 0 | svt_metadata_array_free(&temp_entry->metadata); |
825 | 0 | } |
826 | | |
827 | | // Send the number of bytes per frame to RC |
828 | 474 | pcs->ppcs->total_num_bits = (uint64_t)output_stream_ptr->n_filled_len << 3; |
829 | 474 | if (scs->passes == 2 && scs->static_config.pass == ENC_FIRST_PASS) { |
830 | 0 | StatStruct stat_struct; |
831 | 0 | stat_struct.poc = pcs->picture_number; |
832 | 0 | if (scs->first_pass_downsample) { |
833 | 0 | stat_struct.total_num_bits = pcs->ppcs->total_num_bits * DS_SC_FACT / 10; |
834 | 0 | } else { |
835 | 0 | stat_struct.total_num_bits = pcs->ppcs->total_num_bits; |
836 | 0 | } |
837 | 0 | stat_struct.qindex = frm_hdr->quantization_params.base_q_idx; |
838 | 0 | stat_struct.worst_qindex = quantizer_to_qindex[(uint8_t)scs->static_config.qp]; |
839 | 0 | if (svt_aom_is_pic_skipped(pcs->ppcs)) { |
840 | 0 | stat_struct.total_num_bits = 0; |
841 | 0 | } |
842 | 0 | stat_struct.temporal_layer_index = pcs->temporal_layer_index; |
843 | 0 | update_firstpass_stats(pcs->ppcs, (const int)pcs->picture_number, pcs->ppcs->ts_duration, &stat_struct); |
844 | 0 | if (ppcs->end_of_sequence_flag) { |
845 | 0 | svt_av1_end_first_pass(ppcs); |
846 | 0 | } |
847 | 0 | } |
848 | 474 | queue_entry_ptr->total_num_bits = pcs->ppcs->total_num_bits; |
849 | 474 | queue_entry_ptr->frame_type = frm_hdr->frame_type; |
850 | 474 | queue_entry_ptr->poc = pcs->picture_number; |
851 | 474 | svt_memcpy(&queue_entry_ptr->av1_ref_signal, &pcs->ppcs->av1_ref_signal, sizeof(Av1RpsNode)); |
852 | | |
853 | 474 | queue_entry_ptr->slice_type = pcs->slice_type; |
854 | | #if DETAILED_FRAME_OUTPUT |
855 | | queue_entry_ptr->ref_poc_list0 = pcs->ppcs->ref_pic_poc_array[REF_LIST_0][0]; |
856 | | queue_entry_ptr->ref_poc_list1 = pcs->ppcs->ref_pic_poc_array[REF_LIST_1][0]; |
857 | | svt_memcpy(queue_entry_ptr->ref_poc_array, pcs->ppcs->av1_ref_signal.ref_poc_array, 7 * sizeof(uint64_t)); |
858 | | #endif |
859 | 474 | queue_entry_ptr->show_frame = frm_hdr->show_frame; |
860 | 474 | queue_entry_ptr->has_show_existing = pcs->ppcs->has_show_existing; |
861 | 474 | queue_entry_ptr->show_existing_frame = frm_hdr->show_existing_frame; |
862 | | |
863 | | //Store the output buffer in the Queue |
864 | 474 | queue_entry_ptr->output_stream_wrapper_ptr = output_stream_wrapper_ptr; |
865 | | |
866 | | // Note: last chance here to add more output meta data for an encoded picture --> |
867 | | |
868 | 474 | if (scs->speed_control_flag) { |
869 | | // update speed control variables |
870 | 0 | svt_block_on_mutex(enc_ctx->sc_buffer_mutex); |
871 | 0 | enc_ctx->sc_frame_out++; |
872 | 0 | svt_release_mutex(enc_ctx->sc_buffer_mutex); |
873 | 0 | } |
874 | | |
875 | 474 | if (scs->enable_dec_order || (pcs->ppcs->is_ref == true && pcs->ppcs->ref_pic_wrapper)) { |
876 | | // Post the Full Results Object |
877 | 0 | svt_post_full_object(picture_manager_results_wrapper_ptr); |
878 | 0 | } |
879 | | // Post Rate Control Task. Be done after postig to PM as RC might release ppcs |
880 | 474 | svt_post_full_object(rate_control_tasks_wrapper_ptr); |
881 | 474 | if (pcs->ppcs->frm_hdr.allow_intrabc) { |
882 | 0 | svt_av1_hash_table_destroy(&pcs->hash_table); |
883 | 0 | } |
884 | 474 | svt_release_object(pcs->ppcs->enc_dec_ptr->enc_dec_wrapper); // Child |
885 | | // Release the Parent PCS then the Child PCS |
886 | 474 | assert(entropy_coding_results_ptr->pcs_wrapper->live_count == 1); |
887 | 474 | svt_release_object(entropy_coding_results_ptr->pcs_wrapper); // Child |
888 | | // Release the Entropy Coding Result |
889 | 474 | svt_release_object(entropy_coding_results_wrapper_ptr); |
890 | | |
891 | | //**************************************************** |
892 | | // Process the head of the queue |
893 | | //**************************************************** |
894 | | // Look at head of queue and see if we got a td |
895 | 474 | uint32_t frames, total_bytes; |
896 | 474 | svt_block_on_mutex(enc_ctx->total_number_of_shown_frames_mutex); |
897 | 474 | bool eos = false; |
898 | 948 | while ((frames = count_frames_in_next_tu(enc_ctx, &total_bytes))) { |
899 | 474 | collect_frames_info(context_ptr, enc_ctx, frames); |
900 | | // last frame in a termporal unit is a displable frame. only the last frame has pts. |
901 | | // so we collect all bitstream to last frames' output buffer. |
902 | 474 | queue_entry_ptr = get_reorder_queue_entry(enc_ctx, frames - 1); |
903 | 474 | output_stream_wrapper_ptr = queue_entry_ptr->output_stream_wrapper_ptr; |
904 | 474 | output_stream_ptr = (EbBufferHeaderType*)output_stream_wrapper_ptr->object_ptr; |
905 | 474 | eos = output_stream_ptr->flags & EB_BUFFERFLAG_EOS; |
906 | 474 | encode_tu(enc_ctx, frames, total_bytes, output_stream_ptr); |
907 | | |
908 | 474 | if (eos && queue_entry_ptr->has_show_existing) { |
909 | 0 | clear_eos_flag(output_stream_ptr); |
910 | 0 | } |
911 | | |
912 | 474 | svt_post_full_object(output_stream_wrapper_ptr); |
913 | 474 | if (queue_entry_ptr->has_show_existing) { |
914 | 0 | EbObjectWrapper* existed = pop_undisplayed_frame(enc_ctx); |
915 | 0 | if (existed) { |
916 | 0 | EbBufferHeaderType* existed_output_stream_ptr = (EbBufferHeaderType*)existed->object_ptr; |
917 | 0 | encode_show_existing(enc_ctx, queue_entry_ptr, existed_output_stream_ptr); |
918 | 0 | if (eos) { |
919 | 0 | set_eos_flag(existed_output_stream_ptr); |
920 | 0 | } |
921 | 0 | svt_post_full_object(existed); |
922 | 0 | } |
923 | 0 | } |
924 | | |
925 | 474 | if (queue_entry_ptr->show_frame) { |
926 | 474 | enc_ctx->total_number_of_shown_frames++; |
927 | 474 | } |
928 | 474 | if (queue_entry_ptr->has_show_existing) { |
929 | 0 | enc_ctx->total_number_of_shown_frames++; |
930 | 0 | } |
931 | 474 | eos = (enc_ctx->total_number_of_shown_frames == enc_ctx->terminating_picture_number + 1) ? 1 : 0; |
932 | 474 | release_frames(enc_ctx, frames); |
933 | 474 | } |
934 | 474 | if (eos) { |
935 | 474 | EbObjectWrapper* tmp_out_str_wrp; |
936 | 474 | svt_get_empty_object(scs->enc_ctx->stream_output_fifo_ptr, &tmp_out_str_wrp); |
937 | 474 | EbBufferHeaderType* tmp_out_str = (EbBufferHeaderType*)tmp_out_str_wrp->object_ptr; |
938 | | |
939 | 474 | tmp_out_str->flags = EB_BUFFERFLAG_EOS; |
940 | 474 | tmp_out_str->n_filled_len = 0; |
941 | | |
942 | 474 | svt_post_full_object(tmp_out_str_wrp); |
943 | 474 | release_references_eos(scs); |
944 | 474 | } |
945 | 474 | svt_release_mutex(enc_ctx->total_number_of_shown_frames_mutex); |
946 | 474 | return EB_ErrorNone; |
947 | 474 | } |
948 | | |
949 | 474 | void* svt_aom_packetization_kernel(void* input_ptr) { |
950 | 474 | EbThreadContext* thread_ctx = (EbThreadContext*)input_ptr; |
951 | 474 | PacketizationContext* context_ptr = (PacketizationContext*)thread_ctx->priv; |
952 | | |
953 | 474 | context_ptr->tot_shown_frames = 0; |
954 | 474 | context_ptr->disp_order_continuity_count = 0; |
955 | | |
956 | 948 | for (;;) { |
957 | 948 | EbErrorType err = svt_aom_packetization_kernel_iter(thread_ctx->priv); |
958 | 948 | if (err == EB_NoErrorFifoShutdown) { |
959 | 474 | return NULL; |
960 | 474 | } |
961 | 948 | } |
962 | 0 | return NULL; |
963 | 474 | } |