#include <stdio.h>
#include <stdlib.h>
#include "omxcore.h"
#include "omx_base_audio_port.h"
#include "omx_atmosdec_component.h"
#include "OMX_Audio.h"
#include "core_struct_version.h"
#include "omx_mtk_extend.h"
#include "sched.h"
#include <dlfcn.h>
#include <stdint.h>
#include "sndbar_dbg.h"
#include <sys/syscall.h>
#include <inttypes.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sched.h>
#include <stdarg.h>
#include <sys/prctl.h>

OMX_U8* pOMXProcessTmpBuf = NULL;
static int count = 0;
static long int total_len = 0;
OMX_AUDIO_PARAM_PCMMODETYPE gOutputPcmMode;

/* sndbar log variable */
#define LATNECY_INFO_SIZE 200
#define LATNECY_RECORD_NUM 300
#define DUMP_NAME_LENGTH 100

static int sndbar_dbg_cfg_log_level = SNDBAR_LOG_INFO;

static FILE *datadump_in_fd = NULL;
static FILE *datadump_out_fd = NULL;
static OMX_BOOL bDataDumping;

static FILE *latency_log_fd = NULL;
static int latency_log_num = 0;
static OMX_BOOL bLatencyDumping;

static int in_count = 0;
static int out_count = 0;
int i4TimeCompare(struct timespec endTime, struct timespec beginTime) {
    return (endTime.tv_sec - beginTime.tv_sec) * 1000000
        + (endTime.tv_nsec - beginTime.tv_nsec) / 1000;
}

void write_to_latency_file(struct timespec endtime, struct timespec begintime,
    struct timespec lasttime, int insize, int outsize) {
    char latency_info[LATNECY_INFO_SIZE];
    int ret = 0;

    if (bLatencyDumping && latency_log_fd) {
        out_count++;
        ret = sprintf(latency_info,
                "[atmos][dec] begin: %ld %ld,end: %ld %ld,d1: %ldus,d2: %ldus,in: %ld,out: %ld,c: %d\n",
                begintime.tv_sec, begintime.tv_nsec,
                endtime.tv_sec, endtime.tv_nsec,
                i4TimeCompare(begintime, lasttime),
                i4TimeCompare(endtime, begintime),
                insize, outsize,
                out_count);
        if (ret < 0) {
            SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] %d sprintf error %d", __LINE__, ret);
        }

        if (0 == latency_log_num) {
            ret = fputs(latency_info, latency_log_fd);
            if (ret < 0)
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] fputs error %d\n", ret);
        }

        if (1 < latency_log_num) {
            ret = fputs(latency_info, latency_log_fd);
            if (ret < 0)
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] fputs error %d\n", ret);
            latency_log_num--;
            if (1 == latency_log_num) {
                bLatencyDumping = 0;
                latency_log_num = 0;
                SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] latency num dump done\n");
            }
        }
    }
    return;
}

void write_to_dump_infile(OMX_PTR buf, int dumpsize) {
    int ret = 0;
    if (bDataDumping && datadump_in_fd) {
        ret = fwrite(buf, dumpsize, 1, datadump_in_fd);
        if (ret <= 0)
           SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] dump fwrite error %d\n", ret);
    }
    return;
}

void write_to_dump_outfile(OMX_PTR buf, int dumpsize) {
    int ret = 0;
    if (bDataDumping && datadump_out_fd) {
        ret = fwrite(buf, dumpsize, 1, datadump_out_fd);
        if (ret <= 0)
           SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] dump fwrite error %d\n", ret);
    }
    return;
}

void debug_open_latency_file(OMX_BOOL latencydumpcmd) {
    char latencydumpfilename[DUMP_NAME_LENGTH];
    int ret = 0;

    if (latencydumpcmd && !bLatencyDumping) {
        struct timespec dump_time = {0, 0};
        memset(latencydumpfilename, 0, DUMP_NAME_LENGTH);
        in_count = 0;
        out_count = 0;
        clock_gettime(CLOCK_MONOTONIC, &dump_time);
        ret = sprintf(latencydumpfilename, "/tmp/atmos_%dtm_latency.log", dump_time.tv_sec);
        if (ret < 0) {
            SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] %d sprintf error %d", __LINE__, ret);
        }

        SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] latencydumpfilename: %s\n", latencydumpfilename);
        latency_log_fd = fopen(latencydumpfilename, "w+");
        if (!latency_log_fd) {
            perror("[omx_atmosdec_component] fopen latency file fail");
            return;
        }
        else
            SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] latency dump file %s create sucess\n",
            latencydumpfilename);
        bLatencyDumping = TRUE;
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] latency start dump\n");
    } else if (latencydumpcmd && bLatencyDumping) {
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] latency is dumpping\n");
    } else if (!latencydumpcmd && bLatencyDumping) {
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] latency is dumpping, disable it\n");
        bLatencyDumping = FALSE;
        usleep(50000);  // 50ms
        ret = fclose(latency_log_fd);
        if (ret < 0) {
            perror("[omx_atmosdec_component] fclose latency file fail");
        }
        latency_log_fd = NULL;
        in_count = 0;
        out_count = 0;
    } else if (!latencydumpcmd && !bLatencyDumping)
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] latency is not dumpping\n");
    return;
}

void debug_open_datadump_file(OMX_BOOL datadumpcmd) {
    char datadumpfileinname[DUMP_NAME_LENGTH] = {0};
    char datadumpfileoutname[DUMP_NAME_LENGTH] = {0};
    int ret = 0;
    if (datadumpcmd && !bDataDumping) {
        struct timespec dump_time = {0, 0};
        clock_gettime(CLOCK_MONOTONIC, &dump_time);
        ret = sprintf(datadumpfileinname, "/tmp/atmos_%dtm_in.pcm", dump_time.tv_sec);
        if (ret < 0) {
            SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] %d sprintf error %d", __LINE__, ret);
        }

        ret = sprintf(datadumpfileoutname, "/tmp/atmos_%dtm_out.pcm", dump_time.tv_sec);
        if (ret < 0) {
            SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] %d sprintf error %d", __LINE__, ret);
        }

        SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] datadumpfileinname: %s\n", datadumpfileinname);
        SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] datadumpfileoutname: %s\n", datadumpfileoutname);
        datadump_in_fd= fopen(datadumpfileinname, "w+");
        if (!datadump_in_fd) {
            perror("[omx_atmosdec_component] fopen dump in file fail");
            return;
        }
        datadump_out_fd = fopen(datadumpfileoutname, "w+");
        if (!datadump_out_fd) {
            perror("[omx_atmosdec_component] fopen dump out file fail");
            return;
        }
        bDataDumping = TRUE;
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] data start dump\n");
    } else if (datadumpcmd && bDataDumping) {
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] data is dumpping\n");
    } else if (!datadumpcmd && bDataDumping) {
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] data is dumpping, disable it\n");
        bDataDumping = FALSE;
        usleep(50000);  // 50ms
        ret = fclose(datadump_in_fd);
        if (ret < 0) {
            perror("[omx_atmosdec_component] fclose dump in file fail");
        }
        ret = fclose(datadump_out_fd);
        if (ret < 0) {
            perror("[omx_atmosdec_component] fclose dump out file fail");
        }
        datadump_in_fd = NULL;
        datadump_out_fd = NULL;
    } else if (!datadumpcmd && !bDataDumping)
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] data is not dumpping\n");

    return;
}
static int i4_Latency_flag = 2;

static void log_tname() {
  char tname[64];
  prctl(PR_GET_NAME, (unsigned long)tname);
  SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] tname: %s\n", tname);
}
static inline int log_tid() {
    return syscall(SYS_gettid);
}

static void check_points_time_too_long (struct timespec* begin, struct timespec* end, long thres_us, char* msg) {
    uint64_t t1 = (begin->tv_sec * 1000 * 1000) + (begin->tv_nsec / (1000));
    uint64_t t2 = (end->tv_sec * 1000 * 1000) + (end->tv_nsec / (1000));

    if ((t2 - t1) > thres_us) {
        SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] %s too slow [tid:%d](diff: %" PRId64 " us, t1:[%lld.%.9ld], t2:[%lld.%.9ld])\n",
                                                                                                            msg, log_tid(), t2 - t1,
                                                                                                            (long long)begin->tv_sec, begin->tv_nsec,
                                                                                                            (long long)end->tv_sec, end->tv_nsec);
        //log_tname ();
    }
}

static inline void utils_check_time_too_long (struct timespec* begin, struct timespec* end, long thres_ms, char* msg) {
    int64_t t1 = (begin->tv_sec * 1000) + (begin->tv_nsec / (1000 * 1000));
    int64_t t2 = (end->tv_sec * 1000) + (end->tv_nsec / (1000 * 1000));

    if ((t2 - t1) > thres_ms) {
        SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] %s too slow (diff: %" PRId64 " ms, t1:[%lld.%.9ld], t2:[%lld.%.9ld])\n",
                                                                                            msg, t2 - t1,
                                                                                           (long long)begin->tv_sec, begin->tv_nsec,
                                                                                           (long long)end->tv_sec,   end->tv_nsec);
    }
}

static void utils_check_time_abnormal (struct timespec* begin, struct timespec* end, char* msg, int max_ms, int min_ms) {
    int64_t t1 = (begin->tv_sec * 1000) + (begin->tv_nsec / (1000 * 1000));
    int64_t t2 = (end->tv_sec * 1000) + (end->tv_nsec / (1000 * 1000));

    if (t1 && t2 && (((t2 - t1) > max_ms) || ((t2 - t1) < min_ms))) {
        SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] %s too slow (diff: %" PRId64 " ms, t1:[%lld.%.9ld], t2:[%lld.%.9ld])\n",
                                                                                           msg, t2 - t1,
                                                                                           (long long)begin->tv_sec, begin->tv_nsec,
                                                                                           (long long)end->tv_sec,   end->tv_nsec);
    }
}


static int i4_Times_before = 1;
static int i4_Times_after = 1;
static int i4_Times_flag = 1;

struct timespec st0;
struct timespec st1;

