// File: /workspace/github_c_makefile_star2_O1/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
movq %rdx, %r15
movq %rdi, %rbx
xorl %eax, %eax
movl %eax, 0x8(%rsp)
movl %eax, 0xc(%rsp)
movl %ecx, 0x300(%rdi)
cmpb $0x0, 0x2e8(%rdi)
jne 0x6d84
leaq 0x8(%rsp), %rdx
leaq 0xc(%rsp), %rcx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2350
cmpl $0x1, %eax
jne 0x6e20
movb $0x0, 0x2e9(%rbx)
movl 0x8(%rsp), %r12d
movq %r12, %rdi
callq 0x2210
movq %rax, 0x2f0(%rbx)
testq %rax, %rax
je 0x6d73
movb %r12b, 0x2e9(%rbx)
movzbl %r12b, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x2140
movl $0x0, 0x2f8(%rbx)
movb $0x1, 0x2e8(%rbx)
movl 0x2f8(%rbx), %ecx
testl %ecx, %ecx
js 0x7026
xorps %xmm0, %xmm0
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movaps %xmm0, 0x30(%rsp)
movaps %xmm0, 0x20(%rsp)
movaps %xmm0, 0x10(%rsp)
movq 0x2e0(%rbx), %rdx
movl 0x10(%rdx), %esi
movl %esi, 0x34(%rsp)
movl 0xc(%rdx), %eax
movl %eax, 0x30(%rsp)
movl 0x38(%rdx), %edi
movl %edi, 0x4c(%rsp)
movl 0x3c(%rdx), %edx
cvtsi2ss %rdx, %xmm1
imull $0x3e8, %ecx, %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 %esi, %eax
movslq %eax, %rcx
addq %r15, %rcx
movq %rcx, 0x18(%rsp)
cmpl $0x5, %ebp
je 0x6e64
cmpl $0x2, %ebp
je 0x6e51
cmpl $0x1, %ebp
jne 0x6e75
movl $0x3, 0x2c(%rsp)
jmp 0x6e59
movl %eax, %r12d
leaq 0x2653b(%rip), %rdi     # 0x2d365
movl %eax, %esi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x2050
movl $0xa, %edi
callq 0x2220
xorl %eax, %eax
cmpl $-0x27, %r12d
sete %al
orl $-0x4, %eax
jmp 0x702a
movl $0x2, 0x2c(%rsp)
movq $0x0, 0x20(%rsp)
jmp 0x6e93
leaq 0x18(%rsp), %rax
movl $0x6, 0x14(%rax)
movups %xmm0, (%rax)
jmp 0x6e93
movl $0x4, 0x2c(%rsp)
leal 0x3(%rax), %edx
testl %eax, %eax
cmovnsl %eax, %edx
sarl $0x2, %edx
movslq %edx, %rax
addq %rax, %rcx
movq %rcx, 0x20(%rsp)
movl $0xffffffff, 0x48(%rsp) # imm = 0xFFFFFFFF
xorl %eax, %eax
movl %eax, 0x28(%rsp)
movl 0x2f8(%rbx), %esi
movl %esi, 0x38(%rsp)
movl %eax, 0x44(%rsp)
cmpb $0x1, 0x2fc(%rbx)
jne 0x6edf
movl $0x1, 0x44(%rsp)
movb $0x0, 0x2fc(%rbx)
leaq 0x264d1(%rip), %rdi     # 0x2d39f
xorl %eax, %eax
callq 0x2050
movl $0xa, %edi
callq 0x2220
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x2250
incl 0x2f8(%rbx)
testl %eax, %eax
jle 0x6f2c
leaq 0x8(%rsp), %rdx
leaq 0xc(%rsp), %rcx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x22a0
movl %eax, %ebp
movb $0x1, %r12b
cmpl $0x1, %eax
jg 0x6f62
cmpl $-0x24, %ebp
je 0x6fd3
cmpl $0x1, %ebp
je 0x7021
jmp 0x6fe9
movl %eax, %ebp
leaq 0x2648f(%rip), %rdi     # 0x2d3c4
xorl %r12d, %r12d
movl %eax, %esi
movl $0xc4, %edx
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2050
movl $0xa, %edi
callq 0x2220
xorl %eax, %eax
cmpl $-0x2, %ebp
sete %al
addl %eax, %eax
jmp 0x701e
cmpl $0x4, %ebp
je 0x6fd3
cmpl $0x2, %ebp
jne 0x6fe9
movl 0xc(%rsp), %eax
decl %eax
cmpl $0x2, %eax
ja 0x6fe7
cmpb $0x0, 0x2fd(%rbx)
jne 0x6f89
cmpl $0x1, 0x2f8(%rbx)
jne 0x6fe7
cmpq $0x0, 0x2f0(%rbx)
je 0x6fe7
movzbl 0x2e9(%rbx), %edi
movl 0x8(%rsp), %r15d
leal (%r15,%rdi), %esi
movl 0x300(%rbx), %edx
cmpl %edx, %esi
jbe 0x7037
leaq 0x25f59(%rip), %rdi     # 0x2cf11
xorl %r12d, %r12d
xorl %eax, %eax
callq 0x2050
movl $0xa, %edi
callq 0x2220
movl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
jmp 0x7021
movl $0x0, 0x8(%rsp)
cmpl $-0x24, %ebp
jne 0x6fe7
movb $0x1, 0x2fc(%rbx)
jmp 0x7021
movl $0x0, 0x8(%rsp)
leaq 0x263cc(%rip), %rdi     # 0x2d3c4
xorl %r12d, %r12d
movl %ebp, %esi
movl $0xe2, %edx
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2050
movl $0xa, %edi
callq 0x2220
xorl %eax, %eax
cmpl $-0x27, %ebp
sete %al
orl $-0x4, %eax
testb %r12b, %r12b
je 0x702a
movl 0x8(%rsp), %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 0x22c0
movq 0x2f0(%rbx), %rsi
movzbl 0x2e9(%rbx), %edx
movq %r14, %rdi
callq 0x2140
movzbl 0x2e9(%rbx), %eax
addl %r15d, %eax
movl %eax, 0x8(%rsp)
jmp 0x6fe7