2023-08-31

移动开发平台视频播放器探索

背景

APP开发中需要使用视频播放器播放视频,我们采用的是开源的第三方播放器IJK。虽然IJK功能强大,但是还是遇到不少问题。这里以iOS平台为例子记录下平时开发中学习到的知识和碰到的问题,以及如何解决。

视频播放基本流程

IJK是基于ffmpeg二次开发,其编解码依赖于ffmpeg和videoToolBox,视频显示采用的是SDL(基于openGL实现)。整个视频到画面的流程我简单用一张图概括下。


视频播放流程.jpg

流程看上去简单,但是其中还涉及了多线程处理、图形学知识、音视频倍速播放等等知识,涉及的技术点很多,想学透还是比较困难的。下面我将挑几个基础的简单介绍。

知识点:视频解码I帧、B帧、P帧以及视频播放顺序

视频其实是一张张图片按照时间点连续显示到画面上而形成的。如果视频的清晰度很高,每张图片都很大,那么在网络上传输所付出代价就很大。所以视频都不是原图完完整整的保存的,而是需要进行"压缩",这个过程就是编码,而按照什么规则"压缩"就是编码格式,比如h265/h264。

在H.264压缩标准中,编码后,图片会变成I帧,B帧,P帧。


视频组成.png

I帧

I帧其实就是完整的图片,其没有压缩,可以直接用来显示

P帧

P帧是基于前面的I帧进行编码的,所以要得到P帧原始的图片需要前面I帧或者P帧的数据。


P帧.png

B帧

B帧是基于前面的帧和后面的帧一起编码的,要叨叨B真原始图片需要前后2个帧。


B帧.png

视频播放顺序和视频解码顺序

由于B帧的存在,所以含有B帧视频的解码顺序和播放顺序是不一致的,比如


播放顺序和解码顺序.jpg

所以有B帧的视频播放顺序不等于解码顺序。

实际遇到问题1

前段时间遇到一个视频播放卡顿的问题,画面播放不连续。一开始以为是码率不够导致的跳帧,后来经过调试发现,音画同步并没有跳过帧,而是在排序队列出口有大量的跳帧。这个问题比较奇怪,于是我对该过程进行了模拟。

由于B帧的存在,解码的顺序不等于播放顺序,所以在解码出帧后需要将现有帧根据播放顺序排序,IJK的设计是将帧放入排序队列,并且保证队列里有2帧以上才允许出队列。那么上图播放流程如下图:


正常思路.jpg

目前按正常思路来看是正常的,2队列深度不应该出现跳帧情况,但是事实调试确实出现了,这就比较奇怪了。后续查资料发现 B帧是依赖P帧和I帧解码,那会不会B帧不是按照队列先进先出,而是先进后出呢?图调整如下,不一样的地方已经标红:


实际上.jpg

是否规定B帧一定要先进先出这个没法考证,硬解码返回的顺序完全依赖VideoToolBox的代码实现,并且IJK有多年未维护,很可能是该问题导致。修改方案是将排序队列扩大,避免丢帧的情况出现。

知识点:RGB和YUV

RGB和YUV都是图像对颜色的编码方式,简单理解就是2中不同的方式来描述颜色,视频帧里面就是存储这些颜色信息。一个“屏幕”有许多像素点,帧数据就是告知“屏幕”中每一个像素点要显示什么颜色,然后所有像素点都显示自己的颜色后就形成了图片。

RGB就比较简单了,就是三原色,每个像素点都有红、绿、蓝个“灯泡”,像素点根据帧传进来的3个值来调整3个灯泡的亮度,光颜色叠加就能显示不同的颜色。

YUV是被欧洲电视系统所采用的一种颜色编码方法,之前都是黑白电视,RGB对黑白电视兼容性不好,YUV可以。Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。那现在显示屏是怎么用YUV显示的呢?其实很简单,就是将YUV根据算法转换成RGB,然后采用RGB的方式进行显示。

IJK播放器从帧转换成图像的过程简化如下:


显示.jpg

图像显示这块讲述比较简单,具体可以参考其他资料,这里不再赘述。

实际问题2

近期在播放视频的时候发现视频播放画面显示异常,显示如下:

问题视频.PNG

起初以为是解码问题,因为直接黑屏。但是仔细看,还有一些红色的影像在动。那么就先定位是什么问题导致。先通过电脑端测试视频,发现可以播放,说明视频本身没有问题。通过调试,发现可以正常解码出帧,并且音画同步和排序队列出帧扣都没有丢帧的情况。那么就可以初步定位问题出在帧->渲染这层。下面继续判断是解出的帧有问题还是渲染有问题。

videoToolBox解出的数据是CVImageBufferRef(可以参考IJKVideoToolBoxSync.m中VTDecoderCallback回调),我们可以通过代码,将CVImageBufferRef转换成UIimage再在页面上显示,看看帧是否能正常显示。结果可以显示,那么问题就出在渲染层了。

IJK的渲染是靠SDL,其核心还是openGL,又由于该视频是硬解码,所以直接定位到其render文件renderer_yuv420sp_vtb.m。下断点后发现,在openGL生成YUV Y层贴图时报错:


Y层错误.png
报错.png

嗯,Y层贴图报错,是剩UV层,Y层是表示亮度,出错后显示黑色合情合理。但是该怎么修改呢,前面已经证明帧数据没有问题,那为什么Y层贴图会报错呢?并且这个错误也没有具体回调,线索就此断了,只知道是这里出问题,但是无法修改,尝试调整SDL几个参数无果,陷入僵局。

后来点击该方法,发现OPENGLES_DEPRECATED(ios(3.0, 12.0) 这么一句话,openGL在iOS12就被废弃了?通过查资料,原来openGL在iOS12之后就不建议使用,苹果采用替代方案Metal全面替代openGL,并且性能据说比之前高10倍。开发文档:开发文档 IJK渲染层只是将帧转化成图像,只要帧已经正确解出来并且格式固定,那么是采用OPENGL渲染还是采用Metal渲染对整个视频播放流程无影响。因此我们决定尝试采用Metal全面替换openGL。

经过几天尝试Metal,发现Metal的写法与OpenGL十分相似,而且采用OC编写面向对象,可以直接用ARC管理内存,省去了释放内存的烦恼。果然还是苹果自家的东西好用。。简单的思路是在IJK播放器盖一个MTKView,当使用Metal渲染时将MTKView解除隐藏,将解析出来的CVPixelBufferRef一层层传出来,递给MTKView显示。

优势:

1、CVPixelBufferRef-> MTKView都是苹果的类,兼容性好,不会像openGL出现异常报错

2、MTKView的性能更高

3、面向对象编程内存释放有保障

劣势:

1、有一定门槛,有openGL开发经验更容易理解。

调整后的视频如下:

结果.PNG
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容