📄 video_dec_api.c
字号:
(g_video_dec_info_ptr->seek_next_frame_time - g_video_dec_info_ptr->seek_time),
g_video_dec_info_ptr->video_time_scale);
video_dec_translate_av_time(decode_time, &decode_time);
/* Rita add,
1. audio frame and seek time may be not the same
2. seek and play may re-check several frames */
MP4_SetPlaybackTimerBase(vid_get_audio_parser(),
(kal_uint32) VIDEO_COMMBASE_TO_ANYBASE(g_video_dec_info_ptr->seek_time, 1000),
KAL_TRUE);
}
else
{
/* not play video. audio also end */
decode_time = 0;
}
g_video_dec_info_ptr->pre_frame_duration = decode_time;
/* set dsp according to different audio and video condition */
if (video_play)
{
savedMask = SaveAndSetIRQMask();
/*Please don't adjust the below sequence!!*/
video_set_dec_isr();
video_dec_set_frametime((kal_uint32)decode_time, KAL_TRUE);
RestoreIRQMask(savedMask);
g_video_dec_info_ptr->stage = VIDEO_DEC_STAGE_PLAY;
}
if (audio_end == KAL_FALSE)
{
if (!video_play)
{
// video end. audio not end
video_dec_disable_irq();
video_dec_set_enable_av_callback(NULL);
}
return MEDIA_STATUS_OK;
}
else
{
/* audio and video both end */
VIDEO_ASSERT(0);
return VIDEO_ERROR;
}
} /*AUDIO ENABLE*/
else /*g_video_dec_info_ptr->audio_enable == KAL_TRUE*/
{
/*audio not enable */
/* do not need to align audio frame time. use video frame time directly */
decode_time = VIDEO_COMMBASE_TO_ANYBASE(
(g_video_dec_info_ptr->seek_next_frame_time - g_video_dec_info_ptr->seek_time),
g_video_dec_info_ptr->video_time_scale);
/* translate and set sync time*/
video_dec_translate_av_time(decode_time, &decode_time);
/* Rita add,
1. audio frame and seek time may be not the same
2. seek and play may re-check several frames */
MP4_SetPlaybackTimerBase(vid_get_audio_parser(),
(kal_uint32) VIDEO_COMMBASE_TO_ANYBASE(g_video_dec_info_ptr->seek_time, 1000),
KAL_TRUE);
savedMask = SaveAndSetIRQMask();
/*Please don't adjust the below sequence!!*/
video_set_dec_isr();
video_dec_set_frametime((kal_uint32)decode_time, KAL_FALSE);
RestoreIRQMask(savedMask);
g_video_dec_info_ptr->stage = VIDEO_DEC_STAGE_PLAY;
return MEDIA_STATUS_OK;
}
}
/* This function is used to check video file is qualified or not.
* @param pstMp4Parser mp4 parser handle
* @param pstFSAL FSAL handle
* @param max_duration Allowed maximum video duration! If the video duration in this video file > input "max_duration", this function will VIDEO_DEC_LONG_DURATION.
* @return Media status, which is based MEDIA_STATUS_CODE structure.
*/
static MEDIA_STATUS_CODE video_dec_clip_check_media_file(STMp4Parser * pstMp4Parser, STFSAL * pstFSAL,
kal_uint32 max_duration_ms)
{
MEDIA_STATUS_CODE result;
kal_uint8 *frame_addr;
kal_uint32 frame_length;
kal_uint32 prev_frame_duration;
kal_uint64 max_duration;
/* check video duration */
max_duration = VIDEO_ANYBASE_TO_COMMBASE((kal_uint64)max_duration_ms, 1000);
if (g_video_dec_info_ptr->video_duration > max_duration)
{
g_video_dec_status.VIDEO_STATUS = VIDEO_DEC_LONG_DURATION;
VIDEO_ASSERT(0);
return VIDEO_ERROR;
}
/* prepare bitstream frame to buffer */
g_video_dec_info_ptr->seek_frame_number = 1;
g_video_dec_info_ptr->seek_result_frame_number = 1;
g_video_dec_info_ptr->prepare_frames_no = 0;
g_video_dec_info_ptr->hdr_parse_frames_no = 0;
g_video_dec_info_ptr->dec_frames_no = 0;
video_dec_clr_buffer(g_video_dec_info_ptr->prepare_frames_no, g_video_dec_info_ptr->prepare_frames_no + 1);
result = video_dec_put_frame_to_buffer();
if (result != MEDIA_STATUS_OK)
{
VIDEO_ASSERT(0);
return result;
}
/* get and decode the first frame */
result = video_dec_get_next_frame(&frame_addr, &frame_length, &prev_frame_duration);
if (result != MEDIA_STATUS_OK)
{
VIDEO_ASSERT(0);
return result;
}
result = mpeg4_decode_start((kal_uint8 *)g_video_dec_info_ptr->VOS,
(g_video_dec_info_ptr->decode_type == DECODE_TYPE_H263),
frame_addr,
frame_length,
KAL_TRUE);
if (result != MEDIA_STATUS_OK)
{
VIDEO_ASSERT(0);
return result;
}
/* check video size is allowed */
if (g_video_dec_info_ptr->width * g_video_dec_info_ptr->height
> (g_video_dec_info_ptr->max_width * g_video_dec_info_ptr->max_height))
{
g_video_dec_status.VIDEO_STATUS = VIDEO_DEC_FRAME_SIZE_ERROR;
VIDEO_ASSERT(0);
return VIDEO_ERROR;
}
return MEDIA_STATUS_OK;
}
/* Use seek time to get seeked frame no and its next frame time
* @param curr_frame input: current_frame, output: adjusted frame from curr_frame to the frame found in seek_time.
* @param org_seek_time seek time. (Unit: comm time scale)
* @param next_frame_time next frame start time (Unit: comm time scale)
* @return Media status, which is based MEDIA_STATUS_CODE structure.
*/
/*Unit: comm time scale*/
static MEDIA_STATUS_CODE video_dec_get_frame_with_time(kal_uint32 * curr_frame, kal_uint64 seek_time,
kal_uint64 * next_frame_time)
{
kal_uint64 next_video_time;
kal_uint64 current_seek_time = seek_time;
MEDIA_STATUS_CODE result;
kal_uint64 frame_time;
/* seek time = 0 maps to the first frame */
if (current_seek_time == 0)
{
*curr_frame = 1;
g_video_dec_status.PARSE_STATUS = MP4_GetDecodeTime(g_video_dec_info_ptr->pMp4Parser, 1, &next_video_time,
MP4_TRACK_VIDEO);
if (g_video_dec_status.PARSE_STATUS != MP4_PARSER_OK)
return MP4_PARSER_ERROR;
/* translate next frame time to common base */
*next_frame_time = VIDEO_ANYBASE_TO_COMMBASE(next_video_time, g_video_dec_info_ptr->video_time_scale);
g_video_dec_info_ptr->play_time = 0;
return MEDIA_STATUS_OK;
}
/* translate seek time from common base to video base */
current_seek_time = VIDEO_COMMBASE_TO_ANYBASE(seek_time, g_video_dec_info_ptr->video_time_scale);
g_video_dec_status.PARSE_STATUS = MP4_GetSampleNumber(g_video_dec_info_ptr->pMp4Parser, curr_frame, current_seek_time,
MP4_TRACK_VIDEO);
if (g_video_dec_status.PARSE_STATUS != MP4_PARSER_OK)
{
if (g_video_dec_status.PARSE_STATUS == MP4_PARSER_NO_SUCH_SAMPLE)
{
/* seek time larger than video duration. Set the seeked frame no to the last one */
g_video_dec_status.PARSE_STATUS = MP4_PARSER_OK;
*curr_frame = g_video_dec_info_ptr->total_frames_in_file - 1;
}
else
{
VIDEO_ASSERT(0);
return MP4_PARSER_ERROR;
}
}
/* get current frame decode time */
g_video_dec_status.PARSE_STATUS = MP4_GetDecodeTime(g_video_dec_info_ptr->pMp4Parser, *curr_frame, &frame_time,
MP4_TRACK_VIDEO);
if (g_video_dec_status.PARSE_STATUS != MP4_PARSER_OK)
{
VIDEO_ASSERT(0);
return MP4_PARSER_ERROR;
}
if ((*curr_frame<g_video_dec_info_ptr->dec_frames_no)
&& (*curr_frame>(g_video_dec_info_ptr->dec_frames_no - 10))
&& ((g_video_dec_info_ptr->dec_frames_no + 1) < g_video_dec_info_ptr->total_frames_in_file))
{
/*Tricky to short the seek time*/
/* If the seek frame is very close to the current decode frame. use current decode frame instead */
kal_uint32 index;
kal_uint64 frame_time_next;
for (index = *curr_frame; index < (g_video_dec_info_ptr->dec_frames_no - 1); index++)
{
g_video_dec_status.PARSE_STATUS =
MP4_GetDecodeTime_Next(g_video_dec_info_ptr->pMp4Parser, &frame_time_next, MP4_TRACK_VIDEO);
if (g_video_dec_status.PARSE_STATUS != MP4_PARSER_OK)
{
VIDEO_ASSERT(0);
return MP4_PARSER_ERROR;
}
}
if (VIDEO_ANYBASE_TO_ANYBASE((frame_time_next - frame_time), g_video_dec_info_ptr->video_time_scale,
1000) < 1000)
{
/* check the [decode frame time] - [seek frame time ] < 1sec */
*curr_frame = g_video_dec_info_ptr->dec_frames_no - 1;
frame_time = frame_time_next;
}
}
*curr_frame = ( *curr_frame)+1;
next_video_time = frame_time;
if (*curr_frame<g_video_dec_info_ptr->total_frames_in_file)
{
/* get next frame time when current frame is not the last frame */
g_video_dec_status.PARSE_STATUS =
MP4_GetDecodeTime_Next(g_video_dec_info_ptr->pMp4Parser, &next_video_time, MP4_TRACK_VIDEO);
if (g_video_dec_status.PARSE_STATUS != MP4_PARSER_OK)
{
VIDEO_ASSERT(0);
return MP4_PARSER_ERROR;
}
}
/*translate to common base */
*next_frame_time = VIDEO_ANYBASE_TO_COMMBASE(next_video_time, g_video_dec_info_ptr->video_time_scale);
/*Obtain Video play_time*/
result = video_dec_translate_av_time(frame_time, &g_video_dec_info_ptr->play_time);
if (result != MEDIA_STATUS_OK)
{
VIDEO_ASSERT(0);
return result;
}
return MEDIA_STATUS_OK;
}
/* Decode process is done. Notify upper layer and refresh when needed.
* @param frame_no the frame that should be seek
* @param callback video callback function when driver want to notify MED or upper layer.
* @param seek_from_current_frame_mode. application can decide whether to seek from current frame or not
* @return None
*/
MEDIA_STATUS_CODE video_dec_seek_by_frame(kal_uint32 frame_no, void (*callback)(kal_uint8 event),
kal_bool seek_from_current_frame_mode)
{
kal_uint32 frame_length;
kal_uint8 *frame_addr;
kal_uint32 first_frame_no;
kal_uint32 prev_frame_duration;
kal_uint32 dec_frame_number;
kal_bool init_refref_buffer = KAL_TRUE;
MEDIA_STATUS_CODE result;
if (g_video_dec_info_ptr->stage == VIDEO_DEC_STAGE_CLOSE)
return MEDIA_STATUS_OK;
video_dbg_trace(MP4_DEC_TASK_SEEK, video_get_current_time());
/*To guarantee all decode process is done*/
video_dec_internal_stop();
/* check seek frame is available */
if (frame_no > g_video_dec_info_ptr->total_frames_in_file)
{
video_dbg_trace(MP4_DEC_SEEK_ERROR_PARAMETER, video_get_current_time());
g_video_dec_status.VIDEO_STATUS = VIDEO_DEC_FUNC_PARAMETER_ERROR;
VIDEO_ASSERT(0);
return VIDEO_ERROR;
}
/*1~frame_no*/
if ((frame_no > g_video_dec_info_ptr->total_frames_in_file) || (frame_no == 0))
{
VIDEO_ASSERT(0);
g_video_dec_status.VIDEO_STATUS = VIDEO_DEC_FUNC_PARAMETER_ERROR;
return VIDEO_ERROR;
}
dec_frame_number = g_video_dec_info_ptr->dec_frames_no;
video_dec_struct_init(g_video_dec_info_ptr, g_video_dec_info_ptr->decode_type,
g_video_dec_info_ptr->VOS, g_video_dec_info_ptr->total_frames_in_file);
g_video_dec_info_ptr->is_allow_isr = KAL_FALSE;
g_video_dec_info_ptr->video_dec_callback = callback;
g_video_dec_info_ptr->video_end = KAL_FALSE;
/* Seek action should be from previous sync sample */
g_video_dec_status.PARSE_STATUS =
MP4_GetPrevSyncSampleNo(g_video_dec_info_ptr->pMp4Parser, (frame_no - 1), &first_frame_no, MP4_TRACK_VIDEO);
if (g_video_dec_status.PARSE_STATUS != MP4_PARSER_OK)
{
VIDEO_ASSERT(0);
return MP4_PARSER_ERROR;
}
if ((frame_no - 1) < first_frame_no)
{
/* no sync frame before seek frame */
VIDEO_ASSERT(0);
g_video_dec_status.VIDEO_STATUS = VIDEO_DEC_FUNC_PARAMETER_ERROR;
return VIDEO_ERROR;
}
if ((frame_no > dec_frame_number) && (dec_frame_number > first_frame_no)
&& (seek_from_current_frame_mode == KAL_TRUE))
{
/* sync frame -- dec_frame -- seek frame*/
/* devode from dec_frame but not sync frame */
first_frame_no = dec_frame_number;
init_refref_buffer = KAL_FALSE;
}
#ifdef VIDEO_DEC_YUV_MODE
first_frame_no = 0;
#endif /*VIDEO_DEC_YUV_MODE*/
g_video_dec_info_ptr->seek_frame_number = frame_no;
g_video_dec_info_ptr->seek_result_frame_number = frame_no;
g_video_dec_info_ptr->prepare_frames_no = first_frame_no;
g_video_dec_info_ptr->hdr_parse_frames_no = first_frame_no;
g_video_dec_info_ptr->dec_frames_no = first_frame_no;
g_video_dec_info_ptr->dec_state = VIDEO_DEC_STATE_SEEK;
/* prepare buffer */
video_dec_clr_buffer(g_video_dec_info_ptr->prepare_frames_no, g_video_dec_info_ptr->seek_frame_number);
result = video_dec_put_frame_to_buffer();
if (result != MEDIA_STATUS_OK)
{
VIDEO_ASSERT(0);
return result;
}
/* get frame and start to decode */
result = video_dec_get_next_fram
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -