void *audio_dtsdecode_loop(void *args)
{
    int ret,dlen;
    aml_audio_dec_t *audec;
    audio_out_operations_t *aout_ops;
    audio_decoder_operations_t *adec_ops;       
    char *outbuf=pcm_buf_tmp;
    int outlen = 0;
    adec_print("adec_DtsArmDec_loop start!\n");
    audec = (aml_audio_dec_t *)args;
    adec_ops=audec->adec_ops;
    memset(outbuf, 0, AVCODEC_MAX_AUDIO_FRAME_SIZE);
    while (1){
exit_decode_loop:
          //detect quit condition
          if(exit_decode_thread){
        	  exit_decode_thread_success=1;
        	  break;
	      }
	      //detect audio info changed
	      memset(&g_AudioInfo,0,sizeof(AudioInfo));
	      adec_ops->getinfo(audec->adec_ops, &g_AudioInfo);
	      if(g_AudioInfo.channels!=0&&g_AudioInfo.samplerate!=0)
		  {
	         if((g_AudioInfo.channels !=g_bst->channels)||(g_AudioInfo.samplerate!=g_bst->samplerate))
	         {
	            adec_print("====Info Changed: src:sample:%d  channel:%d dest sample:%d  channel:%d \n",g_bst->samplerate,g_bst->channels,g_AudioInfo.samplerate,g_AudioInfo.channels);
				audec->format_changed_flag = 1;
				g_bst->channels=audec->channels=g_AudioInfo.channels;
				g_bst->samplerate=audec->samplerate=g_AudioInfo.samplerate;				
	         }
	      } 
            
		  if(exit_decode_thread)
    		  goto exit_decode_loop;
    	  
    	  outlen = AVCODEC_MAX_AUDIO_FRAME_SIZE;
		  adec_print("[TRACE]: start decoder!%s %d \n",__FUNCTION__,__LINE__);
    	  dlen=adec_ops->decode(audec->adec_ops, outbuf, &outlen,(void*)read_buffer,0);
		  adec_print("[TRACE]:g_bst->buf_length=%d g_bst->buf_level=%d outlen=%d %s %d \n",
		  	        g_bst->buf_length,g_bst->buf_level,outlen,__FUNCTION__,__LINE__);
    	  decode_offset+=dlen;
    	  pcm_cache_size=outlen;
    	  if(g_bst)
    	  {
              while(g_bst->buf_length-g_bst->buf_level<outlen){
            	  if(exit_decode_thread)
            		  goto exit_decode_loop;
            	  usleep(100000);
              }
              int wlen=0;
              while(outlen){
            	 wlen=write_pcm_buffer(outbuf, g_bst,outlen); 
            	 outlen-=wlen;
            	 pcm_cache_size-=wlen;
              }
    	  }
		  adec_print("[TRACE]: finish write pcm!%s %d \n",__FUNCTION__,__LINE__);
    }
    adec_print("Exit adec_DtsArmDec_loop Thread!");
    pthread_exit(NULL);
error:	
    pthread_exit(NULL);
    return NULL;
}
static void *adec_armdec_loop(void *args)
{
    int ret;
	int rlen = 0;
	int inlen = 0;
	int dlen = 0;
	int declen = 0;
    aml_audio_dec_t *audec;
    audio_out_operations_t *aout_ops;
    adec_cmd_t *msg = NULL;
	AVPacket apkt;
	char *inbuf = NULL;
	char apkt_end[APACKET_END_SIZE];
	char outbuf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
	int outlen = 0;
	AVCodecContext *ctxCodec = NULL;
	AVCodec *acodec = NULL;
	int in_ape_fp = -1;
	int out_ape_fp = -1;
	int audio_handle = -1;
	
	adec_print("adec_armdec_loop start!\n");

	audec = (aml_audio_dec_t *)args;
    aout_ops = &audec->aout_ops;
	av_init_packet(&apkt); 
	//memset(inbuf, 0, READ_ABUFFER_SIZE);
	memset(outbuf, 0, AVCODEC_MAX_AUDIO_FRAME_SIZE);

	//buffer_stream_t init and set adsp_ops param
	audec->bs=malloc(sizeof(buffer_stream_t));
	int ret_value=init_buff(audec->bs);
	if(ret_value==1)
		adec_print("=====pcm buffer init ok buf_size:%d buf_data:0x%x  end:0x%x !\n",audec->bs->buf_length,audec->bs->data,audec->bs->data+1024*1024);
	audec->adsp_ops.dsp_on=1;
	aout_ops->init(audec);
	aout_ops->start(audec);

	ctxCodec = avcodec_alloc_context();
	if(!ctxCodec) {
		adec_print("APE AVCodecContext allocate error!\n");
		ctxCodec = NULL;
	}
	adec_print("ctxCodec!\n");

	
	adec_print("adec_armdec_loop   audec->pcodec = %d, audec->pcodec->ctxCodec = %d!\n", audec->pcodec, audec->pcodec->ctxCodec);
		
	ctxCodec = audec->pcodec->ctxCodec;
	ctxCodec->codec_type = CODEC_TYPE_AUDIO;
		
	adec_print("open codec_id = %d--\n",ctxCodec->codec_id);
	acodec = avcodec_find_decoder(ctxCodec->codec_id);
	if (!acodec) {
		adec_print("acodec not found\n");
	}
	adec_print("open codec_id = %d----------------------------------\n",ctxCodec->codec_id);
		
	if (avcodec_open(ctxCodec, acodec) < 0) {
		adec_print("Could not open acodec = %d\n", acodec);
	}

	out_ape_fp = open("./dump/123.dat", O_CREAT | O_RDWR);
	if (out_ape_fp < 0) {
        adec_print("Create input file failed! fd=%d------------------------------\n", out_ape_fp);
    }
    adec_print("out_ape_fp = %d!", out_ape_fp);
	in_ape_fp = open("./dump/in.dat", O_CREAT | O_RDWR);
	if (in_ape_fp < 0) {
        adec_print("Create input file failed! fd=%d------------------------------\n", out_ape_fp);
    }
    adec_print("in_ape_fp = %d!", in_ape_fp);

	ret = uio_init();
	if (ret < 0){
		adec_print("uio init error! \n");
		goto error;
	}
		
    while (1){

		if (inlen > 0) {
			if (inbuf) {
				free(inbuf);
				inbuf = NULL;
			}
			inbuf = malloc(READ_ABUFFER_SIZE + inlen);
			memcpy(inbuf, apkt_end, inlen);
			rlen = read_buffer(inbuf+inlen, READ_ABUFFER_SIZE);
			rlen += inlen;
		}
		else {
			if (inbuf) {
				free(inbuf);
				inbuf = NULL;
			}
			inbuf = malloc(READ_ABUFFER_SIZE);
			rlen = read_buffer(inbuf+inlen, READ_ABUFFER_SIZE);
		}
		if (out_ape_fp >= 0) {
			write(in_ape_fp, inbuf, rlen);
			adec_print("write ape data in rlen = %d bytes\n",rlen);
		}
		declen = 0;
		if (rlen > 0){
			inlen = rlen;
			while (declen<rlen) {	
				outlen = AVCODEC_MAX_AUDIO_FRAME_SIZE;
				dlen = decode_audio(ctxCodec, outbuf, &outlen, inbuf+declen, inlen);
				if (dlen <= 0){
					adec_print("dlen = %d error----\n",dlen);
					if (inlen > 0) {
						adec_print("packet end %d bytes----\n",inlen);
						memcpy(apkt_end, (uint8_t *)(inbuf+declen), inlen);
					}
					break;
				}
				declen += dlen;
				inlen -= dlen;
				write_pcm_buffer(outbuf, audec->bs,outlen);
				//write_buffer(outbuf, outlen);
				if (outlen > 0) {
					if (out_ape_fp >= 0) {
						write(out_ape_fp, outbuf, outlen);
					}
				}
			} 
		
#if 0			
			outsize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
			apkt.data = inbuffer;
			apkt.size = rlen;
			while (apkt.size > 0){
				dlen = avcodec_decode_audio3(ctxCodec, (int16_t *)outbuffer, &outsize, &apkt);
				if (dlen <= 0){
					adec_print("dlen = %d error----\n",dlen);
				}
				if (outsize > 0) {
					if (out_ape_fp >= 0) {
						write(out_ape_fp, outbuffer, outsize);
						adec_print("write ape data%d bytes\n UUUUUUUU----\n",outsize);
					}
				}				
				declen += dlen;
				apkt.size -= dlen;					
				if (apkt.size > 0){
					apkt.data += dlen;
				}
				else if (apkt.size < 0){
					adec_print("wrong aptk.size = %d, declen = %d, dlen = %d!", apkt.size, declen, dlen);
				}					
			}
#endif			
		}
		else {			
			adec_print("rlen = %d", rlen);
			break;
		}
	}
    close(out_ape_fp);
    close(in_ape_fp);
	
    adec_print("Exit adec_armdec_loop Thread!");

error:	
    pthread_exit(NULL);
    return NULL;
}
void *audio_decode_loop(void *args)
{
    int ret;
    aml_audio_dec_t *audec;
    audio_out_operations_t *aout_ops;
    audio_decoder_operations_t *adec_ops;
    int nNextFrameSize=0;//next read frame size
    int inlen = 0;//real data size in in_buf
    int nRestLen=0;//left data after last decode 
    int nInBufferSize=0;//full buffer size
    //int nStartDecodePoint=0;//start decode point in in_buf
    char *inbuf = NULL;//real buffer
    int rlen = 0;//read buffer ret size
    char *pRestData=NULL;
    char *inbuf2;
    
    int dlen = 0;//decode size one time
    int declen = 0;//current decoded size
    int nCurrentReadCount=0;
    
    char startcode[5];	
    int extra_data = 8;
    int nCodecID;
    int nAudioFormat;
    char *outbuf=pcm_buf_tmp;
    int outlen = 0;
    	
    adec_print("adec_armdec_loop start!\n");
    audec = (aml_audio_dec_t *)args;
    aout_ops = &audec->aout_ops;
    adec_ops=audec->adec_ops;
    memset(outbuf, 0, AVCODEC_MAX_AUDIO_FRAME_SIZE);

    //nAudioFormat=audec->pcodec->audio_type;
    nAudioFormat=audec->format;
    inlen=0;
    //nNextFrameSize=READ_ABUFFER_SIZE;//default frame size
    nNextFrameSize=adec_ops->nInBufSize;    
    while (1){
exit_decode_loop:
          //detect quit condition
          if(exit_decode_thread)
	      {
        	        if (inbuf) 
        	        {
            	            free(inbuf);
            		     inbuf = NULL;
        		  }
        		  //if(pRestData)
        		  //{
        		  //  free(pRestData);
        		  //  pRestData=NULL;
        		  //}
        		  //adec_print("====exit decode thread\n");
        		  exit_decode_thread_success=1;
        		  break;
	      }
	      //detect audio info changed
	      memset(&g_AudioInfo,0,sizeof(AudioInfo));
	     adec_ops->getinfo(audec->adec_ops, &g_AudioInfo);
	      if(g_AudioInfo.channels!=0&&g_AudioInfo.samplerate!=0)
	      {
	        if((g_AudioInfo.channels !=g_bst->channels)||(g_AudioInfo.samplerate!=g_bst->samplerate))
	        {
	            adec_print("====Info Changed: src:sample:%d  channel:%d dest sample:%d  channel:%d \n",g_bst->samplerate,g_bst->channels,g_AudioInfo.samplerate,g_AudioInfo.channels);
				audec->format_changed_flag = 1;
				g_bst->channels=audec->channels=g_AudioInfo.channels;
				g_bst->samplerate=audec->samplerate=g_AudioInfo.samplerate;
				
#if 0
				if(aout_stop_mutex==0)
	            {
        	            aout_stop_mutex=1;
        	            //send Message
        	            //reset param
        	            
    	            	aout_ops->stop(audec);
						aout_ops->init(audec);
						aout_ops->start(audec);
        	            aout_stop_mutex=0;
	            }
#endif				
				
	        }
	      }
	      //step 2  get read buffer size
             struct package *p_Package;
             p_Package=package_get();
             if(!p_Package){
                usleep(1000);
                continue;
             }
             if (inbuf != NULL) {
        	    free(inbuf);
                  inbuf = NULL;
             }
             if(inlen&&pRestData)
    	      {
    	            rlen=p_Package->size+inlen;
    	            inbuf=malloc(rlen);
    	            memcpy(inbuf, pRestData, inlen);
    	            memcpy(inbuf+inlen,p_Package->data,p_Package->size);
    	            free(pRestData);
    	            free(p_Package->data);
    	      }
    	      else
    	      {
    	        rlen=p_Package->size;
    	        inbuf=p_Package->data;
    	        p_Package->data=NULL;
    	      }
    	       free(p_Package);
    	       nCurrentReadCount=rlen;
    	       inlen=rlen;
              declen  = 0;
              if (nCurrentReadCount > 0)
              {
    			  //inlen = rlen;
    			  //adec_print("declen=%d,rlen = %d--------------------------------------------------\n\n", declen,rlen);
    			  while (declen<rlen) {
				 if(exit_decode_thread)
    				  {
					 adec_print("exit decoder,-----------------------------\n");
    				        goto exit_decode_loop;
    				  }
    				  outlen = AVCODEC_MAX_AUDIO_FRAME_SIZE;
    				  //adec_print("decode_audio------------------------------------\n");
    				  //dlen = decode_audio(audec->pcodec->ctxCodec, outbuf, &outlen, inbuf+declen, inlen);
    				  dlen = adec_ops->decode(audec->adec_ops, outbuf, &outlen, inbuf+declen, inlen);
    				  //dlen = decodeAACfile(outbuf, &outlen, inbuf+declen, inlen);
    				  if (dlen <= 0)
    				  {
    				  	  //adec_print("dlen = %d error----\n",dlen);
    					  if (nAudioFormat==ACODEC_FMT_APE)
    					  {
    					        inlen=0;	  
    					  }
    					  else if(inlen>0)
    					  {
    					         // adec_print("packet end %d bytes----\n",inlen);
    						  //memcpy(apkt_end, (uint8_t *)(inbuf+declen), inlen);
    						  pRestData=malloc(inlen);
    						  if(pRestData)
    						    memcpy(pRestData, (uint8_t *)(inbuf+declen), inlen);
    					  }
    					  nDecodeErrCount++;//decode failed, add err_count
    					  break;
    				  }
    				  nDecodeErrCount=0;//decode success reset to 0
    				  declen += dlen;
    				  inlen -= dlen;
    				  //adec_print("after decode_audio rlen=%d,declen=%d,inlen=%d,dlen=%d,outlen=%d,-----------------------------\n",rlen,declen,inlen,dlen,outlen);

    				  //write to the pcm buffer
    				  decode_offset+=dlen;
    				  pcm_cache_size=outlen;
    				  if(g_bst)
    				  {
            				//while(g_bst->buf_level>=g_bst->buf_length*0.8)
            				while(g_bst->buf_length-g_bst->buf_level<outlen)
            				{
            				    if(exit_decode_thread)
            				    {
    						 adec_print("exit decoder,-----------------------------\n");
            				        goto exit_decode_loop;
            				        break;
            				    }
            				    usleep(100000);
            				}
            				int wlen=0;
            				while(outlen)
            				{
            				    wlen=write_pcm_buffer(outbuf, g_bst,outlen); 
            				    outlen-=wlen;
            				    pcm_cache_size-=wlen;
            				}
    				  }
    				//write end
    			  }
        	  }
              else
              {
                   //get data failed,maybe at the end
                   usleep(1000);
                   continue;
              }
	}
    
    adec_print("Exit adec_armdec_loop Thread!");
    pthread_exit(NULL);
error:	
    pthread_exit(NULL);
    return NULL;
}