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