/*
 * Copyright 2015 Rockchip Electronics Co. LTD
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define MODULE_TAG "m2vd_parser"

#include <string.h>
#include <math.h>

#include "mpp_env.h"
#include "mpp_debug.h"
#include "mpp_packet_impl.h"

#include "m2vd_parser.h"
#include "m2vd_codec.h"

#define VPU_BITSTREAM_START_CODE    (0x42564b52)  /* RKVB, rockchip video bitstream */

/* ignore unofficial frame poriod */
#define MIN_FRAME_PERIOD_27M        449000  /* more than 60 fps a little*/
#define MAX_FRAME_PERIOD_27M        1130000  /* less than 23.976 fps a little */
#define MAX_FRAME_PERIOD_DIFF       13500   /* 500us */

RK_U32 m2vd_debug = 0x0;

static RK_U8 scanOrder[2][64] = {
    {   /* zig-zag */
        0, 1, 8, 16, 9, 2, 3, 10,
        17, 24, 32, 25, 18, 11, 4, 5,
        12, 19, 26, 33, 40, 48, 41, 34,
        27, 20, 13, 6, 7, 14, 21, 28,
        35, 42, 49, 56, 57, 50, 43, 36,
        29, 22, 15, 23, 30, 37, 44, 51,
        58, 59, 52, 45, 38, 31, 39, 46,
        53, 60, 61, 54, 47, 55, 62, 63
    },

    {   /* Alternate */
        0, 8, 16, 24, 1, 9, 2, 10,
        17, 25, 32, 40, 48, 56, 57, 49,
        41, 33, 26, 18, 3, 11, 4, 12,
        19, 27, 34, 42, 50, 58, 35, 43,
        51, 59, 20, 28, 5, 13, 6, 14,
        21, 29, 36, 44, 52, 60, 37, 45,
        53, 61, 22, 30, 7, 15, 23, 31,
        38, 46, 54, 62, 39, 47, 55, 63
    }
};

static RK_U8 intraDefaultQMatrix[64] = {
    8, 16, 19, 22, 26, 27, 29, 34,
    16, 16, 22, 24, 27, 29, 34, 37,
    19, 22, 26, 27, 29, 34, 34, 38,
    22, 22, 26, 27, 29, 34, 37, 40,
    22, 26, 27, 29, 32, 35, 40, 48,
    26, 27, 29, 32, 35, 40, 48, 58,
    26, 27, 29, 34, 38, 46, 56, 69,
    27, 29, 35, 38, 46, 56, 69, 83
};

static int frame_period_Table_27M[16] = {
    1,
    1126125, /* 23.976 fps */
    1125000, /* 24 fps */
    1080000, /* 25 fps */
    900900,  /* 29.97 fps */
    900000,  /* 30 fps */
    540000,  /* 50 fps */
    450450,  /* 59.94 fps */
    450000,  /* 60 fps */
    1800000,  /* unofficial: xing 15 fps */
    /* unofficial: libmpeg3 "Unofficial economy rates" 5/10/12/15 fps */
    5400000,
    2700000,
    2250000,
    1800000,
    1,
    1
};

static const MppFrameRational mpeg2_aspect[16] = {
    {0, 1},
    {1, 1},
    {4, 3},
    {16, 9},
    {221, 100},
    {0, 1},
    {0, 1},
    {0, 1},
    {0, 1},
    {0, 1},
    {0, 1},
    {0, 1},
    {0, 1},
    {0, 1},
    {0, 1},
    {0, 1},
};

static inline RK_S32 m2vd_get_readbits(BitReadCtx_t *bx)
{
    return bx->used_bits;
}

static inline RK_S32 m2vd_get_leftbits(BitReadCtx_t *bx)
{
    return  (bx->bytes_left_ * 8 + bx->num_remaining_bits_in_curr_byte_);
}

static RK_S32 m2vd_read_bits(BitReadCtx_t *bx, RK_U32 bits)
{
    RK_S32 ret = 0;
    if (bits < 32)
        mpp_read_bits(bx, bits, &ret);
    else
        mpp_read_longbits(bx, bits, (RK_U32 *)&ret);
    return ret;
}

static RK_S32 m2vd_show_bits(BitReadCtx_t *bx, RK_U32 bits)
{
    RK_S32 ret = 0;
    mpp_show_bits(bx, bits, &ret);
    return ret;
}

static MPP_RET m2vd_parser_init_ctx(M2VDParserContext *ctx, ParserCfg *cfg)
{
    MPP_RET ret = MPP_OK;
    RK_S32 i = 0;
    m2vd_dbg_func("FUN_I");

    M2VD_CHK_I(ctx);
    memset(ctx, 0, sizeof(*ctx));

    ctx->cfg = cfg->cfg;
    ctx->dxva_ctx = mpp_calloc(M2VDDxvaParam, 1);
    ctx->bitread_ctx = mpp_calloc(BitReadCtx_t, 1);

    ctx->packet_slots = cfg->packet_slots;
    ctx->frame_slots = cfg->frame_slots;

    mpp_buf_slot_setup(ctx->frame_slots, 16);

    ctx->initFlag = 0;
    ctx->info_changed = 0;

    /* copy from mpeg2decoder::mpeg2decoder */
    memset(&ctx->Framehead, 0, 3 * sizeof(M2VDFrameHead));

    ctx->frame_ref0 = &ctx->Framehead[0];
    ctx->frame_ref1 = &ctx->Framehead[1];
    ctx->frame_cur = &ctx->Framehead[2];
    for (i = 0; i < 3; i++) {
        mpp_frame_init(&ctx->Framehead[i].f);
        if (!ctx->Framehead[i].f) {
            mpp_err("Failed to allocate frame buffer %d\n", i);
            return MPP_ERR_NOMEM;
        }
        ctx->Framehead[i].picCodingType = 0xffffffff;
        ctx->Framehead[i].slot_index = -1;
    }
#if M2VD_SKIP_ERROR_FRAME_EN
    ctx->mHwDecStatus = MPP_OK;
#endif
    ctx->resetFlag = 0;
    ctx->flush_dpb_eos = 0;
    ctx->pic_head.pre_temporal_reference = 0;
    ctx->pic_head.pre_picture_coding_type = 0;
    ctx->pic_head.picture_coding_type = 0;

    /* copy form mpeg2decoder::decoder_init */
    //----------------------------------------------------
    ctx->bitstream_sw_buf = mpp_calloc(RK_U8, M2VD_BUF_SIZE_BITMEM);
    mpp_packet_init(&ctx->input_packet, ctx->bitstream_sw_buf, M2VD_BUF_SIZE_BITMEM);

    ctx->qp_tab_sw_buf = mpp_calloc(RK_U8, M2VD_BUF_SIZE_QPTAB);
    ctx->seq_head.pIntra_table = ctx->qp_tab_sw_buf;
    ctx->seq_head.pInter_table = ctx->seq_head.pIntra_table + 64;

    ctx->MPEG2_Flag = 0;
    ctx->seq_ext_head.progressive_sequence = 1;
    ctx->pic_code_ext_head.progressive_frame = 1;
    ctx->pic_code_ext_head.picture_structure = M2VD_PIC_STRUCT_FRAME;
    ctx->pic_head.pre_picture_coding_type = M2VD_CODING_TYPE_D;
    ctx->top_first_cnt = 0;
    ctx->bottom_first_cnt = 0;
    ctx->pic_code_ext_head.frame_pred_frame_dct = 1;
    ctx->seq_ext_head.chroma_format = 1;
    ctx->seq_disp_ext_head.matrix_coefficients = 5;
    ctx->pre_pts_27M = 0;
    ctx->maxFrame_inGOP = 0;
    ctx->preframe_period = 0;
    ctx->mHeaderDecFlag = 0;
    ctx->mExtraHeaderDecFlag = 0;
    ctx->max_stream_size = M2VD_BUF_SIZE_BITMEM;
    ctx->ref_frame_cnt = 0;
    ctx->left_length = 0;
    ctx->vop_header_found = 0;

    if (M2VD_DBG_DUMP_REG & m2vd_debug) {
        RK_S32 k = 0;
        for (k = 0; k < M2VD_DBG_FILE_NUM; k++)
            ctx->fp_dbg_file[k] = NULL;

        ctx->fp_dbg_file[0] = fopen("/sdcard/m2vd_dbg_stream.txt", "wb");
        if (!ctx->fp_dbg_file[0])
            mpp_log("open file failed: %s", "/sdcard/m2vd_dbg_stream.txt");

        ctx->fp_dbg_yuv = fopen("/sdcard/m2vd_dbg_yuv_out.txt", "wb");
        if (!ctx->fp_dbg_yuv)
            mpp_log("open file failed: %s", "/sdcard/m2vd_dbg_yuv_out.txt");
    } else {
        RK_S32 k = 0;
        for (k = 0; k < M2VD_DBG_FILE_NUM; k++)
            ctx->fp_dbg_file[k] = NULL;
    }


    m2vd_dbg_func("FUN_O");
__FAILED:

    return ret;
}

