// File: lukasz-wiecaszek[P]h264iframedecoder/h264_parser.cpp
// Function: h264_parser_nal_to_rbsp(unsigned char*, unsigned long, unsigned char const*, unsigned long)
static int h264_parser_nal_to_rbsp(
    uint8_t* rbsp_buf, std::size_t rbsp_size, const uint8_t* nal_buf, std::size_t nal_size)
{
    std::size_t i     = 0;
    std::size_t j     = 0;
    std::size_t count = 0;

    while (i < nal_size) {
        /* within the NAL unit, the following three-byte sequences shall not occur */
        /* at any byte-aligned position: 0x000000, 0x000001, 0x000002 */
        if ((count == 2) && (nal_buf[i] < 0x03))
            return -1;

        if ((count == 2) && (nal_buf[i] == 0x03)) {
            /* within the NAL unit, any four-byte sequence that starts with 0x000003 */
            /* other than the following sequences shall not occur at any byte-aligned position: */
            /* 0x00000300, 0x00000301, 0x00000302, 0x00000303 */
            /* check the 4th byte after 0x000003, except when cabac_zero_word is used, */
            /* in which case the last three bytes of this NAL unit must be 0x000003 */
            if((i < nal_size - 1) && (nal_buf[i + 1] > 0x03))
                return -1;

            /* if cabac_zero_word is used, the final byte of this NAL unit(0x03) is discarded, */
            /* and the last two bytes of RBSP must be 0x0000 */
            if (i == nal_size - 1)
                break;

            i++;
            count = 0;
        }

        if (j >= rbsp_size)
            return -1; /* error, not enough space */

        rbsp_buf[j] = nal_buf[i];

        if(nal_buf[i] == 0x00)
            count++;
        else
            count = 0;

        i++;
        j++;
    }

    return j;
}

// Assembly:
movq %rdi, -0x10(%rsp)
movq %rsi, -0x18(%rsp)
movq %rdx, -0x20(%rsp)
movq %rcx, -0x28(%rsp)
movq $0x0, -0x30(%rsp)
movq $0x0, -0x38(%rsp)
movq $0x0, -0x40(%rsp)
movq -0x30(%rsp), %rax
cmpq -0x28(%rsp), %rax
jae 0x16e62
cmpq $0x2, -0x40(%rsp)
jne 0x16d67
movq -0x20(%rsp), %rax
movq -0x30(%rsp), %rcx
movzbl (%rax,%rcx), %eax
cmpl $0x3, %eax
jge 0x16d67
movl $0xffffffff, -0x4(%rsp) # imm = 0xFFFFFFFF
jmp 0x16e6b
cmpq $0x2, -0x40(%rsp)
jne 0x16de5
movq -0x20(%rsp), %rax
movq -0x30(%rsp), %rcx
movzbl (%rax,%rcx), %eax
cmpl $0x3, %eax
jne 0x16de5
movq -0x30(%rsp), %rax
movq -0x28(%rsp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jae 0x16db6
movq -0x20(%rsp), %rax
movq -0x30(%rsp), %rcx
movzbl 0x1(%rax,%rcx), %eax
cmpl $0x3, %eax
jle 0x16db6
movl $0xffffffff, -0x4(%rsp) # imm = 0xFFFFFFFF
jmp 0x16e6b
movq -0x30(%rsp), %rax
movq -0x28(%rsp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jne 0x16dce
jmp 0x16e62
movq -0x30(%rsp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rsp)
movq $0x0, -0x40(%rsp)
movq -0x38(%rsp), %rax
cmpq -0x18(%rsp), %rax
jb 0x16dfb
movl $0xffffffff, -0x4(%rsp) # imm = 0xFFFFFFFF
jmp 0x16e6b
movq -0x20(%rsp), %rax
movq -0x30(%rsp), %rcx
movb (%rax,%rcx), %dl
movq -0x10(%rsp), %rax
movq -0x38(%rsp), %rcx
movb %dl, (%rax,%rcx)
movq -0x20(%rsp), %rax
movq -0x30(%rsp), %rcx
movzbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jne 0x16e38
movq -0x40(%rsp), %rax
addq $0x1, %rax
movq %rax, -0x40(%rsp)
jmp 0x16e41
movq $0x0, -0x40(%rsp)
movq -0x30(%rsp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rsp)
movq -0x38(%rsp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rsp)
jmp 0x16d2f
movq -0x38(%rsp), %rax
movl %eax, -0x4(%rsp)
movl -0x4(%rsp), %eax
retq