Coverage Report

Created: 2026-10-28 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}