iOS ijkplayer 数据缓存过程 详解

原创 2017年05月31日 15:26:16


ijkplayer buffering过程
static void *SDL_RunThread(void *data)
{
    @autoreleasepool {
        SDL_Thread *thread = data;
        pthread_setname_np(thread->name);
        thread->retval = thread->func(thread->data);
        return NULL;
    }
}
//read_thread线程在此处开启
在read_thread函数内 如果ijkplayer播放器处于缓冲状态ffp->packet_buffering标志位为true
        if (ffp->packet_buffering) {
            io_tick_counter = SDL_GetTickHR();
            if (abs((int)(io_tick_counter - prev_io_tick_counter)) > BUFFERING_CHECK_PER_MILLISECONDS) {
                prev_io_tick_counter = io_tick_counter;
                ffp_check_buffering_l(ffp);
            }
        }
ffp_check_buffering_l(ffp);//此处会检查buffering缓冲状态
在ffp_check_buffering_l函数内会判断收到的未解码数据包个数是否大于最小能播放的数据包大小 当大于最小播放数据包
并且再判断音视频流的个数和音视频流的请求是否中止 如果都满足条件就修改音视频流的缓冲开关 代码如下:
        if (is->buffer_indicator_queue && is->buffer_indicator_queue->nb_packets > 0) {
            if (   (is->audioq.nb_packets > MIN_MIN_FRAMES || is->audio_stream < 0 || is->audioq.abort_request)
                && (is->videoq.nb_packets > MIN_MIN_FRAMES || is->video_stream < 0 || is->videoq.abort_request)) {
                ffp_toggle_buffering(ffp, 0);//此处关闭缓冲 开始播放
            }
        }
通过此处可以看出如果想修改ijkplayer的播放缓冲时间和缓冲长度 可以通过修改 MIN_MIN_FRAMES 来实现
#define MIN_MIN_FRAMES      5
void ffp_toggle_buffering(FFPlayer *ffp, int start_buffering)
{
    SDL_LockMutex(ffp->is->play_mutex);
    ffp_toggle_buffering_l(ffp, start_buffering);
    SDL_UnlockMutex(ffp->is->play_mutex);
}
void ffp_toggle_buffering_l(FFPlayer *ffp, int buffering_on)
{
    if (!ffp->packet_buffering)
        return;

    VideoState *is = ffp->is;
    if (buffering_on && !is->buffering_on) {
        av_log(ffp, AV_LOG_DEBUG, "ffp_toggle_buffering_l: start\n");
        is->buffering_on = 1;
        stream_update_pause_l(ffp);
        ffp_notify_msg1(ffp, FFP_MSG_BUFFERING_START);
    } else if (!buffering_on && is->buffering_on){
        av_log(ffp, AV_LOG_DEBUG, "ffp_toggle_buffering_l: end\n");
        is->buffering_on = 0;
        stream_update_pause_l(ffp);
        ffp_notify_msg1(ffp, FFP_MSG_BUFFERING_END);
    }
}
static void stream_update_pause_l(FFPlayer *ffp)
{
    VideoState *is = ffp->is;
    if (!is->step && (is->pause_req || is->buffering_on)) {
        stream_toggle_pause_l(ffp, 1);
    } else {
        stream_toggle_pause_l(ffp, 0);
    }
}
/* pause or resume the video */
static void stream_toggle_pause_l(FFPlayer *ffp, int pause_on)
{
    VideoState *is = ffp->is;
    if (is->paused && !pause_on) {
        is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;

#ifdef FFP_MERGE
        if (is->read_pause_return != AVERROR(ENOSYS)) {
            is->vidclk.paused = 0;
        }
#endif
        set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
    } else {
    }
    set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
    is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = pause_on;

    SDL_AoutPauseAudio(ffp->aout, pause_on);
}
void SDL_AoutPauseAudio(SDL_Aout *aout, int pause_on)
{
    if (aout && aout->pause_audio)
        aout->pause_audio(aout, pause_on);
}
static void aout_pause_audio(SDL_Aout *aout, int pause_on)
{
    SDLTRACE("aout_pause_audio(%d)\n", pause_on);
    SDL_Aout_Opaque *opaque = aout->opaque;
    
    if (pause_on) {
        [opaque->aoutController pause];
    } else {
        [opaque->aoutController play];
    }
}
- (void)play
{
    if (!_audioQueueRef)
        return;

    self.spec.callback(self.spec.userdata, NULL, 0);

    @synchronized(_lock) {
        _isPaused = NO;
        NSError *error = nil;
        if (NO == [[AVAudioSession sharedInstance] setActive:YES error:&error]) {
            NSLog(@"AudioQueue: AVAudioSession.setActive(YES) failed: %@\n", error ? [error localizedDescription] : @"nil");
        }

        OSStatus status = AudioQueueStart(_audioQueueRef, NULL);
        if (status != noErr)
            NSLog(@"AudioQueue: AudioQueueStart failed (%d)\n", (int)status);
    }
}
通过以上分析可以看出当通过 ffp_toggle_buffering(ffp, 0);函数修改缓冲状态时中间会通过SDL函数来调用AudioQueue来开始播放


