Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ijkplayer播放rtmp直播流,延迟明显 #210

Closed
walkermi opened this issue Apr 15, 2015 · 25 comments
Closed

ijkplayer播放rtmp直播流,延迟明显 #210

walkermi opened this issue Apr 15, 2015 · 25 comments

Comments

@walkermi
Copy link

Android上使用master或stable分支的代码,编译后的demo播放rtmp直播流,从打开操作到屏幕显示活动视频,测试差不多需要8s左右,有时更长。

视频打开后,对比实际活动,播放延迟要明显滞后超过5s以上。

在PC端测试原版ffplay,也有类似现象,但如果加入如下参数,则播放延迟会明显减低至2s以内。

ffplay -fflags nobuffer -i rtmp://dev:1935//live/livestream

请问如果ijkplayer要增加该参数,要如何操作呢?
我尝试在ijkplayer/android/ijkmediawidget/src/tv/danmaku/ijk/media/widget/VideoView.java这个文件中增加
ijkMediaPlayer.setOverlayFormat(AvFourCC.SDL_FCC_RV32);
ijkMediaPlayer.setAvFormatOption("fflags", “nobuffer”); // add
ijkMediaPlayer.setAvCodecOption("skip_loop_filter", "48");
ijkMediaPlayer.setFrameDrop(12);

貌似没有任何效果

@walkermi
Copy link
Author

另外,开始打开操作到屏幕实际显示视频的延时,查找资料基本上集中在
avformat_open_input函数中的一个for(;;) 循环,其中的一个break条件如下
if (t >= ic->max_analyze_duration) {
av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %d reached at %"PRId64" microseconds\n", ic->max_analyze_duration, t);

break;

}

PC下的ffplay我增加如下代码修改这个阻塞时间,效果还是很明显的
ic = avformat_alloc_context();

ic->interrupt_callback.callback = decode_interrupt_cb;

ic->interrupt_callback.opaque = is;

//add 下面两行

ic->max_analyze_duration =1_1000_1000;

av_log(NULL, AV_LOG_ERROR, "ic->max_analyze_duration %d.\n", ic->max_analyze_duration);

err = avformat_open_input(&ic, is->filename, is->iformat, &ffp->format_opts);

但是ijkplayer我修改相同位置,却没有任何效果。

@tanhx2008
Copy link

首先感谢作者贡献了这么好的项目!
关于rtmp直播流打开慢和延时大的问题,是issue里反馈比较多的问题,根据网上的资料,做了一些实验和改进,不敢独享,拿出来供大家参考。

1、rtmp直播流打开慢
avformat_find_stream_info(),这个函数会花去主要的时间,因为要做流的分析拆分等,所以优化可以重点从这个函数入手。
一种是设置probesize,这个的缺点是如果这个值设置过小,会导致流的信息分析不完整,从而导致丢失流。
另一种方法比较极端些,自己实现这个函数的功能。根据metadata信息,手动设置解码参数,这个效果比较明显,针对264+aac的rtmp可以考虑这种优化方案。
具体可以根据个人项目需求来取舍。

2、关于播放延时的问题,因为ffplay默认的帧率控制没有追帧的策略,所以网络如果发生抖动,延时会累加。优化策略就是调整帧率控制部分。原则就是要在流畅度和实时性之间得到一个平衡。

@walkermi
Copy link
Author

感谢@tanhx2008 ,如果我想设置probsize的值,是这样吗?
ijkMediaPlayer.setAvFormatOption("probsize", “5000000”);

@tanhx2008
Copy link

av_dict_set(&ffp->format_opts, "probesize", "4096", 0);
如果很小的话,会探测到一帧数据就返回

@walkermi
Copy link
Author

如果按你的改法,就涉及到ffplay的代码修改了,我希望可以将接口暴露给调用VideoView的用户。

看了下代码,感觉是setAvFormatOption,你了解的这个接口吗?

@walkermi
Copy link
Author

另外,@tanhx2008 第二部分追帧的策略,不是太明白,能详细的说明下吗?

@tanhx2008
Copy link

应用层用你的设法应该可以。
追帧策略,可以引入手机本地时间,第一帧计算手机与流pts的时间差(本地时间和流时间同步),流的时间落后本地时间多的情况下,快放或者考虑丢包。当然音频处理上要复杂些,这部分我也没有做,目前只是有这样一个思路。

@bbcallen
Copy link
Contributor

ijkMediaPlayer.setAvFormatOption("fflags", “nobuffer”);
这段应该是生效了。

下面两句是等效的
ijkMediaPlayer.setAvFormatOption("probsize", “4096”);
av_dict_set(&ffp->format_opts, "probesize", "4096", 0);

目前我自己的需求是优化高清点播的效率,而不是直播,所以有一套自己的 packet 缓存。
直播需要你根据自己的需要修改 ff_ffplay_def.h 里的一些参数

