IOS上编译ffmpeg 播放本地 .h264视频(三)---播放网络视频流

http://blog.csdn.net/u013028303/article/details/41308519

 

写作前面:继能够播放本地的.h264文件后,就只剩最后一个功能——播放网络视频了。这个工程用的时socket接受数据的方式。

 

 

主要的思路是:主要有三个线程,主线程负责显示图片,线程二负责解码,线程三负责接收网络数据。当用户点击播放开始建立socket连接,然后启动解码线程,并循环从线程三取数据来解码。

 

一、准备工作

1.点击下载AsyncSocket库文件,并将AsyncSocket.h、AsyncSocket.m添加到工程中。

2.添加CFNetwork.framework。

 

二、建立连接

 

 

[objc] view plaincopy
 
  1. AsyncSocket *asyncSocket;  

 

 

[objc] view plaincopy
 
  1. <span style="font-size:18px;">    NSError *err = nil;  
  2.     NSString *serveIP = @"10.0.0.29";  
  3.     const UInt16    port = 8000;  
  4.     asyncSocket = [[AsyncSocket alloc] initWithDelegate:self];  
  5.     NSLog(@"serveIP is %@",serveIP);  
  6.     if (![asyncSocket connectToHost:serveIP onPort:port error:&err]) {  
  7.         NSLog(@"Error: %@",err);  
  8.     }  
  9.     [asyncSocket readDataWithTimeout:-1 tag:0];//开始接受数据  
  10. </span>  

在这里我直接写了固定的IP地址以及端口,当然也可以一个textField来填写IP。

 

 

[objc] view plaincopy
 
  1. -(void)textFieldDidBeginEditing:(UITextField *)textField{  
  2.     [textField becomeFirstResponder];  
  3. }  
  4.   
  5. -(BOOL)textFieldShouldReturn:(UITextField *)textField{  
  6.     [textField resignFirstResponder];  
  7.     serveIP = textField.text;  
  8.     [ipField removeFromSuperview];  
  9.     return YES;  
  10. }  

 

当点击textfield时响应并弹出键盘,完成输入时将输入的值赋给serveIP然后销毁textfield。

 

三、接受数据

 

[objc] view plaincopy
 
  1. NSMutableData *dataAll = [[NSMutableData alloc] init];//用来累积每次收到的数据  

 

 

[objc] view plaincopy
 
  1. <pre name="code" class="objc"><span style="font-family: Arial, Helvetica, sans-serif;">-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{</span><span style="font-family: Arial, Helvetica, sans-serif;">    </span>  

[dataAll appendData:data];}

 


这个函数是AsyncSocket判断收到数据时自动执行的函数,在这里我用一个MutableData来累积每次data的数据。

 

 

四、内存拷贝的函数

 

[objc] view plaincopy
 
  1. NSMutableData *dataTem = [[NSMutableArray alloc] init];  

 

 

[objc] view plaincopy
 
  1. -(BOOL)memoryCopy{  
  2.     dataTem = [dataAll copy];  
  3.     NSLog(@"拷贝完成!");  
  4.     [dataAll init];  
  5.     isReceive = NO;  
  6.     return YES;  
  7.   
  8. }  

当解码开始或者完成时调用该函数,把dataAll也就是累积下来的数据传送到dataTem也就是解码数据Buff中。

 

 

五、修改解码函数

 

[objc] view plaincopy
 
  1. while (!playButton.enabled) {  
  2.          
  3.        [self memoryCopy];  
  4.        readBuf = [dataTem bytes];  
  5.          
  6.        if(readFileLen <= 0){  
  7.              
  8.        }else{  
  9.            int handleLen = 0;  
  10.            int handleFileLen = [dataTem length];  
  11.              
  12.            while(handleFileLen >0){  
  13.                int nLength = av_parser_parse2(avParserContext,codec_, &parseBuf, &parseBufLen, readBuf + handleLen, handleFileLen, 0, 0, 0);//查找264帧头  
  14.                handleFileLen -= nLength;  
  15.                handleLen += nLength;  
  16.                  
  17.                if(parseBufLen <= 0){  
  18.                    continue;  
  19.                }else{  
  20.                }  
  21.                  
  22.                packetBuf.size = parseBufLen;  
  23.                packetBuf.data = parseBuf;  
  24.                  
  25.                while (packetBuf.size > 0) {  
  26.                    int decodeLen = avcodec_decode_video2(codec_, pFrame_, &frameFinished, &packetBuf);  
  27.                    if(decodeLen <= 0){  
  28.                        break;  
  29.                    }  
  30.                    packetBuf.size -= decodeLen;  
  31.                    packetBuf.data += decodeLen;  
  32.                      
  33.                    if (frameFinished >0) {  
  34.   
  35.                        avpicture_get_size(PIX_FMT_RGB24, codec_->width, codec_->height);                  
  36.                          
  37.                        [self performSelectorOnMainThread:@selector(displayPhoto) withObject:nil waitUntilDone:YES];  
  38.                          
  39.                        [NSThread sleepForTimeInterval:0.02];  
  40.                    }  
  41.                }  
  42.            }  
  43.        }  
  44.    }  

将上一篇播放本地h264文件的解码函数替换成这个,当按键按下时

 

 

[objc] view plaincopy
 
  1. [playButton setEnabled:NO];  

 

 

这样就完成了网络视频流的播放。

posted on 2015-09-01 18:01  pTrack  阅读(378)  评论(0)    收藏  举报