MPP_RET m2vd_parser_init(void *ctx, ParserCfg *parser_cfg)
{
    MPP_RET ret = MPP_OK;
    M2VDContext *c = (M2VDContext *)ctx;
    M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx;
    m2vd_dbg_func("FUN_I");
    if (p == NULL) {
        M2VD_CHK_M(p = (M2VDParserContext*)mpp_calloc(M2VDParserContext, 1));
        c->parse_ctx = p;
    }

    M2VD_CHK_F(m2vd_parser_init_ctx(p, parser_cfg));

    mpp_env_get_u32("m2vd_debug", &m2vd_debug, 0);

    m2vd_dbg_func("FUN_O");
__FAILED:
    return ret;
}

MPP_RET m2vd_parser_deinit(void *ctx)
{
    RK_U32 k = 0;
    MPP_RET ret = MPP_OK;
    M2VDContext *c = (M2VDContext *)ctx;
    M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx;

    m2vd_dbg_func("FUN_I");

    for (k = 0; k < M2VD_DBG_FILE_NUM; k++) {
        M2VD_FCLOSE(p->fp_dbg_file[k]);
    }
    M2VD_FCLOSE(p->fp_dbg_yuv);

    if (p->bitstream_sw_buf) {
        mpp_free(p->bitstream_sw_buf);
        p->bitstream_sw_buf = NULL;
    }
    if (p->qp_tab_sw_buf) {
        mpp_free(p->qp_tab_sw_buf);
        p->qp_tab_sw_buf = NULL;
    }

    if (p->input_packet) {
        mpp_packet_deinit(&p->input_packet);
    }

    if (p->dxva_ctx) {
        mpp_free(p->dxva_ctx);
        p->dxva_ctx = NULL;
    }
    if (p->bitread_ctx) {
        mpp_free(p->bitread_ctx);
        p->bitread_ctx = NULL;
    }

    for (k = 0; k < 3; k++) {
        mpp_frame_deinit(&p->Framehead[k].f);
    }

    if (p) {
        mpp_free(p);
    }

    m2vd_dbg_func("FUN_O");
    return ret;
}

/*!
***********************************************************************
* \brief
*   reset
***********************************************************************
*/
MPP_RET m2vd_parser_reset(void *ctx)
{
    MPP_RET ret = MPP_OK;
    M2VDContext *c = (M2VDContext *)ctx;
    M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx;
    m2vd_dbg_func("FUN_I");
    if (p->frame_cur->slot_index >= 0)
        mpp_buf_slot_clr_flag(p->frame_slots, p->frame_cur->slot_index,
                              SLOT_CODEC_USE);

    if (p->frame_ref0->slot_index >= 0) {
        if (p->frame_ref0->flags) {
            mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref0->slot_index,
                                  SLOT_QUEUE_USE);
            mpp_buf_slot_enqueue(p->frame_slots, p->frame_ref0->slot_index,
                                 QUEUE_DISPLAY);
            p->frame_ref0->flags = 0;
        }
        mpp_buf_slot_clr_flag(p->frame_slots, p->frame_ref0->slot_index,
                              SLOT_CODEC_USE);
    }

    if (p->frame_ref1->slot_index >= 0)
        mpp_buf_slot_clr_flag(p->frame_slots, p->frame_ref1->slot_index,
                              SLOT_CODEC_USE);

    if (p->input_packet) {
        mpp_packet_clr_eos(p->input_packet);
    }

    p->frame_cur->slot_index = -1;
    p->frame_ref0->slot_index = -1;
    p->frame_ref1->slot_index = -1;
    p->ref_frame_cnt = 0;
    p->resetFlag = 1;
    p->eos = 0;
    p->left_length = 0;
    p->vop_header_found = 0;
    m2vd_dbg_func("FUN_O");
    return ret;
}

/*!
***********************************************************************
* \brief
*   flush
***********************************************************************
*/
MPP_RET m2vd_parser_flush(void *ctx)
{
    MPP_RET ret = MPP_OK;
    M2VDContext *c = (M2VDContext *)ctx;
    M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx;
    m2vd_dbg_func("FUN_I");

    if ((p->frame_ref0->slot_index >= 0) && p->frame_ref0->flags) {
        mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref0->slot_index,
                              SLOT_QUEUE_USE);
        mpp_buf_slot_enqueue(p->frame_slots, p->frame_ref0->slot_index,
                             QUEUE_DISPLAY);
        p->frame_ref0->flags = 0;
    }

    m2vd_dbg_func("FUN_O");
    return ret;
}

/*!
***********************************************************************
* \brief
*   control/perform
***********************************************************************
*/
MPP_RET m2vd_parser_control(void *ctx, MpiCmd cmd_type, void *param)
{
    MPP_RET ret = MPP_OK;
    m2vd_dbg_func("FUN_I");
    (void)ctx;
    (void)cmd_type;
    (void)param;
    m2vd_dbg_func("FUN_O");
    return ret;
}

/*!
***********************************************************************
* \brief
*   prepare
***********************************************************************
*/
MPP_RET mpp_m2vd_parser_split(M2VDParserContext *ctx, MppPacket dst, MppPacket src)
{
    MPP_RET ret = MPP_NOK;
    M2VDParserContext *p = ctx;
    RK_U8 *src_buf = (RK_U8 *)mpp_packet_get_pos(src);
    RK_U32 src_len = (RK_U32)mpp_packet_get_length(src);
    RK_U32 src_eos = mpp_packet_get_eos(src);
    RK_U8 *dst_buf = (RK_U8 *)mpp_packet_get_data(dst);
    RK_U32 dst_len = (RK_U32)mpp_packet_get_length(dst);
    RK_U32 src_pos = 0;

    if (!p->vop_header_found) {
        if ((dst_len < sizeof(p->state)) &&
            ((p->state & 0x00FFFFFF) == 0x000001)) {
            dst_buf[0] = 0;
            dst_buf[1] = 0;
            dst_buf[2] = 1;
            dst_len = 3;
        }

        while (src_pos < src_len) {
            p->state = (p->state << 8) | src_buf[src_pos];
            dst_buf[dst_len++] = src_buf[src_pos++];

            /*
             * 0x1b3 : sequence header
             * 0x100 : frame header
             * we see all 0x1b3 and 0x100 as boundary
             */
            if (p->state == SEQUENCE_HEADER_CODE || p->state == PICTURE_START_CODE) {
                p->pts = mpp_packet_get_pts(src);
                p->vop_header_found = 1;
                break;
            }
        }
    }

    if (p->vop_header_found) {
        while (src_pos < src_len) {
            p->state = (p->state << 8) | src_buf[src_pos];
            dst_buf[dst_len++] = src_buf[src_pos++];

            if (((p->state & 0x00FFFFFF) == 0x000001) && (src_pos < src_len) &&
                (src_buf[src_pos] == (SEQUENCE_HEADER_CODE & 0xFF) ||
                 src_buf[src_pos] == (PICTURE_START_CODE & 0xFF))) {
                dst_len -= 3;
                p->vop_header_found = 0;
                ret = MPP_OK;
                break;
            }
        }
    }

    if (src_eos && src_pos >= src_len) {
        mpp_packet_set_eos(dst);
        ret = MPP_OK;
    }

    mpp_packet_set_length(dst, dst_len);
    mpp_packet_set_pos(src, src_buf + src_pos);

    return ret;
}

