ios FFmpeg第一阶段学习总结

时间:2021-05-15 19:28:16

前记

作为一篇没啥内在的文章,我记在博客中主要有两点:1.总结 2.希望刚接触的FFmpeg的朋友能少绕路,希望它起到一定作用。

在第一阶段学习中,对FFmpeg的精华几乎没有涉及,主要是在ios下实现了一个能播放视频的Demo。Demo目前再声音和图像同步方面做的不够出色,这也是我目前未解决的问题。


 

输出图像

我在编译FFmpeg lib时就使用了iFrameExtractor作为样例。使用一个时钟输出下一帧的图像,然后显示图像就能显示。就这样。。。。

参考

[1]iFrameExtractor on GitHub

[2]An ffmpeg and SDL Tutorial(第一章,第二章)


声音呢?

FFmpeg输出声音需要借助平台音频库,针对于ios你可以是用AudioQueue(我用的是这个,我还会告诉你一篇很好的教程),OpenAL。

参考

[1]Bear實驗室: iOS用AudioToolbox播放網路收音機 (使用FFmpeg) [Part 2][Part 3]

[2]《Learing Core Audio》Chapter 4 Recording

[3]《Learing Core Audio》Chapter 5 PlayBack


节奏一致

我们希望我们的图像声音保持同步,iFrameExtractor的作者在自己的WordPress上说明了方法,在GitHub上也有Demo做到了这一点。

我很奇怪为什么WordPress也得FQ?

参考

[1]Programming FFmpeg in iOS (1) (2) (3)

[2]iOSFFmpeg-master on GitHub

总结

其实实现大自同步并不难,我是说“大自”,好吧,其实我现在也知道大自同步。下面我来说说我的实现:

第一点:如果你同时播放声音和图片,你会发现图片总是跑在音乐的前面,所以我们得将解码得到的图片存起来,减慢它的节奏。

第二点:你得知道pts,dts。pts =Presentation timestamp in AVStream->time_base units;我们将使用AVPacket中的pts,它意味着这个Frame也就是图片应该在什么时候显示在屏幕上。与主时钟同步需要将pts装换成second。

1 double _second = pReadPkt.pts * av_q2d(pFormatCtx->streams[VideoStreamIndex]->time_base);
ios FFmpeg第一阶段学习总结ios FFmpeg第一阶段学习总结
 1 //程序主时钟
 2 -(void)refreshCurrentTime{
 3     if (pCurrentTime){
 4         [pCurrentTime release];
 5         pCurrentTime = nil;
 6     }
 7     if (!pCurrentTime){
 8         pCurrentTime = [[NSDate date]retain];
 9     }
10 }
11 
12 -(void)loopVideoOutput:(NSTimer *)timer {
13     
14     
15     NSTimeInterval elapsedTime = [pCurrentTime timeIntervalSinceNow];
16     pCurrentSecond -= elapsedTime;
17     [self refreshCurrentTime];
18 }
View Code

综上来看一段伪代码基本上就是参考[1]的奥义了:

ios FFmpeg第一阶段学习总结ios FFmpeg第一阶段学习总结
 1 尝试策略:
 2 //我缓存的图片的时钟是否小于主时钟
 3     if([self objectAtIndex:0].second < _syncSecond) 
 4 //是的,读取它,并从队列中删除
 5         [self removeobjectAtIndex:0];
 6 //输出图片更新
 7         poutImage = obj[0];
 8     else
 9 //不,还没轮到它显示 do nothing
10         [self notRead];
11  //ImageView更新显示
12     controller.imageView.image = pOutImage;
View Code

这样大自的同步就做到了,你会发现这样的实现图片会快1~2秒,蛋疼。

在写Demo的时候发现对AVPicture存取的封装好坏会对程序影响很大,参考[2]做出了很好的展示。


第二阶段的探索

完全同步并不是接下来的主要方向,在第一阶段我尝试使用过OpenAL做为音频输出,但是得到只有杂音~~~~~这将会是一个棘手的问题。

当你刚开始在iOS上学习FFmpeg的时候,使用imageView.image = pOutImage是一个很好的选择,除非你一开始就会Opengl,这样你能大大减少代码量。但是Opengl有它的伟大之处,它能输出YUV格式的图片,否则你只能把它变成RGB,然后输出。。。。

还有一点学习两者,能使你的代码更加通用。。。。因为两者都是跨平台的。

同步问题却是存在。。。所以解决它。


最后

ios FFmpeg第一阶段学习总结

enjoy it!!!