在iOS平台使用ffmpeg解码h264视频流(转)

本文介绍了如何在iOS平台上利用ffmpeg库解码h264视频流,详细讲解了手动设定AVCodec和AVCodecContext的过程,以及如何检测nal unit类型,确保SPS、PPS和IDR帧的正确传递。文中还提到了使用Objective-C类配合CocoaAsyncSocket接收视频流,并提到解码后的YUV数据通过OpenGL进行播放。
摘要由CSDN通过智能技术生成

在iOS平台使用ffmpeg解码h264视频流,有需要的朋友可以参考下。

对于视频文件和rtsp之类的主流视频传输协议,ffmpeg提供avformat_open_input接口,直接将文件路径或URL传入即可打开。读取视频数据、解码器初始参数设置等,都可以通过调用API来完成。

但是对于h264流,没有任何封装格式,也就无法使用libavformat。所以许多工作需要自己手工完成。

这里的h264流指AnnexB,也就是每个nal unit以起始码00 00 00 01 或 00 00 01开始的格式。关于h264码流格式,可以参考这篇文章

首先是手动设定AVCodec和AVCodecContext:

AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
AVCodecContext *codecCtx = avcodec_alloc_context3(codec);
avcodec_open2(codecCtx, codec, nil);

在AVCodecContext中会保存很多解码需要的信息,比如视频的长和宽,但是现在我们还不知道。

这些信息存储在h264流的SPS(序列参数集)和PPS(图像参数集)中。

对于每个nal unit,起始码后面第一个字节的后5位,代表这个nal unit的类型。7代表SPS,8代表PPS。一般在SPS和PPS后面的是IDR帧,无需前面帧的信息就可以解码,用5来代表。

检测nal unit类型的方法:

- (int)typeOfNalu:(NSData *)data
{
    char first = *(char *)[data bytes];
    return first & 0x1f;
}

264解码器在解码SPS和PPS的时候会提取出视频的信息,保存在AVCodecContext中。但是只把SPS和PPS传递进去是不行的,需要把后面的IDR帧一起传给解码器,才能够正确解码。

可以写一个简单的检测,如果接收到SPS,就把后面的PPS和IDR帧都接收过来,然后一起传给解码器。

初始化一个AVPacket和AVFrame,然后把SPS、PPS、IDR帧连在一起的数据块传给AVPacket的data指针,再进行解码。

我们假设包含SPS、PPS、IDR帧的数据块保存在videoData中,长度为len。

char *videoData;
int len;
AVFrame *frame = av_frame_alloc();
AVPacket packet;
av_new_packet(&packet, len);
memcpy(packet.data, videoData, len);
int ret, got_picture;
ret = avcodec_decode_video2(codecCtx, frame, &got_picture, &packet);
if (ret > 0){
    if(got_picture){
    //进行下一步的处理
    }
}

这样就可以顺利解码h264流了,解码出的数据保存在AVFrame中。

我写了一个Objective-C类用来执行接收视频流、解码、播放一系列步骤。

视频数据的接收采用socket直接接收,使用了开源项目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值