MPP_RET m2vd_parser_prepare(void *ctx, MppPacket pkt, HalDecTask *task)
{
    M2VDContext *c = (M2VDContext *)ctx;
    M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx;
    RK_U8 *pos = NULL;
    size_t length = 0;
    RK_U32 eos = 0;

    if (ctx == NULL || pkt == NULL || task == NULL) {
        mpp_err_f("found NULL input ctx %p pkt %p task %p\n", ctx, pkt, task);
        return MPP_ERR_NULL_PTR;
    }

    pos = mpp_packet_get_pos(pkt);
    length = mpp_packet_get_length(pkt);
    eos = mpp_packet_get_eos(pkt);

    if (eos && !length && !p->left_length) {
        task->valid = 0;
        task->flags.eos = 1;
        m2vd_parser_flush(ctx);
        return MPP_OK;
    }

    if (p->bitstream_sw_buf == NULL) {
        mpp_err("failed to malloc task buffer for hardware with size %d\n", length);
        return MPP_ERR_UNKNOW;
    }

    mpp_packet_set_length(p->input_packet, p->left_length);

    size_t total_length = MPP_ALIGN(p->left_length + length, 16) + 64;

    if (total_length > p->max_stream_size) {
        RK_U8 *dst = NULL;

        do {
            p->max_stream_size <<= 1;
        } while (total_length > p->max_stream_size);

        dst = mpp_malloc_size(RK_U8, p->max_stream_size);
        mpp_assert(dst);

        if (p->left_length > 0) {
            memcpy(dst, p->bitstream_sw_buf, p->left_length);
        }
        mpp_free(p->bitstream_sw_buf);
        p->bitstream_sw_buf = dst;

        mpp_packet_set_data(p->input_packet, p->bitstream_sw_buf);
        mpp_packet_set_size(p->input_packet, p->max_stream_size);
    }

    if (!p->cfg->base.split_parse) {
        RK_U32 *val = (RK_U32 *)mpp_packet_get_pos(pkt);
        /* if input data is rk format styl skip those 32 byte */
        RK_S32 offset = (VPU_BITSTREAM_START_CODE == val[0]) ? 32 : 0;
        memcpy(p->bitstream_sw_buf, pos + offset, length - offset);

        mpp_packet_set_length(p->input_packet, length - offset);
        mpp_packet_set_data(p->input_packet, p->bitstream_sw_buf);
        mpp_packet_set_size(p->input_packet, p->max_stream_size);

        if (mpp_packet_get_eos(pkt))
            mpp_packet_set_eos(p->input_packet);

        p->pts = mpp_packet_get_pts(pkt);
        task->valid = 1;
        mpp_packet_set_length(pkt, 0);
    } else {
        if (MPP_OK == mpp_m2vd_parser_split(p, p->input_packet, pkt)) {
            p->left_length = 0;
            task->valid = 1;
        } else {
            task->valid = 0;
            p->left_length = mpp_packet_get_length(p->input_packet);
        }
    }

    if (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA) {
        mpp_packet_set_extra_data(p->input_packet);
    }

    p->eos = mpp_packet_get_eos(p->input_packet);
    mpp_packet_set_pts(p->input_packet, p->pts);
    task->input_packet = p->input_packet;
    task->flags.eos = p->eos;

    return MPP_OK;
}

/*!
***********************************************************************
* \brief
*   parser
***********************************************************************
*/

static RK_U32 m2vd_search_header(BitReadCtx_t *bx)
{
    mpp_align_get_bits(bx);
    while (m2vd_show_bits(bx, 24) != 0x01) {
        mpp_skip_bits(bx, 8);
        if (m2vd_get_leftbits(bx) < 32) {
            if (M2VD_DBG_SEC_HEADER & m2vd_debug) {
                mpp_log("[m2v]: seach_header: str.leftbit()[%d] < 32", m2vd_get_leftbits(bx));
            }
            return NO_MORE_STREAM;
        }
    }
    return m2vd_show_bits(bx, 32);
}

static int m2vd_decode_seq_ext_header(M2VDParserContext *ctx)
{
    BitReadCtx_t *bx = ctx->bitread_ctx;
    m2vd_dbg_func("FUN_I");
    ctx->MPEG2_Flag = 1;
    ctx->seq_ext_head.profile_and_level_indication = m2vd_read_bits(bx, 8);
    ctx->seq_ext_head.progressive_sequence         = m2vd_read_bits(bx, 1);
    ctx->seq_ext_head.chroma_format                = m2vd_read_bits(bx, 2);
    if (ctx->seq_ext_head.chroma_format != 1)
        return M2VD_DEC_UNSURPORT;
    ctx->seq_ext_head.horizontal_size_extension    = m2vd_read_bits(bx, 2);
    ctx->seq_ext_head.vertical_size_extension      = m2vd_read_bits(bx, 2);
    ctx->seq_ext_head.bit_rate_extension           = m2vd_read_bits(bx, 12);
    mpp_skip_bits(bx, 1);
    ctx->seq_ext_head.vbv_buffer_size_extension    = m2vd_read_bits(bx, 8);
    ctx->seq_ext_head.low_delay                    = m2vd_read_bits(bx, 1);
    ctx->seq_ext_head.frame_rate_extension_n       = m2vd_read_bits(bx, 2);
    ctx->seq_ext_head.frame_rate_extension_d       = m2vd_read_bits(bx, 5);

    ctx->seq_head.bit_rate_value |= (ctx->seq_ext_head.bit_rate_extension << 18);
    ctx->seq_head.vbv_buffer_size += (ctx->seq_ext_head.vbv_buffer_size_extension << 10);

    m2vd_dbg_func("FUN_O");
    return  M2VD_DEC_OK;
}

static int m2vd_decode_seqdisp_ext_header(M2VDParserContext *ctx)
{
    BitReadCtx_t *bx = ctx->bitread_ctx;
    ctx->seq_disp_ext_head.video_format      = m2vd_read_bits(bx, 3);
    ctx->seq_disp_ext_head.color_description = m2vd_read_bits(bx, 1);

    if (ctx->seq_disp_ext_head.color_description) {
        ctx->seq_disp_ext_head.color_primaries          = m2vd_read_bits(bx, 8);
        ctx->seq_disp_ext_head.transfer_characteristics = m2vd_read_bits(bx, 8);
        ctx->seq_disp_ext_head.matrix_coefficients      = m2vd_read_bits(bx, 8);
    }

    m2vd_read_bits(bx, 14);
    mpp_skip_bits(bx, 1);
    m2vd_read_bits(bx, 14);
    return  M2VD_DEC_OK;
}

static int m2vd_decode_matrix_ext_header(M2VDParserContext *ctx)
{
    RK_U32  load_intra_quantizer_matrix;
    RK_U32  load_non_intra_quantizer_matrix;
    RK_U32  load_chroma_intra_quantizer_matrix;
    RK_U32  load_chroma_non_intra_quantizer_matrix;
    RK_U32  i;
    BitReadCtx_t *bx = ctx->bitread_ctx;

    load_intra_quantizer_matrix = m2vd_read_bits(bx, 1);
    if (load_intra_quantizer_matrix) {
        for (i = 0; i < 64; i++)
            ctx->seq_head.pIntra_table[scanOrder[0][i]] = (unsigned char)m2vd_read_bits(bx, 8);

    }
    load_non_intra_quantizer_matrix = m2vd_read_bits(bx, 1);
    if (load_non_intra_quantizer_matrix) {
        for (i = 0; i < 64; i++)
            ctx->seq_head.pInter_table[scanOrder[0][i]] = (unsigned char)m2vd_read_bits(bx, 8);
    }
    load_chroma_intra_quantizer_matrix = m2vd_read_bits(bx, 1);
    if (load_chroma_intra_quantizer_matrix) {
        return M2VD_DEC_UNSURPORT;
    }
    load_chroma_non_intra_quantizer_matrix = m2vd_read_bits(bx, 1);
    if (load_chroma_non_intra_quantizer_matrix) {
        return M2VD_DEC_UNSURPORT;
    }
    return  M2VD_DEC_OK;
}

static int m2vd_decode_scalable_ext_header(M2VDParserContext *ctx)
{
    /* ISO/IEC 13818-2 section 6.2.2.5: sequence_scalable_extension() header */
    int layer_id;
    int lower_layer_prediction_horizontal_size;
    int lower_layer_prediction_vertical_size;
    int horizontal_subsampling_factor_m;
    int horizontal_subsampling_factor_n;
    int vertical_subsampling_factor_m;
    int vertical_subsampling_factor_n;
    int scalable_mode;
    BitReadCtx_t *bx = ctx->bitread_ctx;

    /* scalable_mode */
#define SC_NONE 0
#define SC_DP   1
#define SC_SPAT 2
#define SC_SNR  3
#define SC_TEMP 4

    scalable_mode = m2vd_read_bits(bx, 2) + 1; /* add 1 to make SC_DP != SC_NONE */

    layer_id = m2vd_read_bits(bx, 4);

    if (scalable_mode == SC_SPAT) {
        lower_layer_prediction_horizontal_size = m2vd_read_bits(bx, 14);
        mpp_skip_bits(bx, 1);
        lower_layer_prediction_vertical_size   = m2vd_read_bits(bx, 14);
        horizontal_subsampling_factor_m        = m2vd_read_bits(bx, 5);
        horizontal_subsampling_factor_n        = m2vd_read_bits(bx, 5);
        vertical_subsampling_factor_m          = m2vd_read_bits(bx, 5);
        vertical_subsampling_factor_n          = m2vd_read_bits(bx, 5);
    }

    (void)layer_id;
    (void)lower_layer_prediction_horizontal_size;
    (void)lower_layer_prediction_vertical_size;
    (void)horizontal_subsampling_factor_m;
    (void)horizontal_subsampling_factor_n;
    (void)vertical_subsampling_factor_m;
    (void)vertical_subsampling_factor_n;


    if (scalable_mode == SC_TEMP)
        return M2VD_DEC_UNSURPORT;
    else
        return  M2VD_DEC_OK;
}

