1.VLC介绍
官网链接:VLC官网
2.本人踩的坑
wiki上面有两篇文章,一篇是“VLCKit”,一篇是“iOSCompile”,因为本人比较小白,实在搞不明白该用哪个,再加上搜的资料中两个都有,真的是一头雾水……试试第一个,再试试第二个,搞得晕头转向
现在我可以明确的说:如果你是需要一个VLC的库和代码例子,选择前者;至于后者,有大神看到这篇文章可以留言给一个专业的解释,两者的区别是什么,因为按照后者我没有编译出来。
3.准备工作
(1)我的系统环境 os x 10.11.5 + xcode 7.3.1,cocoapods2.3.0(不确定这个的作用),Iterm2(没用系统的终端,自己下一个Iterm2)
注:对xcode的sdk最低版本要求是iOS7.0,理论上7.0以上都能编译,有一些之前的文章说要修改一下脚本中对sdk的要求(哪个脚本后面会提到),现在不用,因为脚本里面没有写死,是判断当前sdk版本的。但是建议你用最新版的xcode和系统,xcode不要动过手脚(比如自己手动换过sdk之类)
(2)网络环境:最好FQ(不FQ得话你要自己找到一些依赖库放到对应目录下,下来我会上传我编译过程中下载好的依赖库,但是如果你看到我的帖子时距离我发帖时间很长了,建议不要直接用我给的依赖库,因为这些依赖库也会更新。依赖库路径....../VLCKit/MobileVLCKit/ImportedSources/vlc/contrib/tarballs),编译过程中某个依赖库下载不下来的话就会编译失败,如果因为这个导致编译失败,你可以单独找找这个依赖库,或者对照库的名字从我给的库里面copy一份放在前面的目录下(放的时候要对照版本哦),编译完成后,终端上面显示的最后一句话必须是:all done!(我的网络环境算比较好的,编译过程持续大约一小时)
(3)/usr/bin/目录下必须有gas-preprocessor.pl这个脚本,没有这个也会编译成功,但是运行时会报错不支持64位和32位架构,都不支持肯定是库的问题了,我又重新编译一遍。CSDN上有很多下载这个脚本的地方,具体怎么将它放到/usr/bin/目录下:
1)下载gas-preprocessor.pl;
2)打开终端,先cd到 gas-preprocessor.pl目录下,终端中输入“sudo空格-s(获取管理员权限)”,输入密码点击回车,输入“cp空格gas-preprocessor.pl空格/usr/bin/(cp是copy,这句话执行的是把 gas-preprocessor.pl复制到/usr/bin/目录下)”。
3)终端输入“chmod空格a+rwx空格/usr/bin/gas-preprocessor.pl(更改gas-preprocessor.pl的执行权限)”,结束
4.开始编译
开始编译就是按照VLCKit的步骤
(1)终端输入“git空格clone空格http://code.videolan.org/videolan/VLCKit.git”,等待下载完成,会下载到 /Users/你的用户名/ 下面
(2)cd到VLCKit目录下,“sh空格buildMobileVLCKit.sh(执行buildMobileVLCKit.sh脚本)"
(3)等......顺利的话一小时左右会出现all done!
(4)all done出现后,想要的.a的静态库并没有出现,这时再“sh空格buildMobileVLCKit.sh空格-s(编译模拟器版)”
(5)等......这次要快一些出现all done!
(6)仍然没有出现.a文件,这时再“sh空格buildMobileVLCKit.sh空格-f(编译通用版framework)”
(7)等......最后出现
(8)VLCKit目录下出现一个build文件夹
(9)至此,编译部分完成。
5.运行
新建一个简单的单视图工程,以在模拟器运行为例
(1)导入库:打开工程,选择add files ,将Release-iphonesimulator整个添加进工程(要选上copy item if needed),Xcode自动将libMobileVLCKit.a导入项目的link Binary中
(2)导入需要的其它库
注:这里有一点需要注意,AudioUnit.framework这个库应该先导入,然后在link Binary中将其减掉,不减掉的话会报错,你可以对比一下上图左右两边,左边项目文件夹下是有AudioUnit.framework的,但右边没有。至于什么原因我没有搞清楚,只是在stack overflow上有人这样说,我这样做了然后不报错,如果哪位大神看到这里知道的话可以留言说明一下!
(3)ViewController.m代码
#import "ViewController.h" #import "VLCMediaPlayer.h" @interface ViewController () <VLCMediaPlayerDelegate> @end @implementation ViewController { VLCMediaPlayer *player; UIView *mediaView; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"播放器"; self.view.backgroundColor = [UIColor whiteColor]; CGFloat statusH = [UIApplication sharedApplication].statusBarFrame.size.height; CGFloat navH = self.navigationController.navigationBar.frame.size.height; mediaView = [[UIView alloc]initWithFrame:CGRectMake(0, statusH + navH, self.view.frame.size.width, self.view.frame.size.height - statusH - navH)]; [self.view addSubview:mediaView]; CGFloat butWidth = 80.f; CGFloat butHeight = 40.f; CGFloat delta = 20.f; CGFloat screenW = self.view.frame.size.width; CGFloat screenH = [[UIScreen mainScreen]bounds].size.height; UIButton *but = [UIButton buttonWithType:UIButtonTypeRoundedRect]; but.frame = CGRectMake((screenW - 3 * butWidth - 2 * delta) / 2, screenH - butHeight - 100, butWidth, butHeight); [but setTitle:@"playRTSP" forState:UIControlStateNormal]; [but setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [but setBackgroundColor:[UIColor redColor]]; but.layer.borderColor = [[UIColor redColor]CGColor]; but.layer.borderWidth = 2.f; but.layer.cornerRadius = 10.f; [but addTarget:self action:@selector(playRTSP) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:but]; UIButton *localBut = [UIButton buttonWithType:UIButtonTypeRoundedRect]; localBut.frame = CGRectMake(but.frame.origin.x + butWidth +delta, screenH - butHeight - 100, butWidth, butHeight); [localBut setTitle:@"playLocal" forState:UIControlStateNormal]; [localBut setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [localBut setBackgroundColor:[UIColor redColor]]; localBut.layer.borderColor = [[UIColor redColor]CGColor]; localBut.layer.borderWidth = 2.f; localBut.layer.cornerRadius = 10.f; [localBut addTarget:self action:@selector(playLocalFile) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:localBut]; UIButton *stopBut = [UIButton buttonWithType:UIButtonTypeRoundedRect]; stopBut.frame = CGRectMake(localBut.frame.origin.x + butWidth + delta, screenH - butHeight - 100, butWidth, butHeight); [stopBut setTitle:@"stop" forState:UIControlStateNormal]; [stopBut setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [stopBut setBackgroundColor:[UIColor redColor]]; stopBut.layer.borderColor = [[UIColor redColor]CGColor]; stopBut.layer.borderWidth = 2.f; stopBut.layer.cornerRadius = 10.f; [stopBut addTarget:self action:@selector(stop) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:stopBut]; player = [[VLCMediaPlayer alloc]init]; player.delegate = self; player.drawable = mediaView; } - (void)playRTSP { if (player.media != NULL) { if (player.isPlaying) { [player pause]; }else{ [player play]; } }else{ player.media = [VLCMedia mediaWithURL:[NSURL URLWithString:@"rtsp://218.204.223.237:554/live/1/66251FC11353191F/e7ooqwcfbqjoo80j.sdp"]]; [player play]; } } - (void)playLocalFile { if (player.media != NULL) { if (player.isPlaying) { [player pause]; }else{ [player play]; } }else{ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docDir = [paths objectAtIndex:0]; NSString *filePath = [docDir stringByAppendingPathComponent:@"test.mp4"]; NSFileManager *fileMannager = [NSFileManager defaultManager]; if ([fileMannager fileExistsAtPath:filePath]) { player.media = [VLCMedia mediaWithPath:filePath]; [player play]; } } } - (void)stop { [player stop]; player.media = NULL; } #pragma mark - VLCMediaPlayerDelegate - (void)mediaPlayerStateChanged:(NSNotification *)aNotification { NSLog(@"mediaPlayerStateChanged name = %ld", (long)player.state); } /** * Sent by the default notification center whenever the player's time has changed. * \details Discussion The value of aNotification is always an VLCMediaPlayerTimeChanged notification. You can retrieve * the VLCMediaPlayer object in question by sending object to aNotification. */ - (void)mediaPlayerTimeChanged:(NSNotification *)aNotification { NSLog(@"mediaPlayerTimeChanged name = %@", aNotification.name); } /** * Sent by the default notification center whenever the player's title has changed (if any). * \details Discussion The value of aNotification is always an VLCMediaPlayerTitleChanged notification. You can retrieve * the VLCMediaPlayer object in question by sending object to aNotification. * \note this is about a title in the navigation sense, not about metadata */ - (void)mediaPlayerTitleChanged:(NSNotification *)aNotification { NSLog(@"mediaPlayerTitleChanged name = %@", aNotification.name); } /** * Sent by the default notification center whenever the player's chapter has changed (if any). * \details Discussion The value of aNotification is always an VLCMediaPlayerChapterChanged notification. You can retrieve * the VLCMediaPlayer object in question by sending object to aNotification. */ - (void)mediaPlayerChapterChanged:(NSNotification *)aNotification { NSLog(@"mediaPlayerChapterChanged name = %@", aNotification.name); } @end
至此,本地文件test.mp4可以正常播放并且图像声音均非常正,rtsp流还没播放成功,这两天研究后再回来更新。
七月一日更新
研究了两天,明确了几个问题:
1.前面第二点提到的两个链接,VLCKit是只编译VLC的库加上两个很简单的sample code(目前本人可以编译成功),iOSCompile是编译VLC的iOS客户端的源码(目前本人按照官网指导不能编译成功);
2.按照VLCKit的步骤,编译出的库播放rtsp实时流的时候,画面不能显示出来。具体表现为:用官方sample code(Drop-in)运行时,能看到时间在走,能正常调用VLCMediaPlayer以及VLCMedia的代理方法,程序看似很正常,但就是不出图像,画面一片黑。
对于第二点问题做的尝试:(1)从官网下载编译好的MobileVLCKit.framework,替换自己编译的库,并且把deployment target设置为6.1,可以正常显示rtsp视频流,但项目报警告,警告内容见下图,意思是库文件是为较新的iOS7.0版本创建的,但是被链接到了iOS6.1上面;
(2)用官网下载的库,但是项目里面deployment target设置为7.0,项目不能正常运行,报编译错误,见下图
3.综上,官网编译的库也是将sdk最低版本设置为iOS7.0的,但是用这个库的时候将项目的deployment target设为7.0时又用不了;编译的时候完全按照官网说法,不更改任何东西,编译出来的库播放rtsp又是上面那个吊样子,所以,该怎么办?继续研究……
七月一日更新完毕 11.09