void InitOutputPCMFormat() {
    gOutputPcmMode.nSize = sizeof(gOutputPcmMode);
    gOutputPcmMode.nPortIndex = 1;
    gOutputPcmMode.nChannels = 2; //fix soundbreak
    gOutputPcmMode.eNumData = OMX_NumericalDataSigned;
    gOutputPcmMode.eEndian = OMX_EndianLittle;
    gOutputPcmMode.bInterleaved = OMX_TRUE;
    gOutputPcmMode.nBitPerSample = 32;
    gOutputPcmMode.nSamplingRate = 48000;
    gOutputPcmMode.ePCMMode = OMX_AUDIO_PCMModeLinear;
    gOutputPcmMode.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
    gOutputPcmMode.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
    gOutputPcmMode.eChannelMapping[2] = OMX_AUDIO_ChannelCF;
    gOutputPcmMode.eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
    gOutputPcmMode.eChannelMapping[4] = OMX_AUDIO_ChannelLS;
    gOutputPcmMode.eChannelMapping[5] = OMX_AUDIO_ChannelRS;
}

typedef struct _GST_INFO_ATMOS {
    int32_t   stream_type;
    int32_t   proc_type;
    int32_t   atmos_stream_ch_num;
    int32_t   atmos_stream_ch_mask;
    uint32_t  u4first_au_latency;
    uint32_t  atmos_sample_rate;
} GST_INFO_ATMOS;

static int checkAnyPortBeingFlushed(omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private) {
    omx_base_PortType *pPort;
    int ret = OMX_FALSE, i;

    if (omx_type1_decoder_component_Private->state == OMX_StateLoaded ||
        omx_type1_decoder_component_Private->state == OMX_StateInvalid)
    {
        return 0;
    }

    pthread_mutex_lock(&omx_type1_decoder_component_Private->flush_mutex);
    for (i = 0; i < omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts; i++)
    {
        pPort = omx_type1_decoder_component_Private->ports[i];
        if (PORT_IS_BEING_FLUSHED(pPort))
        {
            ret = OMX_TRUE;
            break;
        }
    }
    pthread_mutex_unlock(&omx_type1_decoder_component_Private->flush_mutex);
    return ret;
}

OMX_ERRORTYPE omx_type1_decoder_component_Constructor(OMX_COMPONENTTYPE *openmaxStandComp, OMX_STRING cComponentName) {
    OMX_ERRORTYPE err = OMX_ErrorNone;
    omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private;
    omx_type1_decoder_component_PortType *pPort = NULL;
    OMX_U32 i;
    type1_dec_component *ptDecCompGot = NULL;
    type1_dec_output_header *ptDecOutputHdr = NULL;
    type1_dec_pcm_attr *ptDecPcmAttr = NULL;
    type1_dec_sideinfo_attr *ptSideInfo = NULL;
    OMX_S32 retval = 0;
    void *handle = NULL;
    OMX_S32 (*fptr)(type1_dec_component **deccomp);
    open_atrace_file();
    atrace_begin("[omx_atmosdec_component] component_Constructor");

    /* setup sndbar cfg begin */
    sndbar_dbg_log_file_init ("atmosdec", LATNECY_RECORD_NUM);
    /* setup sndbar cfg end */

    handle = dlopen("/usr/lib/libaudio_decoder_atmos.so", RTLD_LAZY);
    if (handle == NULL) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "/usr/lib/libaudio_decoder_atmos.so is not exist(%s)\n", dlerror());
        return OMX_ErrorInsufficientResources;
    }
    fptr = NULL;
    fptr = dlsym(handle, "get_decoder_component_description");
    if (fptr == NULL) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] get_decoder_component_description error\n");
        return OMX_ErrorInsufficientResources;
    }

    (*fptr)(&ptDecCompGot);

    if (NULL == ptDecCompGot) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] ptDecCompGot NULL\n");
        return OMX_ErrorInsufficientResources;
    }

    RM_RegisterComponent(ptDecCompGot->pcName, MAX_TYPE1_DECODER_COMPONENTS);
    if (!openmaxStandComp->pComponentPrivate) {
        SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] allocating component private\n");
        openmaxStandComp->pComponentPrivate = calloc(1, sizeof(omx_type1_decoder_component_PrivateType));
        if (openmaxStandComp->pComponentPrivate == NULL) {
            SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] allocating component private fail!\n");
            return OMX_ErrorInsufficientResources;
        }
    }
    else {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Error Component %p Already Allocated\n", openmaxStandComp->pComponentPrivate);
    }
#if 0
    if (NULL == pOMXProcessTmpBuf)
    {
        pOMXProcessTmpBuf = calloc(1, 61310 * 2);
    }
#endif
    omx_type1_decoder_component_Private = openmaxStandComp->pComponentPrivate;
    omx_type1_decoder_component_Private->ports = NULL;

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] call omx_base_component_Constructor\n");
    err = omx_base_component_Constructor(openmaxStandComp, ptDecCompGot->pcName);
    if (OMX_ErrorNone != err) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] omx_base_component_Constructor return fail %d!\n", (int)err);
        return err;
    }

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Private->name=%s\n", omx_type1_decoder_component_Private->name);

    omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nStartPortNumber = 0;
    omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts = TYPE1_DECODER_COMP_MAX_PORTS;

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Allocate Ports and call port constructor\n");
    if (omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts && !omx_type1_decoder_component_Private->ports) {
        omx_type1_decoder_component_Private->ports = calloc(omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts, sizeof(omx_base_PortType *));
        if (!omx_type1_decoder_component_Private->ports) {
            SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] omx_type1_decoder_component_Private->ports alloc fail!\n");
            return OMX_ErrorInsufficientResources;
        }
        for (i = 0; i < omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts; i++) {
            omx_type1_decoder_component_Private->ports[i] = calloc(1, sizeof(omx_type1_decoder_component_PortType));
            if (!omx_type1_decoder_component_Private->ports[i]) {
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] omx_type1_decoder_component_Private->ports[%d] alloc fail!\n", (int)i);
                return OMX_ErrorInsufficientResources;
            }
        }
    }

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] construct input ports\n");
    base_audio_port_Constructor(openmaxStandComp, &omx_type1_decoder_component_Private->ports[0], 0, OMX_TRUE);

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] construct output ports\n");
    base_audio_port_Constructor(openmaxStandComp,
                                &omx_type1_decoder_component_Private->ports[omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts - 1],
                                omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts - 1, OMX_FALSE);

    for (i = 0; i < omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts; i++) {
        if (omx_type1_decoder_component_Private->ports && omx_type1_decoder_component_Private->ports[i])
        {
            pPort = (omx_type1_decoder_component_PortType *)omx_type1_decoder_component_Private->ports[i];
            pPort->sPortParam.nBufferCountActual = 40;
            pPort->sPortParam.nBufferCountMin = 40;
        }

        if (i == 0) {
            memset(pPort->sPortParam.format.audio.cMIMEType, 0, DEFAULT_MIME_STRING_LENGTH);
            strcpy(pPort->sPortParam.format.audio.cMIMEType, "audio/atmos");
            pPort->sPortParam.format.audio.pNativeRender = NULL;
            pPort->sPortParam.format.audio.bFlagErrorConcealment  = OMX_FALSE;
            pPort->sPortParam.format.audio.eEncoding = OMX_AUDIO_CodingATMOS;
        } else if (i == 1) {
            memset(pPort->sPortParam.format.audio.cMIMEType, 0, DEFAULT_MIME_STRING_LENGTH);
            strcpy(pPort->sPortParam.format.audio.cMIMEType, "audio/raw");
            pPort->sPortParam.format.audio.pNativeRender = NULL;
            pPort->sPortParam.format.audio.bFlagErrorConcealment = OMX_FALSE;
            pPort->sPortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
        }
    }

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] init private member\n");
    omx_type1_decoder_component_Private->destructor = omx_type1_decoder_component_Destructor;
    openmaxStandComp->SetParameter = omx_type1_decoder_component_SetParameter;
    openmaxStandComp->GetParameter = omx_type1_decoder_component_GetParameter;
    openmaxStandComp->AllocateBuffer = omx_type1_decoder_component_AllocateBuffer;
    openmaxStandComp->FreeBuffer = omx_type1_decoder_component_FreeBuffer;

    omx_type1_decoder_component_Private->BufferMgmtFunction = omx_type1_decoder_component_BufferMgmtFunction;
    omx_type1_decoder_component_Private->deccomptypeversion = TYPE1_DEC_COMP_VERSION;
    omx_type1_decoder_component_Private->ptDecComp = ptDecCompGot;
    omx_type1_decoder_component_Private->pvDecSelfData = NULL;
    omx_type1_decoder_component_Private->eIsIgnoreDecCurActionErr = OMX_FALSE;
    memset(&(omx_type1_decoder_component_Private->tTmpInputBuf), 0, sizeof(OMX_BUFFERHEADERTYPE));
    memset(&(omx_type1_decoder_component_Private->tTmpOutputBuf), 0, sizeof(OMX_BUFFERHEADERTYPE));

    omx_type1_decoder_component_Private->tTmpOutputBuf.nSize = sizeof(OMX_BUFFERHEADERTYPE);
    omx_type1_decoder_component_Private->tTmpOutputBuf.nAllocLen = TYPE1_DECODER_COMP_OUTPUT_BUF_ALIGNED_SAMPLE_BYTE_SIZE +
            (((sizeof(type1_dec_output_header) + sizeof(type1_dec_pcm_attr) + sizeof(type1_dec_sideinfo_attr) + TYPE1_MAX_SIDEINFO_NUM * sizeof(S_SIDEINFO) + 16) >> 4) << 4);
    omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer = (OMX_U8 *)calloc(1, omx_type1_decoder_component_Private->tTmpOutputBuf.nAllocLen);
    omx_type1_decoder_component_Private->tTmpOutputBuf.nOffset = ((sizeof(type1_dec_output_header) + sizeof(type1_dec_sideinfo_attr) + sizeof(type1_dec_pcm_attr) + 16) >> 4) << 4;
    omx_type1_decoder_component_Private->tTmpOutputBuf.nFilledLen = omx_type1_decoder_component_Private->tTmpOutputBuf.nOffset;
    if (NULL == omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level,"[omx_atmosdec_component] Alloc Down Sample && Drop Sample buffer fail!\n");
        return OMX_ErrorInsufficientResources;
    }
    memset(omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer, 0, omx_type1_decoder_component_Private->tTmpOutputBuf.nOffset);
    ptDecOutputHdr = (type1_dec_output_header *)omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer;

    ptSideInfo = (type1_dec_sideinfo_attr *)(omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer + sizeof(type1_dec_output_header) );
    ptDecOutputHdr->ptSideinfoAttrArray = ptSideInfo;
    ptSideInfo->pvSideinfoData = (OMX_PTR)(omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer +
                                           omx_type1_decoder_component_Private->tTmpOutputBuf.nOffset);
    ptSideInfo->u4SideinfoNum = 0;

    ptDecPcmAttr = (type1_dec_pcm_attr *)(omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer + sizeof(type1_dec_output_header) +
                                          sizeof(type1_dec_sideinfo_attr));
    ptDecOutputHdr->u4Version = TYPE1_DEC_OUTPUT_BUFFER_VERSION;
    ptDecOutputHdr->u4Size = sizeof(type1_dec_output_header);
    ptDecOutputHdr->u4Pcmattrnum = 1;
    ptDecOutputHdr->ptPcmAttrArray = ptDecPcmAttr;

    ptDecPcmAttr->u4Version = TYPE1_DEC_PCM_ATTR_VERSION;
    ptDecPcmAttr->u4Size = sizeof(type1_dec_pcm_attr);
    ptDecPcmAttr->pvPcmData = (OMX_PTR)(omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer +
                                        omx_type1_decoder_component_Private->tTmpOutputBuf.nOffset +
                                        TYPE1_MAX_SIDEINFO_NUM * sizeof(S_SIDEINFO) +
                                        TYPE1_DECODER_COMP_OUTPUT_BUF_ALIGNED_SAMPLE_BYTE_SIZE);;
    ptDecPcmAttr->u4SampleNumPerChannel = 0;

    omx_type1_decoder_component_Private->u4IsDecDownSampleOpen = 0;
    omx_type1_decoder_component_Private->u4IsDecDropSampleOpen = 0;
    omx_type1_decoder_component_Private->u4IsDecUpSampleOpen = 0;
    if (0 != tsem_init(&(omx_type1_decoder_component_Private->tAudDropSampleSem), 1)) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] tAudDropSampleSem tsem_init fail!\n");
        return OMX_ErrorInsufficientResources;
    }

    omx_type1_decoder_component_Private->fpDecInputDump = NULL;
    omx_type1_decoder_component_Private->fpDecOutputDump = NULL;
    omx_type1_decoder_component_Private->eNotResendData = OMX_FALSE;
    omx_type1_decoder_component_Private->nqualitylevels = 0;
    omx_type1_decoder_component_Private->currentQualityLevel = 0;
    omx_type1_decoder_component_Private->multiResourceLevel = NULL;

    InitOutputPCMFormat();

    OMX_MTK_COMMON_DEC_FLOW_CTRL_STRUCT ptOmxMtkDecFlowCtrl;
    memset(&ptOmxMtkDecFlowCtrl, 0, sizeof(ptOmxMtkDecFlowCtrl));
    OMX_PTR pvDecInitInfo = NULL;

    ptOmxMtkDecFlowCtrl.nSize = sizeof(OMX_MTK_COMMON_DEC_FLOW_CTRL_STRUCT);
    ptOmxMtkDecFlowCtrl.nVersion.s.nVersionMajor = SPECVERSIONMAJOR;
    ptOmxMtkDecFlowCtrl.nVersion.s.nVersionMinor = SPECVERSIONMINOR;
    ptOmxMtkDecFlowCtrl.nVersion.s.nRevision = SPECREVISION;
    ptOmxMtkDecFlowCtrl.nVersion.s.nStep = SPECSTEP;
    ptOmxMtkDecFlowCtrl.eDecFlowCtrlType = CommonDecFlowCtrl_DecInit;
    ptOmxMtkDecFlowCtrl.uParam.eDecInitInfo.pvDecInitInfo = pvDecInitInfo;
    ptOmxMtkDecFlowCtrl.uParam.eDecInitInfo.u4DecInitInfoSize = sizeof(AUD_DEC_AUD_INFO_T);

    TYPE1_DEC_ACTION_INTF *ptDecActionIntf = &(omx_type1_decoder_component_Private->ptDecComp->tDecActionIntf);
    atrace_begin("[omx_atmosdec_component] decoder init");

    OMX_PTR pvDecSelfData = omx_type1_decoder_component_Private->pvDecSelfData;
    OMX_S32 i4DecIntfRet = ptDecActionIntf->decoder_init(&(omx_type1_decoder_component_Private->pvDecSelfData), ptOmxMtkDecFlowCtrl.uParam.eDecInitInfo.pvDecInitInfo, ptOmxMtkDecFlowCtrl.uParam.eDecInitInfo.u4DecInitInfoSize);
    if (i4DecIntfRet < 0) {
        err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component]decoder_init return OMX_ErrorDecoderActionIntfError\n");
    }
    atrace_end("[omx_atmosdec_component] decoder init");
    atrace_end("[omx_atmosdec_component] component_Constructor");
    return err;
}