// 下面的参数决定了缓冲多少毫秒的播放数据后,从缓冲状态返回到播放状态。
#define DEFAULT_START_HIGH_WATER_MARK_IN_MS     (100) // 第一次缓冲结束的 packet 水位线
#define DEFAULT_NEXT_HIGH_WATER_MARK_IN_MS      (1 * 1000) // 第二次缓冲
#define DEFAULT_MAX_HIGH_WATER_MARK_IN_MS       (5 * 1000) // packet 水位线的最高位置

// 下面的参数决定 packet 队列最多预读多少数据
#define MAX_QUEUE_SIZE (10 * 1024 * 1024)
#define MIN_FRAMES 50000

@tanhx2008
Copy link

多谢

@walkermi
Copy link
Author

http://www.ffmpeg.org/doxygen/trunk/ffplay_8c-source.html

官方的ffplay.c
00066 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
00067 #define MIN_FRAMES 5

为什么ijkplayer是50000? @bbcallen

@bbcallen
Copy link
Contributor

如果预读的 packet 超过 MIN_FRAMES 个,那么 ffplay 就会停止预读。
对于天朝的网络状况来说,这显然是不可接受的。
所以这里设了一个足够大的值,确保尽可能预读较多的数据。

更合理的预读实现正在考虑中。

@walkermi
Copy link
Author

增加了下面的额外设置参数
ijkMediaPlayer.setAvFormatOption("analyzeduration", “2000000”);
ijkMediaPlayer.setAvFormatOption("fflags", “nobuffer”);
ijkMediaPlayer.setAvFormatOption("probsize", “4096”);

播放rtmp直播流,打开速度确实快了,3s左右;播放延时也能满意,<2s。

但有个问题,偶尔会存在,声音已经开始正常播放,播放窗口显示出来,但是黑屏,无法显示视频的情况。也没有接口告知错误的原因。这是什么原因呢?或者有什么办法通知应用层存在这个错误?让应用层尝试关闭后再次打开?@bbcallen

@bbcallen
Copy link
Contributor

日志贴出来看看。

@adteven
Copy link

adteven commented Dec 11, 2015

老大setAvFormatOption("fflags","nobuffer");新版的ijkplayer这个接口没有了,怎么设置ffmpeg的参数啊,还有就是用nobuffer会黑屏,应该怎么做

@zhangcheng1989
Copy link

setAvFormatOptio 新版的这个方法是不是没有暴漏出来啊

@RobinLW
Copy link

RobinLW commented Apr 1, 2016

@walkermi 我碰到一次时开始播放有声音没视频,看log发现是analyzeduration不够。我把这个值调大了,但是打开速度慢了。这个可能跟服务器端的编码有关。你后来是怎么处理的?

@dourgulf
Copy link

@tanhx2008 可以留个联系方式, 请教一下rtmp的延迟问题, 我QQ号2359617622

@dourgulf
Copy link

@tanhx2008 没有声音的日志, 问题应该是探测时间不够, 没有拿到正确的yuv格式, 导致VideoToolBox创建失败.
Stream #0:1, 0, 1/1000: Video: h264, 1 reference frame, none, 1k tbr, 1k tbn
正确的情况是应该能解析到这样的结果:
Stream #0:1, 1, 1/1000: Video: h264, 2 reference frames, yuv420p(left), 414x736 (416x736), 0/1, 1k tbr, 1k tbn

