📄 video_dec_isr.c
字号:
/* all decode done */
if (g_video_dec_info_ptr->video_end == KAL_FALSE)
{
video_dbg_trace(MP4_DEC_HISR_LAST_ONE, video_get_current_time());
ASSERT(g_video_dec_info_ptr->video_dec_callback != NULL);
g_video_dec_info_ptr->video_end = KAL_TRUE;
#if defined(__VIDEO_EDITOR__)
if (g_video_dec_status.scenario == VIDEO_SCENARIO_EDITOR)
{
ASSERT(0);
}
else
#endif /*__VIDEO_EDITOR__*/
{
/* all decode done */
video_dec_complete();
}
}
return;
}
else if (g_video_dec_info_ptr->hdr_parse_frames_no == g_video_dec_info_ptr->total_frames_in_file)
{
/* all parse done */
return;
}
video_dbg_trace(MP4_DEC_HISR_ENTRY, video_get_current_time());
/* get next frame for parsing */
result = video_dec_get_next_frame(&frame_addr, &frame_length, &prev_frame_duration);
if (result != MEDIA_STATUS_OK)
{
/* Exception cases: Task can't prepare the enough buffer */
g_video_dec_info_ptr->skip_frames++;
Buffer_WRITE(BUFFER_MP4_FRAME_DURATION, prev_frame_duration);
g_video_dec_info_ptr->hdr_parse_frames_no++;
g_video_dec_info_ptr->lost_frames++;
return;
}
else
{
/* Skip frame only increment in previous HISR, shoule be clear to 0 before next time comes here */
if (g_video_dec_info_ptr->skip_frames)
EXT_ASSERT(0, g_video_dec_info_ptr->skip_frames, 0, 0);
}
if (prev_frame_duration == 0)
{
VIDEO_ASSERT(0);
mpeg4_dec_isr_error_report_hdlr();
return;
}
/* parse next frame */
result = mpeg4_decode_main((kal_uint8 *)frame_addr, frame_length, prev_frame_duration);
if (result != MEDIA_STATUS_OK)
{
/* This frame is non-coded */
VIDEO_ASSERT(0);
g_video_dec_info_ptr->is_non_coded = KAL_TRUE;
}
video_dbg_trace(MP4_DEC_HISR_END, video_get_current_time());
}
/* Decode lisr process function. Check interrupt status and do corresponding handling
* @param None
* @return None
*/
static void mpeg4_dec_lisr_process(void)
{
kal_uint32 status;
kal_uint32 lost_display;
video_dbg_trace(MP4_DEC_LISR_ENTRY, video_get_current_time());
#if ( defined(MT6219) || defined(MT6226) || defined(MT6227) || defined(MT6226M) )
IRQMask(IRQ_MPEG4_CODE);
#else /*MT6228, MT6229, MT6230*/
IRQMask(IRQ_MPEG4_DEC_CODE);
#endif /*MT6228, MT6229, MT6230*/
/* check state */
if (g_video_dec_info_ptr->dec_state != VIDEO_DEC_STATE_NORMAL)
{
VIDEO_ASSERT(0);
g_video_dec_info_ptr->isr_error_event_happen = KAL_TRUE;
g_video_dec_status.VIDEO_STATUS = VIDEO_DEC_FUNC_STATE_ERROR;
visual_active_hisr(VISUAL_MPEG4_DEC_HISR_ID);
return;
}
//Jensen's tricky
if ((g_video_dec_info_ptr->dec_frames_no == g_video_dec_info_ptr->total_frames_in_file)
|| (g_video_dec_info_ptr->dec_frames_no == g_video_dec_info_ptr->stop_frame_no))
{
VIDEO_ASSERT(0);
return;
}
/* check re-entry */
if(g_video_dec_isr_param.b_check_reentry != KAL_FALSE)
{
VIDEO_ASSERT(0);
g_video_dec_info_ptr->isr_error_event_happen = KAL_TRUE;
g_video_dec_status.VIDEO_STATUS = VIDEO_DEC_FATAL_ERROR;
visual_active_hisr(VISUAL_MPEG4_DEC_HISR_ID);
g_video_dec_isr_param.b_check_reentry = KAL_FALSE;
return;
}
g_video_dec_isr_param.b_check_reentry = KAL_TRUE;
/* skip frame != 0 means task can't prepare enough buffer, should stop decode and activate recover mechanism */
if ((g_video_dec_info_ptr->skip_frames == 0) && (g_video_dec_info_ptr->prepare_recover==KAL_FALSE))
{
/* Previous HISR has parsed frame successfully, decode it ! */
#if ( defined(MT6219) || defined(MT6226) || defined(MT6227) || defined(MT6226M) )
status = DRV_Reg32(MP4_IRQ_STS);
#else /* !(MT6219, MT6226, MT6227, MT6226M) */
status = DRV_Reg32(MP4_DEC_IRQ_STS);
#endif /* (MT6219, MT6226, MT6227, MT6226M) */
/* Skip check isr status happens when the previous decoded frame is on-coded.
so dose not really write register to decode it */
if (g_video_dec_info_ptr->skip_check_isr_status == KAL_FALSE)
{
#if ( defined(MT6219) || defined(MT6226) || defined(MT6227) || defined(MT6226M) )
if (status & MP4_IRQ_STS_DEC)
{
/* decode done */
g_video_dec_isr_param.speed_recover_count = 0;
DRV_WriteReg32(MP4_IRQ_ACK, MP4_IRQ_STS_DEC);
DRV_WriteReg32(MP4_VLC_COMD, MP4_VLC_COMD_STOP);
if (g_video_dec_info_ptr->play_speed > 100)
{
g_video_dec_info_ptr->decode_error_frame_count_in_high_speed = 0;
}
video_dec_display();
}
else if ((status == 0)
&& (((g_video_dec_info_ptr->play_speed % 100) != 0)
|| (g_video_dec_info_ptr->play_speed <= 100))
&& (g_video_dec_isr_param.speed_recover_count < 3))
{
/* Audio support time stretch in this case. error recover for this case */
VIDEO_ASSERT(0);
video_dbg_trace(MP4_MAY_ISR_ERROR, video_get_current_time());
g_video_dec_isr_param.speed_recover_count++;
g_video_dec_isr_param.b_check_exception = KAL_TRUE;
video_dec_set_frametime(video_dec_get_curr_frame_duration(), KAL_FALSE);
GPTI_StartItem(g_video_dec_isr_param.gpt_exception_protect_handle, 2, /*20ms*/
mpeg4_exception_handler, NULL);
g_video_dec_isr_param.b_check_reentry = KAL_FALSE;
IRQ_Register_LISR(IRQ_MPEG4_CODE, mpeg4_dec_recover_LISR, "MPEG4");
IRQSensitivity(IRQ_MPEG4_CODE, LEVEL_SENSITIVE);
IRQUnmask(IRQ_MPEG4_CODE);
return;
}
else
{
/* not decode done, something error */
video_dbg_trace(MP4_MAY_ISR_ERROR, video_get_current_time());
if (g_video_dec_info_ptr->play_speed > 100)
{
g_video_dec_info_ptr->decode_error_frame_count_in_high_speed++;
if (g_video_dec_info_ptr->decode_error_frame_count_in_high_speed
<= (g_video_dec_info_ptr->play_speed / 100))
{
/*Tricky for high speed*/
/* In this case, audio mute. No AV sync issue. So just set one more frame time to decode this frame */
/* It may decode done in next AV sync interrupt handler */
video_dec_set_frametime(video_dec_get_curr_frame_duration(), KAL_FALSE);
g_video_dec_isr_param.b_check_reentry = KAL_FALSE;
VIDEO_ASSERT(0);
return;
}
else
{
/* High speed, but decode too long (more than N frames). So reset it */
mpeg4_dec_reset();
VIDEO_ASSERT(0);
}
}
else
{
/* Normal/Slow speed can not decode more than one frame time */
mpeg4_dec_reset();
VIDEO_ASSERT(0);
}
DRV_WriteReg32(MP4_IRQ_ACK, status);
/* Use the current ref frame as the next ref frame, since the rec frame data is not correct*/
Buffer_WRITE(BUFFER_MP4_REC_ADDR, DRV_Reg32(MP4_REC_ADDR));
Buffer_WRITE(BUFFER_MP4_REF_ADDR, DRV_Reg32(MP4_REF_ADDR));
video_dec_prev_display();
}
#else /* !(MT6219, MT6226, MT6227, MT6226M) */
if (status & MP4_DEC_IRQ_STS_DEC)
{
/* decode done */
g_video_dec_isr_param.speed_recover_count = 0;
DRV_WriteReg32(MP4_DEC_IRQ_ACK, MP4_DEC_IRQ_STS_DEC);
DRV_WriteReg32(MP4_VLC_DMA_COMD, MP4_VLC_DMA_COMD_STOP);
if (g_video_dec_info_ptr->play_speed > 100)
{
g_video_dec_info_ptr->decode_error_frame_count_in_high_speed = 0;
}
video_dec_display();
}
else if (status & MP4_DEC_IRQ_STS_DMA)
{
if (g_video_dec_isr_param.check_vlc_addr == KAL_TRUE)
{
/* frame length is larger than 0xffff */
VIDEO_ASSERT(0);
/* Reload VLC DMA */
DRV_WriteReg32(MP4_CORE_VLC_LIMIT, 0xffff);
DRV_WriteReg32(MP4_CORE_VLC_ADDR, (g_video_dec_isr_param.vlc_addr + 0xffff));
g_video_dec_isr_param.vlc_addr = (g_video_dec_isr_param.vlc_addr + 0xffff);
DRV_WriteReg32(MP4_VLC_DMA_COMD, MP4_VLC_DMA_COMD_RELOAD);
/* Start error check mechanism */
g_video_dec_isr_param.b_check_exception = KAL_TRUE;
video_dec_set_frametime(video_dec_get_curr_frame_duration(), KAL_FALSE);
GPTI_StartItem(g_video_dec_isr_param.gpt_exception_protect_handle, 3, /*20~30ms*/
mpeg4_exception_handler, NULL);
g_video_dec_isr_param.b_check_reentry = KAL_FALSE;
IRQ_Register_LISR(IRQ_MPEG4_DEC_CODE, mpeg4_dec_recover_LISR, "MPEG4");
IRQSensitivity(IRQ_MPEG4_DEC_CODE, LEVEL_SENSITIVE);
IRQUnmask(IRQ_MPEG4_DEC_CODE);
return;
}
else
{
EXT_ASSERT(0, g_video_dec_info_ptr->dec_frames_no, g_video_dec_info_ptr->total_frames_in_file,
g_video_dec_info_ptr->hdr_parse_frames_no);
}
}
else if ((status == 0)
&& (((g_video_dec_info_ptr->play_speed % 100) != 0)
|| (g_video_dec_info_ptr->play_speed <= 100))
&& (g_video_dec_isr_param.speed_recover_count < 3))
{
/* Audio support time stretch in this case. error recover for this case */
VIDEO_ASSERT(0);
video_dbg_trace(MP4_MAY_ISR_ERROR, video_get_current_time());
g_video_dec_isr_param.speed_recover_count++;
g_video_dec_isr_param.b_check_exception = KAL_TRUE;
video_dec_set_frametime(video_dec_get_curr_frame_duration(), KAL_FALSE);
GPTI_StartItem(g_video_dec_isr_param.gpt_exception_protect_handle, 2, /*20ms*/
mpeg4_exception_handler, NULL);
g_video_dec_isr_param.b_check_reentry = KAL_FALSE;
IRQ_Register_LISR(IRQ_MPEG4_DEC_CODE, mpeg4_dec_recover_LISR, "MPEG4");
IRQSensitivity(IRQ_MPEG4_DEC_CODE, LEVEL_SENSITIVE);
IRQUnmask(IRQ_MPEG4_DEC_CODE);
return;
}
else
{
video_dbg_trace(MP4_MAY_ISR_ERROR, video_get_current_time());
if (g_video_dec_info_ptr->play_speed > 100)
{
/* Audio mute in this case */
g_video_dec_info_ptr->decode_error_frame_count_in_high_speed++;
if (g_video_dec_info_ptr->decode_error_frame_count_in_high_speed
<= (g_video_dec_info_ptr->play_speed / 100))
{
/* Tricky for high speed */
/* In this case, audio mute. No AV sync issue. So just set one more frame time to decode this frame */
/* It may decode done in next AV sync interrupt handler */
video_dec_set_frametime(video_dec_get_curr_frame_duration(), KAL_FALSE);
g_video_dec_isr_param.b_check_reentry = KAL_FALSE;
VIDEO_ASSERT(0);
return;
}
else
{
/* High speed, but decode too long (more than N frames). So reset it */
mpeg4_dec_reset();
mpeg4_core_reset();
VIDEO_ASSERT(0);
}
}
else
{
/* Normal/Slow speed can not decode more than one frame time */
mpeg4_dec_reset();
mpeg4_core_reset();
VIDEO_ASSERT(0);
}
DRV_WriteReg32(MP4_DEC_IRQ_ACK, status);
{
/* Use the current ref frame as the next ref frame, since the rec frame data is not correct*/
MPEG4_FRAME_BUFFER_ADDR frame_buffer_addr;
mpeg4_dec_sort_frame_buffer(DRV_Reg32(MP4_DEC_REC_ADDR), &frame_buffer_addr);
Buffer_WRITE(BUFFER_MP4_REC_ADDR, frame_buffer_addr.rec_addr);
Buffer_WRITE(BUFFER_MP4_REF_ADDR, frame_buffer_addr.ref_addr);
Buffer_WRITE(BUFFER_MP4_DEBLOCK_ADDR, frame_buffer_addr.deblock_addr);
}
video_dec_prev_display();
}
#endif /* (MT6219, MT6226, MT6227, MT6226M) */
}
else /* !if (g_video_dec_info_ptr->skip_check_isr_status == KAL_FALSE) */
{
/* Skip check isr status happens when the previous decoded frame is on-coded.
so dose not really write register to decode it */
#if ( defined(MT6219) || defined(MT6226) || defined(MT6227) || defined(MT6226M) )
DRV_WriteReg32(MP4_IRQ_ACK, status);
#else /* !(MT6219, MT6226, MT6227, MT6226M) */
DRV_WriteReg32(MP4_DEC_IRQ_ACK, status);
#endif /* (MT6219, MT6226, MT6227, MT6226M) */
g_video_dec_info_ptr->skip_check_isr_status = KAL_FALSE;
video_dec_display();
}
g_video_dec_info_ptr->dec_frames_no++;
if(g_video_dec_info_ptr->pre_frame_duration==0)
VIDEO_ASSERT(0);
/* update play time, upper layer may use this as play time */
g_video_dec_info_ptr->play_time += g_video_dec_info_ptr->pre_frame_duration;
/* set next frame time */
video_dec_set_frametime(video_dec_get_curr_frame_duration(), KAL_FALSE);
g_video_dec_info_ptr->pre_frame_duration = video_dec_get_curr_frame_duration();
/* decode next frame when needed */
if (g_video_dec_info_ptr->dec_frames_no < g_video_dec_info_ptr->total_frames_in_file)
{
if ((g_video_dec_info_ptr->stop_frame_no != g_video_dec_info_ptr->total_frames_in_file)
&& (g_video_dec_info_ptr->dec_frames_no == g_video_dec_info_ptr->stop_frame_no))
{
g_video_dec_info_ptr->isr_error_event_happen = KAL_TRUE;
g_video_dec_status.VIDEO_STATUS = VIDEO_DEC_FATAL_ERROR;
}
else
{
mpeg4_decode_write_register();
}
}
}
else /*if (g_video_dec_info_ptr->skip_frames == 0)*/
{
/* Exception cases: Task can't prepare the enough buffer */
if (g_video_dec_info_ptr->play_speed >= 200)
{
lost_display = g_video_dec_info_ptr->disp_lost_frames;
video_dec_display();
if(lost_display!=g_video_dec_info_ptr->disp_lost_frames)
{
// fail display
g_video_dec_info_ptr->prepare_recover = KAL_TRUE;
video_dec_set_frametime(video_dec_get_curr_frame_duration(), KAL_FALSE);
g_video_dec_isr_param.b_check_reentry = KAL_FALSE;
return;
}
}
g_video_dec_info_ptr->dec_frames_no++;
g_video_dec_info_ptr->prepare_recover = KAL_FALSE;
g_video_dec_info_ptr->recover_start = KAL_TRUE;
g_video_dec_info_ptr->recover_start_frame = g_video_dec_info_ptr->dec_frames_no;
video_dec_disable_irq();
video_dec_start_refresh();
// Rey's A2V
//video_dec_stop_av();
}
visual_active_hisr(VISUAL_MPEG4_DEC_HISR_ID);
g_video_dec_isr_param.b_check_reentry = KAL_FALSE;
video_dbg_trace(MP4_DEC_LISR_END, video_get_current_time());
}
/* Decode error recover LISR function. Act in MPEG4 LISR context
* It is used when decode can not be done in normal AV sync LISR
* @param None
* @return None
*/
static void mpeg4_dec_recover_LISR(void) /*Mpeg4 ISR*/
{
#ifdef __VIDEO_EDITOR__
if (g_video_dec_status.scenario == VIDEO_SCENARIO_EDITOR)
{
ASSERT(0);
}
else
#endif /*__VIDEO_EDITOR__*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -