ijk流程

作者: 紫色冰雨 | 来源:发表于2020-11-03 16:24 被阅读0次

    自定义组件主要包括protocol和demuxer。协议有:ijkimp_ff_ijkio_protocol,ijkimp_ff_async_protocol,ijkimp_ff_ijktcphook_protocol,ijkimp_ff_ijkhttphook_protocol和ijkimp_ff_ijklongurl_protocol;demuxer为ijkimp_ff_ijklivehook_demuxer。

    注册各种协议

        消息循环处理函数media_player_msg_loop是在调用接口ijkmp_ios_create时候传到底层的,调用ijkmp_prepare_async时,创建了消息处理线程。media_player_msg_loop里面主要就是获取消息并处理消息。

    在函数ffp_prepare_async_l调用stream_open,stream_open中创建了视频渲染线程,该线程主要是进行视频渲染工作,并对视频进行同步,同步相关逻辑主要在这个线程里面,同步的大概思路就是:有一个绝对时间作为同步起点,然后计算当前帧与上一帧时间差,然后与当前绝对时间基准源比较,如果不到时间,计算remaining_time,然后sleep等待。如果时间参考时钟不是视频源,还会时钟就行调整,如果当前视频帧落后于主时钟源,则需要减小下一帧画面的等待时间,如果视频帧超前,并且该帧的显示时间大于显示更新门槛,则显示下一帧的时间为超前的时间差加上上一帧的显示时间,如果视频帧超前,并且上一帧的显示时间小于显示更新门槛,则采取加倍延时的策略。

    intffp_prepare_async_l(FFPlayer*ffp,constchar*file_name)

    {

        assert(ffp);

        assert(!ffp->is);

        assert(file_name);

        if(av_stristart(file_name,"rtmp",NULL) ||

            av_stristart(file_name,"rtsp",NULL)) {

            // There is total different meaning for 'timeout' option in rtmp

            av_log(ffp, AV_LOG_WARNING, "remove 'timeout' option for rtmp.\n");

            av_dict_set(&ffp->format_opts,"timeout",NULL,0);

        }

        /* there is a length limit in avformat */

        if(strlen(file_name) +1>1024) {

            av_log(ffp,AV_LOG_ERROR,"%s too long url\n",__func__);

            if (avio_find_protocol_name("ijklongurl:")) {

                av_dict_set(&ffp->format_opts,"ijklongurl-url", file_name,0);

                file_name ="ijklongurl:";

            }

        }

        av_log(NULL, AV_LOG_INFO, "===== versions =====\n");

        ffp_show_version_str(ffp, "ijkplayer",      ijk_version_info());

        ffp_show_version_str(ffp, "FFmpeg",        av_version_info());

        ffp_show_version_int(ffp, "libavutil",      avutil_version());

        ffp_show_version_int(ffp, "libavcodec",    avcodec_version());

        ffp_show_version_int(ffp, "libavformat",    avformat_version());

        ffp_show_version_int(ffp, "libswscale",    swscale_version());

        ffp_show_version_int(ffp, "libswresample",  swresample_version());

        av_log(NULL, AV_LOG_INFO, "===== options =====\n");

        ffp_show_dict(ffp, "player-opts", ffp->player_opts);

        ffp_show_dict(ffp, "format-opts", ffp->format_opts);

        ffp_show_dict(ffp, "codec-opts ", ffp->codec_opts);

        ffp_show_dict(ffp, "sws-opts  ", ffp->sws_dict);

        ffp_show_dict(ffp, "swr-opts  ", ffp->swr_opts);

        av_log(NULL, AV_LOG_INFO, "===================\n");

        av_opt_set_dict(ffp, &ffp->player_opts);

        if(!ffp->aout) {

            ffp->aout = ffpipeline_open_audio_output(ffp->pipeline, ffp);

            if(!ffp->aout)

                return-1;

        }

    #if CONFIG_AVFILTER

        if(ffp->vfilter0) {

            GROW_ARRAY(ffp->vfilters_list, ffp->nb_vfilters);

            ffp->vfilters_list[ffp->nb_vfilters -1] = ffp->vfilter0;

        }

    #endif

        VideoState*is =stream_open(ffp, file_name,NULL);

        if(!is) {

            av_log(NULL, AV_LOG_WARNING, "ffp_prepare_async_l: stream_open failed OOM");

            return EIJK_OUT_OF_MEMORY;

        }

        ffp->is= is;

        ffp->input_filename=av_strdup(file_name);

        return0;

    }


    stream_open还创建了read_thread,read_thread里面主要有打开文件或流,然后并获取媒体信息。拿到信息后,初始化音视频解码器,并开创建了音视频解码线程。线程创建后,开始demuxer文件,并解除音视频pkt,并将pkt放到对应的音频、视频和字幕pkt队列里面。

        音频解码线程和视频解码线程的主要工作是从音频和视频pkt队列里面取包并解码,并将解码数据送到缓冲区等待渲染。

        ffpipeline主要就是运用c函数指针,实现动态选择编解码接口,并与在硬解和软解之间切换。

    相关文章

      网友评论

          本文标题:ijk流程

          本文链接:https://www.haomeiwen.com/subject/nzeuahtx.html