iOS 使用libx264编码视频

转载

首先视频采集使用AVCaptureSession,输出参数设置如下

 AVCaptureVideoDataOutput *newVideoOutput = [[AVCaptureVideoDataOutputalloc] init];

    [newVideoOutput setAlwaysDiscardsLateVideoFrames:YES];

    NSDictionary *settings = [[NSDictionaryalloc] initWithObjectsAndKeys:

                              [NSNumbernumberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange],

//                              [NSNumber numberWithInt:kCVPixelFormatType_32BGRA],

                              kCVPixelBufferPixelFormatTypeKey,

                             nil];


在代理里面取得视频的buffer,先把x264编译,我参照了http://blog.csdn.net/ixfly/article/details/7621258。

首先到http://www.videolan.org/developers/x264.html下载x264的库,然后解压,我解压出是x264-snapshot-20130604-2245文件夹

打开shell,进入x264的目录,执行如下语句

CC=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc ./configure --host=arm-apple-darwin --sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk --prefix='dist' --extra-cflags='-arch armv7s' --extra-ldflags='-arch armv7s -L/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/usr/lib/system' --enable-pic

然后make&&make install,libx264.a就出来啦。

libx264.a添加到工程

将x264目录手动拷贝到工程下面,方便以后跟着工程走



在xcode下面BuildSetting里面设置Header Search Paths,一相对路径的形式指向你刚才拷贝的目录


好啦,现在可以使用x264了

要包含下面三个.h文件

#include "x264.h"

#include "common/common.h"

#include "encoder/set.h"

我写了个x264管理的类

代码如下

头文件

#import <Foundation/Foundation.h>

#import <CoreMedia/CoreMedia.h>

#include "x264.h"

#include "common/common.h"

#include "encoder/set.h"


@interface x264Manager :NSObject{

   x264_param_t * p264Param;

   x264_picture_t * p264Pic;

   x264_t *p264Handle;

   x264_nal_t  *p264Nal;

   int previous_nal_size;

   unsigned  char * pNal;

   FILE *fp;

   unsigned char szBodyBuffer[1024*32];

}


- (void)initForX264;//初始化x264

- (void)initForFilePath;//初始化编码后文件的保存路径

- (void)encoderToH264:(CMSampleBufferRef )pixelBuffer;//将CMSampleBufferRef格式的数据编码成h264并写入文件

@end


//

//  x264Manager.m

//  IOSCamDemo

//

//  Created by huangyuling on 6/5/13.

//  Copyright (c) 2013 hyl. All rights reserved.

//


#import "x264Manager.h"


@implementation x264Manager


- (void)initForX264{

 

        p264Param =malloc(sizeof(x264_param_t));

        p264Pic  =malloc(sizeof(x264_picture_t));

        memset(p264Pic,0,sizeof(x264_picture_t));

        //x264_param_default(p264Param);  //set default param

        x264_param_default_preset(p264Param,"veryfast","zerolatency");

        p264Param->i_threads =1;

       p264Param->i_width   =352//set frame width

        p264Param->i_height  =288//set frame height

        p264Param->b_cabac =0;

        p264Param->i_bframe =0;

        p264Param->b_interlaced=0;

        p264Param->rc.i_rc_method=X264_RC_ABR;//X264_RC_CQP

        p264Param->i_level_idc=21;

        p264Param->rc.i_bitrate=128;

        p264Param->b_intra_refresh =1;

        p264Param->b_annexb =1;

        p264Param->i_keyint_max=25;

        p264Param->i_fps_num=15;

        p264Param->i_fps_den=1;

        p264Param->b_annexb =1;

        //    p264Param->i_csp = X264_CSP_I420;

        x264_param_apply_profile(p264Param,"baseline");

       if((p264Handle =x264_encoder_open(p264Param)) ==NULL)

        {

            fprintf(stderr, "x264_encoder_open failed/n" );

           return ;

        }

        x264_picture_alloc(p264Pic,X264_CSP_I420,p264Param->i_width,p264Param->i_height);

       p264Pic->i_type =X264_TYPE_AUTO;


  

}


- (void)initForFilePath{

    char *path = [selfGetFilePathByfileName:"IOSCamDemo.h264"];

   NSLog(@"%s",path);

   fp = fopen(path,"wb");

}


- (char*)GetFilePathByfileName:(char*)filename


{

    NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);

   NSString *documentsDirectory = [paths objectAtIndex:0];

   NSString *strName = [NSStringstringWithFormat:@"%s",filename];

    

   NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:strName];

    

   int len = [writablePath length];

    

   char *filepath = (char*)malloc(sizeof(char) * (len +1));

    

    [writablePath getCString:filepathmaxLength:len + 1encoding:[NSStringdefaultCStringEncoding]];

    

   return filepath;

}


- (void)encoderToH264:(CMSampleBufferRef)sampleBuffer{

    

   CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    

    CVPixelBufferLockBaseAddress(pixelBuffer,0);

   

   uint8_t  *baseAddress0 = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer,0);

   uint8_t  *baseAddress1 = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer,1);

    

   int         i264Nal;

    x264_picture_t pic_out;

    

   memcpy(p264Pic->img.plane[0], baseAddress0,352*288);

   uint8_t * pDst1 = p264Pic->img.plane[1];

   uint8_t * pDst2 = p264Pic->img.plane[2];

   for( int i =0; i < 352*288/4; i ++ )

    {

        *pDst1++ = *baseAddress1++;

        *pDst2++ = *baseAddress1++;

    }

    

   if( x264_encoder_encode(p264Handle, &p264Nal, &i264Nal,p264Pic ,&pic_out) < 0 )

    {

        fprintf(stderr, "x264_encoder_encode failed/n" );

    }

    NSLog(@"i264Nal======%d",i264Nal);

    

   if (i264Nal > 0) {

        

       int i_size;

       char * data=(char *)szBodyBuffer+100;

       for (int i=0 ; i<i264Nal; i++) {

            if (p264Handle->nal_buffer_size <p264Nal[i].i_payload*3/2+4) {

                p264Handle->nal_buffer_size =p264Nal[i].i_payload*2+4;

               x264_free( p264Handle->nal_buffer );

                p264Handle->nal_buffer =x264_malloc(p264Handle->nal_buffer_size );

            }

            i_size =p264Nal[i].i_payload;

            

            memcpy(data,p264Nal[i].p_payload,p264Nal[i].i_payload);

           fwrite(data, 1, i_size,fp);

        }

        

    }

    CVPixelBufferUnlockBaseAddress(pixelBuffer,0);

}


@end


注意到这里x264设置的时候也是352x288的,要与上面output里面设置的一致才好,你也选择其他宽高


然后先初始化保存路径,在哪里初始化自己选择,我的程序是

[self.manager264initForFilePath];

AVCaptureVideoDataOutputSampleBufferDelegate代理的方法中我们会获得数据,在那里调用前面的方法编码,不过记得编码签要初始化x264,我实在一开始就初始化了

 x264Manager *m264 = [[x264Manageralloc]init];

        [m264initForX264];

       self.manager264 = m264;

        [m264release];

下面是代理的方法

#pragma - remark AVCaptureVideo(Audio)DataOutputSampleBufferDelegate method

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{

   if (captureOutput == self.captureManager.videOutput) {

        [self.manager264encoderToH264:sampleBuffer];

    }

}

感觉差不多结束了,以后发现漏了啥再补充吧

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值