// File: lukasz-wiecaszek[P]h264iframedecoder/h264_decoder.cpp
// Function: ymn::h264_decoder::decode_slice(ymn::h264::slice_header const&, ymn::h264::slice_data const&)
void h264_decoder::decode_slice(const h264::slice_header& sh, const h264::slice_data& sd)
{
    bool sps_changed = false;
    bool pps_changed = false;

    const h264::pps* active_pps = sh.get_active_pps();

    if (nullptr == active_pps)
        return;

    const h264::sps* active_sps = active_pps->get_active_sps();

    if (nullptr == active_sps)
        return;

    if (nullptr == m_active_sps ||
        m_active_sps->seq_parameter_set_id != active_sps->seq_parameter_set_id) {
        m_active_sps = active_sps;
        sps_changed = true;
    }

    if (nullptr == m_active_pps ||
        m_active_pps->pic_parameter_set_id != active_pps->pic_parameter_set_id) {
        m_active_pps = active_pps;
        pps_changed = true;
    }

    if (sps_changed) {
        /* active sps has changed, so reinit dimensions */
        m_dimensions.reset(*m_active_sps);
        std::cout << std::endl << m_dimensions.to_string();
    }

    if (pps_changed) {
        /* active pps has changed, so reinit:
           - dequantisation tables
           - chroma_qp_tables
        */
        init_dequantisation_tables();
        init_chroma_qp_tables();
    }

    if ((sh.slice_type == h264::slice_type_e::I) || (sh.slice_type == h264::slice_type_e::SI)) {
        /* entropy_coding_mode_flag selects the entropy decoding method to be applied
        for the syntax elements for which two descriptors appear in the syntax tables as follows.
        - If entropy_coding_mode_flag is equal to 0, the method specified by the left
          descriptor in the syntax table is applied (Exp-Golomb coded, see subclause 9.1
          or CAVLC, see subclause 9.2).
        - Otherwise (entropy_coding_mode_flag is equal to 1), the method specified by
          the right descriptor in the syntax table is applied (CABAC, see subclause 9.3). */
        if (m_active_pps->entropy_coding_mode_flag)
            m_picture = new h264::picture_cabac(*this, sh);
        else
            m_picture = new h264::picture_cavlc(*this, sh);

        m_picture->decode(sh, sd);

        delete m_picture;
    }
}

// Assembly:
subq $0x78, %rsp
movq %rdi, 0x70(%rsp)
movq %rsi, 0x68(%rsp)
movq %rdx, 0x60(%rsp)
movq 0x70(%rsp), %rax
movq %rax, 0x20(%rsp)
movb $0x0, 0x5f(%rsp)
movb $0x0, 0x5e(%rsp)
movq 0x68(%rsp), %rdi
callq 0x10670
movq %rax, 0x50(%rsp)
xorl %eax, %eax
cmpq 0x50(%rsp), %rax
jne 0x1ac24
jmp 0x1ae2a
movq 0x50(%rsp), %rdi
callq 0x10690
movq %rax, 0x48(%rsp)
xorl %eax, %eax
cmpq 0x48(%rsp), %rax
jne 0x1ac41
jmp 0x1ae2a
movq 0x20(%rsp), %rcx
xorl %eax, %eax
cmpq 0x88358(%rcx), %rax
je 0x1ac6a
movq 0x20(%rsp), %rax
movq 0x88358(%rax), %rax
movl 0xc(%rax), %eax
movq 0x48(%rsp), %rcx
cmpl 0xc(%rcx), %eax
je 0x1ac80
movq 0x20(%rsp), %rax
movq 0x48(%rsp), %rcx
movq %rcx, 0x88358(%rax)
movb $0x1, 0x5f(%rsp)
movq 0x20(%rsp), %rcx
xorl %eax, %eax
cmpq 0x88360(%rcx), %rax
je 0x1aca9
movq 0x20(%rsp), %rax
movq 0x88360(%rax), %rax
movl 0xc(%rax), %eax
movq 0x50(%rsp), %rcx
cmpl 0xc(%rcx), %eax
je 0x1acbf
movq 0x20(%rsp), %rax
movq 0x50(%rsp), %rcx
movq %rcx, 0x88360(%rax)
movb $0x1, 0x5e(%rsp)
testb $0x1, 0x5f(%rsp)
je 0x1ad28
movq 0x20(%rsp), %rax
movq %rax, %rdi
addq $0x88340, %rdi          # imm = 0x88340
movq 0x88358(%rax), %rsi
callq 0x1b100
movq 0x132d8(%rip), %rdi     # 0x2dfc0
movq 0x132b9(%rip), %rsi     # 0x2dfa8
callq 0x2180
movq 0x20(%rsp), %rsi
movq %rax, 0x18(%rsp)
addq $0x88340, %rsi          # imm = 0x88340
leaq 0x28(%rsp), %rdi
callq 0x1b160
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x2130
leaq 0x28(%rsp), %rdi
callq 0x20e0
testb $0x1, 0x5e(%rsp)
je 0x1ad43
movq 0x20(%rsp), %rdi
callq 0x1aac0
movq 0x20(%rsp), %rdi
callq 0x1a4d0
movq 0x68(%rsp), %rax
movl 0x18(%rax), %edi
movl $0x2, %esi
callq 0x1ae30
testb $0x1, %al
jne 0x1ad74
movq 0x68(%rsp), %rax
movl 0x18(%rax), %edi
movl $0x4, %esi
callq 0x1ae30
testb $0x1, %al
jne 0x1ad74
jmp 0x1ae2a
movq 0x20(%rsp), %rax
movq 0x88360(%rax), %rax
cmpl $0x0, 0x14(%rax)
je 0x1adba
movl $0x2e10, %edi           # imm = 0x2E10
callq 0x2150
movq 0x20(%rsp), %rsi
movq %rax, %rdi
movq %rdi, 0x10(%rsp)
movq 0x68(%rsp), %rdx
callq 0x1eec0
movq 0x10(%rsp), %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x88368(%rax)
jmp 0x1adec
movl $0xdc0, %edi            # imm = 0xDC0
callq 0x2150
movq 0x20(%rsp), %rsi
movq %rax, %rdi
movq %rdi, 0x8(%rsp)
movq 0x68(%rsp), %rdx
callq 0x1e340
movq 0x8(%rsp), %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x88368(%rax)
movq 0x20(%rsp), %rax
movq 0x88368(%rax), %rdi
movq 0x68(%rsp), %rsi
movq 0x60(%rsp), %rdx
movq (%rdi), %rax
callq *0x10(%rax)
movq 0x20(%rsp), %rax
movq 0x88368(%rax), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x1ae28
movq (%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
jmp 0x1ae2a
addq $0x78, %rsp
retq
nop