static int m2vd_decode_picdisp_ext_header(M2VDParserContext *ctx)
{
    int i;
    int number_of_frame_center_offsets;
    BitReadCtx_t *bx = ctx->bitread_ctx;
    /* based on ISO/IEC 13818-2 section 6.3.12
    (November 1994) Picture display extensions */

    /* derive number_of_frame_center_offsets */
    if (ctx->seq_ext_head.progressive_sequence) {
        if (ctx->pic_code_ext_head.repeat_first_field) {
            if (ctx->pic_code_ext_head.top_field_first)
                number_of_frame_center_offsets = 3;
            else
                number_of_frame_center_offsets = 2;
        } else {
            number_of_frame_center_offsets = 1;
        }
    } else {
        if (ctx->pic_code_ext_head.picture_structure != M2VD_PIC_STRUCT_FRAME) {
            number_of_frame_center_offsets = 1;
        } else {
            if (ctx->pic_code_ext_head.repeat_first_field)
                number_of_frame_center_offsets = 3;
            else
                number_of_frame_center_offsets = 2;
        }
    }

    /* now parse */
    for (i = 0; i < number_of_frame_center_offsets; i++) {
        ctx->pic_disp_ext_head.frame_center_horizontal_offset[i] = m2vd_read_bits(bx, 16);
        mpp_skip_bits(bx, 1);

        ctx->pic_disp_ext_head.frame_center_vertical_offset[i]   = m2vd_read_bits(bx, 16);
        mpp_skip_bits(bx, 1);
    }
    return  M2VD_DEC_OK;
}

static int m2vd_decode_spatial_ext_header(M2VDParserContext *ctx)
{
    /* ISO/IEC 13818-2 section 6.2.3.5: picture_spatial_scalable_extension() header */
    int lower_layer_temporal_reference;
    int lower_layer_horizontal_offset;
    int lower_layer_vertical_offset;
    int spatial_temporal_weight_code_table_index;
    int lower_layer_progressive_frame;
    int lower_layer_deinterlaced_field_select;
    BitReadCtx_t *bx = ctx->bitread_ctx;

    lower_layer_temporal_reference = m2vd_read_bits(bx, 10);
    mpp_skip_bits(bx, 1);
    lower_layer_horizontal_offset = m2vd_read_bits(bx, 15);
    if (lower_layer_horizontal_offset >= 16384)
        lower_layer_horizontal_offset -= 32768;
    mpp_skip_bits(bx, 1);
    lower_layer_vertical_offset = m2vd_read_bits(bx, 15);
    if (lower_layer_vertical_offset >= 16384)
        lower_layer_vertical_offset -= 32768;
    spatial_temporal_weight_code_table_index = m2vd_read_bits(bx, 2);
    lower_layer_progressive_frame = m2vd_read_bits(bx, 1);
    lower_layer_deinterlaced_field_select = m2vd_read_bits(bx, 1);

    (void)lower_layer_temporal_reference;
    (void)lower_layer_vertical_offset;
    (void)spatial_temporal_weight_code_table_index;
    (void)lower_layer_progressive_frame;
    (void)lower_layer_deinterlaced_field_select;

    return  M2VD_DEC_OK;
}

static int m2vd_decode_pic_ext_header(M2VDParserContext *ctx)
{
    BitReadCtx_t *bx = ctx->bitread_ctx;
    ctx->pic_code_ext_head.f_code[0][0] = m2vd_read_bits(bx, 4);
    ctx->pic_code_ext_head.f_code[0][1] = m2vd_read_bits(bx, 4);
    ctx->pic_code_ext_head.f_code[1][0] = m2vd_read_bits(bx, 4);
    ctx->pic_code_ext_head.f_code[1][1] = m2vd_read_bits(bx, 4);
    if (ctx->MPEG2_Flag) {
        ctx->pic_head.full_pel_forward_vector = ctx->pic_code_ext_head.f_code[0][0];
        ctx->pic_head.forward_f_code = ctx->pic_code_ext_head.f_code[0][1];
        ctx->pic_head.full_pel_backward_vector = ctx->pic_code_ext_head.f_code[1][0];
        ctx->pic_head.backward_f_code = ctx->pic_code_ext_head.f_code[1][1];
    }

    ctx->pic_code_ext_head.intra_dc_precision         = m2vd_read_bits(bx, 2);
    ctx->pic_code_ext_head.picture_structure          = m2vd_read_bits(bx, 2);
    if (ctx->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_FRAME)
        ctx->pic_code_ext_head.top_field_first            = m2vd_read_bits(bx, 1);
    else {
        m2vd_read_bits(bx, 1);
        if ((ctx->pic_head.pre_picture_coding_type != ctx->pic_head.picture_coding_type) &&
            (ctx->pic_head.pre_picture_coding_type != M2VD_CODING_TYPE_I)) {
            if (ctx->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD)
                ctx->top_first_cnt++;
            else
                ctx->bottom_first_cnt++;
        }
        if (ctx->top_first_cnt >= ctx->bottom_first_cnt)
            ctx->pic_code_ext_head.top_field_first = 1;
        else
            ctx->pic_code_ext_head.top_field_first = 0;
    }
    ctx->pic_code_ext_head.frame_pred_frame_dct       = m2vd_read_bits(bx, 1);
    ctx->pic_code_ext_head.concealment_motion_vectors = m2vd_read_bits(bx, 1);
    ctx->pic_code_ext_head.q_scale_type           = m2vd_read_bits(bx, 1);
    ctx->pic_code_ext_head.intra_vlc_format           = m2vd_read_bits(bx, 1);
    ctx->pic_code_ext_head.alternate_scan         = m2vd_read_bits(bx, 1);
    ctx->pic_code_ext_head.repeat_first_field         = m2vd_read_bits(bx, 1);
    ctx->pic_code_ext_head.chroma_420_type            = m2vd_read_bits(bx, 1);
    ctx->pic_code_ext_head.progressive_frame          = m2vd_read_bits(bx, 1);
    ctx->pic_code_ext_head.composite_display_flag     = m2vd_read_bits(bx, 1);
    if (ctx->pic_code_ext_head.composite_display_flag) {
        ctx->pic_code_ext_head.v_axis            = m2vd_read_bits(bx, 1);
        ctx->pic_code_ext_head.field_sequence    = m2vd_read_bits(bx, 3);
        ctx->pic_code_ext_head.sub_carrier       = m2vd_read_bits(bx, 1);
        ctx->pic_code_ext_head.burst_amplitude   = m2vd_read_bits(bx, 7);
        ctx->pic_code_ext_head.sub_carrier_phase = m2vd_read_bits(bx, 8);
    }
    return  M2VD_DEC_OK;
}

static inline int m2vd_decode_temp_ext_header(void)
{
    return  M2VD_DEC_UNSURPORT;
}

static int m2vd_decode_copyright_ext_header(M2VDParserContext *ctx)
{
    int copyright_flag;
    int copyright_identifier;
    int original_or_copy;
    int copyright_number_1;
    int copyright_number_2;
    int copyright_number_3;
    int reserved_data;
    BitReadCtx_t *bx = ctx->bitread_ctx;

    copyright_flag =       m2vd_read_bits(bx, 1);
    copyright_identifier = m2vd_read_bits(bx, 8);
    original_or_copy =     m2vd_read_bits(bx, 1);

    /* reserved */
    reserved_data = m2vd_read_bits(bx, 7);

    mpp_skip_bits(bx, 1);
    copyright_number_1 =   m2vd_read_bits(bx, 20);
    mpp_skip_bits(bx, 1);
    copyright_number_2 =   m2vd_read_bits(bx, 22);
    mpp_skip_bits(bx, 1);
    copyright_number_3 =   m2vd_read_bits(bx, 22);

    (void)copyright_flag;
    (void)copyright_identifier;
    (void)original_or_copy;
    (void)copyright_number_1;
    (void)copyright_number_2;
    (void)copyright_number_3;
    (void)reserved_data;

    return  M2VD_DEC_OK;
}