OMX_ERRORTYPE omx_type1_decoder_component_Destructor(OMX_COMPONENTTYPE *openmaxStandComp) {
    omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private = openmaxStandComp->pComponentPrivate;
    TYPE1_DEC_ACTION_INTF *ptDecActionIntf = NULL;
    OMX_U32 i;
    OMX_S32 i4DecActionIntfRet = 0;

    atrace_begin("[omx_atmosdec_component] component_Destructor");

    if (omx_type1_decoder_component_Private->ports) {
        for (i = 0; i < omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts; i++) {
            if (omx_type1_decoder_component_Private->ports[i]) {
                omx_type1_decoder_component_Private->ports[i]->PortDestructor(omx_type1_decoder_component_Private->ports[i]);
            }
        }
        free(omx_type1_decoder_component_Private->ports);
        omx_type1_decoder_component_Private->ports = NULL;
    }

    if (NULL != omx_type1_decoder_component_Private->tTmpInputBuf.pBuffer) {
        free(omx_type1_decoder_component_Private->tTmpInputBuf.pBuffer);
    }
    omx_type1_decoder_component_Private->tTmpInputBuf.pBuffer = NULL;

    ptDecActionIntf = &(omx_type1_decoder_component_Private->ptDecComp->tDecActionIntf);
    if (NULL != omx_type1_decoder_component_Private->pvDecSelfData) {
        if (NULL != ptDecActionIntf->decoder_uninit) {
            atrace_begin("[omx_atmosdec_component] decoder uninit");
            i4DecActionIntfRet = ptDecActionIntf->decoder_uninit(omx_type1_decoder_component_Private->pvDecSelfData);
            if (0 != i4DecActionIntfRet) {
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Call decoder_uninit meeting error(%d)\n", (int)i4DecActionIntfRet);
            }
            atrace_end("[omx_atmosdec_component] decoder uninit");
        } else {
            free(omx_type1_decoder_component_Private->pvDecSelfData);
        }
        omx_type1_decoder_component_Private->pvDecSelfData = NULL;
    }

    if (NULL != omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer) {
        free(omx_type1_decoder_component_Private->tTmpOutputBuf.pBuffer);
        SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Free Down Sample && Drop Sample buffer!\n");
    }

    if (NULL != pOMXProcessTmpBuf) {
        free(pOMXProcessTmpBuf);
        pOMXProcessTmpBuf = NULL;
        SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Free pOMXProcessTmpBuf!\n");
    }

    if (NULL != omx_type1_decoder_component_Private->fpDecInputDump) {
        fclose(omx_type1_decoder_component_Private->fpDecInputDump);
        omx_type1_decoder_component_Private->fpDecInputDump = NULL;
    }
    if (NULL != omx_type1_decoder_component_Private->fpDecOutputDump) {
        fclose(omx_type1_decoder_component_Private->fpDecOutputDump);
        omx_type1_decoder_component_Private->fpDecOutputDump = NULL;
    }

    omx_base_component_Destructor(openmaxStandComp);
    atrace_end("[omx_atmosdec_component] component_Destructor");
    close_atrace_file();

    return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_type1_decoder_component_AllocateBuffer(
    OMX_HANDLETYPE hComponent,
    OMX_BUFFERHEADERTYPE** ppBuffer,
    OMX_U32 nPortIndex,
    OMX_PTR pAppPrivate,
    OMX_U32 nSizeBytes) {
    omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private = (omx_type1_decoder_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate;
    omx_base_PortType *pPort;
    OMX_ERRORTYPE err;
    OMX_U8* ptmpbuf = NULL;
    OMX_U8* ptmpbuf01 = NULL;
    OMX_U32 bufcpylen = 0;

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s for component %p\n", __func__, hComponent);

    if (nPortIndex >= (omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts +
                       omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts +
                       omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts +
                       omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s: wrong port index\n", __func__);
        return OMX_ErrorBadPortIndex;
    }

    if ((nPortIndex < omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts - 1) &&
        (omx_type1_decoder_component_Private->tTmpInputBuf.nAllocLen < nSizeBytes * 2)) {
        ptmpbuf = calloc(1, nSizeBytes * 2);
        if (NULL == ptmpbuf) {
            SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s, can't alloc buffer for tTmpInputBuf!\n", __func__);
            return OMX_ErrorInsufficientResources;
        }
        if (NULL != omx_type1_decoder_component_Private->tTmpInputBuf.pBuffer) {
            SNDBAR_LOGW(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s: warning, temp buffer is not free\n", __func__);
            ptmpbuf01 = (OMX_U8*)(omx_type1_decoder_component_Private->tTmpInputBuf.pBuffer +
                                  omx_type1_decoder_component_Private->tTmpInputBuf.nOffset);
            bufcpylen = omx_type1_decoder_component_Private->tTmpInputBuf.nFilledLen -
                        omx_type1_decoder_component_Private->tTmpInputBuf.nOffset;
            if (bufcpylen > omx_type1_decoder_component_Private->tTmpInputBuf.nFilledLen) {
                bufcpylen = 0;
            }
            else {
                memcpy(ptmpbuf, ptmpbuf01, bufcpylen);
            }
            free(omx_type1_decoder_component_Private->tTmpInputBuf.pBuffer);
        }
        omx_type1_decoder_component_Private->tTmpInputBuf.nSize = sizeof(OMX_BUFFERHEADERTYPE);
        omx_type1_decoder_component_Private->tTmpInputBuf.pBuffer = ptmpbuf;
        omx_type1_decoder_component_Private->tTmpInputBuf.nAllocLen = nSizeBytes * 2;
        omx_type1_decoder_component_Private->tTmpInputBuf.nFilledLen = bufcpylen;
        omx_type1_decoder_component_Private->tTmpInputBuf.nOffset = 0;
    }

    pPort = omx_type1_decoder_component_Private->ports[nPortIndex];
    err = pPort->Port_AllocateBuffer(pPort, ppBuffer, nPortIndex, pAppPrivate, nSizeBytes);
    if (err != OMX_ErrorNone) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s, component %p Port_AllocateBuffer return err %i\n", __func__, hComponent, (int)err);
        return err;
    }
    pPort->sPortParam.nBufferSize = nSizeBytes;

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Out of %s for component %p buffer %p\n", __func__, hComponent, ppBuffer);
    return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_type1_decoder_component_FreeBuffer(
    OMX_HANDLETYPE hComponent,
    OMX_U32 nPortIndex,
    OMX_BUFFERHEADERTYPE* pBuffer) {
    omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private = (omx_type1_decoder_component_PrivateType*)((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate;
    omx_base_PortType *pPort;
    OMX_ERRORTYPE err;

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Free Buffer In for component[port:%d] %p\n", nPortIndex, hComponent);
    if (nPortIndex >= (omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts +
                       omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainVideo].nPorts +
                       omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainImage].nPorts +
                       omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainOther].nPorts)) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In wrong port index\n");
        return OMX_ErrorBadPortIndex;
    }

    pPort = omx_type1_decoder_component_Private->ports[nPortIndex];
    err = pPort->Port_FreeBuffer(pPort, nPortIndex, pBuffer);
    if (err != OMX_ErrorNone) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Out of for component %p with err %i\n", hComponent, (int)err);
        return err;
    }
    pPort->sPortParam.nBufferSize = 0;
    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Free Buffer Out of for component[port:%d] %p\n", nPortIndex, hComponent);
    return OMX_ErrorNone;
}

OMX_ERRORTYPE omx_type1_decoder_component_GetParameter(
    OMX_HANDLETYPE hComponent,
    OMX_INDEXTYPE nParamIndex,
    OMX_PTR ComponentParameterStructure) {
    OMX_ERRORTYPE err = OMX_ErrorNone;
    OMX_MTK_COMMON_DEC_PARAM_STRUCT *peType1DecParam = NULL;
    OMX_S32 i4DecIntfRet = 0;
    TYPE1_DEC_ACTION_INTF *ptDecActionIntf = NULL;
    OMX_PTR pvDecSelfData = NULL;

    OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE *)hComponent;
    omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private = openmaxStandComp->pComponentPrivate;
    ptDecActionIntf = &(omx_type1_decoder_component_Private->ptDecComp->tDecActionIntf);
    pvDecSelfData = omx_type1_decoder_component_Private->pvDecSelfData;

    if (ComponentParameterStructure == NULL) {
        return OMX_ErrorBadParameter;
    }

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Getting parameter in: 0x%x\n", nParamIndex);
    switch (nParamIndex) {
        case OMX_IndexParamAudioPcm:
        {
            OMX_AUDIO_PARAM_PCMMODETYPE mOutputPcmMode;
            mOutputPcmMode.nSize = sizeof(mOutputPcmMode);
            mOutputPcmMode.nPortIndex = gOutputPcmMode.nPortIndex;
            mOutputPcmMode.nChannels = gOutputPcmMode.nChannels;
            mOutputPcmMode.eNumData = gOutputPcmMode.eNumData;
            mOutputPcmMode.eEndian = gOutputPcmMode.eEndian;
            mOutputPcmMode.bInterleaved = gOutputPcmMode.bInterleaved;
            mOutputPcmMode.nBitPerSample = gOutputPcmMode.nBitPerSample;
            mOutputPcmMode.nSamplingRate = gOutputPcmMode.nSamplingRate;
            mOutputPcmMode.ePCMMode = gOutputPcmMode.ePCMMode;
            mOutputPcmMode.eChannelMapping[0] = gOutputPcmMode.eChannelMapping[0];
            mOutputPcmMode.eChannelMapping[1] = gOutputPcmMode.eChannelMapping[1];
            mOutputPcmMode.eChannelMapping[2] = gOutputPcmMode.eChannelMapping[2];
            mOutputPcmMode.eChannelMapping[3] = gOutputPcmMode.eChannelMapping[3];
            mOutputPcmMode.eChannelMapping[4] = gOutputPcmMode.eChannelMapping[4];
            mOutputPcmMode.eChannelMapping[5] = gOutputPcmMode.eChannelMapping[5];

            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] [Getparam]nChannels[%d], nSamplingRate[%d]\n", mOutputPcmMode.nChannels, mOutputPcmMode.nSamplingRate);

            OMX_AUDIO_PARAM_PCMMODETYPE *pPcmMode = (OMX_AUDIO_PARAM_PCMMODETYPE *)ComponentParameterStructure;
            if (pPcmMode->nPortIndex == mOutputPcmMode.nPortIndex) {
                memcpy(ComponentParameterStructure, &mOutputPcmMode, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
            }
            break;
        }
        default:
        {
            err = omx_base_component_GetParameter(hComponent, nParamIndex, ComponentParameterStructure);
            if (nParamIndex == OMX_IndexParamPortDefinition)
            {
                OMX_PARAM_PORTDEFINITIONTYPE *pPortdef = (OMX_PARAM_PORTDEFINITIONTYPE *)ComponentParameterStructure;
                if (pPortdef->nPortIndex == 1)
                {
                    pPortdef->nBufferSize = 384 * 1024 * 2;
                }
            }
        }
    }
    return err;
}

