// File: /workspace/github_cpp_makefile_star2_O2/lukasz-wiecaszek[P]h264iframedecoder/main.cpp
// Function: main
int main(int argc, char *argv[])
{
    bool status;
    struct {
        bool rtp;
        bool ts;
        bool annex_b;
    } encapsulation = {};
    uint16_t pid = MPEG2TS_PID_INVALID;
    const char* ofile = nullptr;
    ymn::h264_parser_container_e container = ymn::h264_parser_container_e::NONE;
    mpeg2ts_parser_user_data mpeg2ts_user_data;

    static struct option long_options[] = {
        {"rtp",     no_argument,       0, 'r'},
        {"ts",      required_argument, 0, 't'},
        {"annex-b", no_argument,       0, 'a'},
        {"ofile",   required_argument, 0, 'o'},
        {0,         0,                 0,  0 }
    };

    for (;;) {
        int c = getopt_long(argc, argv, "rt:ao:", long_options, 0);
        if (-1 == c)
            break;

        switch(c) {
            case 'r':
                encapsulation.rtp = true;
                break;

            case 't':
                encapsulation.ts = true;
                encapsulation.annex_b = true;
                container = ymn::h264_parser_container_e::ANNEX_B;
                status = (ymn::strtointeger_conversion_status_e::success == ymn::strtointeger(optarg, pid));
                if (!status) {
                    std::cerr << "error: cannot convert '" << optarg << "' to integer" << std::endl;
                    h264iframedecoder_usage(argv[0]);
                    exit(EXIT_FAILURE);
                }
                break;

            case 'a':
                encapsulation.annex_b = true;
                container = ymn::h264_parser_container_e::ANNEX_B;
                break;

            case 'o':
                ofile = optarg;
                break;

            default:
                std::cout << "default option received" << std::endl;
                /* does nothing */
                break;
        }
    }

    std::cout << "encapsulation:"
        << " rtp=" << (encapsulation.rtp ? "y" : "n")
        << " ts=" << (encapsulation.ts ? "y" : "n")
        << " annex-b=" << (encapsulation.annex_b ? "y" : "n")
        << std::endl;
    if (encapsulation.ts)
        std::cout << "pid: " << HEXDEC(pid) << std::endl;
    std::cout << "container: " << to_string(container) << std::endl;

    const char* filename = argv[optind];
    if (!filename) {
         std::cerr << "error: missing input file" << std::endl;
         h264iframedecoder_usage(argv[0]);
         exit(EXIT_FAILURE);
    }

   if (ofile != nullptr) {
      h264_ofile = std::ofstream(ofile, std::ios::out | std::ios::binary);
      if (!h264_ofile.is_open()) {
         std::cerr << "error: could not open '" << ofile << "'" << std::endl;
         h264iframedecoder_usage(argv[0]);
         exit(EXIT_FAILURE);
      }
   }

    h264_decoder = new ymn::h264_decoder(container);
    assert(h264_decoder != nullptr);

    if (encapsulation.ts) {
        mpeg2ts_parser = new ymn::mpeg2ts_parser(TS_PARSER_BUFFER_SIZE);
        assert(mpeg2ts_parser != nullptr);

        mpeg2ts_user_data.pid = pid;
        mpeg2ts_user_data.h264_decoder = h264_decoder;

        mpeg2ts_parser->set_user_data(&mpeg2ts_user_data);
    }

    if (encapsulation.rtp) {
    }

    std::size_t read_bytes = 0;
    std::ifstream file(filename, std::ios::in | std::ios::binary);
    if (file.is_open()) {
        std::streamsize count;
        char* memblock;

        memblock = new char[READ_BUFFER_SIZE];

        do {
            count = file.readsome(memblock, READ_BUFFER_SIZE);
            read_bytes += count;
            if (count > 0) {
                if (encapsulation.rtp)
                    /* to be implemented */;
                else
                if (encapsulation.ts)
                    mpeg2ts_parser_feed(*mpeg2ts_parser, reinterpret_cast<uint8_t*>(memblock), count);
                else
                    h264_decoder_feed(*h264_decoder, reinterpret_cast<uint8_t*>(memblock), count);
            }
        } while (count > 0);

        file.close();
        std::cout << "read " << read_bytes << " bytes from '" << filename << "'" << std::endl;
    }
    else {
        std::cerr << "error: could not open '" << filename << "'" << std::endl;
    }

    if (mpeg2ts_parser)
        delete mpeg2ts_parser;

    if (h264_decoder)
        delete h264_decoder;

    if (h264_ofile.is_open())
        h264_ofile.close();

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x288, %rsp            # imm = 0x288
movq %rsi, %rbx
movl %edi, %r15d
leaq 0x6(%rsp), %rax
movw $0x2000, (%rax)         # imm = 0x2000
movl $0x2000, 0x70(%rsp)     # imm = 0x2000
movq $0x0, 0x30(%rsp)
leaq 0x11b07(%rip), %r13     # 0x1403c
leaq 0x1bc24(%rip), %r12     # 0x1e160
movq 0x1ba7d(%rip), %r14     # 0x1dfc0
leaq 0x11b1e(%rip), %rbp     # 0x14068
movl $0x0, 0x20(%rsp)
movq $0x0, 0x18(%rsp)
movq $0x0, 0x28(%rsp)
movq $0x0, 0x48(%rsp)
movl %r15d, %edi
movq %rbx, %rsi
movq %r13, %rdx
movq %r12, %rcx
xorl %r8d, %r8d
callq 0x2250
cmpl $-0x1, %eax
je 0x2618
cmpl $0x61, %eax
je 0x25f1
cmpl $0x6f, %eax
je 0x2604
cmpl $0x72, %eax
je 0x25e5
cmpl $0x74, %eax
je 0x25b3
movq %r14, %rdi
movq %rbp, %rsi
callq 0x2120
movq %rax, %rdi
callq 0x20b0
jmp 0x256d
movq 0x1b9f6(%rip), %rax     # 0x1dfb0
movq (%rax), %rdi
leaq 0x6(%rsp), %rsi
callq 0x3267
movb $0x1, %cl
movq %rcx, 0x18(%rsp)
pushq $0x1
popq %rcx
movl %ecx, 0x20(%rsp)
movb $0x1, %cl
movq %rcx, 0x28(%rsp)
testl %eax, %eax
je 0x256d
jmp 0x2ddb
movb $0x1, %al
movq %rax, 0x48(%rsp)
jmp 0x256d
movb $0x1, %al
movq %rax, 0x18(%rsp)
pushq $0x1
popq %rax
movl %eax, 0x20(%rsp)
jmp 0x256d
movq 0x1b9a5(%rip), %rax     # 0x1dfb0
movq (%rax), %rax
movq %rax, 0x30(%rsp)
jmp 0x256d
movq 0x1b9a1(%rip), %rdi     # 0x1dfc0
leaq 0x11a5a(%rip), %rsi     # 0x14080
callq 0x2120
leaq 0x11a5d(%rip), %rsi     # 0x1408f
movq %rax, %rdi
callq 0x2120
leaq 0x11b53(%rip), %r15     # 0x14194
leaq 0x15ea9(%rip), %r14     # 0x184f1
testb $0x1, 0x48(%rsp)
movq %r14, %rsi
cmovneq %r15, %rsi
movq %rax, %rdi
callq 0x2120
leaq 0x11a32(%rip), %rsi     # 0x14095
movq %rax, %rdi
callq 0x2120
movq 0x28(%rsp), %r12
testb $0x1, %r12b
movq %r14, %rsi
cmovneq %r15, %rsi
movq %rax, %rdi
callq 0x2120
leaq 0x11a10(%rip), %rsi     # 0x1409a
movq %rax, %rdi
callq 0x2120
testb $0x1, 0x18(%rsp)
cmovneq %r15, %r14
movq %rax, %rdi
movq %r14, %rsi
callq 0x2120
movq %rax, %rdi
callq 0x20b0
testb $0x1, %r12b
je 0x2744
movq 0x1b901(%rip), %rdi     # 0x1dfc0
leaq 0x119de(%rip), %rsi     # 0x140a4
callq 0x2120
leaq 0x11952(%rip), %rsi     # 0x14024
movq %rax, %rdi
callq 0x2120
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x8, %edx
movl %edx, 0x18(%rax,%rcx)
movzwl 0x6(%rsp), %esi
movq %rax, %rdi
callq 0x2270
leaq 0x11924(%rip), %rsi     # 0x14027
movq %rax, %rdi
callq 0x2120
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x2, %edx
movl %edx, 0x18(%rax,%rcx)
movzwl 0x6(%rsp), %esi
movq %rax, %rdi
callq 0x2270
leaq 0x123c2(%rip), %rsi     # 0x14af6
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x20b0
movq 0x1b875(%rip), %rdi     # 0x1dfc0
leaq 0x11958(%rip), %rsi     # 0x140aa
callq 0x2120
movl 0x20(%rsp), %ebp
testl %ebp, %ebp
leaq 0x11d8f(%rip), %rcx     # 0x144f3
leaq 0x11d8d(%rip), %rsi     # 0x144f8
cmoveq %rcx, %rsi
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x20b0
movq 0x1b842(%rip), %rax     # 0x1dfc8
movslq (%rax), %rax
movq (%rbx,%rax,8), %r15
testq %r15, %r15
movq 0x30(%rsp), %r12
je 0x2dcb
testq %r12, %r12
je 0x27e1
leaq 0x80(%rsp), %r14
pushq $0x14
popq %rdx
movq %r14, %rdi
movq %r12, %rsi
callq 0x2160
leaq 0x1ba5b(%rip), %rdi     # 0x1e218
movq %r14, %rsi
callq 0x2180
movq %r14, %rdi
callq 0x2298
leaq 0x1bab4(%rip), %rdi     # 0x1e288
callq 0x2070
testb %al, %al
je 0x2e09
pushq $0x40
popq %rsi
movl $0xa6480, %edi          # imm = 0xA6480
callq 0x2170
movq %rax, 0x40(%rsp)
movq %rax, %rdi
movl %ebp, %esi
callq 0x6d44
testb $0x1, 0x28(%rsp)
je 0x2844
pushq $0x40
popq %rsi
movl $0x180, %edi            # imm = 0x180
callq 0x2170
movq %rax, %rbx
movl $0x2000, %esi           # imm = 0x2000
movq %rax, %rdi
callq 0x2fea
movq %rbx, 0x1bbf0(%rip)     # 0x1e418
movzwl 0x6(%rsp), %eax
leaq 0x70(%rsp), %rcx
movl %eax, (%rcx)
movq 0x40(%rsp), %rax
movq %rax, 0x8(%rcx)
movq %rcx, 0x100(%rbx)
leaq 0x80(%rsp), %rdi
pushq $0xc
popq %rdx
movq %r15, %rsi
callq 0x2280
leaq 0xf8(%rsp), %rdi
callq 0x2070
testb %al, %al
je 0x2d07
movq %r15, 0x60(%rsp)
movl $0x1000, %edi           # imm = 0x1000
callq 0x2030
movq %rax, 0x50(%rsp)
xorl %ebx, %ebx
leaq 0x1177b(%rip), %r13     # 0x14004
movq %rbx, 0x68(%rsp)
movl $0x1000, %edx           # imm = 0x1000
leaq 0x80(%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x2210
movq %rax, 0x58(%rsp)
testq %rax, %rax
setle %al
orb 0x48(%rsp), %al
testb $0x1, %al
movq 0x1b703(%rip), %rbx     # 0x1dfc0
jne 0x2cb0
testb $0x1, 0x28(%rsp)
je 0x2c9c
movq 0x1bb43(%rip), %r12     # 0x1e418
movq 0x58(%rsp), %r14
movq 0x50(%rsp), %r15
movq %r12, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x30da
testq %rax, %rax
je 0x2c89
movq %r15, 0x18(%rsp)
movq %rax, 0x30(%rsp)
subq %rax, %r14
movq %r14, 0x20(%rsp)
jb 0x2da8
movq 0x100(%r12), %rax
movl (%rax), %ebp
movq %r12, %rdi
callq 0x3210
cmpl $0x3, %eax
ja 0x2918
movl %eax, %eax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movq %rbx, %rdi
leaq 0x11c0b(%rip), %rsi     # 0x14546
jmp 0x2947
movq %rbx, %rdi
leaq 0x11c0b(%rip), %rsi     # 0x14552
callq 0x2120
movq %rax, %rdi
callq 0x20b0
jmp 0x2918
movq %r12, %rdi
callq 0x322c
movq %rax, %r14
movzbl 0x1(%rax), %eax
movzbl 0x2(%r14), %ecx
movl %eax, %edx
andl $0x1f, %edx
shll $0x8, %edx
orl %ecx, %edx
cmpl %ebp, %edx
jne 0x2918
movzbl 0x3(%r14), %ecx
shrl $0x4, %ecx
andl $0x3, %ecx
leaq 0x1168a(%rip), %rsi     # 0x14014
movslq (%rsi,%rcx,4), %rdx
addq %rsi, %rdx
pushq $0x4
popq %rcx
jmpq *%rdx
movzbl 0x4(%r14), %ecx
addl $0x5, %ecx
movl %ecx, %edx
addq %rdx, %r14
movl $0xbc, %r15d
subl %ecx, %r15d
movq 0x100(%r12), %r8
testb $0x40, %al
jne 0x29e3
movl 0x1ba62(%rip), %eax     # 0x1e420
testl %eax, %eax
je 0x2918
cmpl $0x2, %eax
jne 0x2aa5
movq 0x8(%r8), %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x2fa6
jmp 0x2918
movl $0x1, 0x1ba33(%rip)     # 0x1e420
andq $0x0, 0x1ba33(%rip)     # 0x1e428
cmpl $0xb5, %ecx
jbe 0x2a1b
leaq 0x1ba2c(%rip), %rdi     # 0x1e430
movq %r14, %rsi
movq %r15, %rdx
callq 0x20f0
movq %r15, 0x1ba12(%rip)     # 0x1e428
jmp 0x2918
movq %r14, %rbx
xorl %esi, %esi
movq %r15, %rdx
cmpb $0x0, (%rbx)
jne 0x2a92
cmpb $0x0, 0x1(%rbx)
jne 0x2a92
cmpb $0x1, 0x2(%rbx)
jne 0x2a92
movb 0x3(%rbx), %al
andb $-0x10, %al
cmpb $-0x20, %al
jne 0x2a92
movb 0x6(%rbx), %al
andb $-0x40, %al
negb %al
jno 0x2a92
pushq $0x9
popq %rax
subl %edx, %eax
testl %eax, %eax
jle 0x2b4d
testq %rsi, %rsi
je 0x2bea
movl %eax, %ecx
leaq 0x1b9cb(%rip), %rax     # 0x1e430
leaq (%rax,%rsi), %rdi
movq %r15, %rax
subq %rcx, %rax
movq %rsi, 0x8(%rsp)
jae 0x2b52
movq %r14, %rsi
movq %r15, %rdx
callq 0x20f0
movq 0x8(%rsp), %rax
addq %r15, %rax
jmp 0x2bd7
andl $0x0, 0x1b987(%rip)     # 0x1e420
movq 0x1b520(%rip), %rbx     # 0x1dfc0
jmp 0x2918
movq 0x1b97c(%rip), %rsi     # 0x1e428
testq %rsi, %rsi
leaq 0x1b97a(%rip), %rbx     # 0x1e430
cmoveq %r14, %rbx
movq %rsi, %rdx
cmoveq %r15, %rdx
pushq $0x7
popq %rax
subl %edx, %eax
testl %eax, %eax
jle 0x2a23
testq %rsi, %rsi
movq 0x1b4e8(%rip), %rbx     # 0x1dfc0
je 0x29fd
leaq 0x1b94b(%rip), %rcx     # 0x1e430
leaq (%rcx,%rsi), %rdi
cmpl %r15d, %eax
movq %rsi, 0x8(%rsp)
jbe 0x2b12
movq %r14, %rsi
movq %r15, %rdx
callq 0x20f0
movq 0x8(%rsp), %rax
addq %r15, %rax
movq %rax, 0x1b91b(%rip)     # 0x1e428
jmp 0x2918
movl %eax, %ebx
movq %r14, %rsi
movq %r8, 0x10(%rsp)
movq %rbx, %rdx
callq 0x20f0
movq 0x10(%rsp), %r8
movq 0x8(%rsp), %rsi
addq %rbx, %rsi
movq %rsi, 0x1b8f0(%rip)     # 0x1e428
addq %rbx, %r14
subq %rbx, %r15
leaq 0x1b8eb(%rip), %rbx     # 0x1e430
pushq $0x7
popq %rdx
jmp 0x2a23
movq %r15, %rcx
jmp 0x2b89
movq %r14, %rsi
movq %r8, 0x10(%rsp)
movq %rcx, %r15
movq %rcx, %rdx
movq %rax, 0x38(%rsp)
callq 0x20f0
movq 0x38(%rsp), %rcx
movq 0x10(%rsp), %r8
movq 0x8(%rsp), %rsi
addq %r15, %rsi
movq %rsi, 0x1b8a5(%rip)     # 0x1e428
addq %r15, %r14
pushq $0x9
popq %rdx
movzbl 0x8(%rbx), %r9d
addq $0x9, %r9
movq %r9, %r15
subq %rdx, %r15
testl %r15d, %r15d
jle 0x2c0f
testq %rsi, %rsi
je 0x2bea
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
leaq 0x1b880(%rip), %rax     # 0x1e430
leaq (%rax,%rsi), %rdi
movq %rcx, %rbx
subq %r15, %rbx
movq %rsi, 0x8(%rsp)
jae 0x2c14
movq %r14, %rsi
movq %rcx, %rdx
movq %rcx, %rbx
callq 0x20f0
movq 0x8(%rsp), %rax
addq %rbx, %rax
movq %rax, 0x1b84a(%rip)     # 0x1e428
movq 0x1b3db(%rip), %rbx     # 0x1dfc0
jmp 0x2918
leaq 0x1b83f(%rip), %rdi     # 0x1e430
movq %rbx, %rsi
movq %rdx, %rbx
callq 0x20f0
movq %rbx, 0x1b825(%rip)     # 0x1e428
movq 0x1b3b6(%rip), %rbx     # 0x1dfc0
jmp 0x2918
movq %rcx, %rbx
jmp 0x2c45
movq %r14, %rsi
movq %r8, 0x10(%rsp)
movq %r15, %rdx
movq %r9, 0x38(%rsp)
callq 0x20f0
movq 0x38(%rsp), %r9
movq 0x10(%rsp), %r8
movq 0x8(%rsp), %rsi
addq %r15, %rsi
movq %rsi, 0x1b7e6(%rip)     # 0x1e428
addq %r15, %r14
testq %rsi, %rsi
je 0x2c4d
xorl %r9d, %r9d
subq %r9, %rbx
addq %r9, %r14
movq 0x8(%r8), %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x2fa6
movl $0x2, 0x1b7b4(%rip)     # 0x1e420
movq 0x1b34d(%rip), %rbx     # 0x1dfc0
jmp 0x2918
movq 0x18(%rsp), %r15
addq 0x30(%rsp), %r15
movq 0x20(%rsp), %r14
jmp 0x2c91
movq %r12, %rdi
callq 0x310e
testq %r14, %r14
jne 0x28df
jmp 0x2cb0
movq 0x40(%rsp), %rdi
movq 0x50(%rsp), %rsi
movq 0x58(%rsp), %rdx
callq 0x2fa6
movq 0x68(%rsp), %rbx
movq 0x58(%rsp), %rax
addq %rax, %rbx
testq %rax, %rax
jg 0x2889
leaq 0x80(%rsp), %rdi
callq 0x2050
movq 0x1b2e6(%rip), %rdi     # 0x1dfc0
leaq 0x11407(%rip), %rsi     # 0x140e8
callq 0x2120
movq %rax, %rdi
movq %rbx, %rsi
callq 0x20e0
leaq 0x113f6(%rip), %rsi     # 0x140ee
movq %rax, %rdi
callq 0x2120
movq 0x60(%rsp), %r15
jmp 0x2d1a
movq 0x1b2e2(%rip), %rdi     # 0x1dff0
leaq 0x113bb(%rip), %rsi     # 0x140d0
callq 0x2120
movq %rax, %rdi
movq %r15, %rsi
callq 0x2120
leaq 0x15a00(%rip), %rsi     # 0x1872c
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x20b0
movq 0x1b6d5(%rip), %rdi     # 0x1e418
testq %rdi, %rdi
je 0x2d4e
movq (%rdi), %rax
callq *0x8(%rax)
movq 0x40(%rsp), %rbx
movq %rbx, %rdi
callq 0x6d76
pushq $0x40
popq %rdx
movl $0xa6480, %esi          # imm = 0xA6480
movq %rbx, %rdi
callq 0x2060
leaq 0x1b516(%rip), %rdi     # 0x1e288
callq 0x2070
testb %al, %al
je 0x2d87
leaq 0x1b496(%rip), %rdi     # 0x1e218
callq 0x21f0
leaq 0x80(%rsp), %rdi
callq 0x2090
xorl %eax, %eax
addq $0x288, %rsp            # imm = 0x288
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x1b241(%rip), %rdi     # 0x1dff0
leaq 0x1174a(%rip), %rsi     # 0x14500
callq 0x2120
movq %rax, %rdi
callq 0x20b0
pushq $0x1
popq %rdi
callq 0x2190
movq 0x1b21e(%rip), %rdi     # 0x1dff0
leaq 0x112dd(%rip), %rsi     # 0x140b6
jmp 0x2e31
movq 0x1b20e(%rip), %rdi     # 0x1dff0
leaq 0x1125a(%rip), %rsi     # 0x14043
callq 0x2120
movq 0x1b1bb(%rip), %rcx     # 0x1dfb0
movq (%rcx), %rsi
movq %rax, %rdi
callq 0x2120
leaq 0x11254(%rip), %rsi     # 0x1405b
jmp 0x2e2e
movq 0x1b1e0(%rip), %rdi     # 0x1dff0
leaq 0x112b9(%rip), %rsi     # 0x140d0
callq 0x2120
movq %rax, %rdi
movq %r12, %rsi
callq 0x2120
leaq 0x158fe(%rip), %rsi     # 0x1872c
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x20b0
movq (%rbx), %rdi
callq 0x2e4b
jmp 0x2dc3