static int m2vd_decode_ext_header(M2VDParserContext *ctx)
{
    RK_U32      code;
    RK_U32      ext_ID;
    int         result;
    BitReadCtx_t *bx = ctx->bitread_ctx;

    code = m2vd_search_header(bx);

    if (M2VD_DBG_SEC_HEADER & m2vd_debug) {
        mpp_log("[m2v]: decoder_ext_header : seach_header return code: %#03x", code);
    }
    while (code == EXTENSION_START_CODE || code == USER_DATA_START_CODE) {
        if (code == EXTENSION_START_CODE) {
            mpp_skip_bits(bx, 32);
            ext_ID = m2vd_read_bits(bx, 4);
            if (M2VD_DBG_SEC_HEADER & m2vd_debug) {
                mpp_log("[m2v]: decoder_ext_header : ext_ID: %d", ext_ID);
            }
            switch (ext_ID) {
            case SEQUENCE_EXTENSION_ID:
                result = m2vd_decode_seq_ext_header(ctx);
                break;
            case SEQUENCE_DISPLAY_EXTENSION_ID:
                result = m2vd_decode_seqdisp_ext_header(ctx);
                break;
            case QUANT_MATRIX_EXTENSION_ID:
                result = m2vd_decode_matrix_ext_header(ctx);
                break;
            case SEQUENCE_SCALABLE_EXTENSION_ID:
                result = m2vd_decode_scalable_ext_header(ctx);
                break;
            case PICTURE_DISPLAY_EXTENSION_ID:
                result = m2vd_decode_picdisp_ext_header(ctx);
                break;
            case PICTURE_CODING_EXTENSION_ID:
                result = m2vd_decode_pic_ext_header(ctx);
                break;
            case PICTURE_SPATIAL_SCALABLE_EXTENSION_ID:
                result = m2vd_decode_spatial_ext_header(ctx);
                break;
            case PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID:
                result = m2vd_decode_temp_ext_header();
                break;
            case COPYRIGHT_EXTENSION_ID:
                result = m2vd_decode_copyright_ext_header(ctx);
                break;
            case NO_MORE_STREAM:
                break;
            default:
                break;
            }

            if (M2VD_DBG_SEC_HEADER & m2vd_debug) {
                mpp_log("[m2v]: decoder_ext_header result: %d", result);
            }
            if (result)
                return result;
        } else {
            mpp_skip_bits(bx, 32);
        }
        code = m2vd_search_header(bx);
    }

    return MPP_OK;
}

static int m2vd_decode_gop_header(M2VDParserContext *ctx)
{
    BitReadCtx_t *bx = ctx->bitread_ctx;

    ctx->gop_head.drop_flag   = m2vd_read_bits(bx, 1);
    ctx->gop_head.hour        = m2vd_read_bits(bx, 5);
    ctx->gop_head.minute      = m2vd_read_bits(bx, 6);

    mpp_skip_bits(bx, 1);

    ctx->gop_head.sec         = m2vd_read_bits(bx, 6);
    ctx->gop_head.frame       = m2vd_read_bits(bx, 6);
    ctx->gop_head.closed_gop  = m2vd_read_bits(bx, 1);
    ctx->gop_head.broken_link = m2vd_read_bits(bx, 1);

    return m2vd_decode_ext_header(ctx);
}

static int m2vd_decode_seq_header(M2VDParserContext *ctx)
{
    RK_U32 i;
    RK_S32 pre_frame_rate_code = ctx->seq_head.frame_rate_code;
    BitReadCtx_t *bx = ctx->bitread_ctx;
    RK_U32 width = m2vd_read_bits(bx, 12);
    RK_U32 height = m2vd_read_bits(bx, 12);

    ctx->display_width = width;
    ctx->display_height = height;

    height = MPP_ALIGN(height, 16);
    width = MPP_ALIGN(width, 16);

    if (ctx->seq_head.decode_width && ctx->seq_head.decode_height) {
        if (width != ctx->seq_head.decode_width ||
            height != ctx->seq_head.decode_height)
            ctx->info_changed = 1;
    }

    ctx->seq_head.decode_width = width;
    ctx->seq_head.decode_height = height;
    ctx->seq_head.aspect_ratio_information = m2vd_read_bits(bx, 4);
    ctx->seq_head.frame_rate_code = m2vd_read_bits(bx, 4);
    if (!ctx->frame_period || pre_frame_rate_code != ctx->seq_head.frame_rate_code)
        ctx->frame_period = frame_period_Table_27M[ctx->seq_head.frame_rate_code];
    ctx->seq_head.bit_rate_value = m2vd_read_bits(bx, 18);
    mpp_skip_bits(bx, 1);
    ctx->seq_head.vbv_buffer_size = m2vd_read_bits(bx, 10);
    ctx->seq_head.constrained_parameters_flag = m2vd_read_bits(bx, 1);
    ctx->seq_head.load_intra_quantizer_matrix = m2vd_read_bits(bx, 1);
    if (ctx->seq_head.load_intra_quantizer_matrix) {
        for (i = 0; i < 64; i++)
            ctx->seq_head.pIntra_table[scanOrder[0][i]] = (unsigned char)m2vd_read_bits(bx, 8);
    } else {
        for (i = 0; i < 64; i++)
            ctx->seq_head.pIntra_table[i] = intraDefaultQMatrix[i];
    }

    ctx->seq_head.load_non_intra_quantizer_matrix = m2vd_read_bits(bx, 1);
    if (ctx->seq_head.load_non_intra_quantizer_matrix) {
        for (i = 0; i < 64; i++)
            ctx->seq_head.pInter_table[scanOrder[0][i]] = (unsigned char)m2vd_read_bits(bx, 8);
    } else {
        for (i = 0; i < 64; i++)
            ctx->seq_head.pInter_table[i] = 16;
    }

    return m2vd_decode_ext_header(ctx);
}

static int m2vd_extra_bit_information(M2VDParserContext *ctx)
{
    BitReadCtx_t *bx = ctx->bitread_ctx;
    while (m2vd_read_bits(bx, 1)) {
        mpp_skip_bits(bx, 8);
    }
    return M2VD_DEC_OK;
}

static int m2vd_decode_pic_header(M2VDParserContext *ctx)
{
    BitReadCtx_t *bx = ctx->bitread_ctx;
    ctx->pic_head.temporal_reference  = m2vd_read_bits(bx, 10);
    ctx->pic_head.picture_coding_type = m2vd_read_bits(bx, 3);
    ctx->pic_head.vbv_delay           = m2vd_read_bits(bx, 16);
    if (ctx->pic_head.temporal_reference > 50) {
        ctx->pic_head.temporal_reference = ctx->pretemporal_reference;
    }
    //if ((maxFrame_inGOP < temporal_reference)&&(temporal_reference<60))
    //  maxFrame_inGOP = temporal_reference;
    if (((RK_S32)ctx->maxFrame_inGOP < ctx->pic_head.temporal_reference) && (ctx->pic_head.temporal_reference < 60))
        ctx->maxFrame_inGOP = ctx->pic_head.temporal_reference;


    if (ctx->pic_head.picture_coding_type == M2VD_CODING_TYPE_P ||
        ctx->pic_head.picture_coding_type == M2VD_CODING_TYPE_B) {
        ctx->pic_head.full_pel_forward_vector = m2vd_read_bits(bx, 1);
        ctx->pic_head.forward_f_code = m2vd_read_bits(bx, 3);
    }
    if (ctx->pic_head.picture_coding_type == M2VD_CODING_TYPE_B) {
        ctx->pic_head.full_pel_backward_vector = m2vd_read_bits(bx, 1);
        ctx->pic_head.backward_f_code = m2vd_read_bits(bx, 3);
    }

    m2vd_extra_bit_information(ctx);

    return m2vd_decode_ext_header(ctx);
}

static MPP_RET m2vd_decode_head(M2VDParserContext *ctx)
{
    RK_U32      code;
    int         ret = 0;
    BitReadCtx_t *bx = ctx->bitread_ctx;

    m2vd_dbg_func("FUN_I");
    while (1) {
        code = m2vd_search_header(bx);
        if (M2VD_DBG_SEC_HEADER & m2vd_debug) {
            mpp_log("[m2v]: decoder_header : seach_header return code: 0x%3x", code);
        }
        if (code == NO_MORE_STREAM)
            return M2VD_DEC_FILE_END;
        code = m2vd_read_bits(bx, 32);

        switch (code) {
        case SEQUENCE_HEADER_CODE:
            ret = m2vd_decode_seq_header(ctx);
            if (!ret) {
                MppPacket pkt = ctx->input_packet;
                if (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA) {
                    ctx->mExtraHeaderDecFlag = 1;
                } else {
                    ctx->mHeaderDecFlag = 1;
                }
            }
            break;
        case GROUP_START_CODE:
            ret = m2vd_decode_gop_header(ctx);
            break;
        case PICTURE_START_CODE:
            ret = m2vd_decode_pic_header(ctx);
            ret = M2VD_DEC_PICHEAD_OK;
            break;
        case SEQUENCE_END_CODE:
            ret = M2VD_DEC_STREAM_END;
            break;
        default:
            if (M2VD_DBG_SEC_HEADER & m2vd_debug) {
                mpp_log("code=%x,leftbit=%d", code, m2vd_get_leftbits(bx));
            }
            break;
        }
        if (ret)
            break;
    }
    m2vd_dbg_func("FUN_O");

    return ret;
}

