Ejemplo n.º 1
0
/* put packet into reorder buffer, sequence is the packet's sequnce number */
void video_rtp_reorder_put_pkt(kal_uint8 *data, kal_uint32 size, kal_uint32 sequence)
{
    kal_uint32 index;
    kal_uint32 match_index;
    kal_uint8 *p_buffer = NULL;

    /* free previous got buffer memory */
    if(g_video_rtp_reorder_buff_info.p_free_addr !=NULL)
    {
        kal_adm_free(g_video_rtp_reorder_buff_info.adm_id, g_video_rtp_reorder_buff_info.p_free_addr);
        g_video_rtp_reorder_buff_info.p_free_addr = NULL;
    }

    if(g_video_rtp_reorder_buff_info.total_pkt >= VIDEO_RTP_MAX_REORDER_NUM)
    {
#ifdef STREAM_REORDER_BUFFER_DBG_TRACE
	    video_dbg_trace(STREAM_REORDER_BUFFER_DROP_SEQ, sequence);
#endif
        /* re-order buffer is full, drop the packet */
        VIDEO_ASSERT(0);
        return;
    }

    p_buffer = kal_adm_internal_alloc(g_video_rtp_reorder_buff_info.adm_id, size, __FILE__, __LINE__);
    if(p_buffer==NULL)
    {
#ifdef STREAM_REORDER_BUFFER_DBG_TRACE
    	video_dbg_trace(STREAM_REORDER_BUFFER_DROP_SEQ, sequence);
#endif
        /* re-order buffer is full, drop the packet */
        VIDEO_ASSERT(0);
        g_video_rtp_reorder_buff_info.b_buffer_full = KAL_TRUE;
        return;
    }

    /* search for the matched sequnce index*/
    for(index=0; index<g_video_rtp_reorder_buff_info.total_pkt; index++)
    {
        if(g_video_rtp_reorder_buff_info.sequence[index] > sequence)
        {
            break;
        }
    }

    /* shift the items that has larger sequnce than the input item */
    match_index = index;
    for(index = 0; index < (g_video_rtp_reorder_buff_info.total_pkt-match_index); index++)
    {
        g_video_rtp_reorder_buff_info.sequence[g_video_rtp_reorder_buff_info.total_pkt - index] = g_video_rtp_reorder_buff_info.sequence[g_video_rtp_reorder_buff_info.total_pkt - index - 1];
        g_video_rtp_reorder_buff_info.start_addr[g_video_rtp_reorder_buff_info.total_pkt - index] = g_video_rtp_reorder_buff_info.start_addr[g_video_rtp_reorder_buff_info.total_pkt - index - 1];
        g_video_rtp_reorder_buff_info.buffer_size[g_video_rtp_reorder_buff_info.total_pkt - index] = g_video_rtp_reorder_buff_info.buffer_size[g_video_rtp_reorder_buff_info.total_pkt - index - 1];
    }

    /* add the input  packet */
    g_video_rtp_reorder_buff_info.sequence[match_index] = sequence;
    g_video_rtp_reorder_buff_info.start_addr[match_index] = (kal_uint32)p_buffer;
    g_video_rtp_reorder_buff_info.buffer_size[match_index] = size;
    kal_mem_cpy(p_buffer, data, size);
    g_video_rtp_reorder_buff_info.total_pkt++;
}
void MPEG4HWHwResourceFree(VIDEO_MPEG4HW_USER_T eMPEG4HWUser)
{
    kal_uint32 savedMask;

    video_dbg_trace(VIDEO_DBG_OWNER_ENCODER, VIDEO_DBG_MPEG4HW_RESOURCE_FREE, video_get_current_time());
    video_dbg_trace(VIDEO_DBG_OWNER_ENCODER, VIDEO_DBG_MPEG4HW_RESOURCE_FREE, _eMPEG4HWUser);
    drv_trace1(TRACE_GROUP_10, MPEG4HW_RESOURCE_FREE, eMPEG4HWUser);

    ASSERT(_eMPEG4HWUser == eMPEG4HWUser);

    savedMask = SaveAndSetIRQMask();
    _eMPEG4HWUser = VIDEO_MPEG4HW_NONE;
    RestoreIRQMask(savedMask);
}
kal_bool MPEG4HWHwResourceFreeIfOccupy(VIDEO_MPEG4HW_USER_T eMPEG4HWUser)
{
    kal_bool fgResult = KAL_FALSE;
    kal_uint32 savedMask;

    if(_eMPEG4HWUser != eMPEG4HWUser)
        return fgResult;

    video_dbg_trace(VIDEO_DBG_OWNER_ENCODER, VIDEO_DBG_MPEG4HW_RESOURCE_FREE, video_get_current_time());
    video_dbg_trace(VIDEO_DBG_OWNER_ENCODER, VIDEO_DBG_MPEG4HW_RESOURCE_FREE, _eMPEG4HWUser);
    drv_trace1(TRACE_GROUP_10, MPEG4HW_RESOURCE_FREE, eMPEG4HWUser);

    ASSERT(_eMPEG4HWUser == eMPEG4HWUser);

    savedMask = SaveAndSetIRQMask();
    _eMPEG4HWUser = VIDEO_MPEG4HW_NONE;
    RestoreIRQMask(savedMask);
    fgResult = KAL_TRUE;
    return fgResult;
}
kal_bool MPEG4HWHwResourceGet(VIDEO_MPEG4HW_USER_T eMPEG4HWUser)
{
    kal_bool   fgResult;
    kal_uint32 savedMask;

    video_dbg_trace(VIDEO_DBG_OWNER_ENCODER, VIDEO_DBG_MPEG4HW_RESOURCE_GET, video_get_current_time());
    video_dbg_trace(VIDEO_DBG_OWNER_ENCODER, VIDEO_DBG_MPEG4HW_RESOURCE_GET, eMPEG4HWUser);
    drv_trace1(TRACE_GROUP_10, MPEG4HW_RESOURCE_GET, eMPEG4HWUser);

    savedMask = SaveAndSetIRQMask();
    if (!_eMPEG4HWUser)
    {
        _eMPEG4HWUser = eMPEG4HWUser;
        fgResult = KAL_TRUE;
    }
    else
    {
        fgResult = KAL_FALSE;
    }
    RestoreIRQMask(savedMask);
    return fgResult;
}
VIDEO_ENCODER_CODEC_ERROR_T MPEG4HWEncEncodeOneUnit(VIDEO_BUFFERHEADER_TYPE_T *prBufferHeader)
{
    VIDEO_ENCODER_CODEC_ERROR_T eRet = VIDEO_ENCODER_CODEC_ERROR_NONE;
//    kal_uint8* pu1Buffer;
    kal_uint8* pu1StartAddr;
    kal_uint8* pu1EndAddr;
    kal_uint8* pu1WritePtr;
    kal_uint8* pu1ReadAddr;
    kal_uint8* pu1NextWritePtr;
    kal_uint32 u4AvailLen, u4BuffLen;
    kal_uint32 u4NextAvailLen;
    kal_uint8* pu1Addr;

    ASSERT(rpMPEG4HWEncDriver);

    if(prBufferHeader)
        video_dbg_trace(VIDEO_DBG_OWNER_ENCODER, VIDEO_DBG_HWENCV2_ENCODEONEUNIT, (kal_uint32) prBufferHeader->pu1Buffer);

    if(!prBufferHeader && !rMPEG4HWEncCtrl.pu1YUV)
        return VIDEO_ENCODER_CODEC_ERROR_NONE;

    if(!mpeg4_encore_check_encoder_status() ||
       !mepg4_encore_check_bits_buffer_status())
    {
        //return VIDEO_ENCODER_CODEC_PAUSE_ENCODE; //hw in use
        ASSERT(0);
    }

    VideoEncoderAllocateBitstreamBuffer(&pu1StartAddr, &pu1EndAddr, &pu1WritePtr, &pu1ReadAddr, &u4BuffLen);
    ASSERT(KAL_FALSE == VideoCommIsExtBufferCacheable((kal_uint32)pu1StartAddr, ROUND_UP_TO_POWER_OF_TWO(u4BuffLen,CPU_CACHE_LINE_SIZE)));

    if ((kal_uint32)pu1ReadAddr <= (kal_uint32)pu1WritePtr)
    {
        u4AvailLen = (kal_uint32)pu1EndAddr - (kal_uint32)pu1WritePtr;
        pu1Addr = pu1EndAddr;
#if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif
    }
    else  // (u4WP < u4RP)
    {
        u4AvailLen = (kal_uint32)pu1ReadAddr - (kal_uint32)pu1WritePtr;
        pu1Addr = pu1ReadAddr;
    }
    VideoEncoderQueryBitstreamNewWP((pu1WritePtr+u4AvailLen), &pu1NextWritePtr, &u4NextAvailLen);

    if( (rMPEG4HWEncCtrl.eScenario == VIDEO_ENCODER_SCENARIO_VT && u4AvailLen <ENC_MIN_BUF_SIZE_VT) ||
        (rMPEG4HWEncCtrl.eScenario == VIDEO_ENCODER_SCENARIO_ENCODER && u4AvailLen < ENC_MAX_VOP_SIZE) )
    {
        // next free buffer is not continuous
        if (pu1NextWritePtr != pu1WritePtr+1)
        {
            VideoEncoderUpdateBitstreamWP((pu1WritePtr+u4AvailLen), 0);
        }

        VideoEncoderAllocateBitstreamBuffer(&pu1StartAddr, &pu1EndAddr, &pu1WritePtr, &pu1ReadAddr, &u4BuffLen);
        if ((kal_uint32)pu1ReadAddr <= (kal_uint32)pu1WritePtr)
        {
            u4AvailLen = (kal_uint32)pu1EndAddr - (kal_uint32)pu1WritePtr;
            pu1Addr = pu1EndAddr;
        }
        else  // (u4WP < u4RP)
        {
            u4AvailLen = (kal_uint32)pu1ReadAddr - (kal_uint32)pu1WritePtr;
            pu1Addr = pu1ReadAddr;
        }

       if( (rMPEG4HWEncCtrl.eScenario == VIDEO_ENCODER_SCENARIO_VT && u4AvailLen <ENC_MIN_BUF_SIZE_VT) ||
           (rMPEG4HWEncCtrl.eScenario == VIDEO_ENCODER_SCENARIO_ENCODER && u4AvailLen < ENC_MAX_VOP_SIZE) )
       {
            MPEG4EncCallbackEncPause(pu1StartAddr);
            drv_trace1(TRACE_GROUP_10, MPEG4HWENC_ENCODE_BUF_NOT_ENOUGH, u4AvailLen);
            return VIDEO_ENCODER_CODEC_BS_BUFFER_NOT_ENOUGH;
       }
    }

    rMPEG4HWEncCtrl.pu1Buffer = prBufferHeader->pu1Buffer;
    rMPEG4HWEncCtrl.u8TimeStamp = prBufferHeader->u8TimeStamp;
    rMPEG4HWEncCtrl.pu1YUV = 0;

    drv_trace2(TRACE_GROUP_10, MPEG4HWENC_ENCODE, (kal_uint32)(rMPEG4HWEncCtrl.pu1Buffer), rMPEG4HWEncCtrl.u8TimeStamp);

    rpMPEG4HWEncDriver->encode( rMPEG4HWEncCtrl.pu1Buffer, rMPEG4HWEncCtrl.u8TimeStamp, pu1WritePtr, pu1Addr);

    return eRet;
}
H264_DPB_entry* open_api_h264_get_next_parse_dpb(kal_uint32 *p_frame_addr, kal_uint32 *p_frame_length)
{
    H264_dpb_frame_entry *p_dpb_entry = g_open_api_h264_dpb_frame_info.p_next_parse;
    H264_DPB_entry *p_free_dpb;
    kal_uint32 i;
    H264_DPB_entry *p_DPB = NULL, *dpbe;

    if(p_dpb_entry == NULL)
    {
    	video_dbg_trace(H264_DEC_ASSERT,__LINE__);
    	EXT_ASSERT(0, g_open_api_h264_dpb_frame_info.max_queue_num, (kal_uint32)g_open_api_h264_dpb_frame_info.p_start, (kal_uint32)g_open_api_h264_dpb_frame_info.p_end);
        return NULL;
    }
    
    // get empty dpb and assign to it
    p_free_dpb = open_api_h264_get_empty_dpb();
    if(p_free_dpb == NULL)
    {
        // If we can't get any empty DPB
        // This is an error case
        // The decoder will mark all frame as unused for reference in DPB list.
        //
        dpbe = g_open_api_h264_DPB_list.dpbe;
		for (i=0; i < (g_open_api_h264_dec_info_ptr->dec_param.max_DPB_number+1);  i++)// find the one with smallest POC
		{
			p_DPB = dpbe++;
			p_DPB->status_marked = H264_unused_ref;
		}
        g_open_api_h264_dec_info_ptr->dec_param.ref_pic_list0.num_STR_used = 0;
        g_open_api_h264_dec_info_ptr->dec_param.ref_pic_list0.num_LTR_used = 0;

        // Try to get one empty DPB again
        //
        p_free_dpb = open_api_h264_get_empty_dpb();

        if (p_free_dpb == NULL)
        {
            ASSERT(0);
            return NULL;
        }
    }

    // frame information and time information
    *p_frame_addr = p_dpb_entry->addr;
    *p_frame_length = p_dpb_entry->length;
    g_open_api_h264_dpb_frame_info.p_next_parse = p_dpb_entry->p_next_dpb;

    // get empty dpb and assign to it
    p_dpb_entry->p_dpb = p_free_dpb;
    p_free_dpb ->frame_no = p_dpb_entry->frame_no;
    p_free_dpb->isOutputed = 0;		// refer to store_a_pic_into_DPB
    p_free_dpb->status_marked = -1;
    if(p_dpb_entry->p_dpb == NULL)
    {
    	video_dbg_trace(H264_DEC_ASSERT,__LINE__);
    	EXT_ASSERT(0, 0, 0, 0);
    }
    p_dpb_entry->p_dpb->index_to_list = p_dpb_entry->index;
    p_dpb_entry->index_to_entry = p_dpb_entry->p_dpb->index;

    return p_dpb_entry->p_dpb;
}
H264_DPB_entry* open_api_h264_get_empty_dpb(void)
{
    kal_uint32 index, i, Ind;
    kal_int32 minPOC;
    H264_DPB_entry *p_DPB = NULL, *dpbe;

    /*Scott, Check if there is any free dpb be marked as un-used for ref. in the ref marking process */
    open_api_h264_check_free_dpb();

    // check fullness
    if (g_open_api_h264_DPB_list.num_used == (g_open_api_h264_dec_info_ptr->dec_param.max_DPB_number+1))
    {
        //Needs to do bumping process here!!
        // Find the removable entry with minimal POC
        minPOC = (kal_int32)maxINT;
        Ind = 0;
        dpbe = g_open_api_h264_DPB_list.dpbe;
        for (i=0; i < (g_open_api_h264_dec_info_ptr->dec_param.max_DPB_number+1);  i++)// find the one with smallest POC
        {
            p_DPB = dpbe++;
            if ( (p_DPB->isOutputed == 1) && (p_DPB->status_marked == H264_unused_ref) )
            {
                if (p_DPB->POC < minPOC)
                {
                    minPOC = p_DPB->POC;
					Ind = i;
				}
			}
		}
		if (minPOC != maxINT)
		{
			p_DPB = &g_open_api_h264_DPB_list.dpbe[Ind];
			//clear_rpe_by_ind(dpbe->statusMarked, Ind);
			open_api_h264_free_dpb(p_DPB);
			g_open_api_h264_DPB_list.num_used--;
			//return p_DPB;		// Move to the final
			goto GET_EMPTY_END;
		}

        // In the non-display-ordering mode, if goes here there must be something wrong...
        //
        if (fgDisplayOrderMode == KAL_FALSE)
        {
            //ASSERT(0);
            return NULL;
        }

		// Find non-outputed one with smallest POC and do bumping process.
		while (1)
		{
			minPOC = get_ind_dpbe_with_smallest_poc(&Ind);
			if (minPOC == maxINT)
			{
				video_dbg_trace(H264_DEC_FIND_SMALLEST_POC_FAIL, 0);
				dbg_print("[DRV H264]get_ind_dpbe_with_smallest_poc fails\n\r");
				return NULL;
			}

			p_DPB = &g_open_api_h264_DPB_list.dpbe[Ind];
			if (p_DPB->isOutputed == 0) 
			{
				p_DPB->isOutputed = 1;
				if (output_a_pic_normal(p_DPB) != 1)
				{
					video_dbg_trace(H264_DEC_OUTPUT_PIC_FAIL, p_DPB->frame_no);
					dbg_print("[DRV H264]output_a_pic_normal() fails, frames_no = %d\n\r", p_DPB->frame_no);
					return NULL;
				}
			}

			video_dbg_trace(H264_DEC_BUMPING_PROCESS, p_DPB->frame_no);
			dbg_print("[DRV H264]open_api_h264_get_empty_dpb() DPB Full, Bumping process remove frame: %d\n\r", p_DPB->frame_no);
			if (p_DPB->status_marked == H264_unused_ref)
			{
				open_api_h264_free_dpb(p_DPB);
				g_open_api_h264_DPB_list.num_used--;
				//return p_DPB;		// Move to the final
				break;
			}
		}
	}

	GET_EMPTY_END: 
	for (index=0; index < (g_open_api_h264_dec_info_ptr->dec_param.max_DPB_number+1); index++)
	{
		if (g_open_api_h264_DPB_list.dpbe[index].b_used == KAL_FALSE)
		{
			g_open_api_h264_DPB_list.dpbe[index].b_used = KAL_TRUE;
			p_DPB = &g_open_api_h264_DPB_list.dpbe[index];
			g_open_api_h264_DPB_list.num_used++;
			break;
		}
	}

	return p_DPB;
}
/* Free dpb entry from list
 * @param p_DPB the dpb which will be removed and set as un-used from the list
 * @return None
 */