OMX_ERRORTYPE omx_type1_decoder_component_SetParameter(
    OMX_HANDLETYPE hComponent,
    OMX_INDEXTYPE nParamIndex,
    OMX_PTR ComponentParameterStructure) {
    OMX_ERRORTYPE err = OMX_ErrorNone;
    OMX_MTK_COMMON_DEC_PARAM_STRUCT *peType1DecParam = NULL;
    OMX_MTK_COMMON_DEC_FLOW_CTRL_STRUCT *peType1DecFlowCtrl = NULL;
    OMX_S32 i4DecIntfRet = 0;
    TYPE1_DEC_ACTION_INTF *ptDecActionIntf = NULL;
    OMX_PTR pvDecSelfData = NULL;
    OMX_S32 i = 0;

    OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE *)hComponent;
    omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private = openmaxStandComp->pComponentPrivate;
    ptDecActionIntf = &(omx_type1_decoder_component_Private->ptDecComp->tDecActionIntf);
    pvDecSelfData = omx_type1_decoder_component_Private->pvDecSelfData;

    if (ComponentParameterStructure == NULL) {
        return OMX_ErrorBadParameter;
    }

    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Setting parameter in: 0x%x\n", nParamIndex);
    switch (nParamIndex) {
        case OMX_IndexDebugGstLoglevel:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *omx_atmos_loglevel = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            COMMON_DEC_AUDIO_DYNAMIC_PARAM atmos_loglevel;
            memset(&atmos_loglevel, 0, sizeof(COMMON_DEC_AUDIO_DYNAMIC_PARAM));
            atmos_loglevel.u4LogLevel = omx_atmos_loglevel->u4LogLevel;
            sndbar_dbg_cfg_log_level = omx_atmos_loglevel->u4LogLevel;
            SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Loglevel: %d\n", sndbar_dbg_cfg_log_level);

            if (NULL == ptDecActionIntf->set_parameter)
            {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfNone;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s set_parameter is NULL Error=%x\n", __func__, err);
                break;
            }
            i4DecIntfRet = ptDecActionIntf->set_parameter(pvDecSelfData, CommonDecParam_LogLeval, (OMX_PTR)&atmos_loglevel);
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param OMX_IndexConfigATMOSDecDynamicParam end (ret: %d)\n", i4DecIntfRet);
            if (i4DecIntfRet < 0) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In return OMX_ErrorDecoderActionIntfError\n");
            }
            break;
        }
        case OMX_IndexParamStandardComponentRole:
        {
            OMX_U8 mCompRole[OMX_MAX_STRINGNAME_SIZE] = {0};
            OMX_PARAM_COMPONENTROLETYPE *pRoleParams = (OMX_PARAM_COMPONENTROLETYPE *)ComponentParameterStructure;
            strcpy((char *)mCompRole, (char *)pRoleParams->cRole);
            err = OMX_ErrorNone;
            break;
        }
        case OMX_IndexConfigATMOSDecProfile:
        {
            OMX_AUDIO_ATMOS_APP_PARAM_PROFILE_T* omx_atmos_profile = (OMX_AUDIO_ATMOS_APP_PARAM_PROFILE_T *)ComponentParameterStructure;
            COMMON_DEC_AUDIO_PROFILE profile;
            profile.u4DecAudioProfile = omx_atmos_profile->u4DecAudioProfile;

            if (NULL == ptDecActionIntf->set_parameter) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfNone;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s set_parameter is NULL Error=%x\n", __func__, err);
                break;
            }

            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param OMX_IndexConfigATMOSDecProfile begin (value: %u)\n", profile.u4DecAudioProfile);
            i4DecIntfRet = ptDecActionIntf->set_parameter(pvDecSelfData, CommonDecParam_ProfileSet, (OMX_PTR)&profile);
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param OMX_IndexConfigATMOSDecProfile end (ret: %d)\n", i4DecIntfRet);

            if (i4DecIntfRet < 0) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In return OMX_ErrorDecoderActionIntfError\n");
            }
            break;
        }
        case OMX_IndexConfigATMOSDecMode:
        {
            SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param dec output channels start\n");
            OMX_AUDIO_ATMOS_APP_PARAM *ptAtmosParam = (OMX_AUDIO_ATMOS_APP_PARAM *)ComponentParameterStructure;
            gOutputPcmMode.nChannels = ptAtmosParam->u4Channels;
            SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set dec_output_channels:%u\n",gOutputPcmMode.nChannels);
            break;
        }
        case OMX_IndexConfigATMOSDecDrcModeSet:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T* omx_atmos_drc_mode = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            COMMON_DEC_AUDIO_DYNAMIC_PARAM atmos_drc_mode;
            memset(&atmos_drc_mode, 0, sizeof(COMMON_DEC_AUDIO_DYNAMIC_PARAM));
            atmos_drc_mode.u4DecAudioDrc = omx_atmos_drc_mode->u4DecAudioDrc;

            if (NULL == ptDecActionIntf->set_parameter) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfNone;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s set_parameter is NULL Error=%x\n", __func__, err);
                break;
            }

            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, " Set Param OMX_IndexConfigATMOSDecDynamicParam begin (value: %u)\n",atmos_drc_mode.u4DecAudioDrc);
            i4DecIntfRet = ptDecActionIntf->set_parameter(pvDecSelfData, CommonDecParam_DrcModeSet, (OMX_PTR)&atmos_drc_mode);
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, " Set Param OMX_IndexConfigATMOSDecDynamicParam end (ret: %d)\n", i4DecIntfRet);

            if (i4DecIntfRet < 0) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In return OMX_ErrorDecoderActionIntfError\n");
            }
            break;
        }
        case OMX_IndexConfigATMOSDecDrcCutSet:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T* omx_atmos_drc_cut = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            COMMON_DEC_AUDIO_DYNAMIC_PARAM atmos_drc_cut;
            memset(&atmos_drc_cut, 0, sizeof(COMMON_DEC_AUDIO_DYNAMIC_PARAM));

            atmos_drc_cut.DecAudioDrcCut = omx_atmos_drc_cut->DecAudioDrcCut;

            if (NULL == ptDecActionIntf->set_parameter) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfNone;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s set_parameter is NULL Error=%x\n", __func__, err);
                break;
            }

            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, " Set Param OMX_IndexConfigATMOSDecDynamicParam begin (value: %u)\n",atmos_drc_cut.u4DecAudioDrc);
            i4DecIntfRet = ptDecActionIntf->set_parameter(pvDecSelfData, CommonDecParam_DrcCutSet, (OMX_PTR)&atmos_drc_cut);
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, " Set Param OMX_IndexConfigATMOSDecDynamicParam end (ret: %d)\n", i4DecIntfRet);

            if (i4DecIntfRet < 0) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In return OMX_ErrorDecoderActionIntfError\n");
            }
            break;
        }
        case OMX_IndexConfigATMOSDecDrcBoostSet:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T* omx_atmos_drc_boost = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            COMMON_DEC_AUDIO_DYNAMIC_PARAM atmos_drc_boost;
            memset(&atmos_drc_boost, 0, sizeof(COMMON_DEC_AUDIO_DYNAMIC_PARAM));

            atmos_drc_boost.DecAudioDrcBoost = omx_atmos_drc_boost->DecAudioDrcBoost;

            if (NULL == ptDecActionIntf->set_parameter) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfNone;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s set_parameter is NULL Error=%x\n", __func__, err);
                break;
            }

            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, " Set Param OMX_IndexConfigATMOSDecDynamicParam begin (value: %u)\n",atmos_drc_boost.u4DecAudioDrc);
            i4DecIntfRet = ptDecActionIntf->set_parameter(pvDecSelfData, CommonDecParam_DrcBoostSet, (OMX_PTR)&atmos_drc_boost);
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, " Set Param OMX_IndexConfigATMOSDecDynamicParam end (ret: %d)\n", i4DecIntfRet);

            if (i4DecIntfRet < 0) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In return OMX_ErrorDecoderActionIntfError\n");
            }
            break;
        }
        case OMX_IndexConfigATMOSDecNolm:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T* omx_atmos_nolm = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            COMMON_DEC_AUDIO_DYNAMIC_PARAM atmos_nolm;
            memset(&atmos_nolm, 0, sizeof(COMMON_DEC_AUDIO_DYNAMIC_PARAM));
            atmos_nolm.u4DecAudioNolm = omx_atmos_nolm->u4DecAudioNolm;

            if (NULL == ptDecActionIntf->set_parameter)
            {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfNone;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s set_parameter is NULL Error=%x\n", __func__, err);
                break;
            }

            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, " Set Param OMX_IndexConfigATMOSDecDynamicParam begin (value: %u)\n", atmos_nolm.u4DecAudioNolm);
            i4DecIntfRet = ptDecActionIntf->set_parameter(pvDecSelfData, CommonDecParam_NolmSet, (OMX_PTR)&atmos_nolm);
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, " Set Param OMX_IndexConfigATMOSDecDynamicParam end (ret: %d)\n", i4DecIntfRet);

            if (i4DecIntfRet < 0)
            {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In return OMX_ErrorDecoderActionIntfError\n");
            }
            break;
        }
        case OMX_IndexConfigATMOSDecNoupmix:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T* omx_atmos_noupmix = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            COMMON_DEC_AUDIO_DYNAMIC_PARAM atmos_noupmix;
            memset(&atmos_noupmix, 0, sizeof(COMMON_DEC_AUDIO_DYNAMIC_PARAM));
            atmos_noupmix.u4DecAudioNoupmix = omx_atmos_noupmix->u4DecAudioNoupmix;

            if (NULL == ptDecActionIntf->set_parameter) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfNone;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s set_parameter is NULL Error=%x\n", __func__, err);
                break;
            }

            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param OMX_IndexConfigATMOSDecDynamicParam begin (value: %u)\n", atmos_noupmix.u4DecAudioNoupmix);
            i4DecIntfRet = ptDecActionIntf->set_parameter(pvDecSelfData, CommonDecParam_NoupmixSet, (OMX_PTR)&atmos_noupmix);
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param OMX_IndexConfigATMOSDecDynamicParam end (ret: %d)\n", i4DecIntfRet);

            if (i4DecIntfRet < 0) {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In return OMX_ErrorDecoderActionIntfError\n");
            }
            break;
        }
        case OMX_IndexDebugGstLogLatencyCmd:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *omx_atmos_latency_cmd = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            OMX_BOOL latency_cmd = omx_atmos_latency_cmd->u4LatencyLogCmd;
            SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set LatencyLogCmd: %d\n", latency_cmd);
            debug_open_latency_file(latency_cmd);
            break;
        }
        case OMX_IndexDebugGstLogLatencyNum:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *omx_atmos_latency_num = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            latency_log_num = omx_atmos_latency_num->u4LatencyLogNum;
            SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set LatencyLogNum: %d\n", latency_log_num);
            break;
        }
        case OMX_IndexDebugGstDumpCmd:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *omx_atmos_dump_cmd = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            OMX_BOOL data_dump_cmd = omx_atmos_dump_cmd->u4DataDumpCmd;
            SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set DumpCmd: %d\n", data_dump_cmd);
            debug_open_datadump_file(data_dump_cmd);
            break;
        }
        case OMX_IndexDebugGstUseCase:
        {
            OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *omx_atmos_use_case = (OMX_AUDIO_ATMOS_APP_DYNAMIC_PARAM_T *)ComponentParameterStructure;
            omx_type1_decoder_component_Private->s4UseCase = omx_atmos_use_case->s4UseCase;

            SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set UseCase: %d\n",
                                                  omx_type1_decoder_component_Private->s4UseCase);
            break;
        }
        case OMX_IndexParamMtkCommon:
        {
            OMX_PARAM_MTK_COMMON* mtk_param = (OMX_PARAM_MTK_COMMON *)ComponentParameterStructure;
            omx_type1_decoder_component_Private->atrace_log_level_p = mtk_param->atrace_log_level_p;

            SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set mtk common: atrace lvl %d\n",
                                                  *(omx_type1_decoder_component_Private->atrace_log_level_p));
            break;
        }
        case OMX_IndexConfigATMOSDecMatFlag:
        {
            OMX_AUDIO_ATMOS_APP_PARAM* omx_atmos_matflag = (OMX_AUDIO_ATMOS_APP_PARAM *)ComponentParameterStructure;
            COMMON_DEC_AUDIO_DYNAMIC_PARAM atmos_matflag;
            memset(&atmos_matflag, 0, sizeof(COMMON_DEC_AUDIO_DYNAMIC_PARAM));
            atmos_matflag.s4MatFlag = omx_atmos_matflag->s4MatFlag;

            if (NULL == ptDecActionIntf->set_parameter)
            {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfNone;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s set_parameter is NULL Error=%x\n", __func__, err);
                break;
            }

            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param OMX_IndexConfigATMOSDecMatFlag begin (value: %u)\n", atmos_matflag.s4MatFlag);
            i4DecIntfRet = ptDecActionIntf->set_parameter(pvDecSelfData, CommonDecParam_MatFlag, (OMX_PTR)&atmos_matflag);
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param OMX_IndexConfigATMOSDecMatFlag end (ret: %d)\n", i4DecIntfRet);

            if (i4DecIntfRet < 0)
            {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In return OMX_ErrorDecoderActionIntfError\n");
            }
            break;
        }
        case OMX_IndexConfigATMOSDecDualMode:
        {
            OMX_AUDIO_ATMOS_APP_PARAM_DUAL_MODE_T* omx_dual_mode = (OMX_AUDIO_ATMOS_APP_PARAM_DUAL_MODE_T *)ComponentParameterStructure;
            COMMON_DEC_DUAL_MODE DualMode;
            DualMode.u4DecDualMode = omx_dual_mode->u4DecDualMode;
            printf("omx_atmosdec_component set dual mode \n");
            if (NULL == ptDecActionIntf->set_parameter)
            {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfNone;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In %s set_parameter is NULL Error=%x\n", __func__, err);
                break;
            }

            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param OMX_IndexConfigATMOSDecDualMode begin (value: %u)\n", DualMode.u4DecDualMode);
            i4DecIntfRet = ptDecActionIntf->set_parameter(pvDecSelfData, CommonDecParam_DualmodeSet, (OMX_PTR)&DualMode);
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Set Param OMX_IndexConfigATMOSDecProfile end (ret: %d)\n", i4DecIntfRet);

            if (i4DecIntfRet < 0)
            {
                err = (OMX_ERRORTYPE)OMX_ErrorDecoderActionIntfError;
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] In return OMX_ErrorDecoderActionIntfError\n");
            }
            break;
        }
        default:
        {
            err = omx_base_component_SetParameter(hComponent, nParamIndex, ComponentParameterStructure);
        }
    }
    return err;
}