1463827211.318063 avformat_find_stream_info begin
[flv @ 0x13d830600] Before avformat_find_stream_info() pos: 13 bytes read:751 seeks:0
[flv @ 0x13d830600] Unknown type |RtmpSampleAccess
[flv @ 0x13d830600] video stream discovered after head already parsed
[flv @ 0x13d830600] Probe buffer size limit of 4096 bytes reached
[flv @ 0x13d830600] Stream #1: not enough frames to estimate rate; consider increasing probesize
[flv @ 0x13d830600] Could not find codec parameters for stream 1 (Video: h264, 1 reference frame, none): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options
[flv @ 0x13d830600] After avformat_find_stream_info() pos: 5285 bytes read:5285 seeks:0 frames:17
1463827211.691627 avformat_find_stream_info end
[FFPlayer @ 0x13f51a230] max_frame_duration: 10.000
Input #0, flv, from 'rtmp://xxxxxxxxx(匿了)':
Metadata:
displaywidth : 414
displayheight : 736
framewidth : 414
frameheight : 736
videoframerate : 30
timescale : 1000
description : {AACFrame: codec:AAC, channels: 2, frequency:44100, samplesPerFrame:1024, objectType:LC}
type : video
sampletype : H264
Duration: N/A, start: 1417.028000, bitrate: N/A
Stream #0:0, 17, 1/1000: Audio: aac, 44100 Hz, stereo, fltp
Stream #0:1, 0, 1/1000: Video: h264, 1 reference frame, none, 1k tbr, 1k tbn
aout_open_audio()
[FFPlayer @ 0x13f51a230] AudioCodec: avcodec, aac
aout_pause_audio(0)
init_videotoolbox - using avcC atom of size(25), ref_frames(2)after scale width 0 height 0
2016-05-21 18:40:12.013 JCLiveApp[6427:2408921] Error Error Domain=NSOSStatusErrorDomain Code=-12911 "(null)"
CreateVTBSession - failed with status = (-12911)could not init video tool box decoder !!!vtb fail!!! switch to ffmpeg decode!!!!
[FFPlayer @ 0x13f51a230] VideoCodec: avcodec, h264
[FFPlayer @ 0x13f51a230] fps: 1000.000000 (normal)
2016-05-21 18:40:12.014 JCLiveApp[6427:2408487] FFP_MSG_VIDEO_DECODER_OPEN: false
2016-05-21 18:40:12.014 JCLiveApp[6427:2408487] FFP_MSG_VIDEO_SIZE_CHANGED: 0, 0
2016-05-21 18:40:12.014 JCLiveApp[6427:2408487] FFP_MSG_SAR_CHANGED: 0, 1
ijkmp_get_msg: FFP_MSG_PREPARED
2016-05-21 18:40:12.014 JCLiveApp[6427:2408487] FFP_MSG_PREPARED:
ijkmp_get_meta_l
ijkmp_get_meta_l()=void
2016-05-21 18:40:12.015 JCLiveApp[6427:2408487] mediaIsPreparedToPlayDidChange
2016-05-21 18:40:12.015 JCLiveApp[6427:2408487] loadStateDidChange: IJKMPMovieLoadStatePlaythroughOK: 3
2016-05-21 18:40:12.015 JCLiveApp[6427:2408487] IJKMPMoviePlayBackStateDidChange 1: playing
[h264 @ 0x13d181800] Increasing reorder buffer to 1
[h264 @ 0x13d181800] no picture

2016-05-21 18:40:12.241 JCLiveApp[6427:2408487] FFP_MSG_VIDEO_SIZE_CHANGED: 414, 736
_float GL_EXT_debug_label GL_EXT_debug_marker GL_EXT_discard_framebuffer GL_EXT_draw_instanced GL_EXT_instanced_arrays GL_EXT_map_buffer_range GL_EXT_occlusion_query_boolean GL_EXT_pvrtc_sRGB GL_EXT_read_format_bgra GL_EXT_separate_shader_objects GL_EXT_sh2016-05-21 18:40:12.253 JCLiveApp[6427:2408487] FFP_MSG_VIDEO_RENDERING_START:
2016-05-21 18:40:12.254 JCLiveApp[6427:2408487] UIImageView(观众测-加载预览视图) deallocated
2016-05-21 18:40:12.254 JCLiveApp[6427:2408487] <UIVisualEffectView: 0x13f47a3a0; frame = (0 0; 0 0); layer = <CALayer: 0x13cdce3a0>> has been deallocated
SDL_VoutFFmpeg_CreateOverlay(w=414, h=736, fmt=I420(0x30323449, dp=0x13cdd3450)
2016-05-21 18:40:12.280 JCLiveApp[6427:2408487] FFP_MSG_VIDEO_SIZE_CHANGED: 414, 736
SDL_VoutFFmpeg_CreateOverlay(w=414, h=736, fmt=I420(0x30323449, dp=0x13cdd3450)
2016-05-21 18:40:12.345 JCLiveApp[6427:2408487] FFP_MSG_VIDEO_SIZE_CHANGED: 414, 736
2016-05-21 18:40:12.345 JCLiveApp[6427:2408487] movieNaturalSizeAvailable

@yangyunfeng666
Copy link

ijkMediaPlayer.setAvFormatOption() 方法 在tv.danmaku.ijk.media.player.IjkMediaPlayer 里面没有这个方法啊,怎么搞,里面使用的版本不一样?

@HatsuneMikuV
Copy link

@tanhx2008 tan rtmp延迟问题怎么处理针对264+aac的rtmp,能说一下 你是怎么优化的吗?谢谢

@xsfgdut
Copy link

xsfgdut commented Jun 19, 2018

@bbcallen 请问一下用demo的ijkVideoView进行播放,发现每次进入的时候会有几百毫秒左右的黑屏出现,之后才是正常的视频图像,请问这个是什么原因造成的?

@PineapplePie
Copy link

@xsfgdut it appears if you use hardware decoding (option "media-codec")

@beta-li
Copy link

beta-li commented Oct 8, 2018

关于累计延迟的问题,追帧或者丢帧策略有什么办法么?

1 similar comment
@yixi195
Copy link

yixi195 commented Apr 27, 2020

关于累计延迟的问题,追帧或者丢帧策略有什么办法么?

@cool-518
Copy link

cool-518 commented Aug 6, 2020

同楼上:关于累计延迟的问题,追帧或者丢帧策略有什么办法么?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests