/* 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; }