static inline int gst_gettid() {
    return syscall(SYS_gettid);
}

static void notifyDecInfo(GST_INFO_ATMOS* info, AUD_NOTIFY_INFO* rDecNfyInfo) {
    info->stream_type = rDecNfyInfo->rAudUpdateInfo.rCodecInfo.rAtmos.stream_type;
    info->proc_type = rDecNfyInfo->rAudUpdateInfo.rCodecInfo.rAtmos.proc_type;
    info->atmos_stream_ch_num = rDecNfyInfo->rAudUpdateInfo.u1stream_ch_num;
    info->atmos_stream_ch_mask = rDecNfyInfo->rAudUpdateInfo.u4stream_ch_mask;
    info->u4first_au_latency = rDecNfyInfo->rAudUpdateInfo.u4first_au_latency;
    info->atmos_sample_rate = rDecNfyInfo->rAudUpdateInfo.u4out_sample_Rate;
    SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] stream_type:%d, proc_type:%d, rate:%d, stream_ch_num:%d, stream_ch_mask:%d, first_au_latency:%d\n",
                info->stream_type,
                info->proc_type,
                info->atmos_sample_rate,
                info->atmos_stream_ch_num,
                info->atmos_stream_ch_mask,
                info->u4first_au_latency);
}

static void fillDecPcmAttr(type1_dec_pcm_attr *ptDecPcmAttr, TYPE1_DEC_OUTPUT_BUF* tDecOutput) {
    ptDecPcmAttr->u4Version = TYPE1_DEC_PCM_ATTR_VERSION;
    ptDecPcmAttr->u4Size = sizeof(type1_dec_pcm_attr);
    ptDecPcmAttr->u4SampleNumPerChannel =  tDecOutput->ePcmInfo.u4SampleNumPerChannel;
    ptDecPcmAttr->u4BitsPerSample = tDecOutput->ePcmInfo.u4BitsPerSample;
    ptDecPcmAttr->u4NeedBytesPerSample =  tDecOutput->ePcmInfo.u4NeedBytesPerSample;
    ptDecPcmAttr->u4SampleIsLittleEnd =  tDecOutput->ePcmInfo.u4SampleIsLittleEnd;
    ptDecPcmAttr->eAccessMode =  tDecOutput->ePcmInfo.eAccessMode;
    ptDecPcmAttr->u4ChannelConfig0 =  tDecOutput->ePcmInfo.u4ChannelConfig0;
    ptDecPcmAttr->u4ChannelConfig1 =  tDecOutput->ePcmInfo.u4ChannelConfig1;
    ptDecPcmAttr->u4ChannelConfig2 =  tDecOutput->ePcmInfo.u4ChannelConfig2;
    ptDecPcmAttr->u4ChannelNum =  tDecOutput->ePcmInfo.u4ChannelNum;
    ptDecPcmAttr->u4SampleRate =  tDecOutput->ePcmInfo.u4SampleRate;
}

