// File: lukasz-wiecaszek[P]h264iframedecoder/picture_cabac.cpp
// Function: ymn::h264::picture_cabac::decode(ymn::h264::slice_header const&, ymn::h264::slice_data const&)
void picture_cabac::decode(const h264::slice_header& sh, const h264::slice_data& sd)
{
    mb* curr_mb;

    int slice_qp = std::clamp(
        m_context_variables.QPy - 6 * static_cast<int>(m_decoder.m_active_sps->bit_depth_luma_minus8), 0, 51);

    m_cabac_decoder.init_context_variables(sh, slice_qp);
    m_cabac_decoder.init_decoding_engine(sd);

    for (curr_mb = m_context_variables.curr_mb; curr_mb != nullptr; curr_mb = advance_mb_pos()) {

        curr_mb->x = m_context_variables.mb_x;
        curr_mb->y = m_context_variables.mb_y;
        curr_mb->pos = m_context_variables.mb_pos;
        curr_mb->slice_num = 0;

        calculate_neighbours_part1();

        if ((sh.slice_type != h264::slice_type_e::I) && (sh.slice_type != h264::slice_type_e::SI)) {
            bool is_skipped = true; /* TODO: check for skipped macroblocks */
            if (is_skipped)
                continue;
        }

        if ((m_context_variables.mb_aff_frame) && ((m_context_variables.mb_y & 1) == 0))
            m_context_variables.mb_field_decoding_flag = decode_mb_field_decoding_flag();

        calculate_neighbours_part2();

        decode_mb(sh); /* macroblock_layer */

        //std::cout << mb->to_string();
    }
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x40(%rsp)
movq %rsi, 0x38(%rsp)
movq %rdx, 0x30(%rsp)
movq 0x40(%rsp), %rcx
movq %rcx, 0x8(%rsp)
movl 0x34(%rcx), %eax
movq 0x8(%rcx), %rcx
movq 0x88358(%rcx), %rcx
imull $0x6, 0x18(%rcx), %ecx
subl %ecx, %eax
movl %eax, 0x20(%rsp)
movl $0x0, 0x1c(%rsp)
movl $0x33, 0x18(%rsp)
leaq 0x20(%rsp), %rdi
leaq 0x1c(%rsp), %rsi
leaq 0x18(%rsp), %rdx
callq 0x19190
movq 0x8(%rsp), %rdi
movl (%rax), %eax
movl %eax, 0x24(%rsp)
addq $0xdc0, %rdi            # imm = 0xDC0
movq 0x38(%rsp), %rsi
movl 0x24(%rsp), %edx
callq 0x18e30
movq 0x8(%rsp), %rdi
addq $0xdc0, %rdi            # imm = 0xDC0
movq 0x30(%rsp), %rsi
callq 0x18fe0
movq 0x8(%rsp), %rax
movq 0x28(%rax), %rax
movq %rax, 0x28(%rsp)
cmpq $0x0, 0x28(%rsp)
je 0x1f104
movq 0x8(%rsp), %rdi
movl 0x1c(%rdi), %ecx
movq 0x28(%rsp), %rax
movl %ecx, (%rax)
movl 0x20(%rdi), %ecx
movq 0x28(%rsp), %rax
movl %ecx, 0x4(%rax)
movl 0x24(%rdi), %ecx
movq 0x28(%rsp), %rax
movl %ecx, 0x8(%rax)
movq 0x28(%rsp), %rax
movl $0x0, 0xc(%rax)
callq 0x1cf40
movq 0x38(%rsp), %rax
movl 0x18(%rax), %edi
movl $0x2, %esi
callq 0x1f110
testb $0x1, %al
jne 0x1f077
jmp 0x1f09f
movq 0x38(%rsp), %rax
movl 0x18(%rax), %edi
movl $0x4, %esi
callq 0x1f110
testb $0x1, %al
jne 0x1f08f
jmp 0x1f09f
movb $0x1, 0x17(%rsp)
testb $0x1, 0x17(%rsp)
je 0x1f09d
jmp 0x1f0f0
jmp 0x1f09f
movq 0x8(%rsp), %rax
testb $0x1, 0x18(%rax)
je 0x1f0d7
movq 0x8(%rsp), %rax
movl 0x20(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x1f0d7
movq 0x8(%rsp), %rdi
callq 0x1f130
movl %eax, %ecx
movq 0x8(%rsp), %rax
cmpl $0x0, %ecx
setne %cl
andb $0x1, %cl
movb %cl, 0x19(%rax)
movq 0x8(%rsp), %rdi
callq 0x1d2e0
movq 0x8(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x1f200
movq 0x8(%rsp), %rdi
callq 0x1ce60
movq %rax, 0x28(%rsp)
jmp 0x1f01d
addq $0x48, %rsp
retq
nopl (%rax)