void open_api_h264_check_free_dpb(void)
{
    H264_DPB_entry *p_free_DPB;
    kal_uint32 index;
    
    /* Check previous wait_for_free list first. If any displayed frame is unused for reference, discard it!!*/
    if(g_open_api_h264_DPB_list.wait_for_free !=0)
    {
        for(index = 0; index < (g_open_api_h264_dec_info_ptr->dec_param.max_DPB_number+1); index++)
        {
            if((g_open_api_h264_DPB_list.wait_for_free & (1<<index)) != 0)
            {
                p_free_DPB = &g_open_api_h264_DPB_list.dpbe[index];
                if(p_free_DPB->status_marked == H264_unused_ref/* ||
                   open_api_h264_get_dpb_frame_number(p_free_DPB)>g_open_api_h264_dec_info_ptr->dec_frames_no*/)
                {
                   if( p_free_DPB->status_marked != H264_unused_ref)
                   {
                   	video_dbg_trace(H264_DEC_ASSERT,__LINE__);
                   	ASSERT(0);
                   }

                  	video_dbg_trace(H264_DEC_FREE_DPB,open_api_h264_get_dpb_frame_number(p_free_DPB));
                    p_free_DPB->b_used = KAL_FALSE;
                    p_free_DPB->b_dec_done=KAL_FALSE;
                    g_open_api_h264_DPB_list.num_used--;
                    g_open_api_h264_DPB_list.wait_for_free &= (~(1<<index)); //Discard!!
                    
                }
            }
        }
    }
    
    /*Scott,If DPB is full, search for corrupted frame and discard it.*/
    if(g_open_api_h264_DPB_list.num_used == (g_open_api_h264_dec_info_ptr->dec_param.max_DPB_number+1))
    {
         if(g_open_api_h264_DPB_list.wait_for_free !=0)
         {
           for(index = 0; index < (g_open_api_h264_dec_info_ptr->dec_param.max_DPB_number+1); index++)
           {
               if((g_open_api_h264_DPB_list.wait_for_free & (1<<index)) != 0)
               {
                   p_free_DPB = &g_open_api_h264_DPB_list.dpbe[index];
                   if(p_free_DPB->is_corrupted == KAL_TRUE)
                   {
                   	   video_dbg_trace(H264_DEC_FREE_CORRUPTED_DPB,p_free_DPB->frame_no);
                       p_free_DPB->b_used = KAL_FALSE;
                       p_free_DPB->b_dec_done=KAL_FALSE;
                       g_open_api_h264_DPB_list.num_used--;
                       g_open_api_h264_DPB_list.wait_for_free &= (~(1<<index)); //Discard!!
                   }
               }
           }
         }     
    }    

   /*Scott, something wrong with this condition. Free the displayed unref frame*/
   if(g_open_api_h264_dpb_frame_info.p_prev_display != NULL)
   {
         for(index = 0; index < (g_open_api_h264_dec_info_ptr->dec_param.max_DPB_number+1); index++)
         {
               p_free_DPB = &g_open_api_h264_DPB_list.dpbe[index];
               if(p_free_DPB->b_used == KAL_TRUE &&
                  /*g_open_api_h264_dpb_frame_info.frame_list[p_free_DPB->index_to_list].time < g_open_api_h264_dpb_frame_info.frame_list[g_open_api_h264_dpb_frame_info.p_prev_display->index_to_list].time && */
                  p_free_DPB->status_marked == H264_unused_ref)
               {
                   /* We can't do this due to allegro error bit stream. PS. MAUI_00981880 */
                  #if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
                  #else
                    g_open_api_h264_dec_info_ptr->is_error_occur = KAL_TRUE;
                  #endif
                }
        }    
   }  

   video_dbg_trace(H264_DEC_DPB_WAIT_FREE_LIST,g_open_api_h264_DPB_list.wait_for_free);
}
kal_bool open_api_h264_add_dpb_info(kal_uint32 frame_addr, kal_uint32 frame_length)
{
    kal_uint32 index;
    kal_bool b_found = KAL_FALSE;
    H264_dpb_frame_entry *p_frame_entry = g_open_api_h264_dpb_frame_info.frame_list;

    dbg_print("[DRV H264]open_api_h264_add_dpb_info(), frame_no:%d\n\r", g_open_api_h264_dec_info_ptr->hdr_add_frames_no);
    video_dbg_trace(H264_DEC_ADD_FRAME, g_open_api_h264_dec_info_ptr->hdr_add_frames_no);

    //Pre Check If the frame_no is exists
    for(index = 0; index < (g_open_api_h264_dpb_frame_info.max_queue_num*2); index++)
    {
        if((p_frame_entry->b_used == KAL_TRUE) && 
           (p_frame_entry->frame_no==g_open_api_h264_dec_info_ptr->hdr_add_frames_no))
        {
            //if previous decode fail is due to dpb full 
            video_dbg_trace(H264_DEC_ADD_EXIST_FRAME,g_open_api_h264_dec_info_ptr->hdr_add_frames_no);
            dbg_print("[DRV H264]open_api_h264_add_dpb_info(), frame_no:%d\n\r", g_open_api_h264_dec_info_ptr->hdr_add_frames_no);
            b_found = KAL_TRUE;
            if(p_frame_entry->p_dpb != 0)
            {
            	video_dbg_trace(H264_DEC_ASSERT,__LINE__);
             VIDEO_ASSERT(0);
            }
             
            p_frame_entry->addr = frame_addr;
            p_frame_entry->length = frame_length;
            
            if(g_open_api_h264_dpb_frame_info.p_next_parse == NULL)
               g_open_api_h264_dpb_frame_info.p_next_parse = p_frame_entry;
            
            return KAL_TRUE;
        }
        
        p_frame_entry++;      
    }
    
    p_frame_entry = g_open_api_h264_dpb_frame_info.frame_list;
    // find empty slot from list
    for(index = 0; index < (g_open_api_h264_dpb_frame_info.max_queue_num*2); index++)
    {
        if(p_frame_entry->b_used == KAL_FALSE)
        {
            b_found = KAL_TRUE;
            break;
        }
        p_frame_entry++;
    }

   
    //if(b_found == KAL_FALSE)
        //EXT_ASSERT(0, g_open_api_h264_dpb_frame_info.max_queue_num, 0, 0);
    
    if(b_found == KAL_FALSE)
    {
    	video_dbg_trace(H264_DEC_DPB_FRAME_ENTRY_FULL,video_get_current_time());
    	dbg_print("[DRV H264]open_api_h264_add_dpb_info()\n\r");
    	return KAL_FALSE;  
    }

    // store the information into the found slot
    p_frame_entry->addr = frame_addr;
    p_frame_entry->length = frame_length;
    p_frame_entry->frame_no=g_open_api_h264_dec_info_ptr->hdr_add_frames_no;
    //p_frame_entry->b_dec_done = KAL_FALSE;
    p_frame_entry->b_used = KAL_TRUE;
    p_frame_entry->p_next_dpb = NULL;
    p_frame_entry->p_prev_dpb = NULL;
    p_frame_entry->p_dpb = NULL;


    //reconstruct the list
    if(g_open_api_h264_dpb_frame_info.p_start == NULL)
    {
        g_open_api_h264_dpb_frame_info.p_start = p_frame_entry;	
        g_open_api_h264_dpb_frame_info.p_end = p_frame_entry;
        g_open_api_h264_dpb_frame_info.p_next_parse = p_frame_entry;
    }
    else
    {
        g_open_api_h264_dpb_frame_info.p_end->p_next_dpb = p_frame_entry;
        p_frame_entry->p_prev_dpb = g_open_api_h264_dpb_frame_info.p_end;
        g_open_api_h264_dpb_frame_info.p_end = p_frame_entry;
        if(g_open_api_h264_dpb_frame_info.p_next_parse == NULL)
            g_open_api_h264_dpb_frame_info.p_next_parse = p_frame_entry;
    }

    return KAL_TRUE;
}