static MPP_RET m2v_update_ref_frame(M2VDParserContext *p, RK_S32 force)
{
    //push frame
    if (force || (p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_FRAME) ||
        ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_BOTTOM_FIELD) && p->pic_code_ext_head.top_field_first ) ||
        ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) && (!p->pic_code_ext_head.top_field_first))) {
        if (p->frame_cur->picCodingType == M2VD_CODING_TYPE_B) {
            mpp_buf_slot_set_flag(p->frame_slots, p->frame_cur->slot_index, SLOT_QUEUE_USE);
            mpp_buf_slot_enqueue(p->frame_slots, p->frame_cur->slot_index, QUEUE_DISPLAY);
            mpp_buf_slot_clr_flag(p->frame_slots, p->frame_cur->slot_index, SLOT_CODEC_USE);
            p->frame_cur->slot_index = -1;
        } else if (p->frame_cur->picCodingType != 0xffffffff) {
            M2VDFrameHead *tmpHD = NULL;
            p->ref_frame_cnt++;
            if (p->frame_ref0->slot_index >= 0) {
                if (p->frame_ref0->flags) {
                    mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref0->slot_index, SLOT_QUEUE_USE);
                    mpp_buf_slot_enqueue(p->frame_slots, p->frame_ref0->slot_index, QUEUE_DISPLAY);
                    p->frame_ref0->flags = 0;
                }

                if (p->info_changed) {
                    mpp_buf_slot_clr_flag(p->frame_slots, p->frame_ref0->slot_index, SLOT_CODEC_USE);
                    p->frame_ref0->slot_index = -1;
                    p->info_changed = 0;
                }
            }

            if (p->frame_ref1->slot_index >= 0) {
                mpp_buf_slot_clr_flag(p->frame_slots, p->frame_ref1->slot_index, SLOT_CODEC_USE);
                p->frame_ref1->slot_index = -1;
            }
            tmpHD = p->frame_ref1;
            p->frame_ref1 = p->frame_ref0;
            p->frame_ref0 = p->frame_cur;
            p->frame_cur = tmpHD;
        }
    }

    return MPP_OK;
}

static MPP_RET m2vd_alloc_frame(M2VDParserContext *ctx)
{
    M2VDHeadPic *pic_head = &ctx->pic_head;
    M2VDHeadPicCodeExt *pic_code_ext_head = &ctx->pic_code_ext_head;
    RK_U64 pts_27M = ctx->pts;

    if (ctx->resetFlag && pic_head->picture_coding_type != M2VD_CODING_TYPE_I) {
        mpp_log("[m2v]: resetFlag[%d] && picture_coding_type[%d] != I_TYPE", ctx->resetFlag, pic_head->picture_coding_type);
        return MPP_NOK;
    }

    ctx->resetFlag = 0;

    if ((ctx->ref_frame_cnt < 2) && (pic_head->picture_coding_type == M2VD_CODING_TYPE_B)) {
        mpp_log("[m2v]: (ref_frame_cnt[%d] < 2) && (frame_cur->picCodingType[%d] == B_TYPE)",
                ctx->ref_frame_cnt, pic_head->picture_coding_type);
        return MPP_NOK;
    }

    if ((pic_code_ext_head->picture_structure == M2VD_PIC_STRUCT_FRAME ) ||
        ((pic_code_ext_head->picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) && pic_code_ext_head->top_field_first) ||
        ((pic_code_ext_head->picture_structure == M2VD_PIC_STRUCT_BOTTOM_FIELD) && (!pic_code_ext_head->top_field_first))) {
        RK_S64 frm_pts = 0;
        RK_U32 frametype = 0;

        if (ctx->pts_is_90K) {
            pts_27M = ctx->pts * 300;
        } else {
            pts_27M = ctx->pts * 27;
        }

        if (ctx->frame_cur->slot_index >= 0) {
            MppFrame frame = NULL;

            mpp_buf_slot_get_prop(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_FRAME_PTR, &frame);
            if (ctx->cfg->base.disable_error)
                mpp_frame_set_discard(frame, 1);
            else
                mpp_frame_set_errinfo(frame, 1);

            mpp_log("[m2v]: miss match field order at ref_frame_cnt[%d] picture_structure %d top_field_first %d\n",
                    ctx->ref_frame_cnt, pic_head->picture_coding_type, pic_code_ext_head->top_field_first);

            m2v_update_ref_frame(ctx, 1);
        }

        if (ctx->pre_pts_27M != pts_27M) {
            RK_S64 tmp_frame_period;

            if (ctx->group_frm_cnt) {
                ctx->group_frm_cnt = ctx->group_frm_cnt + pic_head->temporal_reference;
            } else if (pic_head->temporal_reference == (RK_S32)ctx->prechange_temporal_ref)
                ctx->group_frm_cnt = ctx->max_temporal_reference + 1;
            else if (pic_head->temporal_reference)
                ctx->group_frm_cnt = pic_head->temporal_reference - ctx->prechange_temporal_ref;
            else
                ctx->group_frm_cnt = ctx->max_temporal_reference - ctx->prechange_temporal_ref + 1;

            tmp_frame_period = pts_27M - ctx->pre_pts_27M;

            if ((pts_27M > ctx->pre_pts_27M)
                && (pic_head->temporal_reference > (RK_S32)ctx->prechange_temporal_ref)) {
                RK_S32 theshold_frame_period = tmp_frame_period * 2;
                RK_S32 last_frame_period = ctx->preframe_period ? ctx->preframe_period : ctx->frame_period;
                RK_S32 predict_frame_period =
                    (pic_head->temporal_reference - ctx->prechange_temporal_ref) * last_frame_period;
                if (theshold_frame_period < predict_frame_period) {
                    // check pts is 90KHZ raw pts
                    RK_S64 diff_90K_frame_period = tmp_frame_period * 1000 / 90 - predict_frame_period;

                    if (!ctx->pts_is_90K && llabs(diff_90K_frame_period) <= 300) {
                        mpp_log("judge result pts is base in 90KHZ.\n");
                        ctx->pts_is_90K = 1;
                        // pre pts is 1MHZ, so need convert to 90KHZ
                        pts_27M = ctx->pre_pts_27M * 1000 / 90 + predict_frame_period;
                    } else {
                        pts_27M = ctx->pre_pts_27M + predict_frame_period;
                    }
                    tmp_frame_period = predict_frame_period;
                }
            }

            if ((pts_27M > ctx->pre_pts_27M) && (ctx->group_frm_cnt > 0)) {
                tmp_frame_period = tmp_frame_period / ctx->group_frm_cnt;
                // judge frame rate changed
                if ((tmp_frame_period > MIN_FRAME_PERIOD_27M)
                    && (tmp_frame_period < MAX_FRAME_PERIOD_27M) &&
                    (llabs(ctx->frame_period - tmp_frame_period) > MAX_FRAME_PERIOD_DIFF)) {
                    if (llabs(ctx->preframe_period - tmp_frame_period) > MAX_FRAME_PERIOD_DIFF) {
                        ctx->preframe_period = tmp_frame_period;
                    } else {
                        ctx->frame_period = tmp_frame_period;
                        ctx->preframe_period = 0;
                    }
                } else {
                    ctx->preframe_period = 0;
                }
            }

            ctx->group_start_time_27M = pts_27M - pic_head->temporal_reference * ctx->frame_period;
            if (ctx->group_start_time_27M <= -ctx->frame_period)
                ctx->group_start_time_27M = 0;
            ctx->pre_pts_27M = pts_27M;
            ctx->prechange_temporal_ref = pic_head->temporal_reference;
            ctx->group_frm_cnt = 0;
        } else if ((RK_S32)ctx->pretemporal_reference > pic_head->temporal_reference + 5) {
            ctx->group_start_time_27M += (ctx->max_temporal_reference + 1) * ctx->frame_period;
            ctx->group_frm_cnt = ctx->max_temporal_reference - ctx->prechange_temporal_ref + 1;
            ctx->max_temporal_reference = 0;
        }
        if ((RK_S32)ctx->pretemporal_reference > pic_head->temporal_reference + 5)
            ctx->max_temporal_reference = 0;
        if (pic_head->temporal_reference > (RK_S32)ctx->max_temporal_reference)
            ctx->max_temporal_reference = pic_head->temporal_reference;
        ctx->pretemporal_reference = pic_head->temporal_reference;
        frm_pts = ctx->group_start_time_27M;
        frm_pts += pic_head->temporal_reference * ctx->frame_period;
        if (frm_pts < 0) {
            frm_pts = 0;
        }
        if (ctx->pts_is_90K) {
            frm_pts = frm_pts / 300;
        } else {
            frm_pts = frm_pts / 27;
        }

        /*
        mpp_log("picture_coding_type %d picture_structure %d top_field_first %d frame slot %d ref_frame_cnt %d pts %lld\n",
                pic_head->picture_coding_type, pic_code_ext_head->picture_structure,
                pic_code_ext_head->top_field_first, ctx->frame_cur->slot_index, ctx->ref_frame_cnt, frm_pts);
        */

        //base.Current_frame->ShowTime = Time;//Video_Bitsream.Slice_Time.low_part;
        //!< mark current slot error
        if (pic_head->picture_coding_type != M2VD_CODING_TYPE_I
            && pic_head->pre_picture_coding_type == pic_head->picture_coding_type) {
            if ((pic_head->temporal_reference - pic_head->pre_temporal_reference > 3)
                || (pic_head->temporal_reference - pic_head->pre_temporal_reference < -3)) {
                mpp_frame_set_errinfo(ctx->frame_cur->f, 1);
            } else {
                mpp_frame_set_errinfo(ctx->frame_cur->f, 0);
            }
        }
        pic_head->pre_temporal_reference = pic_head->temporal_reference;
        pic_head->pre_picture_coding_type = pic_head->picture_coding_type;
        ctx->frame_cur->picCodingType = pic_head->picture_coding_type;

        mpp_frame_set_width(ctx->frame_cur->f, ctx->display_width);
        mpp_frame_set_height(ctx->frame_cur->f, ctx->display_height);
        mpp_frame_set_hor_stride(ctx->frame_cur->f, 0);
        mpp_frame_set_ver_stride(ctx->frame_cur->f, 0);
        mpp_frame_set_errinfo(ctx->frame_cur->f, 0);
        mpp_frame_set_pts(ctx->frame_cur->f, frm_pts);
        ctx->frame_cur->flags = M2V_OUT_FLAG;

        if (ctx->seq_ext_head.progressive_sequence) {
            frametype = MPP_FRAME_FLAG_FRAME;
        } else {
            frametype = MPP_FRAME_FLAG_PAIRED_FIELD;
            if (pic_code_ext_head->top_field_first)
                frametype |= MPP_FRAME_FLAG_TOP_FIRST;
            else
                frametype |= MPP_FRAME_FLAG_BOT_FIRST;
        }
        if ((ctx->cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) &&
            frametype == MPP_FRAME_FLAG_FRAME)
            frametype = MPP_FRAME_FLAG_DEINTERLACED;

        mpp_frame_set_mode(ctx->frame_cur->f, frametype);

        if (ctx->seq_head.aspect_ratio_information >= 0 && ctx->seq_head.aspect_ratio_information < 16)
            mpp_frame_set_sar(ctx->frame_cur->f, mpeg2_aspect[ctx->seq_head.aspect_ratio_information]);

        //alloc frame space
        mpp_buf_slot_get_unused(ctx->frame_slots, &ctx->frame_cur->slot_index);
        mpp_buf_slot_set_prop(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_FRAME, ctx->frame_cur->f);
        mpp_buf_slot_set_flag(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_CODEC_USE);
        mpp_buf_slot_set_flag(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_HAL_OUTPUT);
    } else {
        if (ctx->frame_cur->slot_index >= 0)
            mpp_buf_slot_set_flag(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_HAL_OUTPUT);
        else {
            /*
             * frame alloc failed cause by stream error, such as:
             * receive top field while top_field_first = 0,
             * or bottom filed while top_field_first = 1;
             * mark resetFlag to wait for another I frame
             */
            mpp_log("frame alloc failed, need reset\n");
            ctx->resetFlag = 1;
            return MPP_NOK;
        }
    }

    return MPP_OK;
}

