X264_frame函数执行编码过程。需要注意的是data参数保存了需要编码的数据,是一个四维的数组,要把它转换成一维数组用于S3C6410编码器输入。另外,编码数据存在空的情况,也就是空帧。这是需要处理的,方法是返回“0”,表示没有输出数据,否则程序运行时会出现段错误。
static int X264_frame(AVCodecContext *ctx,uint8_t *buf,int bufsize,void *data){
……
//空间转换
if(frame){
memcpy(x4>in_buf,frame>data[0],ctx>width*ctx>height);
memcpy(x4>in_buf+ctx>width*ctx>height,frame>data[1],ctx>width*ctx>height/4);
memcpy(x4>in_buf+ctx>width*ctx>height+ctx>width*ctx>height/4,frame>data[2],
ctx>width*ctx>height/4);
}
else
return 0;//空帧,返回
//执行编码过程
ioctl(x4>dev_fd,S3C_MFC_IOCTL_MFC_H264_ENC_EXE,&x4>enc_exe);
//编码数据输出
bufsize = x4>enc_exe.out_encoded_size;
memcpy(buf,x4>out_buf,bufsize);
……
return bufsize;
}
X264_close关闭函数用于编码结束后的资源释放,包括取消空间映射和关闭设备文件。
static av_cold int X264_close(AVCodecContext *avctx){
…
//取消空间映射
munmap(x4>addr,BUF_SIZE);
//关闭设备文件
close(x4>dev_fd);
return 0;
}
解码函数的实现过程类似于编码函数,包括空间转换、执行解码和解码数据输出。初始化时使用S3C_MFC_IOCTL_MFC_H264_DEC_INIT参数,执行时使用S3C_MFC_IOCTL_MFC_H264_ENC_EXE参数。
4 运行测试
s3cx264编解码器添加到FFmpeg后,可以通过以下方式测试:
① 用如下命令编译FFmpeg。
./configure enablecrosscompile
arch=armv6 cpu=armv6
targetos=linux crossprefix
=http://www.likecs.com/usr/local/arm/4.3.2/bin/
armlinux
② 运行 ./ffmpeg codecs查看可以找到s3cx264编解码器,如图2所示。
图2 FFmpeg显示s3cx264编解码器信息
③ 结合USB摄像头测试s3cx264编码。运行 ./ffmpeg s 320x240 r 50 f video4linux2 i /dev/video2 vcodec s3cx264 test.mp4 可以看到FFmpegg正使用s3cx264编码器将USB摄像头采集的数据编码压缩成test.mp4文件。test.mp4能够正常播放显示。
以上测试说明已经成功地将s3cx264硬件视频编码器添加到了FFmpeg中,能够编码视频数据,可以运用到其他使用FFmpeg库的多媒体程序中。
结语
对于多媒体开发来说,编解码时使用FFmpeg多媒体库是一个不错的选择,支持较多的音视频编解码,编程接口简单易用。了解FFmpeg编解码过程,熟悉FFmpeg硬件编解码器添加方法,对多媒体开发,尤其是资源有限的嵌入式多媒体开发有很大帮助。本文通过分析FFmpeg视频编解码过程和三星S3C6410处理器视频硬件编解码方法,在FFmpeg库中成功添加S3C6410硬件编解码器,使FFmpeg库具有H.264视频格式的硬件编解码能力,可运用于游戏设备、监控设备、视频会议设备和数字网络电视等嵌入式系统中,同时也为其他嵌入式设备添加别的视频格式的编解码器到FFmpeg多媒体库提供了参考。