iOS开发 - 使用IJKPlayer时,关于需求要边下边播的缓存功能,退回来后播放缓存不再耗流量

博主以前做的项目,使用的流播放,rtmp,基于bilibili的ijkplayer,想必大家都有用过或者听过,是一个很不错的开源的直播,播放流视频的播放器,后面又有了一批需求,客户要求我们做一个缓存功...
  • CodingFire
  • CodingFire
  • 2016年12月23日 14:44
  • 4064

Android边缓冲边播放视频(ijkplayer的编译和使用)

当你看到这篇博文的时候希望你先对这个开源项目有所了解。github上的地址: https://github.com/Bilibili/ijkplayer感谢哔哩哔哩团队不吝开放出来。此文主要用于帮助之...
  • u011133213
  • u011133213
  • 2015年08月11日 19:59
  • 12271

直播技术总结(三)ijkplayer的一些问题优化记录

前言:ijkplayer中一些问题记录优化,看下Agenda: 1、在弱网时如何优化 2、ijkplayer播放卡顿如何优化 3、如何支持https链接播放? 4、如何降低ijkplayer延迟效应 ...
  • hejjunlin
  • hejjunlin
  • 2017年02月25日 13:26
  • 10004

IOS 使用IJKPlayer时进行Options设置方法

IOS 使用IJKPlayer时进行Options设置方法
  • atomic123
  • atomic123
  • 2016年01月29日 16:09
  • 9126

Ijkplayer直播App卡顿问题分析

一. 出现问题 观看自己开播的直播间,经常出现卡顿,而且画面一卡6,7s,重新播放时会出现跳帧,卡顿频率也较高,导致该App可用性极低。 二. 分析 1. 直播架构分析 根据l...
  • Guofengpu
  • Guofengpu
  • 2017年11月12日 17:21
  • 552

ijkplayer iOS 音视频解码 详解

ijkplayer iOS 音视频解码 //创建音频解码线程 if ((ret = decoder_start(&is->auddec, audio_thread, ffp, "ff_audio_d...
  • jeffasd
  • jeffasd
  • 2017年05月31日 15:28
  • 2233

iOS项目中集成ijkplayer框架

ijkplayer是B站开源的一款视频直播框架,它是基于ffmpeg的。美拍和斗鱼都使用到了 ijkplayer 项目。ijkplayer 实现了跨平台功能,支持 Android 和 iOS 双平台;...
  • Companion_1314
  • Companion_1314
  • 2016年09月23日 14:34
  • 2550

编译ijkplayer,并添加rtsp、rtmp支持,解决无法播放、unknown、延迟问题

最近在研究利用ndk技术,实现FFmpeg解码解码视频文件、视频流,发现了B站的开源播放框架ijkplayer,真是太强大了,基于ijkplayer开发减少了许多移植FFmpeg的步骤。 首先当然是配...
  • qq372848728
  • qq372848728
  • 2017年03月15日 02:40
  • 5182

ijkplayer设置rtmp秒开

ijkplayer和ffplay在打开rtmp串流视频时,大多数都会遇到5~10秒的延迟,在ffplay播放时,如果加上-fflags nobuffer可以缩短播放的rtmp视频延迟在1s内,而在ij...
  • lp8800
  • lp8800
  • 2017年03月24日 12:03
  • 4407

ijkplayer环境搭建

最近直播比较火,作为曾经的多媒体人,按捺不住想看看现在的直播客户端是如何解码的,解压众多直播app后,看到了熟悉的FFmpeg身影(太熟悉了,之前一直搞FFmpeg,解决各种文件sync问题啊),以及...
  • csds319
  • csds319
  • 2016年06月28日 21:09
  • 390
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS ijkplayer 数据缓存过程 详解
举报原因:
原因补充:

(最多只允许输入30个字)