static MPP_RET m2vd_convert_to_dxva(M2VDParserContext *p)
{
    MPP_RET ret = MPP_OK;
    m2vd_dbg_func("FUN_I");
    M2VDDxvaParam *dst = p->dxva_ctx;
    M2VDFrameHead *pfw = p->frame_ref1;
    M2VDFrameHead *pbw = p->frame_ref0;
    BitReadCtx_t *bx = p->bitread_ctx;
    RK_U32 i = 0;
    RK_U32 error_info = 0;

    RK_S32 readbits = m2vd_get_readbits(bx);

    dst->seq.decode_width                       = p->seq_head.decode_width;
    dst->seq.decode_height                      = p->seq_head.decode_height;
    dst->seq.aspect_ratio_information           = p->seq_head.aspect_ratio_information;
    dst->seq.frame_rate_code                    = p->seq_head.frame_rate_code;
    dst->seq.bit_rate_value                     = p->seq_head.bit_rate_value;
    dst->seq.vbv_buffer_size                    = p->seq_head.vbv_buffer_size;
    dst->seq.constrained_parameters_flag        = p->seq_head.constrained_parameters_flag;
    dst->seq.load_intra_quantizer_matrix        = p->seq_head.load_intra_quantizer_matrix;
    dst->seq.load_non_intra_quantizer_matrix    = p->seq_head.load_non_intra_quantizer_matrix;

    dst->seq_ext.profile_and_level_indication   = p->seq_ext_head.profile_and_level_indication;
    dst->seq_ext.progressive_sequence           = p->seq_ext_head.progressive_sequence;
    dst->seq_ext.chroma_format                  = p->seq_ext_head.chroma_format;
    dst->seq_ext.low_delay                      = p->seq_ext_head.low_delay;
    dst->seq_ext.frame_rate_extension_n         = p->seq_ext_head.frame_rate_extension_n;
    dst->seq_ext.frame_rate_extension_d         = p->seq_ext_head.frame_rate_extension_d;


    dst->gop.drop_flag           = p->gop_head.drop_flag;
    dst->gop.hour                = p->gop_head.hour;
    dst->gop.minute              = p->gop_head.minute;
    dst->gop.sec                 = p->gop_head.sec;
    dst->gop.frame               = p->gop_head.frame;
    dst->gop.closed_gop          = p->gop_head.closed_gop;
    dst->gop.broken_link         = p->gop_head.broken_link;


    dst->pic.temporal_reference             = p->pic_head.temporal_reference;
    dst->pic.picture_coding_type            = p->pic_head.picture_coding_type;
    dst->pic.pre_picture_coding_type        = p->pic_head.pre_picture_coding_type;
    dst->pic.vbv_delay                      = p->pic_head.vbv_delay;
    dst->pic.full_pel_forward_vector        = p->pic_head.full_pel_forward_vector;
    dst->pic.forward_f_code                 = p->pic_head.forward_f_code;
    dst->pic.full_pel_backward_vector       = p->pic_head.full_pel_backward_vector;
    dst->pic.backward_f_code                = p->pic_head.backward_f_code;
    dst->pic.pre_temporal_reference         = p->pic_head.pre_temporal_reference;

    dst->seq_disp_ext.video_format              = p->seq_disp_ext_head.video_format;
    dst->seq_disp_ext.color_description         = p->seq_disp_ext_head.color_description;
    dst->seq_disp_ext.color_primaries           = p->seq_disp_ext_head.color_primaries;
    dst->seq_disp_ext.transfer_characteristics  = p->seq_disp_ext_head.transfer_characteristics;
    dst->seq_disp_ext.matrix_coefficients       = p->seq_disp_ext_head.matrix_coefficients;

    memcpy(dst->pic_code_ext.f_code, p->pic_code_ext_head.f_code, 2 * 2 * sizeof(RK_S32));
    dst->pic_code_ext.intra_dc_precision            = p->pic_code_ext_head.intra_dc_precision;
    dst->pic_code_ext.picture_structure             = p->pic_code_ext_head.picture_structure;
    dst->pic_code_ext.top_field_first               = p->pic_code_ext_head.top_field_first;
    dst->pic_code_ext.frame_pred_frame_dct          = p->pic_code_ext_head.frame_pred_frame_dct;
    dst->pic_code_ext.concealment_motion_vectors    = p->pic_code_ext_head.concealment_motion_vectors;
    dst->pic_code_ext.q_scale_type                  = p->pic_code_ext_head.q_scale_type;
    dst->pic_code_ext.intra_vlc_format              = p->pic_code_ext_head.intra_vlc_format;
    dst->pic_code_ext.alternate_scan                = p->pic_code_ext_head.alternate_scan;
    dst->pic_code_ext.repeat_first_field            = p->pic_code_ext_head.repeat_first_field;
    dst->pic_code_ext.chroma_420_type               = p->pic_code_ext_head.chroma_420_type;
    dst->pic_code_ext.progressive_frame             = p->pic_code_ext_head.progressive_frame;
    dst->pic_code_ext.composite_display_flag        = p->pic_code_ext_head.composite_display_flag;
    dst->pic_code_ext.v_axis                        = p->pic_code_ext_head.v_axis;
    dst->pic_code_ext.field_sequence                = p->pic_code_ext_head.field_sequence;
    dst->pic_code_ext.sub_carrier                   = p->pic_code_ext_head.sub_carrier;
    dst->pic_code_ext.burst_amplitude               = p->pic_code_ext_head.burst_amplitude;
    dst->pic_code_ext.sub_carrier_phase             = p->pic_code_ext_head.sub_carrier_phase;

    memcpy(dst->pic_disp_ext.frame_center_horizontal_offset, p->pic_disp_ext_head.frame_center_horizontal_offset, 3 * sizeof(RK_S32));
    memcpy(dst->pic_disp_ext.frame_center_vertical_offset, p->pic_disp_ext_head.frame_center_vertical_offset, 3 * sizeof(RK_S32));

    dst->bitstream_length = p->frame_size - ((readbits >> 3) & (~7));
    dst->bitstream_offset = ((readbits >> 3) & (~7));
    dst->bitstream_start_bit = readbits & 0x3f;
    dst->qp_tab = p->qp_tab_sw_buf;
    dst->CurrPic.Index7Bits = p->frame_cur->slot_index;
    p->cur_slot_index = p->frame_cur->slot_index;

    if (p->frame_ref0->slot_index < 0)
        pbw = p->frame_cur;

    if (p->frame_ref1->slot_index < 0)
        pfw = pbw;

    for (i = 0; i < 4; i++) {
        dst->frame_refs[i].bPicEntry = 0xff;
    }
    if (p->pic_head.picture_coding_type == M2VD_CODING_TYPE_B) {
        MppFrame frame0 = NULL;
        MppFrame frame1 = NULL;
        dst->frame_refs[0].Index7Bits = pfw->slot_index;
        dst->frame_refs[1].Index7Bits = pfw->slot_index;
        dst->frame_refs[2].Index7Bits = pbw->slot_index;
        dst->frame_refs[3].Index7Bits = pbw->slot_index;
        mpp_buf_slot_get_prop(p->frame_slots, pfw->slot_index, SLOT_FRAME_PTR, &frame0);
        mpp_buf_slot_get_prop(p->frame_slots, pbw->slot_index, SLOT_FRAME_PTR, &frame1);
        error_info = mpp_frame_get_errinfo(frame0) | mpp_frame_get_errinfo(frame1);
    } else {
        MppFrame frame = NULL;
        if ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_FRAME) ||
            ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) && p->pic_code_ext_head.top_field_first) ||
            ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_BOTTOM_FIELD) && (!p->pic_code_ext_head.top_field_first))) {
            dst->frame_refs[0].Index7Bits = pbw->slot_index;
            dst->frame_refs[1].Index7Bits = pbw->slot_index;
        } else if (p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) {
            dst->frame_refs[0].Index7Bits = pbw->slot_index;
            dst->frame_refs[1].Index7Bits = p->frame_cur->slot_index;
        } else if (p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_BOTTOM_FIELD) {
            dst->frame_refs[0].Index7Bits = p->frame_cur->slot_index;
            dst->frame_refs[1].Index7Bits = pbw->slot_index;
        }
        dst->frame_refs[2].Index7Bits = p->frame_cur->slot_index;
        dst->frame_refs[3].Index7Bits = p->frame_cur->slot_index;
        mpp_buf_slot_get_prop(p->frame_slots, pbw->slot_index, SLOT_FRAME_PTR, &frame);
        error_info = mpp_frame_get_errinfo(frame);
    }
    if (p->frame_cur->picCodingType == M2VD_CODING_TYPE_I) {
        error_info = 0;
    }
    dst->seq_ext_head_dec_flag = p->MPEG2_Flag;
    {
        MppFrame frame = NULL;
        mpp_buf_slot_get_prop(p->frame_slots, p->cur_slot_index, SLOT_FRAME_PTR, &frame);
        mpp_frame_set_errinfo(frame, error_info);
    }
    m2vd_dbg_func("FUN_O");
    return ret;
}

