// File: /workspace/github_c_makefile_star2_O2/xiane[P]libvphevcodec/libvp_hevc_codec.cpp
// Function: vl_video_encoder_encode
int vl_video_encoder_encode(vl_codec_handle_t codec_handle, vl_frame_type_t frame_type, unsigned char *in, unsigned int outputBufferLen, unsigned char *out, vl_img_format_t format) {
    AMVEnc_Status ret;
    uint32_t dataLength = 0;
    int type = 0;
    AMVHEVCEncHandle *handle = (AMVHEVCEncHandle *)codec_handle;

    (void)frame_type;

    handle->mOutputBufferLen = outputBufferLen;
    if (!handle->mSpsPpsHeaderReceived) {
        ret = AML_HEVCEncHeader(handle, (unsigned char *)out, (unsigned int *)&dataLength, &type);
        if (ret == AMVENC_SUCCESS) {
            handle->mSPSPPSDataSize = 0;
            handle->mSPSPPSData = (uint8_t *)malloc(dataLength);
            if (handle->mSPSPPSData) {
                handle->mSPSPPSDataSize = dataLength;
                memcpy(handle->mSPSPPSData, (unsigned char *)out, handle->mSPSPPSDataSize);
                VLOG(DEBUG, "get mSPSPPSData size= %d at line %d \n", handle->mSPSPPSDataSize, __LINE__);
            }
            handle->mNumInputFrames = 0;
            handle->mSpsPpsHeaderReceived = true;
        } else {
            VLOG(ERR, "Encode SPS and PPS error, encoderStatus = %d. handle: %p\n", ret, (void *)handle);
            if (ret == AMVENC_OVERFLOW)
                return ERR_OVERFLOW;
            else
                return ERR_HARDWARE;
        }
    }
    if (handle->mNumInputFrames >= 0) {
        AMVHEVCEncFrameIO videoInput;
        memset(&videoInput, 0, sizeof(videoInput));
        videoInput.height = handle->mEncParams->height;
        videoInput.pitch = handle->mEncParams->width;//((handle->mEncParams.width + 15) >> 4) << 4;
        /* TODO*/
        videoInput.bitrate = handle->mEncParams->bitrate;
        videoInput.frame_rate = (float)handle->mEncParams->frame_rate;
        videoInput.coding_timestamp = (float)(handle->mNumInputFrames * 1000) / (float)videoInput.frame_rate;  // in ms
        videoInput.YCbCr[0] = (unsigned long)&in[0];
        videoInput.YCbCr[1] = (unsigned long)(videoInput.YCbCr[0] + videoInput.height * videoInput.pitch);

        switch (format) {
            case IMG_FMT_NV12:
                videoInput.fmt = AMVENC_NV12;
                videoInput.YCbCr[2] = 0;
                break;
            case IMG_FMT_NV21:
                videoInput.fmt = AMVENC_NV21;
                videoInput.YCbCr[2] = 0;
                break;
            case IMG_FMT_RGB888:
                videoInput.fmt = AMVENC_RGB888;
                videoInput.YCbCr[1] = 0;
                videoInput.YCbCr[2] = 0;
                break;
            default:
                videoInput.fmt = AMVENC_YUV420;
                videoInput.YCbCr[2] = (unsigned long)(videoInput.YCbCr[1] + videoInput.height * videoInput.pitch / 4);
                break;
        }

        videoInput.canvas = 0xffffffff;
        videoInput.type = VMALLOC_BUFFER;
        videoInput.disp_order = handle->mNumInputFrames;
        videoInput.op_flag = 0;
        //if(handle->mNumInputFrames == 0)
           //handle->mKeyFrameRequested = true;
        if (handle->mKeyFrameRequested == true) {
            videoInput.op_flag = AMVEncFrameIO_FORCE_IDR_FLAG;
            handle->mKeyFrameRequested = false;
            VLOG(INFO, "Force encode a IDR frame at %d frame", handle->mNumInputFrames);
        }
        //if (handle->idrPeriod == 0) {
            //videoInput.op_flag |= AMVEncFrameIO_FORCE_IDR_FLAG;
        //}
        ret = AML_HEVCSetInput(handle, &videoInput);
        ++(handle->mNumInputFrames);

        VLOG(DEBUG, "AML_HEVCSetInput ret %d\n", ret);
        if (ret == AMVENC_SUCCESS) {
        } else if (ret < AMVENC_SUCCESS) {
            VLOG(ERR, "encoderStatus = %d at line %d, handle: %p", ret, __LINE__, (void *)handle);
            if (ret == AMVENC_NOT_SUPPORTED)
                return ERR_NOTSUPPORT;
            else
                return ERR_HARDWARE;
        }

        ret = AML_HEVCEncNAL(handle, out, (unsigned int *)&dataLength, &type);
        if (ret == AMVENC_PICTURE_READY) {
            if (type == HEVC_IDR || type == HEVC_CRA  || type == HEVC_BLA) {
                if ((handle->mPrependSPSPPSToIDRFrames || handle->mNumInputFrames == 1) && (handle->mSPSPPSData)) {
                    if (handle->mSPSPPSDataSize + dataLength > handle->mOutputBufferLen) {
                        VLOG(ERR, "nal size %d bigger than output buffer %d!\n", handle->mSPSPPSDataSize + dataLength, handle->mOutputBufferLen);
                        return ERR_OVERFLOW;
                    }
                    memmove(out + handle->mSPSPPSDataSize, out, dataLength);
                    memcpy(out, handle->mSPSPPSData, handle->mSPSPPSDataSize);
                    dataLength += handle->mSPSPPSDataSize;
                    //VLOG(DEBUG, "copy mSPSPPSData to buffer size= %d at line %d \n", handle->mSPSPPSDataSize, __LINE__);
                }
            }
        } else if ((ret == AMVENC_SKIPPED_PICTURE) || (ret == AMVENC_TIMEOUT)) {
            dataLength = 0;
            if (ret == AMVENC_TIMEOUT) {
                handle->mKeyFrameRequested = true;
                ret = AMVENC_SKIPPED_PICTURE;
            }
            VLOG(DEBUG, "ret = %d at line %d, handle: %p", ret, __LINE__, (void *)handle);
        } else if (ret != AMVENC_SUCCESS) {
            dataLength = 0;
            VLOG(ERR, "encoderStatus = %d at line %d, handle: %p", ret , __LINE__, (void *)handle);
            if (ret == AMVENC_OVERFLOW)
                return ERR_OVERFLOW;
            else
                return ERR_HARDWARE;
        }
    }
    return dataLength;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x70, %rsp
movl %r9d, %ebp
movq %r8, %r14
andl $0x0, 0x8(%rsp)
movq %rdx, %r15
andl $0x0, 0xc(%rsp)
movq %rdi, %rbx
movl %ecx, 0x300(%rdi)
cmpb $0x0, 0x2e8(%rdi)
je 0x6927
movl 0x2f8(%rbx), %esi
testl %esi, %esi
jns 0x698b
xorl %eax, %eax
jmp 0x6be5
leaq 0x8(%rsp), %rdx
leaq 0xc(%rsp), %rcx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2370
cmpl $0x1, %eax
jne 0x6a14
movb $0x0, 0x2e9(%rbx)
movl 0x8(%rsp), %r12d
movq %r12, %rdi
callq 0x2220
movq %rax, 0x2f0(%rbx)
testq %rax, %rax
je 0x697b
movb %r12b, 0x2e9(%rbx)
movzbl %r12b, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x2150
andl $0x0, 0x2f8(%rbx)
movb $0x1, 0x2e8(%rbx)
xorl %esi, %esi
xorps %xmm0, %xmm0
movups %xmm0, 0x60(%rsp)
movups %xmm0, 0x50(%rsp)
movups %xmm0, 0x40(%rsp)
movups %xmm0, 0x30(%rsp)
movups %xmm0, 0x20(%rsp)
movq 0x2e0(%rbx), %rcx
movl 0x10(%rcx), %edx
movl %edx, 0x34(%rsp)
movl 0xc(%rcx), %eax
movl %eax, 0x30(%rsp)
movl 0x38(%rcx), %edi
movl %edi, 0x4c(%rsp)
movl 0x3c(%rcx), %ecx
cvtsi2ss %rcx, %xmm1
imull $0x3e8, %esi, %ecx      # imm = 0x3E8
cvtsi2ss %ecx, %xmm2
divss %xmm1, %xmm2
cvttss2si %xmm2, %rcx
movss %xmm1, 0x50(%rsp)
movl %ecx, 0x40(%rsp)
movq %r15, 0x10(%rsp)
imull %edx, %eax
movslq %eax, %rcx
addq %r15, %rcx
movq %rcx, 0x18(%rsp)
cmpl $0x5, %ebp
je 0x6a47
cmpl $0x2, %ebp
je 0x6a3d
cmpl $0x1, %ebp
jne 0x6a58
movl $0x3, 0x2c(%rsp)
jmp 0x6a6c
movl %eax, %r12d
leaq 0x25957(%rip), %rdi     # 0x2c375
movl %eax, %esi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x2050
pushq $0xa
popq %rdi
callq 0x2230
xorl %eax, %eax
cmpl $-0x27, %r12d
jmp 0x6bdf
movl $0x2, 0x2c(%rsp)
jmp 0x6a6c
leaq 0x18(%rsp), %rax
movl $0x6, 0x14(%rax)
movups %xmm0, (%rax)
jmp 0x6a6c
pushq $0x4
popq %rdi
movl %edi, 0x2c(%rsp)
cltd
idivl %edi
cltq
addq %rax, %rcx
movq %rcx, 0x20(%rsp)
andl $0x0, 0x28(%rsp)
movl %esi, 0x38(%rsp)
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
movq %rax, 0x44(%rsp)
cmpb $0x1, 0x2fc(%rbx)
jne 0x6ab2
movl $0x1, 0x44(%rsp)
movb $0x0, 0x2fc(%rbx)
leaq 0x2590c(%rip), %rdi     # 0x2c3af
xorl %eax, %eax
callq 0x2050
pushq $0xa
popq %rdi
callq 0x2230
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x2260
incl 0x2f8(%rbx)
testl %eax, %eax
jle 0x6b70
leaq 0x8(%rsp), %rdx
leaq 0xc(%rsp), %rcx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x22b0
movl %eax, %ebp
cmpl $-0x24, %eax
je 0x6b9e
cmpl $0x1, %ebp
je 0x6baf
cmpl $0x4, %ebp
je 0x6b9e
cmpl $0x2, %ebp
jne 0x6bb5
movl 0xc(%rsp), %eax
decl %eax
cmpl $0x2, %eax
ja 0x6baf
cmpb $0x0, 0x2fd(%rbx)
jne 0x6b2d
cmpl $0x1, 0x2f8(%rbx)
jne 0x6baf
cmpq $0x0, 0x2f0(%rbx)
je 0x6baf
movzbl 0x2e9(%rbx), %edi
movl 0x8(%rsp), %r15d
leal (%r15,%rdi), %esi
movl 0x300(%rbx), %edx
cmpl %edx, %esi
jbe 0x6bf2
leaq 0x253cd(%rip), %rdi     # 0x2bf29
xorl %eax, %eax
callq 0x2050
pushq $0xa
popq %rdi
callq 0x2230
pushq $-0x3
popq %rax
jmp 0x6be5
movl %eax, %ebp
leaq 0x2585b(%rip), %rdi     # 0x2c3d4
movl %eax, %esi
movl $0xc4, %edx
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2050
pushq $0xa
popq %rdi
callq 0x2230
xorl %eax, %eax
cmpl $-0x2, %ebp
sete %al
addl %eax, %eax
jmp 0x6be2
andl $0x0, 0x8(%rsp)
cmpl $-0x24, %ebp
jne 0x6baf
movb $0x1, 0x2fc(%rbx)
movl 0x8(%rsp), %eax
jmp 0x6be5
andl $0x0, 0x8(%rsp)
leaq 0x25813(%rip), %rdi     # 0x2c3d4
movl %ebp, %esi
movl $0xe2, %edx
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2050
pushq $0xa
popq %rdi
callq 0x2230
xorl %eax, %eax
cmpl $-0x27, %ebp
sete %al
orl $-0x4, %eax
addq $0x70, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
addq %r14, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x22d0
movq 0x2f0(%rbx), %rsi
movzbl 0x2e9(%rbx), %edx
movq %r14, %rdi
callq 0x2150
movzbl 0x2e9(%rbx), %eax
addl %r15d, %eax
movl %eax, 0x8(%rsp)
jmp 0x6baf