static void notifyDecOutputPcmInfoChange(OMX_COMPONENTTYPE* openmaxStandComp, TYPE1_DEC_OUTPUT_BUF* tDecOutput, omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private) {
    if ((tDecOutput->ePcmInfo.u4ChannelNum &&  tDecOutput->ePcmInfo.u4SampleRate) &&
        (gOutputPcmMode.nBitPerSample !=  tDecOutput->ePcmInfo.u4BitsPerSample ||
            gOutputPcmMode.eEndian !=  tDecOutput->ePcmInfo.u4SampleIsLittleEnd ||
            gOutputPcmMode.nChannels !=  tDecOutput->ePcmInfo.u4ChannelNum ||
            gOutputPcmMode.nSamplingRate !=  tDecOutput->ePcmInfo.u4SampleRate)) {
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] before: channel-num[%d], sample-rate[%d], BitPerSample[%d], eEndian[%d]\n",
                    gOutputPcmMode.nChannels, gOutputPcmMode.nSamplingRate, gOutputPcmMode.nBitPerSample, gOutputPcmMode.eEndian);
        gOutputPcmMode.nBitPerSample =  tDecOutput->ePcmInfo.u4BitsPerSample;
        gOutputPcmMode.eEndian =  tDecOutput->ePcmInfo.u4SampleIsLittleEnd;
        gOutputPcmMode.nChannels =  tDecOutput->ePcmInfo.u4ChannelNum;
        gOutputPcmMode.nSamplingRate =   tDecOutput->ePcmInfo.u4SampleRate;
        SNDBAR_LOGD(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] after: channel-num[%d], sample-rate[%d], BitPerSample[%d], eEndian[%d]\n",
                    gOutputPcmMode.nChannels, gOutputPcmMode.nSamplingRate, gOutputPcmMode.nBitPerSample, gOutputPcmMode.eEndian);
        if(omx_type1_decoder_component_Private->atrace_log_level_p != NULL) {
            ATRACE_LOG_FULL (*(omx_type1_decoder_component_Private->atrace_log_level_p), "[libomxil-atmos](func:%s)(line:%d) notify", "bufmgt", __LINE__);
        }
        (*(omx_type1_decoder_component_Private->callbacks->EventHandler))(openmaxStandComp, omx_type1_decoder_component_Private->callbackData, OMX_EventPortSettingsChanged, 1, 0, NULL);
    }
}

static int checkBufferValid(omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private,
  OMX_BOOL *isBufferNeeded, tsem_t** pSem, omx_base_PortType** pPort, OMX_BUFFERHEADERTYPE* ptTmpInputBuf) {
    int ret = 0;
    for (int i = 0; i < omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts; i++ ) {
        if (omx_type1_decoder_component_Private->state == OMX_StateLoaded || 
            omx_type1_decoder_component_Private->state == OMX_StateInvalid) {
            ret = 1;
            break;
        } else if ((isBufferNeeded[i] == OMX_TRUE && pSem[i]->semval == 0) && PORT_IS_ENABLED(pPort[i]) && !PORT_IS_BEING_FLUSHED(pPort[i])) {
            if((i == 0 &&  (0 == ptTmpInputBuf->nFilledLen - ptTmpInputBuf->nOffset)) || i == 1) {
                tsem_down(omx_type1_decoder_component_Private->bMgmtSem);
            }
        }
        if (checkAnyPortBeingFlushed(omx_type1_decoder_component_Private)) {
            pthread_yield ();
            ret = -1;
            break;
        }
    }
    return ret;
}

static void fillDecInputBuf(OMX_BUFFERHEADERTYPE* ptTmpInputBuf, OMX_BUFFERHEADERTYPE** pBuffer, TYPE1_DEC_INPUT_BUF* tDecInput) {
        OMX_U32 u4TmpBufRemainSize = ptTmpInputBuf->nAllocLen - ptTmpInputBuf->nFilledLen;
        if ((u4TmpBufRemainSize < pBuffer[0]->nFilledLen) && (ptTmpInputBuf->nOffset > 0)) {
            if (tDecInput->u4BufByteSize > 0) {
                memmove(ptTmpInputBuf->pBuffer, tDecInput->pvBuf, tDecInput->u4BufByteSize);
            }
            ptTmpInputBuf->nOffset = 0;
            ptTmpInputBuf->nFilledLen = tDecInput->u4BufByteSize;
            u4TmpBufRemainSize = ptTmpInputBuf->nAllocLen - ptTmpInputBuf->nFilledLen;
        }
        if (pBuffer[0]->nFilledLen > 0) {
            OMX_U32 u4TmpBufCpySize = u4TmpBufRemainSize > pBuffer[0]->nFilledLen ? pBuffer[0]->nFilledLen : u4TmpBufRemainSize;
            if (u4TmpBufCpySize > 0) {
                memcpy((ptTmpInputBuf->pBuffer + ptTmpInputBuf->nFilledLen), (pBuffer[0]->pBuffer + pBuffer[0]->nOffset), u4TmpBufCpySize);
                ptTmpInputBuf->nFilledLen += u4TmpBufCpySize;
                pBuffer[0]->nFilledLen -= u4TmpBufCpySize;
                pBuffer[0]->nOffset += u4TmpBufCpySize;
            }
        }
        tDecInput->pvBuf = (OMX_PTR)(ptTmpInputBuf->pBuffer + ptTmpInputBuf->nOffset);
        tDecInput->u4BufByteSize = ptTmpInputBuf->nFilledLen - ptTmpInputBuf->nOffset;
}

