// File: lukasz-wiecaszek[P]h264iframedecoder/main.cpp
// Function: mpeg2ts_parser_demux(ymn::mpeg2ts_parser&, unsigned char const*, unsigned long, bool)
static void mpeg2ts_parser_demux(ymn::mpeg2ts_parser& parser, const uint8_t *tspayload, std::size_t count, bool payload_unit_start_indicator)
{
    static enum {DMX_IDLE, DMX_HEADER, DMX_DATA} dmx_state = DMX_IDLE;
    static std::size_t buffer_bytes = 0;
    static uint8_t buffer[256];

    mpeg2ts_parser_user_data* mpeg2ts_user_data =
        static_cast<mpeg2ts_parser_user_data*>(parser.get_user_data());

    const uint8_t* p;
    std::size_t available;
    std::size_t len;

#define NEEDBYTES(x)                                                   \
    do {                                                               \
        int missing;                                                   \
                                                                       \
        missing = (x) - available;                                     \
        if (missing > 0) {                                             \
            if (0 == buffer_bytes) {                                   \
                memcpy(buffer, p, available);                          \
                buffer_bytes = available;                              \
                return;                                                \
            }                                                          \
            else {                                                     \
                if ((unsigned int)missing <= count) {                  \
                    memcpy(buffer + buffer_bytes, tspayload, missing); \
                    buffer_bytes += missing;                           \
                    tspayload += missing;                              \
                    count -= missing;                                  \
                    available = (x);                                   \
                }                                                      \
                else {                                                 \
                    memcpy(buffer + buffer_bytes, tspayload, count);   \
                    buffer_bytes += count;                             \
                    return;                                            \
                }                                                      \
            }                                                          \
        }                                                              \
    } while (0)

    if (payload_unit_start_indicator) {
        dmx_state = DMX_HEADER;
        buffer_bytes = 0;
    }

    if (0 == buffer_bytes) {
        p = tspayload;
        available = count;
    }
    else {
        p = buffer;
        available = buffer_bytes;
    }

    switch (dmx_state) {
        case DMX_IDLE:
            return;

        case DMX_HEADER:
            NEEDBYTES(7);

//fprintf(stdout, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6]);

            /* 1110 xxxx - 13818-2 or 11172-2 video stream number xxxxx */
            if ((p[0] != 0x00) || (p[1] != 0x00) || (p[2] != 0x01) ||
                (p[3] <  0xe0) || (p[3] >  0xef) || ((p[6] & 0xc0) != 0x80 /* mpeg2 */)) {
                dmx_state = DMX_IDLE;
                return;
            }

            NEEDBYTES(9);
            len = 9 + p[8];
            NEEDBYTES(len);

            if (0 == buffer_bytes) {
                tspayload += len;
                count -= len;
            }

            h264_decoder_feed(*mpeg2ts_user_data->h264_decoder, tspayload, count);
            dmx_state = DMX_DATA;
            return;

        case DMX_DATA:
            h264_decoder_feed(*mpeg2ts_user_data->h264_decoder, tspayload, count);
            return;
    }

#undef NEEDBYTES
}

