// File: /workspace/github_c_makefile_star2_O3/xiane[P]libvphevcodec/AML_HEVCEncoder.cpp
// Function: AML_HEVCSetInput(AMVHEVCEncHandle_s*, FrameIOhevc_s*)
AMVEnc_Status AML_HEVCSetInput(AMVHEVCEncHandle *Handle, AMVHEVCEncFrameIO *input) {
    Uint32 src_stride;
    Uint32 luma_stride, chroma_stride;
    Uint32 size_src_luma, size_src_chroma;
    char *y = NULL;
    uint32_t idx = Handle->src_idx;

    Handle->src_pics[idx].op_flag = input->op_flag;
    AMVEncFrameFmt fmt = Handle->src_pics[idx].fmt = input->fmt;
    Handle->src_pics[idx].frame_rate = input->frame_rate;
    Handle->src_pics[idx].width = input->pitch;
    Handle->src_pics[idx].height = input->height;
    Handle->src_pics[idx].order = input->disp_order;

    float ms_per_frame = 1000.0f / input->frame_rate;
    int64_t pts = Handle->src_pics[idx].pts = ms_per_frame * input->disp_order + 1;

    if (fmt != AMVENC_NV12 && fmt != AMVENC_NV21 && fmt != AMVENC_YUV420) {
        if (INIT_GE2D) {
#if SUPPORT_SCALE
            if (ge2d_colorFormat(fmt) == AMVENC_SUCCESS) {
                VLOG(DEBUG, "The %d of color format that HEVC need ge2d to change!", fmt);
            } else
#endif
            {
                return AMVENC_NOT_SUPPORTED;
            }
        }
    }
    if (fmt == AMVENC_NV12) {
        Handle->mUvSwap = 0;
    }

    if (Handle->bitrate != input->bitrate) {
        Handle->bitrate = input->bitrate;
        VLOG(DEBUG, "HEVC set bitrate to %d", Handle->bitrate);
        Wave4VpuEncSeqInit(Handle, 0);
    }

    src_stride = wave420l_align32(Handle->enc_width);
    luma_stride = src_stride;
    chroma_stride = src_stride;
#if SUPPORT_SCALE
    if ((input->scale_width !=0 && input->scale_height !=0) || input->crop_left != 0 ||
        input->crop_right != 0 || input->crop_top != 0 || input->crop_bottom != 0 ||
        (fmt != AMVENC_NV12 && fmt != AMVENC_NV21 && fmt != AMVENC_YUV420)) {
        if (INIT_GE2D) {
            INIT_GE2D = false;
            amlge2d.ge2dinfo.src_info[0].format = SRC1_PIXFORMAT;
            amlge2d.ge2dinfo.src_info[1].format = SRC2_PIXFORMAT;
            int ret = aml_ge2d_mem_alloc(&amlge2d);
            if (ret < 0) {
                VLOG(ERR, "encode ge2di mem alloc failed, ret=0x%x", ret);
                return AMVENC_FAIL;
            }
            VLOG(DEBUG, "ge2d init successful!");
        }


        VLOG(DEBUG, "HEVC TEST sclale, enc_width:%d enc_height:%d  pitch:%d height:%d, line:%d",
                 Handle->enc_width, Handle->enc_height, input->pitch, input->height, __LINE__);
        if (input->pitch % 32) {
            VLOG(ERR, "HEVC crop and scale must be 32bit aligned");
            return AMVENC_FAIL;
        }
        if (fmt == AMVENC_RGBA8888)
            memcpy((void *)amlge2d.ge2dinfo.src_info[0].vaddr[0], (void *)input->YCbCr[0], 4 * input->pitch * input->height);
        else if (fmt == AMVENC_NV12 || fmt == AMVENC_NV21) {
            memcpy((void *)amlge2d.ge2dinfo.src_info[0].vaddr[0], (void *)input->YCbCr[0], input->pitch * input->height);
            memcpy((void *) ((char *)amlge2d.ge2dinfo.src_info[0].vaddr[0] + input->pitch * input->height), (void *)input->YCbCr[1], input->pitch * input->height / 2);
        } else if (fmt == AMVENC_YUV420) {
            memcpy((void *)amlge2d.ge2dinfo.src_info[0].vaddr[0], (void *)input->YCbCr[0], input->pitch * input->height);
            memcpy((void *) ((char *)amlge2d.ge2dinfo.src_info[0].vaddr[0] + input->pitch * input->height), (void *)input->YCbCr[1], input->pitch * input->height / 4);
            memcpy((void *) ((char *)amlge2d.ge2dinfo.src_info[0].vaddr[0] + (input->pitch * input->height * 5) /4), (void *)input->YCbCr[2], input->pitch * input->height / 4);
        } else if (fmt == AMVENC_RGB888)
            memcpy((void *)amlge2d.ge2dinfo.src_info[0].vaddr[0], (void *)input->YCbCr[0], input->pitch * input->height * 3);
        do_strechblit(&amlge2d.ge2dinfo, input);
        aml_ge2d_invalid_cache(&amlge2d.ge2dinfo);
        size_src_luma = luma_stride * wave420l_align32(Handle->enc_height);
        size_src_chroma = luma_stride * (wave420l_align16(Handle->enc_height) / 2);
        y = (char *) Handle->src_picx[Handle->src_idx].vb.virt_addr;
        if (Handle->enc_width % 32) {
            for (uint32 i = 0; i < Handle->enc_height; i++) {
                memcpy(y + i * luma_stride, (void *) ((char *) amlge2d.ge2dinfo.dst_info.vaddr[0] + i * Handle->enc_width), Handle->enc_width);
            }
        } else {
            memcpy((void *)Handle->src_pics[Handle->src_idx].vb.virt_addr, amlge2d.ge2dinfo.dst_info.vaddr[0],  Handle->enc_width * Handle->enc_height);
        }
        y = (char *) (Handle->src_pics[Handle->src_idx].vb.virt_addr + size_src_luma);
        memcpy(y, (void *) ((char *)amlge2d.ge2dinfo.dst_info.vaddr[0] + Handle->enc_width * Handle->enc_height), chroma_stride * Handle->enc_height / 2);
    } else
#endif
    {
        // set frame buffers

        // calculate required buffer size
        size_src_luma = luma_stride * wave420l_align32(Handle->enc_height);

        size_src_chroma = luma_stride * (wave420l_align16(Handle->enc_height) / 2);

        y = (char *) Handle->src_pics[Handle->src_idx].vb.virt_addr;
        if (Handle->enc_width % 32) {
            for (unsigned int i = 0; i < Handle->enc_height; i++) {
                memcpy(y + i * luma_stride, (void *) ((char *) input->YCbCr[0] + i * Handle->enc_width), Handle->enc_width);
            }
        } else {
            memcpy(y, (void *) input->YCbCr[0], luma_stride * Handle->enc_height);
        }

        y = (char *) (Handle->src_pics[Handle->src_idx].vb.virt_addr + size_src_luma);
        if (Handle->enc_width % 32) {
            for (unsigned int i = 0; i < Handle->enc_height / 2; i++) {
                memcpy(y + i * chroma_stride, (void *) ((char *) input->YCbCr[1] + i * Handle->enc_width), Handle->enc_width);
            }
        } else {
            memcpy(y, (void *) input->YCbCr[1], chroma_stride * Handle->enc_height / 2);
        }
    }
    flush_memory(Handle->instance_id, &Handle->src_pics[Handle->src_idx].vb);
    return AMVENC_SUCCESS;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %r14
movq %rdi, %rbx
movl 0x4(%rdi), %eax
movl 0x34(%rsi), %ecx
leaq (%rax,%rax,4), %rdx
shlq $0x4, %rdx
movl %ecx, 0xb0(%rdi,%rdx)
movss 0x40(%rsi), %xmm0
movss %xmm0, 0xb4(%rdi,%rdx)
movdqu 0x1c(%rsi), %xmm1
pshufd $0x27, %xmm1, %xmm1     # xmm1 = xmm1[3,1,2,0]
movl 0x1c(%rsi), %ecx
movl 0x28(%rsi), %esi
movdqu %xmm1, 0xe0(%rdi,%rdx)
movss 0x25163(%rip), %xmm1    # 0x2b8c0
cvtsi2ss %rsi, %xmm2
divss %xmm0, %xmm1
mulss %xmm1, %xmm2
addss 0x25152(%rip), %xmm2    # 0x2b8c4
cvttss2si %xmm2, %rsi
movq %rsi, 0xa0(%rdi,%rdx)
cmpl $0x3, %ecx
jne 0x678e
movl $0x0, 0x308(%rbx)
leaq 0xa0(%rbx), %rcx
movq %rcx, 0x8(%rsp)
movl 0x3c(%r14), %ecx
cmpl %ecx, 0x14(%rbx)
je 0x67b3
movl %ecx, 0x14(%rbx)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x2090
movl 0x4(%rbx), %eax
movl 0xc(%rbx), %ecx
movl 0x10(%rbx), %edx
leal 0x1f(%rcx), %r15d
andl $-0x20, %r15d
leal 0x1f(%rdx), %esi
andl $0x7ffffe0, %esi        # imm = 0x7FFFFE0
imull %r15d, %esi
movl %esi, 0x14(%rsp)
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
movq 0x8(%rsp), %rsi
movq 0x38(%rsi,%rax), %r12
testb $0x1f, %cl
je 0x6818
testl %edx, %edx
je 0x6827
xorl %r13d, %r13d
xorl %ebp, %ebp
movl %r13d, %edi
addq %r12, %rdi
movl 0xc(%rbx), %edx
movl %ebp, %esi
imull %edx, %esi
addq (%r14), %rsi
callq 0x2140
incq %rbp
movl 0x10(%rbx), %eax
addl %r15d, %r13d
cmpq %rax, %rbp
jb 0x67f2
jmp 0x6827
movq (%r14), %rsi
imull %r15d, %edx
movq %r12, %rdi
callq 0x2140
movl 0x4(%rbx), %eax
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
movl 0x14(%rsp), %r12d
movq 0x8(%rsp), %rcx
addq 0x38(%rcx,%rax), %r12
testb $0x1f, 0xc(%rbx)
je 0x687b
cmpl $0x2, 0x10(%rbx)
jb 0x6892
xorl %ebp, %ebp
xorl %r13d, %r13d
movl %ebp, %edi
addq %r12, %rdi
movl 0xc(%rbx), %edx
movl %r13d, %esi
imull %edx, %esi
addq 0x8(%r14), %rsi
callq 0x2140
incq %r13
movl 0x10(%rbx), %eax
shrl %eax
addl %r15d, %ebp
cmpq %rax, %r13
jb 0x6852
jmp 0x6892
movq 0x8(%r14), %rsi
imull 0x10(%rbx), %r15d
shrl %r15d
movq %r12, %rdi
movq %r15, %rdx
callq 0x2140
movl (%rbx), %edi
movl 0x4(%rbx), %eax
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax), %rsi
addq $0x20, %rsi
callq 0x20b0
movl $0x1, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq