ios使用ffmpeg解码h264数据封装。
#import "FFMpegAVCDecoder.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
};
#endif
@interface FFMpegAVCDecoder(){
AVCodec *_videoCodec;
AVCodecContext *_pCodecCtx;
AVFrame *_pFrame;
char* _yuvBuf;
}
@end
@implementation FFMpegAVCDecoder
-(int)initDecoder{
av_register_all();
/* find the video encoder */
_videoCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
_pCodecCtx = avcodec_alloc_context3(_videoCodec);
if (!_videoCodec)
return -1;
_pCodecCtx->time_base.num = 1;
_pCodecCtx->frame_number = 1; //每包一个视频帧
if(avcodec_open2(_pCodecCtx, _videoCodec,NULL) >= 0)
_pFrame = av_frame_alloc();// Allocate video frame
else
return -1;
return 0;
}
-(int)decode:(char *)buf len:(int)len{
int frameFinished = len;
AVPacket packet = {
.data = (uint8_t*)buf,
.size = len,
};
avcodec_decode_video2(_pCodecCtx, _pFrame, &frameFinished, &packet);
if(frameFinished)//成功解码
{
int picSize = _pCodecCtx->height * _pCodecCtx->width;
int newSize = picSize * 3/2;
if (!_yuvBuf) {
_yuvBuf = (char*)malloc(newSize);
}
int height = _pCodecCtx->height;
int width = _pCodecCtx->width;
//写入数据
int pos=0,i;
for (i=0; i<height; i++)
{
memcpy(_yuvBuf+pos,_pFrame->data[0] + i * _pFrame->linesize[0], width);
pos+=width;
}
for (i=0; i<height/2; i++)
{
memcpy(_yuvBuf+pos,_pFrame->data[1] + i * _pFrame->linesize[1], width/2);
pos+=width/2;
}
for (i=0; i<height/2; i++)
{
memcpy(_yuvBuf+pos,_pFrame->data[2] + i * _pFrame->linesize[2], width/2);
pos+=width/2;
}
//TODO:解码数据回调
}
return 0;
}
-(void)freeDecoder{
if(_pCodecCtx){
avcodec_close(_pCodecCtx);
_videoCodec = NULL;
}
if (_pFrame) {
av_frame_free(&_pFrame);
_pFrame = NULL;
}
if (_yuvBuf) {
free(_yuvBuf);
_yuvBuf = NULL;
}
}
@end