ios实现H264裸流封装为FLV格式

本文介绍了如何在iOS平台上将H264裸流封装成FLV格式,用于实现低延迟的视频通信。通过解析H264的NALU单元并按照FLV的结构进行封装,同时讲解了FLV头信息、META TAG和视频TAG的构造。最终实现的代码能够将视频数据正确地转换并可被VLC等播放器播放。
摘要由CSDN通过智能技术生成

公司最近想承接一个通过智能手机实现视频双向通讯的功能。提前开始了技术预研究。为保证较小的延迟,和优质的视频功能,我们对手机采集的音频和视频都利用手机硬件提供的硬编码功能直接实现H264+AAC编码。封包采用目前视频网站普遍使用的FLV格式。然后通过开源的RtmpLib库,以RTMP协议发送给音视频分发服务器。从而实现延迟很小的高质量视频通讯。

作为这个实施方案的第一步,我们需要分别实现AndroidIOS手机上的H264裸流封装为FLV格式。我主要负责IOS部分的实现,经过2天的努力,终于实现了目标。看到VLC播放成功我封装的视频,实在非常有成就感。下面我把这几天的努力,总结下。

FLV是一个二进制文件,简单来说,其是由一个文件头(FLV header)和很多tag组成(FLV body)。tag又可以分成三类:audio,video,script,分别代表音频流,视频流,脚本流,而每个tag又由tag header和tag data组成。用通俗语言介绍下我的理解。FLV是音视频的容器。有固定长度的FLV Head和FLV Body组成。FLV Body由里面不同的TAG块组成。主要有3种,META TAG,在最前面,告诉后面视频或音频的头信息,从而告诉播放器播放码率和视频尺寸。这些信息都在H264裸流或AAC裸流的头部,可以直接提取封装,不需要我们解码。后面就是Video TAG视频TAG块和Audio TAG音频TAG块组成。本文只涉及视频部分,音频部分类似,不在本文述说了。

知道这些基本知识,要封装还是不容易的。我们现在通过截图来具体讲解。下面是H264裸流文件构成。

h264是一个个NALU单元组成的,每个单元以00 00 01 或者 00 00 00 01分隔开来,每2个00 00 00 01之间就是一个NALU单元。我们实际上就是将一个个NALU单元封装进FLV文件。头两个NAL块封装的数据描述了该视频的码率和版本都信息。后面就是按照时间顺序的视频数据块了。后面我们需要分割后,循环拼装到FLV格式中的。在IOS中可以用二维数组来分割和保存这些NAL块。代码如下:

-(void)initH264File:(NSString *)path{

    NSInteger fuck = 0;
    
    NSData * reader = [NSData dataWithContentsOfFile:path];//H264裸数据
    
    [reader getBytes:&fuck length:sizeof(fuck)];
    
    Byte *contentByte = (Byte *)[reader bytes];
    
    NSLog(@"fuck:%d byte len:%d",fuck,[reader length]);
    
    int count_i=-1;
    
       Byte kk;
    
    
    for(int i=0;i<[reader length];i++){
        
        
        
        
        if(contentByte[i+0]==0x00&&contentByte[i+1]==0x00&&contentByte[i+2]==0x00&&contentByte[i+3]==0x01){
            
            i=i+3;
            
            count_i++;
            
            [self.VideoListArray addObject:[[NSMutableData alloc] init]];
            
           
            
            
        }
        else if(contentByte[i+0]==0x00&&contentByte[i+1]==0x00&&contentByte[i+2]==0x00){
        
            i=i+2;
            
            count_i++;
            
            [self.VideoListArray addObject:[[NSMutableData alloc] init]];
            

        
        }
        else{
            
            if(count_i>-1){
                
                 kk=contentByte[i];
                
                [[self.VideoListArray objectAtIndex:count_i] appendBytes:&kk length:sizeof(kk)];
                
            }
            
            
        }
        
       
        
    }
    
    
    



}



后面我们看下FLV格式,首先看下图:

绿色标注的前9个Byte是FLVHead头信息。前三个是固定的'F','L','V'。前3个bytes是文件类型,总是“FLV”,也就是(0x46 0x4C 0x56)。第4btye是版本号,目前一般是0x01。第5byte是流的信息,倒数第一bit是1表示有视频(0x01),倒数第三bit是1表示有音频(0x4),有视频又有音频就是0x01 | 0x04(0x05),其他都应该是0。最后4bytes表示FLV 头的长度,3+1+1+4 = 9。 IOS代码可以如下实现:

    NSMutableData *writer = [[NSMutableData alloc] init];
        
        
      
        
        Byte i1 = 0x46;
        
        [writer appendBytes:&i1 length:sizeof(i1)];//1
        
         i1 = 0x4C;
        
         [writer appendBytes:&i1 length:sizeof(i1)];//2
        
        
        i1 = 0x56;
        
        [writer appendBytes:&i1 length:sizeof(i1)];//3
        
        
        i1 = 0x01;
        
        [writer appendBytes:&i1 length:sizeof(i1)];//4
        
         i1 = 0x01;//0x01--代表只有视频,0x05--音频和视频混合,0x04--只有音频
        
        [writer appendBytes:&i1 length:sizeof(i1)];//5
        
        i1 = 0x00;
        
        [writer appendBytes:&i1 length:sizeof(i1)];//6
        
        i1 = 0x00;
        
        [writer appendBytes:&i1 length:sizeof(i1)];//7
        
        i1 = 0x00;
        
        [writer appendBytes:&i1 length:sizeof(i1)];//8
        
        i1 = 0x09;
        
        [writer appendBytes:&i1 length:sizeof(i1)];//9
        
        


然后讲解下META TAG,如下图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值