// File: zhangk145[P]video_envalue/Main.cpp
// Function: main
int main (int argc, char **argv) {
    Context context;
    char *org_file_name = NULL;
    char *new_file_name = NULL;
    EnvalMode mode = EVL_BOTH; //0表示计算psnr和ssim, 1表示只计算psnr，2表示只计算ssim

    const char *psnr_file_name = "psnr.txt";
    const char *ssim_file_name = "ssim.txt";
    FILE *psnr_file = NULL;
    FILE *ssim_file = NULL;
    int ret = 0;
    AVFrame *frame[2] = {0};
    uint8_t *org_image_data[4];
    int      org_image_linesize[4];
    uint8_t *new_image_data[4];
    int      new_image_linesize[4];
    int decode_max_nm = -1;
    int decode_count = 0;

    Decoder decoder[2];

    if (argc < 3) {
        return -1;
    }
    else if (argc > 3) {
        if (!strcmp(argv[3], "psnr")) {
            mode = EVL_PSNR;
        }
        else if (!strcmp(argv[3], "ssim")) {
            mode = EVL_SSIM;
        }
        else {

        }
    }
    else if (argc > 4) {
        decode_max_nm = atoi(argv[4]);
    }
    decode_count = decode_max_nm;
    Envaluer envaluer(mode);
    org_file_name = argv[1];
    new_file_name = argv[2];

    psnr_file = fopen(psnr_file_name, "w");
    if (psnr_file == NULL) {
        return -1;
    }
    context.psnr_file = psnr_file;
    ssim_file = fopen(ssim_file_name, "w");
    if (ssim_file == NULL) {
        return -1;
    }
    context.ssim_file = ssim_file;

    envaluer.setCallback(psnr_write, ssim_write, &context);

    Decoder::global_init();
    
    frame[0] = av_frame_alloc();
    frame[1] = av_frame_alloc();

    ret = decoder[0].open(org_file_name);
    if (ret < 0) {
        return -1;
    }
    ret = av_image_alloc(org_image_data, org_image_linesize,
                            decoder[0].width(), decoder[0].height(), decoder[0].pix_fmt(), 1);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate raw video buffer\n");
        return ret;
    }
    ret = decoder[1].open(new_file_name);
    if (ret < 0) {
        return -1;
    }
    ret = av_image_alloc(new_image_data, new_image_linesize,
                            decoder[1].width(), decoder[1].height(), decoder[1].pix_fmt(), 1);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate raw video buffer\n");
        return ret;
    }

    envaluer.open(decoder[0].width(), decoder[0].height(), decoder[0].pix_fmt());
    // int cnt = 10;
    while(1) {
        if (decode_max_nm > 0) {
            if (decode_count-- <= 0) {
                break;
            }
        }
        ret = decoder[0].decode(frame[0]);
        // printf("[%s:%d]==ret:%d\n", __FUNCTION__, __LINE__, ret);
        if (ret < 0) {
            break;
        }
        av_image_copy(org_image_data, org_image_linesize,
                    (const uint8_t **)(frame[0]->data), frame[0]->linesize,
                    decoder[0].pix_fmt(), decoder[0].width(), decoder[0].height());
        ret = decoder[1].decode(frame[1]);
        // printf("[%s:%d]==ret:%d\n", __FUNCTION__, __LINE__, ret);
        if (ret < 0) {
            printf("[%s:%d]==ret:%d\n", __FUNCTION__, __LINE__, ret);
            break;
        }
        // printf("[%s:%d]==\n", __FUNCTION__, __LINE__);
        av_image_copy(new_image_data, new_image_linesize,
                    (const uint8_t **)(frame[1]->data), frame[1]->linesize,
                    decoder[1].pix_fmt(), decoder[1].width(), decoder[1].height());
        // printf("[%s:%d]==\n", __FUNCTION__, __LINE__);
        envaluer.compute(org_image_data[0], new_image_data[0]);
    }
    envaluer.close();
    av_frame_free(&frame[0]);
    av_frame_free(&frame[1]);
    av_free(org_image_data[0]);
    av_free(new_image_data[0]);
    fclose(psnr_file);
    fclose(ssim_file);
    return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x300, %rsp            # imm = 0x300
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movl $0x2, -0x34(%rbp)
leaq 0x1a09(%rip), %rax      # 0x52a0
movq %rax, -0x40(%rbp)
leaq 0x1a07(%rip), %rax      # 0x52a9
movq %rax, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
movq $0x0, -0x58(%rbp)
movl $0x0, -0x5c(%rbp)
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x20b0
movl $0xffffffff, -0xd4(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0xd8(%rbp)
leaq -0x140(%rbp), %rax
movq %rax, -0x1d8(%rbp)
movq %rax, %rcx
addq $0x60, %rcx
movq %rcx, -0x1d0(%rbp)
movq %rax, -0x1c8(%rbp)
movq -0x1c8(%rbp), %rdi
movq %rdi, -0x1e0(%rbp)
callq 0x2480
jmp 0x3919
movq -0x1d0(%rbp), %rcx
movq -0x1e0(%rbp), %rax
addq $0x30, %rax
cmpq %rcx, %rax
movq %rax, -0x1c8(%rbp)
jne 0x3904
cmpl $0x3, -0x8(%rbp)
jge 0x39b3
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x150(%rbp)
jmp 0x406c
movq -0x1d8(%rbp), %rcx
movq %rax, %rsi
movq -0x1e0(%rbp), %rax
movq %rsi, -0x148(%rbp)
movl %edx, -0x14c(%rbp)
cmpq %rax, %rcx
movq %rax, -0x1e8(%rbp)
je 0x39ae
movq -0x1e8(%rbp), %rdi
addq $-0x30, %rdi
movq %rdi, -0x1f0(%rbp)
callq 0x24d0
movq -0x1d8(%rbp), %rcx
movq -0x1f0(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x1e8(%rbp)
jne 0x397d
jmp 0x410e
cmpl $0x3, -0x8(%rbp)
jle 0x3a03
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
leaq 0x18ea(%rip), %rsi      # 0x52b2
callq 0x21f0
cmpl $0x0, %eax
jne 0x39db
movl $0x0, -0x34(%rbp)
jmp 0x3a01
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
leaq 0x18cd(%rip), %rsi      # 0x52b7
callq 0x21f0
cmpl $0x0, %eax
jne 0x39fd
movl $0x1, -0x34(%rbp)
jmp 0x39ff
jmp 0x39ff
jmp 0x3a01
jmp 0x3a1e
cmpl $0x4, -0x8(%rbp)
jle 0x3a1c
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x20c0
movl %eax, -0xd4(%rbp)
jmp 0x3a1e
jmp 0x3a20
movl -0xd4(%rbp), %eax
movl %eax, -0xd8(%rbp)
movl -0x34(%rbp), %esi
leaq -0x1c0(%rbp), %rdi
callq 0x2b90
jmp 0x3a3d
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rdi
leaq 0x185c(%rip), %rsi      # 0x52bc
callq 0x22e0
movq %rax, -0x1f8(%rbp)
jmp 0x3a6e
movq -0x1f8(%rbp), %rax
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
jne 0x3ad0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x150(%rbp)
jmp 0x4060
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x148(%rbp)
movl %eax, -0x14c(%rbp)
jmp 0x40c2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x148(%rbp)
movl %eax, -0x14c(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x2c00
jmp 0x40c2
movq -0x50(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x48(%rbp), %rdi
leaq 0x17d9(%rip), %rsi      # 0x52bc
callq 0x22e0
movq %rax, -0x200(%rbp)
jmp 0x3af1
movq -0x200(%rbp), %rax
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
jne 0x3b19
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x150(%rbp)
jmp 0x4060
movq -0x58(%rbp), %rax
movq %rax, -0x18(%rbp)
leaq 0x5f8(%rip), %rsi       # 0x4120
leaq 0x681(%rip), %rdx       # 0x41b0
leaq -0x1c0(%rbp), %rdi
leaq -0x20(%rbp), %rcx
callq 0x4240
jmp 0x3b41
callq 0x2510
jmp 0x3b48
callq 0x2100
movq %rax, -0x208(%rbp)
jmp 0x3b56
movq -0x208(%rbp), %rax
movq %rax, -0x70(%rbp)
callq 0x2100
movq %rax, -0x210(%rbp)
jmp 0x3b6f
movq -0x210(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x28(%rbp), %rsi
leaq -0x140(%rbp), %rdi
callq 0x2520
movl %eax, -0x214(%rbp)
jmp 0x3b92
movl -0x214(%rbp), %eax
movl %eax, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
jge 0x3bb7
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x150(%rbp)
jmp 0x4060
leaq -0x90(%rbp), %rax
movq %rax, -0x228(%rbp)
leaq -0xa0(%rbp), %rax
movq %rax, -0x220(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x4280
movl %eax, -0x218(%rbp)
jmp 0x3be7
leaq -0x140(%rbp), %rdi
callq 0x42a0
movl %eax, -0x22c(%rbp)
jmp 0x3bfb
leaq -0x140(%rbp), %rdi
callq 0x42c0
movl %eax, -0x230(%rbp)
jmp 0x3c0f
movl -0x230(%rbp), %r8d
movl -0x22c(%rbp), %ecx
movl -0x218(%rbp), %edx
movq -0x220(%rbp), %rsi
movq -0x228(%rbp), %rdi
movl $0x1, %r9d
callq 0x2140
movl %eax, -0x234(%rbp)
jmp 0x3c43
movl -0x234(%rbp), %eax
movl %eax, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
jge 0x3c7f
movq 0x3387(%rip), %rax      # 0x6fe0
movq (%rax), %rdi
leaq 0x165b(%rip), %rsi      # 0x52be
movb $0x0, %al
callq 0x2090
movl -0x5c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0x150(%rbp)
jmp 0x4060
leaq -0x110(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x2520
movl %eax, -0x238(%rbp)
jmp 0x3c97
movl -0x238(%rbp), %eax
movl %eax, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
jge 0x3cbc
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x150(%rbp)
jmp 0x4060
leaq -0xc0(%rbp), %rax
movq %rax, -0x250(%rbp)
leaq -0xd0(%rbp), %rax
movq %rax, -0x248(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x4280
movl %eax, -0x23c(%rbp)
jmp 0x3cec
leaq -0x110(%rbp), %rdi
callq 0x42a0
movl %eax, -0x254(%rbp)
jmp 0x3d00
leaq -0x110(%rbp), %rdi
callq 0x42c0
movl %eax, -0x258(%rbp)
jmp 0x3d14
movl -0x258(%rbp), %r8d
movl -0x254(%rbp), %ecx
movl -0x23c(%rbp), %edx
movq -0x248(%rbp), %rsi
movq -0x250(%rbp), %rdi
movl $0x1, %r9d
callq 0x2140
movl %eax, -0x25c(%rbp)
jmp 0x3d48
movl -0x25c(%rbp), %eax
movl %eax, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
jge 0x3d84
movq 0x3282(%rip), %rax      # 0x6fe0
movq (%rax), %rdi
leaq 0x1556(%rip), %rsi      # 0x52be
movb $0x0, %al
callq 0x2090
movl -0x5c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0x150(%rbp)
jmp 0x4060
leaq -0x140(%rbp), %rdi
callq 0x4280
movl %eax, -0x260(%rbp)
jmp 0x3d98
leaq -0x140(%rbp), %rdi
callq 0x42a0
movl %eax, -0x264(%rbp)
jmp 0x3dac
leaq -0x140(%rbp), %rdi
callq 0x42c0
movl %eax, -0x268(%rbp)
jmp 0x3dc0
movl -0x268(%rbp), %ecx
movl -0x264(%rbp), %edx
movl -0x260(%rbp), %esi
leaq -0x1c0(%rbp), %rdi
callq 0x2c10
jmp 0x3de0
jmp 0x3de2
jmp 0x3de4
cmpl $0x0, -0xd4(%rbp)
jle 0x3e0a
movl -0xd8(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0xd8(%rbp)
cmpl $0x0, %eax
jg 0x3e08
jmp 0x3ffa
jmp 0x3e0a
movq -0x70(%rbp), %rsi
leaq -0x140(%rbp), %rdi
callq 0x2a60
movl %eax, -0x26c(%rbp)
jmp 0x3e22
movl -0x26c(%rbp), %eax
movl %eax, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
jge 0x3e36
jmp 0x3ffa
leaq -0x90(%rbp), %rax
movq %rax, -0x290(%rbp)
leaq -0xa0(%rbp), %rax
movq %rax, -0x288(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x280(%rbp)
addq $0x40, %rax
movq %rax, -0x278(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x42c0
movl %eax, -0x270(%rbp)
jmp 0x3e7c
leaq -0x140(%rbp), %rdi
callq 0x4280
movl %eax, -0x294(%rbp)
jmp 0x3e90
leaq -0x140(%rbp), %rdi
callq 0x42a0
movl %eax, -0x298(%rbp)
jmp 0x3ea4
movl -0x294(%rbp), %r9d
movl -0x270(%rbp), %r8d
movq -0x278(%rbp), %rcx
movq -0x280(%rbp), %rdx
movq -0x288(%rbp), %rsi
movq -0x290(%rbp), %rdi
movl -0x298(%rbp), %r10d
movq %rsp, %rax
movl %r10d, (%rax)
callq 0x2250
jmp 0x3ee2
leaq -0x110(%rbp), %rdi
movq -0x68(%rbp), %rsi
callq 0x2a60
movl %eax, -0x29c(%rbp)
jmp 0x3efa
movl -0x29c(%rbp), %eax
movl %eax, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
jge 0x3f2d
movl -0x5c(%rbp), %ecx
leaq 0x13d0(%rip), %rdi      # 0x52e3
leaq 0x13da(%rip), %rsi      # 0x52f4
xorl %eax, %eax
movl $0x87, %edx
callq 0x2050
jmp 0x3f28
jmp 0x3ffa
leaq -0xc0(%rbp), %rax
movq %rax, -0x2c0(%rbp)
leaq -0xd0(%rbp), %rax
movq %rax, -0x2b8(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x2b0(%rbp)
addq $0x40, %rax
movq %rax, -0x2a8(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x42c0
movl %eax, -0x2a0(%rbp)
jmp 0x3f73
leaq -0x110(%rbp), %rdi
callq 0x4280
movl %eax, -0x2c4(%rbp)
jmp 0x3f87
leaq -0x110(%rbp), %rdi
callq 0x42a0
movl %eax, -0x2c8(%rbp)
jmp 0x3f9b
movl -0x2c4(%rbp), %r9d
movl -0x2a0(%rbp), %r8d
movq -0x2a8(%rbp), %rcx
movq -0x2b0(%rbp), %rdx
movq -0x2b8(%rbp), %rsi
movq -0x2c0(%rbp), %rdi
movl -0x2c8(%rbp), %r10d
movq %rsp, %rax
movl %r10d, (%rax)
callq 0x2250
jmp 0x3fd9
movq -0x90(%rbp), %rsi
movq -0xc0(%rbp), %rdx
leaq -0x1c0(%rbp), %rdi
callq 0x3580
jmp 0x3ff5
jmp 0x3de2
leaq -0x1c0(%rbp), %rdi
callq 0x2cb0
jmp 0x4008
leaq -0x70(%rbp), %rdi
callq 0x20f0
jmp 0x4013
leaq -0x68(%rbp), %rdi
callq 0x20f0
jmp 0x401e
movq -0x90(%rbp), %rdi
callq 0x2240
jmp 0x402c
movq -0xc0(%rbp), %rdi
callq 0x2240
jmp 0x403a
movq -0x50(%rbp), %rdi
callq 0x20e0
jmp 0x4045
movq -0x58(%rbp), %rdi
callq 0x20e0
jmp 0x4050
movl -0x5c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0x150(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x2c00
leaq -0x140(%rbp), %rax
movq %rax, -0x2d8(%rbp)
addq $0x60, %rax
movq %rax, -0x2d0(%rbp)
movq -0x2d0(%rbp), %rdi
addq $-0x30, %rdi
movq %rdi, -0x2e0(%rbp)
callq 0x24d0
movq -0x2d8(%rbp), %rcx
movq -0x2e0(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x2d0(%rbp)
jne 0x4085
movl -0x4(%rbp), %eax
addq $0x300, %rsp            # imm = 0x300
popq %rbp
retq
leaq -0x140(%rbp), %rax
movq %rax, -0x2f0(%rbp)
addq $0x60, %rax
movq %rax, -0x2e8(%rbp)
movq -0x2e8(%rbp), %rdi
addq $-0x30, %rdi
movq %rdi, -0x2f8(%rbp)
callq 0x24d0
movq -0x2f0(%rbp), %rcx
movq -0x2f8(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x2e8(%rbp)
jne 0x40db
jmp 0x410e
movq -0x148(%rbp), %rdi
callq 0x21a0
nopw (%rax,%rax)