系统环境:ubuntu16.04
FFmpeg:4.1
x264:http://download.videolan.org/x264/snapshots/
nasm:2.13.03
yasm:1.3.0
一、编译nasm、yasm
在第一次编译ffmpeg和x264时,分别报了yasm和nasm相关的错误,解决办法就是编译安装相关库或者在编译ffmpeg和x264库时禁用,编译方法如下:
1、进入源文件目录,执行
./configure --prefix=/usr/local/ffmpeg_build/yasm
make
make install
2、进入源文件目录,执行
./configure --prefix=/usr/local/ffmpeg_build/nasm
make
make install
注意:需要在.bashrc中添加export PATH=$PATH:/usr/local/ffmpeg_build/yasm/bin:/usr/local/ffmpeg_build/nasm/bin
二、编译x264
首先进入x264的source目录,配置如下:
./configure --prefix=/usr/local/ffmpeg_build/x264 --enable-shared --enable-static
然后:
make
sudo make install
三、编译ffmpeg
./configure --prefix=/usr/local/ffmpeg_build/ffmpeg --enable-gpl --enable-version3 --enable-nonfree --enable-pthreads --enable-libx264 --enable-shared --extra-cflags=-I/usr/local/ffmpeg_build/x264/include --extra-ldflags=-L/usr/local/ffmpeg_build/x264/lib
make
sudo make install
测试代码基本来自于雷霄骅前辈(使用ffmpeg版本不同,yuv视频格式不同等)
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "libavdevice/avdevice.h"
#include "libavutil/pixfmt.h"
#include "libswscale/swscale.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/time.h"
#include "libswresample/swresample.h"
#include<stdio.h>
#define OUTWIDTH 640
#define OUTHEIGHT 480
#define FPS 25
#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index)
{
int ret;
int got_frame;
AVPacket enc_pkt;
if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
AV_CODEC_CAP_DELAY))
return 0;
while (1) {
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
NULL, &got_frame);
av_frame_free(NULL);
if (ret < 0)
break;
if (!got_frame){
ret=0;
break;
}
printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size);
/* mux encoded frame */
ret = av_write_frame(fmt_ctx, &enc_pkt);
if (ret < 0)
break;
}
return ret;
}
int main()
{
AVFormatContext * pFormatCtx = NULL;
AVCodecContext * pVCodecCtx = NULL;
AVCodec * pVCodec = NULL;
AVCodec * pVCodecEn = NULL;
AVCodecContext * pACodecCtx = NULL;
AVCodec * pACodec = NULL;
AVFrame * pFrame = NULL;
AVPacket packet;
AVPacket pkt;
AVStream * pAVstream = NULL;
AVCodecContext * pVCodecCtxEn = NULL;
enum AVPixelFormat pixFormat = 0;
struct SwsContext * pSwsCtx = NULL;
unsigned char* out_buffer_rgb;
int videoindex = -1;
int audioindex = 0;
int sampleRate = 0;
int sampleSize = 0;
int channel = 0;
int gotPicture = 0;
int i = 0;
int ret = 0;
int framecnt = 0;
enum AVPixelFormat dst_pix_fmt = AV_PIX_FMT_YUV422P;
const char *dst_size = NULL;
const char *src_size = NULL;
uint8_t *src_data[4];
uint8_t *dst_data[4];
int src_linesize[4];
int dst_linesize[4];
int src_bufsize = 0;
int dst_bufsize = 0;
int src_w = 0;
int src_h = 0;
int dst_w = 0;
int dst_h = 0;
int got_output = 0;
int picture_size = 0;
uint8_t *picture_buf;
FILE *in_file = fopen("out_plant.yuv", "rb"); //Input raw YUV data
int in_w=640,in_h=480; //Input data's width and height
int framenum=200; //Frames to encode
const char* out_file = "out_plant.h264";
av_register_all();
pFormatCtx = avformat_alloc_context();
pFormatCtx->oformat = av_guess_format(NULL, out_file, NULL);
//(1)register device
avdevice_register_all();
//Open output URL
if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){
printf("Failed to open output file! \n");
return -1;
}
//(b)init AVSteam
pAVstream = avformat_new_stream(pFormatCtx, pVCodecEn);
if(pAVstream == NULL)
printf("Create stream error!");
//pAVstream->id = pFormatCtx->nb_streams - 1;
//(c)set AVCodecContext param
pVCodecCtxEn = pAVstream->codec;
avcodec_get_context_defaults3(pVCodecCtxEn, pVCodecEn);
pVCodecCtxEn->codec_id = AV_CODEC_ID_H264;
pVCodecCtxEn->width = OUTWIDTH;
pVCodecCtxEn->height = OUTHEIGHT;
pVCodecCtxEn->time_base.den = FPS; //分母
pVCodecCtxEn->time_base.num = 1; //分子
pVCodecCtxEn->pix_fmt = AV_PIX_FMT_YUV422P;
pVCodecCtxEn->codec_type = AVMEDIA_TYPE_VIDEO;
pVCodecCtxEn->me_range = 16;
pVCodecCtxEn->max_qdiff = 4;
pVCodecCtxEn->qcompress = 0.6;
pVCodecCtxEn->qmin = 10;
pVCodecCtxEn->qmax = 51;
//Optional Param
pVCodecCtxEn->max_b_frames=3;
if(pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
pVCodecCtxEn->flags|= CODEC_FLAG_GLOBAL_HEADER;
//(d)set AVOptions param
av_opt_set(pVCodecCtxEn->priv_data, "preset", "slow", 0);
av_opt_set(pVCodecCtxEn->priv_data, "tune","zerolatency",0);
av_opt_set(pVCodecCtxEn->priv_data, "x264opts","crf=26:vbv-maxrate=728:vbv-bufsize=3640:keyint=25",0);
avcodec_parameters_from_context(pAVstream->codecpar, pVCodecCtxEn);
//Show some Information
av_dump_format(pFormatCtx, 0, out_file, 1);
if(pFrame == NULL)
pFrame = av_frame_alloc();
picture_size = avpicture_get_size(pVCodecCtxEn->pix_fmt, pVCodecCtxEn->width, pVCodecCtxEn->height);
picture_buf = (uint8_t *)av_malloc(picture_size);
avpicture_fill((AVPicture *)pFrame, picture_buf, pVCodecCtxEn->pix_fmt, pVCodecCtxEn->width, pVCodecCtxEn->height);
//(e)打开编码器
pVCodecEn = avcodec_find_encoder(AV_CODEC_ID_H264);
if(pVCodecEn == NULL)
printf("Find encoder error!");
avcodec_open2(pVCodecCtxEn, pVCodecEn, NULL);
//写入数据流的头部
avformat_write_header(pFormatCtx, NULL);
av_new_packet(&pkt,picture_size);
int y_size = pVCodecCtxEn->width * pVCodecCtxEn->height;
//(5)get one frame
for (int i=0; i<framenum; i++){
//Read raw YUV data
if (fread(picture_buf, 1, y_size*2, in_file) <= 0){
printf("Failed to read raw data! \n");
return -1;
}else if(feof(in_file)){
break;
}
pFrame->data[0] = picture_buf; // Y
pFrame->data[1] = picture_buf+ y_size; // U
pFrame->data[2] = picture_buf+ y_size*3/2; // V
//PTS
//pFrame->pts=i;
pFrame->pts=i*(pAVstream->time_base.den)/((pAVstream->time_base.num)*25);
pFrame->format = pVCodecCtxEn->pix_fmt;
pFrame->width = pVCodecCtxEn->width;
pFrame->height = pVCodecCtxEn->height;
int got_picture=0;
//Encode
int ret = avcodec_encode_video2(pVCodecCtxEn, &pkt,pFrame, &got_picture);
if(ret < 0){
printf("Failed to encode! \n");
return -1;
}
if (got_picture==1){
printf("Succeed to encode frame: %5d\tsize:%5d\n",framecnt,pkt.size);
framecnt++;
pkt.stream_index = pAVstream->index;
ret = av_write_frame(pFormatCtx, &pkt);
av_free_packet(&pkt);
}
}
//Flush Encoder
ret = flush_encoder(pFormatCtx,0);
if (ret < 0) {
printf("Flushing encoder failed\n");
return -1;
}
//Write file trailer
av_write_trailer(pFormatCtx);
//Clean
if (pAVstream){
avcodec_close(pAVstream->codec);
av_free(pFrame);
av_free(picture_buf);
}
avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
fclose(in_file);
return 0;
}
执行过程及结果(共编码200帧图像):
muyangren@muyangren-N85-87HP6:~/projectdir/ffmpeg/ffmpeg_toh264$ ./ffmpeg_toh264
Output #0, h264, to 'out_plant.h264':
Stream #0:0: Video: h264, yuv422p, 640x480, q=10-51, 128 kb/s, 25 tbc
[libx264 @ 0x82e200] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 0x82e200] profile High 4:2:2, level 3.0, 4:2:2, 8-bit
Succeed to encode frame: 0 size: 8221
Succeed to encode frame: 1 size: 9006
Succeed to encode frame: 2 size: 1764
Succeed to encode frame: 3 size: 464
Succeed to encode frame: 4 size: 514
Succeed to encode frame: 5 size:36064
Succeed to encode frame: 6 size: 3285
Succeed to encode frame: 7 size: 2481
Succeed to encode frame: 8 size: 5131
Succeed to encode frame: 9 size:30492
Succeed to encode frame: 10 size:16233
Succeed to encode frame: 11 size:10406
Succeed to encode frame: 12 size:10084
Succeed to encode frame: 13 size:104457
Succeed to encode frame: 14 size:81313
Succeed to encode frame: 15 size:70437
Succeed to encode frame: 16 size:70868
Succeed to encode frame: 17 size:121538
Succeed to encode frame: 18 size:96800
Succeed to encode frame: 19 size:77992
Succeed to encode frame: 20 size:95682
Succeed to encode frame: 21 size:98927
Succeed to encode frame: 22 size:108962
Succeed to encode frame: 23 size:100945
Succeed to encode frame: 24 size:99991
Succeed to encode frame: 25 size:120900
Succeed to encode frame: 26 size:107744
Succeed to encode frame: 27 size:100738
Succeed to encode frame: 28 size:101717
Succeed to encode frame: 29 size:122759
Succeed to encode frame: 30 size:110856
Succeed to encode frame: 31 size:101093
Succeed to encode frame: 32 size:99972
Succeed to encode frame: 33 size:132027
Succeed to encode frame: 34 size:104074
Succeed to encode frame: 35 size:99740
Succeed to encode frame: 36 size:99362
Succeed to encode frame: 37 size:122959
Succeed to encode frame: 38 size:110299
Succeed to encode frame: 39 size:100714
Succeed to encode frame: 40 size:101045
Succeed to encode frame: 41 size:122487
Succeed to encode frame: 42 size:110026
Succeed to encode frame: 43 size:99191
Succeed to encode frame: 44 size:100115
Succeed to encode frame: 45 size:131804
Succeed to encode frame: 46 size:111281
Succeed to encode frame: 47 size:99628
Succeed to encode frame: 48 size:99923
Succeed to encode frame: 49 size:122581
Succeed to encode frame: 50 size:109921
Succeed to encode frame: 51 size:101580
Succeed to encode frame: 52 size:101668
Succeed to encode frame: 53 size:122770
Succeed to encode frame: 54 size:110749
Succeed to encode frame: 55 size:101419
Succeed to encode frame: 56 size:100875
Succeed to encode frame: 57 size:132096
Succeed to encode frame: 58 size:108970
Succeed to encode frame: 59 size:99827
Succeed to encode frame: 60 size:102186
Succeed to encode frame: 61 size:118839
Succeed to encode frame: 62 size:106438
Succeed to encode frame: 63 size:101507
Succeed to encode frame: 64 size:97485
Succeed to encode frame: 65 size:121102
Succeed to encode frame: 66 size:113450
Succeed to encode frame: 67 size:100217
Succeed to encode frame: 68 size:101289
Succeed to encode frame: 69 size:132923
Succeed to encode frame: 70 size:108032
Succeed to encode frame: 71 size:101016
Succeed to encode frame: 72 size:98123
Succeed to encode frame: 73 size:121372
Succeed to encode frame: 74 size:110457
Succeed to encode frame: 75 size:98263
Succeed to encode frame: 76 size:100309
Succeed to encode frame: 77 size:122598
Succeed to encode frame: 78 size:105808
Succeed to encode frame: 79 size:101203
Succeed to encode frame: 80 size:99721
Succeed to encode frame: 81 size:133043
Succeed to encode frame: 82 size:108716
Succeed to encode frame: 83 size:100727
Succeed to encode frame: 84 size:99229
Succeed to encode frame: 85 size:120559
Succeed to encode frame: 86 size:109741
Succeed to encode frame: 87 size:98506
Succeed to encode frame: 88 size:99125
Succeed to encode frame: 89 size:118353
Succeed to encode frame: 90 size:111846
Succeed to encode frame: 91 size:101565
Succeed to encode frame: 92 size:102864
Succeed to encode frame: 93 size:133425
Succeed to encode frame: 94 size:106613
Succeed to encode frame: 95 size:99064
Succeed to encode frame: 96 size:101341
Succeed to encode frame: 97 size:118688
Succeed to encode frame: 98 size:110149
Succeed to encode frame: 99 size:100259
Succeed to encode frame: 100 size:102103
Succeed to encode frame: 101 size:116659
Succeed to encode frame: 102 size:101508
Succeed to encode frame: 103 size:96535
Succeed to encode frame: 104 size:95929
Succeed to encode frame: 105 size:126513
Succeed to encode frame: 106 size:103438
Succeed to encode frame: 107 size:96130
Succeed to encode frame: 108 size:98043
Succeed to encode frame: 109 size:116981
Succeed to encode frame: 110 size:106913
Succeed to encode frame: 111 size:99902
Succeed to encode frame: 112 size:98440
Succeed to encode frame: 113 size:116805
Succeed to encode frame: 114 size:106101
Succeed to encode frame: 115 size:100754
Succeed to encode frame: 116 size:101055
Succeed to encode frame: 117 size:125945
Succeed to encode frame: 118 size:104980
Succeed to encode frame: 119 size:99646
Succeed to encode frame: 120 size:99337
Succeed to encode frame: 121 size:115403
Succeed to encode frame: 122 size:107429
Succeed to encode frame: 123 size:100735
Succeed to encode frame: 124 size:100003
Succeed to encode frame: 125 size:118311
Succeed to encode frame: 126 size:109707
Succeed to encode frame: 127 size:99798
Succeed to encode frame: 128 size:105469
Succeed to encode frame: 129 size:138952
Succeed to encode frame: 130 size:125012
Succeed to encode frame: 131 size:119121
Succeed to encode frame: 132 size:119369
Succeed to encode frame: 133 size:134233
Succeed to encode frame: 134 size:123969
Succeed to encode frame: 135 size:118485
Succeed to encode frame: 136 size:113174
Succeed to encode frame: 137 size:131688
Succeed to encode frame: 138 size:119397
Succeed to encode frame: 139 size:113753
Succeed to encode frame: 140 size:109263
Succeed to encode frame: 141 size:137466
Succeed to encode frame: 142 size:120664
Succeed to encode frame: 143 size:110717
Succeed to encode frame: 144 size:110870
Succeed to encode frame: 145 size:131404
Succeed to encode frame: 146 size:122188
Succeed to encode frame: 147 size:113175
Succeed to encode frame: 148 size:113295
Succeed to encode frame: 149 size:127729
Succeed to encode frame: 150 size:119558
Succeed to encode frame: 151 size:112632
Succeed to encode frame: 152 size:112992
Succeed to encode frame: 153 size:132495
Succeed to encode frame: 154 size:114782
Succeed to encode frame: 155 size:111014
Succeed to encode frame: 156 size:109319
Succeed to encode frame: 157 size:121903
Succeed to encode frame: 158 size:112150
Succeed to encode frame: 159 size:109138
Succeed to encode frame: 160 size:107309
Succeed to encode frame: 161 size:122856
Succeed to encode frame: 162 size:111643
Succeed to encode frame: 163 size:106370
Succeed to encode frame: 164 size:107580
Succeed to encode frame: 165 size:135754
Succeed to encode frame: 166 size:119013
Succeed to encode frame: 167 size:111259
Succeed to encode frame: 168 size:109008
Succeed to encode frame: 169 size:126156
Succeed to encode frame: 170 size:118951
Succeed to encode frame: 171 size:108586
Succeed to encode frame: 172 size:112581
Succeed to encode frame: 173 size:122728
Succeed to encode frame: 174 size:117275
Succeed to encode frame: 175 size:111313
Succeed to encode frame: 176 size:109611
Succeed to encode frame: 177 size:126414
Succeed to encode frame: 178 size:113918
Succeed to encode frame: 179 size:109472
Succeed to encode frame: 180 size:109342
Succeed to encode frame: 181 size:125230
Succeed to encode frame: 182 size:115638
Succeed to encode frame: 183 size:109199
Succeed to encode frame: 184 size:111231
Succeed to encode frame: 185 size:126982
Succeed to encode frame: 186 size:118327
Flush Encoder: Succeed to encode 1 frame! size:111735
Flush Encoder: Succeed to encode 1 frame! size:113697
Flush Encoder: Succeed to encode 1 frame! size:132893
Flush Encoder: Succeed to encode 1 frame! size:110890
Flush Encoder: Succeed to encode 1 frame! size:107830
Flush Encoder: Succeed to encode 1 frame! size:108678
Flush Encoder: Succeed to encode 1 frame! size:126643
Flush Encoder: Succeed to encode 1 frame! size:115959
Flush Encoder: Succeed to encode 1 frame! size:113816
Flush Encoder: Succeed to encode 1 frame! size:108753
Flush Encoder: Succeed to encode 1 frame! size:115985
Flush Encoder: Succeed to encode 1 frame! size:118184
Flush Encoder: Succeed to encode 1 frame! size:112657
[libx264 @ 0x82e200] frame I:17 Avg QP:12.11 size:117023
[libx264 @ 0x82e200] frame P:34 Avg QP:10.79 size:116021
[libx264 @ 0x82e200] frame B:149 Avg QP:11.46 size: 99926
[libx264 @ 0x82e200] consecutive B-frames: 0.5% 0.0% 1.5% 98.0%
[libx264 @ 0x82e200] mb I I16..4: 8.2% 45.3% 46.5%
[libx264 @ 0x82e200] mb P I16..4: 5.3% 34.0% 24.1% P16..4: 16.3% 12.0% 6.2% 0.0% 0.0% skip: 2.2%
[libx264 @ 0x82e200] mb B I16..4: 2.5% 22.4% 13.3% B16..8: 21.5% 13.2% 4.8% direct:16.9% skip: 5.4% L0:20.5% L1:21.5% BI:58.1%
[libx264 @ 0x82e200] final ratefactor: -10.58
[libx264 @ 0x82e200] 8x8 transform intra:55.2% inter:23.0%
[libx264 @ 0x82e200] coded y,uvDC,uvAC intra: 98.3% 98.3% 97.8% inter: 77.2% 88.6% 86.3%
[libx264 @ 0x82e200] i16 v,h,dc,p: 10% 3% 13% 74%
[libx264 @ 0x82e200] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 12% 10% 22% 7% 10% 10% 10% 8% 10%
[libx264 @ 0x82e200] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 9% 11% 13% 9% 13% 11% 16% 8% 11%
[libx264 @ 0x82e200] i8c dc,h,v,p: 80% 2% 4% 13%
[libx264 @ 0x82e200] Weighted P-Frames: Y:17.6% UV:14.7%
[libx264 @ 0x82e200] kb/s:5.78
使用ffplay播放,编码得到的x264文件:
支持x264编码的ffmpeg相关源码包,上传资源为:ffmpeg_with_x264.tar.gz