// Assembly:
subq $0x58, %rsp
movb %cl, %al
movq %rdi, 0x50(%rsp)
movq %rsi, 0x48(%rsp)
movq %rdx, 0x40(%rsp)
andb $0x1, %al
movb %al, 0x3f(%rsp)
movq 0x50(%rsp), %rdi
callq 0x11080
movq %rax, 0x30(%rsp)
testb $0x1, 0x3f(%rsp)
je 0x4006
movl $0x1, 0x2a44d(%rip)     # 0x2e448
movq $0x0, 0x2a44a(%rip) # 0x2e450
xorl %eax, %eax
cmpq 0x2a441(%rip), %rax     # 0x2e450
jne 0x4027
movq 0x48(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x20(%rsp)
jmp 0x403f
leaq 0x2a432(%rip), %rax     # 0x2e460
movq %rax, 0x28(%rsp)
movq 0x2a416(%rip), %rax     # 0x2e450
movq %rax, 0x20(%rsp)
movl 0x2a403(%rip), %eax     # 0x2e448
movl %eax, 0x8(%rsp)
testl %eax, %eax
je 0x406c
jmp 0x404f
movl 0x8(%rsp), %eax
subl $0x1, %eax
je 0x4071
jmp 0x405a
movl 0x8(%rsp), %eax
subl $0x2, %eax
je 0x4419
jmp 0x4431
jmp 0x4431
jmp 0x4073
movl $0x7, %eax
subq 0x20(%rsp), %rax
movl %eax, 0x14(%rsp)
cmpl $0x0, 0x14(%rsp)
jle 0x4163
xorl %eax, %eax
cmpq 0x2a3bb(%rip), %rax     # 0x2e450
jne 0x40be
movq 0x28(%rsp), %rsi
movq 0x20(%rsp), %rdx
leaq 0x2a3b8(%rip), %rdi     # 0x2e460
callq 0x2110
movq 0x20(%rsp), %rax
movq %rax, 0x2a397(%rip)     # 0x2e450
jmp 0x4431
movl 0x14(%rsp), %eax
cmpq 0x40(%rsp), %rax
ja 0x412a
leaq 0x2a390(%rip), %rdi     # 0x2e460
addq 0x2a379(%rip), %rdi     # 0x2e450
movq 0x48(%rsp), %rsi
movslq 0x14(%rsp), %rdx
callq 0x2110
movslq 0x14(%rsp), %rax
addq 0x2a35e(%rip), %rax     # 0x2e450
movq %rax, 0x2a357(%rip)     # 0x2e450
movl 0x14(%rsp), %ecx
movq 0x48(%rsp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x48(%rsp)
movslq 0x14(%rsp), %rcx
movq 0x40(%rsp), %rax
subq %rcx, %rax
movq %rax, 0x40(%rsp)
movq $0x7, 0x20(%rsp)
jmp 0x415f
leaq 0x2a32f(%rip), %rdi     # 0x2e460
addq 0x2a318(%rip), %rdi     # 0x2e450
movq 0x48(%rsp), %rsi
movq 0x40(%rsp), %rdx
callq 0x2110
movq 0x40(%rsp), %rax
addq 0x2a2fd(%rip), %rax     # 0x2e450
movq %rax, 0x2a2f6(%rip)     # 0x2e450
jmp 0x4431
jmp 0x4161
jmp 0x4163
jmp 0x4165
movq 0x28(%rsp), %rax
movzbl (%rax), %eax
cmpl $0x0, %eax
jne 0x41c3
movq 0x28(%rsp), %rax
movzbl 0x1(%rax), %eax
cmpl $0x0, %eax
jne 0x41c3
movq 0x28(%rsp), %rax
movzbl 0x2(%rax), %eax
cmpl $0x1, %eax
jne 0x41c3
movq 0x28(%rsp), %rax
movzbl 0x3(%rax), %eax
cmpl $0xe0, %eax
jl 0x41c3
movq 0x28(%rsp), %rax
movzbl 0x3(%rax), %eax
cmpl $0xef, %eax
jg 0x41c3
movq 0x28(%rsp), %rax
movzbl 0x6(%rax), %eax
andl $0xc0, %eax
cmpl $0x80, %eax
je 0x41d2
movl $0x0, 0x2a27b(%rip)     # 0x2e448
jmp 0x4431
jmp 0x41d4
movl $0x9, %eax
subq 0x20(%rsp), %rax
movl %eax, 0x10(%rsp)
cmpl $0x0, 0x10(%rsp)
jle 0x42c4
xorl %eax, %eax
cmpq 0x2a25a(%rip), %rax     # 0x2e450
jne 0x421f
movq 0x28(%rsp), %rsi
movq 0x20(%rsp), %rdx
leaq 0x2a257(%rip), %rdi     # 0x2e460
callq 0x2110
movq 0x20(%rsp), %rax
movq %rax, 0x2a236(%rip)     # 0x2e450
jmp 0x4431
movl 0x10(%rsp), %eax
cmpq 0x40(%rsp), %rax
ja 0x428b
leaq 0x2a22f(%rip), %rdi     # 0x2e460
addq 0x2a218(%rip), %rdi     # 0x2e450
movq 0x48(%rsp), %rsi
movslq 0x10(%rsp), %rdx
callq 0x2110
movslq 0x10(%rsp), %rax
addq 0x2a1fd(%rip), %rax     # 0x2e450
movq %rax, 0x2a1f6(%rip)     # 0x2e450
movl 0x10(%rsp), %ecx
movq 0x48(%rsp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x48(%rsp)
movslq 0x10(%rsp), %rcx
movq 0x40(%rsp), %rax
subq %rcx, %rax
movq %rax, 0x40(%rsp)
movq $0x9, 0x20(%rsp)
jmp 0x42c0
leaq 0x2a1ce(%rip), %rdi     # 0x2e460
addq 0x2a1b7(%rip), %rdi     # 0x2e450
movq 0x48(%rsp), %rsi
movq 0x40(%rsp), %rdx
callq 0x2110
movq 0x40(%rsp), %rax
addq 0x2a19c(%rip), %rax     # 0x2e450
movq %rax, 0x2a195(%rip)     # 0x2e450
jmp 0x4431
jmp 0x42c2
jmp 0x42c4
jmp 0x42c6
movq 0x28(%rsp), %rax
movzbl 0x8(%rax), %eax
addl $0x9, %eax
cltq
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
subq 0x20(%rsp), %rax
movl %eax, 0xc(%rsp)
cmpl $0x0, 0xc(%rsp)
jle 0x43c7
xorl %eax, %eax
cmpq 0x2a155(%rip), %rax     # 0x2e450
jne 0x4324
movq 0x28(%rsp), %rsi
movq 0x20(%rsp), %rdx
leaq 0x2a152(%rip), %rdi     # 0x2e460
callq 0x2110
movq 0x20(%rsp), %rax
movq %rax, 0x2a131(%rip)     # 0x2e450
jmp 0x4431
movl 0xc(%rsp), %eax
cmpq 0x40(%rsp), %rax
ja 0x4391
leaq 0x2a12a(%rip), %rdi     # 0x2e460
addq 0x2a113(%rip), %rdi     # 0x2e450
movq 0x48(%rsp), %rsi
movslq 0xc(%rsp), %rdx
callq 0x2110
movslq 0xc(%rsp), %rax
addq 0x2a0f8(%rip), %rax     # 0x2e450
movq %rax, 0x2a0f1(%rip)     # 0x2e450
movl 0xc(%rsp), %ecx
movq 0x48(%rsp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x48(%rsp)
movslq 0xc(%rsp), %rcx
movq 0x40(%rsp), %rax
subq %rcx, %rax
movq %rax, 0x40(%rsp)
movq 0x18(%rsp), %rax
movq %rax, 0x20(%rsp)
jmp 0x43c3
leaq 0x2a0c8(%rip), %rdi     # 0x2e460
addq 0x2a0b1(%rip), %rdi     # 0x2e450
movq 0x48(%rsp), %rsi
movq 0x40(%rsp), %rdx
callq 0x2110
movq 0x40(%rsp), %rax
addq 0x2a096(%rip), %rax     # 0x2e450
movq %rax, 0x2a08f(%rip)     # 0x2e450
jmp 0x4431
jmp 0x43c5
jmp 0x43c7
jmp 0x43c9
xorl %eax, %eax
cmpq 0x2a07e(%rip), %rax     # 0x2e450
jne 0x43f5
movq 0x18(%rsp), %rax
addq 0x48(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x18(%rsp), %rcx
movq 0x40(%rsp), %rax
subq %rcx, %rax
movq %rax, 0x40(%rsp)
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rdi
movq 0x48(%rsp), %rsi
movq 0x40(%rsp), %rdx
callq 0x3c40
movl $0x2, 0x2a031(%rip)     # 0x2e448
jmp 0x4431
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rdi
movq 0x48(%rsp), %rsi
movq 0x40(%rsp), %rdx
callq 0x3c40
addq $0x58, %rsp
retq
nopw %cs:(%rax,%rax)