MPP_RET m2vd_parser_parse(void *ctx, HalDecTask *in_task)
{
    MPP_RET ret = MPP_OK;
    int rev = 0;
    M2VDContext *c = (M2VDContext *)ctx;
    M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx;
    m2vd_dbg_func("FUN_I");

    M2VD_CHK_I(in_task->valid);

    in_task->valid = 0;

    p->flush_dpb_eos = 0;

    p->frame_size = (RK_U32)mpp_packet_get_length(in_task->input_packet);

    mpp_set_bitread_ctx(p->bitread_ctx, p->bitstream_sw_buf, p->frame_size);

    rev = m2vd_decode_head(p);

    if (!p->mHeaderDecFlag) {
        if (p->mExtraHeaderDecFlag &&
            p->pic_head.picture_coding_type == M2VD_CODING_TYPE_I) {
            p->mHeaderDecFlag = 1;
            if (M2VD_DBG_SEC_HEADER & m2vd_debug)
                mpp_log("[m2v]: use extra data sequence header");
        } else {
            if (M2VD_DBG_SEC_HEADER & m2vd_debug)
                mpp_log("[m2v]: !mHeaderDecFlag");
            goto __FAILED;
        }
    }

    if (p->seq_head.decode_width > 1920 || p->seq_head.decode_height > 1088) {
        mpp_err("Warning: unsupport larger than 1920x1088\n");
        goto __FAILED;
    }

    p->mb_width = (p->seq_head.decode_width + 15) >> 4;
    p->mb_height = (p->seq_head.decode_height + 15) >> 4;

    if (rev < M2VD_DEC_OK) {
        if (M2VD_DBG_SEC_HEADER & m2vd_debug) {
            mpp_log("decoder_header error rev %d", rev);
        }
        goto __FAILED;
    }

    if (rev == M2VD_DEC_PICHEAD_OK) {
        if (m2vd_alloc_frame(p)) {
            goto __FAILED;
        }
        m2vd_convert_to_dxva(p);
        in_task->syntax.data = (void *)p->dxva_ctx;
        in_task->syntax.number = sizeof(M2VDDxvaParam);
        in_task->output = p->frame_cur->slot_index;
        p->pic_head.pre_picture_coding_type = p->pic_head.picture_coding_type;

        if (p->frame_ref0->slot_index >= 0 &&
            (p->frame_ref0->slot_index != p->frame_cur->slot_index)) {
            mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref0->slot_index, SLOT_HAL_INPUT);
            in_task->refer[0] = p->frame_ref0->slot_index;
        }

        if (p->frame_ref1->slot_index >= 0 && (p->frame_ref1->slot_index != p->frame_cur->slot_index)) {
            mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref1->slot_index, SLOT_HAL_INPUT);
            in_task->refer[1] = p->frame_ref1->slot_index;
        }

        MppFrame frame = NULL;
        mpp_buf_slot_get_prop(p->frame_slots, p->cur_slot_index, SLOT_FRAME_PTR, &frame);
        mpp_frame_set_poc(frame, p->pic_head.temporal_reference);

        if (p->dxva_ctx->seq_disp_ext.color_description) {
            mpp_frame_set_color_primaries(frame, p->dxva_ctx->seq_disp_ext.color_primaries);
            mpp_frame_set_color_trc(frame, p->dxva_ctx->seq_disp_ext.transfer_characteristics);
            mpp_frame_set_colorspace(frame, p->dxva_ctx->seq_disp_ext.matrix_coefficients);
        } else {
            mpp_frame_set_color_primaries(frame, MPP_FRAME_PRI_UNSPECIFIED);
            mpp_frame_set_color_trc(frame, MPP_FRAME_TRC_UNSPECIFIED);
            mpp_frame_set_colorspace(frame, MPP_FRAME_SPC_UNSPECIFIED);
        }

        in_task->valid = 1;
        m2v_update_ref_frame(p, 0);
    }

__FAILED:
    if (p->eos)
        m2vd_parser_flush(ctx);

    m2vd_dbg_func("FUN_O");

    return ret;
}

MPP_RET m2vd_parser_callback(void *ctx, void *errinfo)
{
    MPP_RET ret = MPP_OK;
    M2VDContext *c = (M2VDContext *)ctx;
    M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx;
    MppFrame frame = NULL;
    (void)errinfo;

    m2vd_dbg_func("FUN_I");
    mpp_buf_slot_get_prop(p->frame_slots, p->cur_slot_index, SLOT_FRAME_PTR, &frame);
    mpp_frame_set_errinfo(frame, 1);
    m2vd_dbg_func("FUN_O");

    return ret;
}
