⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video_dec_api.c

📁 最新MTK手机软件源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                    (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 + -