static void updateDecOutUsedSize (TYPE1_DEC_OUTPUT_BUF* tDecOutput,  type1_dec_pcm_attr *ptDecPcmAttr) {
    if ( tDecOutput->u4BufUsedByteSize >  tDecOutput->u4BufTotalByteSize) {
        SNDBAR_LOGW(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] tDecOutput.u4BufUsedByteSize(%d) > tDecOutput.u4BufTotalByteSize(%d)!\n", (int) tDecOutput->u4BufUsedByteSize, (int) tDecOutput->u4BufTotalByteSize);
         tDecOutput->u4BufUsedByteSize =  tDecOutput->u4BufTotalByteSize;
    }
    if ( tDecOutput->u4BufUsedByteSize != ptDecPcmAttr->u4SampleNumPerChannel * ptDecPcmAttr->u4NeedBytesPerSample * ptDecPcmAttr->u4ChannelNum) {
        SNDBAR_LOGW(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] tDecOutput.u4BufUsedByteSize(%d) != u4SampleNumPerChannel(%d) * u4NeedBytesPerSample(%d) * u4ChannelNum(%d)! will use the little value!\n",
                (int) tDecOutput->u4BufUsedByteSize, (int)ptDecPcmAttr->u4SampleNumPerChannel, (int)ptDecPcmAttr->u4NeedBytesPerSample, (int)ptDecPcmAttr->u4ChannelNum);
        if ( tDecOutput->u4BufUsedByteSize > ptDecPcmAttr->u4SampleNumPerChannel *
        ptDecPcmAttr->u4NeedBytesPerSample * ptDecPcmAttr->u4ChannelNum) {
             tDecOutput->u4BufUsedByteSize = ptDecPcmAttr->u4SampleNumPerChannel * ptDecPcmAttr->u4NeedBytesPerSample * ptDecPcmAttr->u4ChannelNum;
        } else {
            ptDecPcmAttr->u4SampleNumPerChannel =  tDecOutput->u4BufUsedByteSize / ptDecPcmAttr->u4NeedBytesPerSample / ptDecPcmAttr->u4ChannelNum;
        }
    }
}

static void returnOutputBuf(omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private, OMX_BUFFERHEADERTYPE** pBuffer,
                        OMX_U32 nOutputPortIndex, OMX_BOOL* isBufferNeeded, omx_base_PortType** pPort) {
    if (omx_type1_decoder_component_Private->state == OMX_StatePause &&
        !(checkAnyPortBeingFlushed(omx_type1_decoder_component_Private))) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Waiting at paused state...\n");
        tsem_wait(omx_type1_decoder_component_Private->bStateSem);
    }
    if (pBuffer[nOutputPortIndex]->nFilledLen != 0) {
        pBuffer[nOutputPortIndex]->nFilledLen -= pBuffer[nOutputPortIndex]->nOffset;
        pBuffer[nOutputPortIndex]->nOffset += TYPE1_MAX_SIDEINFO_NUM * sizeof(S_SIDEINFO) + TYPE1_DECODER_COMP_OUTPUT_BUF_ALIGNED_SAMPLE_BYTE_SIZE;
        if (i4_Times_flag) {
            SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Returning output buffer, nFilledLen[%d], noffset[%d]\n", pBuffer[nOutputPortIndex]->nFilledLen, pBuffer[nOutputPortIndex]->nOffset);
            i4_Times_flag--;
        }
        pPort[nOutputPortIndex]->ReturnBufferFunction(pPort[nOutputPortIndex], pBuffer[nOutputPortIndex]);
        pBuffer[nOutputPortIndex] = NULL;
        isBufferNeeded[nOutputPortIndex] = OMX_TRUE;
    }
}

static OMX_BOOL acquireBuffer(omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private, tsem_t** pSem,
                    OMX_BOOL* isBufferNeeded, omx_base_PortType** pPort, queue_t** pQueue, OMX_BUFFERHEADERTYPE** pBuffer) {
    OMX_BOOL isBufferReady = OMX_TRUE;
    for (int i = 0; i < omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts; i++) {
        if (pSem[i]->semval > 0 && isBufferNeeded[i] == OMX_TRUE && PORT_IS_ENABLED(pPort[i])) {
            tsem_down(pSem[i]);
            if (pQueue[i]->nelem > 0) {
                isBufferNeeded[i] = OMX_FALSE;
                SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] [Buffer_Mgmtfunction]dequeue pQueue[%d] a buffer\n", i);
                pBuffer[i] = dequeue(pQueue[i]);
                if(omx_type1_decoder_component_Private->atrace_log_level_p != NULL) {
                    ATRACE_LOG_INFO(*(omx_type1_decoder_component_Private->atrace_log_level_p), "[libomxil-atmos](func:%s)(line:%d) dq pBuffer[%d] = %p\n","bufmgt", __LINE__ , i, pBuffer[i]);
                }
                if (pBuffer[i] == NULL) {
                    SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Had NULL input buffer!!\n");
                    break;
                }
            } else {
                SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] [Buffer_Mgmtfunction]Error,pQueue[%d]->nelem = %d\n", i, pQueue[i]->nelem);
            }
        }
        if (isBufferNeeded[i] == OMX_TRUE) {//if any of them still needs a buffer, it is false.
            isBufferReady = OMX_FALSE;
        }
    }
    return isBufferReady;
}

static void initDecOutput(type1_dec_output_header** ptDecOutputHdr, OMX_U32 nOutputPortIndex, OMX_BUFFERHEADERTYPE** pBuffer,
                        type1_dec_pcm_attr **ptDecPcmAttr, TYPE1_DEC_OUTPUT_BUF* tDecOutput) {
    *ptDecOutputHdr = (type1_dec_output_header *)pBuffer[nOutputPortIndex]->pBuffer;
    *ptDecPcmAttr = (type1_dec_pcm_attr *)(pBuffer[nOutputPortIndex]->pBuffer + sizeof(type1_dec_output_header) + sizeof(type1_dec_sideinfo_attr));
    pBuffer[nOutputPortIndex]->nOffset = (((sizeof(type1_dec_output_header) + sizeof(type1_dec_sideinfo_attr) + sizeof(type1_dec_pcm_attr) + 16) >> 4) << 4);
    pBuffer[nOutputPortIndex]->nFilledLen = pBuffer[nOutputPortIndex]->nOffset;
    tDecOutput->pvPcmBuf = (OMX_PTR)(pBuffer[nOutputPortIndex]->pBuffer + pBuffer[nOutputPortIndex]->nOffset + TYPE1_MAX_SIDEINFO_NUM * sizeof(S_SIDEINFO) + TYPE1_DECODER_COMP_OUTPUT_BUF_ALIGNED_SAMPLE_BYTE_SIZE);
    tDecOutput->u4BufUsedByteSize = 0;
    tDecOutput->u4BufTotalByteSize = pBuffer[nOutputPortIndex]->nAllocLen - (pBuffer[nOutputPortIndex]->nOffset + TYPE1_MAX_SIDEINFO_NUM * sizeof(S_SIDEINFO) + TYPE1_DECODER_COMP_OUTPUT_BUF_ALIGNED_SAMPLE_BYTE_SIZE);
    memset(&(tDecOutput->ePcmInfo), 0, sizeof(TYPE1_DEC_PCM_INFO));
}

void* omx_type1_decoder_component_BufferMgmtFunction(void* param) {
    OMX_COMPONENTTYPE* openmaxStandComp = (OMX_COMPONENTTYPE*)param;
    omx_type1_decoder_component_PrivateType* omx_type1_decoder_component_Private = (omx_type1_decoder_component_PrivateType*)openmaxStandComp->pComponentPrivate;
    omx_base_PortType *pPort[TYPE1_DECODER_COMP_MAX_PORTS] = {NULL};
    tsem_t* pSem[TYPE1_DECODER_COMP_MAX_PORTS] = {NULL};
    queue_t* pQueue[TYPE1_DECODER_COMP_MAX_PORTS] = {NULL};
    OMX_BUFFERHEADERTYPE* pBuffer[TYPE1_DECODER_COMP_MAX_PORTS] = {NULL};
    OMX_BOOL isBufferNeeded[TYPE1_DECODER_COMP_MAX_PORTS] = {OMX_TRUE};
    OMX_BOOL isBufferReady = OMX_FALSE;
    OMX_U32 nOutputPortIndex, i;
    OMX_BUFFERHEADERTYPE* ptTmpInputBuf = &(omx_type1_decoder_component_Private->tTmpInputBuf);
    OMX_PTR pvDecSelfData = omx_type1_decoder_component_Private->pvDecSelfData;
    TYPE1_DEC_INPUT_BUF tDecInput;//dec buffer
    TYPE1_DEC_OUTPUT_BUF tDecOutput;
    TYPE1_DEC_ACTION_INTF *ptDecActionIntf = &(omx_type1_decoder_component_Private->ptDecComp->tDecActionIntf);
    type1_dec_output_header *ptDecOutputHdr = NULL;
    type1_dec_pcm_attr *ptDecPcmAttr = NULL;
    OMX_U32 u4InputBufConsumed = 0;
    OMX_S32 u4DecActionIntfRet = 0;
    OMX_BOOL u4IsDecInfoChg = OMX_FALSE;
    struct timespec temp_time;
    AUD_NOTIFY_INFO rDecNfyInfo = {0};
    int ret = 0;

    if(omx_type1_decoder_component_Private->atrace_log_level_p != NULL) {
        ATRACE_LOG_INFO(*(omx_type1_decoder_component_Private->atrace_log_level_p), "[libomxil-atmos](func:%s)(line:%d) entry", "bufmgt", __LINE__);
    }
    if (NULL == ptDecActionIntf->decode) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component]There is no decode function exit!\n");
        return NULL;
    }
    //struct sched_param sched_param;
    //sched_param.sched_priority = sched_get_priority_min(SCHED_RR) + 92;
    //sched_setscheduler(gst_gettid(), SCHED_RR, &sched_param);
#if 1
    prctl(PR_SET_NAME, "libomx_bufmgt", NULL, NULL, NULL);
    struct sched_param schedule;
    schedule.sched_priority = 4;
    ret = pthread_setschedparam(pthread_self(), SCHED_RR, &schedule);
    if (ret != 0) {
        SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "atmos set sched error, ret = %d\n", ret);
    }
#endif

    for (i = 0; i < omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts; i++) {
        pPort[i] = omx_type1_decoder_component_Private->ports[i];
        pSem[i] = pPort[i]->pBufferSem;
        pQueue[i] = pPort[i]->pBufferQueue;
        isBufferNeeded[i] = OMX_TRUE;
    }
    nOutputPortIndex = omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts - 1;//set output port index==1
    while (omx_type1_decoder_component_Private->state == OMX_StateIdle || omx_type1_decoder_component_Private->state == OMX_StateExecuting ||
           omx_type1_decoder_component_Private->state == OMX_StatePause || omx_type1_decoder_component_Private->transientState == OMX_TransStateLoadedToIdle) {
        while (checkAnyPortBeingFlushed(omx_type1_decoder_component_Private)) {
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] 1 signalling flush all cond iF=%d,oF=%d iSemVal=%d,oSemval=%d\n", isBufferNeeded[0], isBufferNeeded[nOutputPortIndex], pSem[0]->semval, pSem[nOutputPortIndex]->semval);
            for (i = 0; i < omx_type1_decoder_component_Private->sPortTypesParam[OMX_PortDomainAudio].nPorts; i++) {
                if (isBufferNeeded[i] == OMX_FALSE && PORT_IS_BEING_FLUSHED(pPort[i])) {
                    pPort[i]->ReturnBufferFunction(pPort[i], pBuffer[i]);
                    pBuffer[i] = NULL;
                    isBufferNeeded[i] = OMX_TRUE;
                    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Ports are flushing,so returning buffer %i\n", (int)i);
                }
            }
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] 2 signalling flush all cond iF=%d,oF=%d iSemVal=%d,oSemval=%d\n", isBufferNeeded[0], isBufferNeeded[nOutputPortIndex], pSem[0]->semval, pSem[nOutputPortIndex]->semval);
            tsem_up(omx_type1_decoder_component_Private->flush_all_condition);
            tsem_down(omx_type1_decoder_component_Private->flush_condition);
        }
        int ret = checkBufferValid(omx_type1_decoder_component_Private, isBufferNeeded, pSem, pPort, ptTmpInputBuf);
        if (ret == 1) {
            SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Buffer Management Thread is exiting\n");
            break;
        } else if (ret == -1) {
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] [Buffer_Mgmtfunction]continue\n");
            continue;
        }
        if (omx_type1_decoder_component_Private->state == OMX_StateLoaded || omx_type1_decoder_component_Private->state == OMX_StateInvalid) {
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Buffer Management Thread is exiting\n");
            break;
        }
        isBufferReady = acquireBuffer(omx_type1_decoder_component_Private, pSem, isBufferNeeded, pPort, pQueue, pBuffer);
        if (isBufferReady == OMX_FALSE) {
            if (isBufferNeeded[nOutputPortIndex] == OMX_TRUE || (0 == ptTmpInputBuf->nFilledLen - ptTmpInputBuf->nOffset)) {
                usleep(2 * 1000);
                SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Waiting for input buffer to be filled..");
                continue;
            }
        }
        struct timespec p1, p2;
        clock_gettime(CLOCK_MONOTONIC, &p1);
        if (omx_type1_decoder_component_Private->state == OMX_StateExecuting) {
            tDecInput.pvBuf = (OMX_PTR)(ptTmpInputBuf->pBuffer + ptTmpInputBuf->nOffset);//dec buffer location
            tDecInput.u4BufByteSize = ptTmpInputBuf->nFilledLen - ptTmpInputBuf->nOffset;//dec buffer length
            if (tDecInput.u4BufByteSize > ptTmpInputBuf->nFilledLen) { //unsigned out of range check
                SNDBAR_LOGE(sndbar_dbg_cfg_log_level,"[omx_atmosdec_component] the input buffer meet error case!!\n");
                tDecInput.u4BufByteSize = 0;
                ptTmpInputBuf->nFilledLen = ptTmpInputBuf->nOffset;
            }
            if (NULL != pBuffer[0]) {//input is ok
                fillDecInputBuf(ptTmpInputBuf, &pBuffer[0], &tDecInput);
            }
            if (tDecInput.u4BufByteSize != 0) {
                initDecOutput(&ptDecOutputHdr, nOutputPortIndex, pBuffer, &ptDecPcmAttr,  &tDecOutput);
                u4InputBufConsumed = 0;
                SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] starting decode\n");
                if(i4_Times_before) {
                    atrace_begin("[omx_atmosdec_component] decode 1st data");
                    i4_Times_before--;
                }
                static struct timespec dec_time_begin;
                temp_time = dec_time_begin;
                clock_gettime(CLOCK_MONOTONIC, &dec_time_begin);
                u4DecActionIntfRet = ptDecActionIntf->decode(pvDecSelfData, &tDecInput, &tDecOutput, &u4InputBufConsumed, &u4IsDecInfoChg, &rDecNfyInfo);
                static struct timespec dec_time_end;
                clock_gettime(CLOCK_MONOTONIC, &dec_time_end);
                write_to_latency_file(dec_time_end, dec_time_begin, temp_time, u4InputBufConsumed, tDecOutput.u4BufUsedByteSize);
                utils_check_time_too_long (&dec_time_begin, &dec_time_end, 15, "decode");
                utils_check_time_abnormal (&temp_time, &dec_time_begin, "interval", 40, 0);
                write_to_dump_infile(tDecInput.pvBuf, u4InputBufConsumed);
                write_to_dump_outfile(tDecOutput.pvPcmBuf, tDecOutput.u4BufUsedByteSize);
                SNDBAR_LOGT (sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] [atmosdec] output size: %ld, consumed: %ld (%ld)\n", tDecOutput.u4BufUsedByteSize, u4InputBufConsumed, tDecInput.u4BufByteSize);
                if (0 != u4DecActionIntfRet) {
                    SNDBAR_LOGE(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component]Error position, u4DecActionIntfRet=%d\n", (int)u4DecActionIntfRet);
                    omx_type1_decoder_component_Private->eIsIgnoreDecCurActionErr = OMX_FALSE;
                    (*(omx_type1_decoder_component_Private->callbacks->EventHandler))(openmaxStandComp,omx_type1_decoder_component_Private->callbackData,
                            OMX_EventError, OMX_ErrorDecoderActionIntfError, 0, NULL);
                    SNDBAR_LOGE(sndbar_dbg_cfg_log_level,"[omx_atmosdec_component] change omx to OMX_StateInvalid state\n");
                    omx_type1_decoder_component_Private->state = OMX_StateInvalid;
                    continue;
                } else {
                    SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] decode success...\n");
                    if(i4_Times_after) {
                        atrace_end("[omx_atmosdec_component] decode 1st data");
                        i4_Times_after--;
                    }
                }
                if (rDecNfyInfo.fgDecNotify && (omx_type1_decoder_component_Private->callbacks->EventHandler) != NULL) {
                    GST_INFO_ATMOS info;
                    notifyDecInfo(&info, &rDecNfyInfo);
                    if(omx_type1_decoder_component_Private->atrace_log_level_p != NULL) {
                        ATRACE_LOG_FULL (*(omx_type1_decoder_component_Private->atrace_log_level_p), "[libomxil-atmos](func:%s)(line:%d) notify", "bufmgt", __LINE__);
                    }
                    (*(omx_type1_decoder_component_Private->callbacks->EventHandler))(openmaxStandComp,omx_type1_decoder_component_Private->callbackData,
                        OMX_EventNotifyCodecInfo, 0, 0, &info);
                }
                ptDecOutputHdr->u4Pcmattrnum = 1;
                ptDecOutputHdr->ptPcmAttrArray = ptDecPcmAttr;
                ptDecPcmAttr->pvPcmData = (OMX_PTR)(pBuffer[nOutputPortIndex]->pBuffer + pBuffer[nOutputPortIndex]->nOffset + TYPE1_MAX_SIDEINFO_NUM * sizeof(S_SIDEINFO) + TYPE1_DECODER_COMP_OUTPUT_BUF_ALIGNED_SAMPLE_BYTE_SIZE);
                fillDecPcmAttr(ptDecPcmAttr, &tDecOutput);
                notifyDecOutputPcmInfoChange(openmaxStandComp, &tDecOutput, omx_type1_decoder_component_Private);
                updateDecOutUsedSize(&tDecOutput, ptDecPcmAttr);
                pBuffer[nOutputPortIndex]->nFilledLen += tDecOutput.u4BufUsedByteSize;
                ptTmpInputBuf->nOffset += u4InputBufConsumed;
                if (ptTmpInputBuf->nOffset > ptTmpInputBuf->nFilledLen) {
                    SNDBAR_LOGW(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] the input buffer meet error case! But continue try!\n");
                    SNDBAR_LOGW(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Maybe u4InputBufConsumed=%d > tDecInput.u4BufByteSize=%d. Need decoder owner check!\n", (int)u4InputBufConsumed, (int)tDecInput.u4BufByteSize);
                    ptTmpInputBuf->nOffset = ptTmpInputBuf->nFilledLen;
                }
                returnOutputBuf(omx_type1_decoder_component_Private, pBuffer, nOutputPortIndex, isBufferNeeded,  pPort);
            } else {
                    SNDBAR_LOGE(sndbar_dbg_cfg_log_level,"[omx_atmosdec_component] meet error!\n");
            }
        } else {
            SNDBAR_LOGI(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] maybe output buffer not enable!!\n");
        }
        clock_gettime(CLOCK_MONOTONIC, &p2);
        check_points_time_too_long (&p1, &p2, 15000, "bufmgt");
        if (omx_type1_decoder_component_Private->state == OMX_StatePause && !(checkAnyPortBeingFlushed(omx_type1_decoder_component_Private))) {
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Waiting at paused state\n");
            tsem_wait(omx_type1_decoder_component_Private->bStateSem);
        }
        if ((NULL != pBuffer[0]) && (0 == pBuffer[0]->nFilledLen) && PORT_IS_ENABLED(pPort[0])) {
            SNDBAR_LOGT(sndbar_dbg_cfg_log_level, "[omx_atmosdec_component] Returning intput buffer\n");
            pPort[0]->ReturnBufferFunction(pPort[0], pBuffer[0]);
            pBuffer[0] = NULL;
            isBufferNeeded[0] = OMX_TRUE;
        }
    }
    if(omx_type1_decoder_component_Private->atrace_log_level_p != NULL) {
        ATRACE_LOG_INFO(*(omx_type1_decoder_component_Private->atrace_log_level_p), "[libomxil-atmos](func:%s)(line:%d) leave", "bufmgt", __LINE__);
    }
    return NULL;
}
