二、ffmpeg 将YUV编码为.h264
1.下载安装ffmpeg
./configure --enable-libx264 --enable-gpl --enable-shared
make
make install
2.用安装好的ffmpeg用命令将YUV编码为.h264
ffmpeg -s 480x272 -i ds_480x272.yuv -r 25 -vcodec libx264 ds2.h264
yuv文件:
https://github.com/leixiaohua1020/simplest_ffmpeg_video_encoder/blob/master/ds_480x272.yuv
3.用C语言代码调用ffmpeg接口将YUV编码为.h264
编译命令:编译之前,执行下ldconfig命令,把libx264库更新到系统库路径;
gcc simplest_ffmpeg_video_encoder_pure.cpp -g -o sffmpegencoder -I /usr/local/include -L /usr/local/lib -lavformat -lavcodec -lavutil
代码如下
simplest_ffmpeg_video_encoder_pure.cpp
-
/*
-
* Simplest FFmpeg Video Encoder Pure
-
*
-
* Lei Xiaohua
-
* Communication University of China / Digital TV Technology
-
* http://blog.csdn.net/leixiaohua1020
-
*
-
* This software encode YUV420P data to video bitstream
-
* (Such as H.264, H.265, VP8, MPEG2 etc).
-
* It only uses libavcodec to encode video (without libavformat)
-
* It's the simplest video encoding software based on FFmpeg.
-
* Suitable for beginner of FFmpeg
-
*
-
*
-
* modify: openswc
-
* build:
-
* gcc simplest_ffmpeg_video_encoder_pure.cpp -g -o sffmpegencoder -I /usr/local/include -L /usr/local/lib -lavformat -lavcodec -lavutil
-
* before use sffmpegencoder: you need to excute the following command: su root; ldconfig;
-
* or there is an error:
-
* ./sffmpegencoder: error while loading shared libraries: libavcodec.so.57: cannot open shared object file: No such file or directory
-
*/
-
#include <stdio.h>
-
#define __STDC_CONSTANT_MACROS
-
#ifdef _WIN32
-
//Windows
-
extern "C"
-
{
-
#include "libavutil/opt.h"
-
#include "libavcodec/avcodec.h"
-
#include "libavutil/imgutils.h"
-
};
-
#else
-
//Linux...
-
#ifdef __cplusplus
-
extern "C"
-
{
-
#endif
-
#include <libavutil/opt.h>
-
#include <libavcodec/avcodec.h>
-
#include <libavutil/imgutils.h>
-
#ifdef __cplusplus
-
};
-
#endif
-
#endif
-
//test different codec
-
#define TEST_H264 1
-
#define TEST_HEVC 0
-
int main(int argc, char* argv[])
-
{
-
AVCodec *pCodec;
-
AVCodecContext *pCodecCtx= NULL;
-
int i, ret, got_output;
-
FILE *fp_in;
-
FILE *fp_out;
-
AVFrame *pFrame;
-
AVPacket pkt;
-
int y_size;
-
int framecnt=0;
-
char filename_in[]="../ds_480x272.yuv";
-
#if TEST_HEVC
-
AVCodecID codec_id=AV_CODEC_ID_HEVC;
-
char filename_out[]="ds.hevc";
-
#else
-
AVCodecID codec_id=AV_CODEC_ID_H264;
-
char filename_out[]="ds.h264";
-
#endif
-
int in_w=480,in_h=272;
-
int framenum=100;
-
avcodec_register_all();
-
pCodec = avcodec_find_encoder(codec_id);
-
if (!pCodec) {
-
printf("Codec not found\n");
-
return -1;
-
}
-
pCodecCtx = avcodec_alloc_context3(pCodec);
-
if (!pCodecCtx) {
-
printf("Could not allocate video codec context\n");
-
return -1;
-
}
-
pCodecCtx->bit_rate = 400000;
-
pCodecCtx->width = in_w;
-
pCodecCtx->height = in_h;
-
pCodecCtx->time_base.num=1;
-
pCodecCtx->time_base.den=25;
-
pCodecCtx->gop_size = 10;
-
pCodecCtx->max_b_frames = 1;
-
pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
-
if (codec_id == AV_CODEC_ID_H264)
-
av_opt_set(pCodecCtx->priv_data, "preset", "slow", 0);
-
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
-
printf("Could not open codec\n");
-
return -1;
-
}
-
pFrame = av_frame_alloc();
-
if (!pFrame) {
-
printf("Could not allocate video frame\n");
-
return -1;
-
}
-
pFrame->format = pCodecCtx->pix_fmt;
-
pFrame->width = pCodecCtx->width;
-
pFrame->height = pCodecCtx->height;
-
ret = av_image_alloc(pFrame->data, pFrame->linesize, pCodecCtx->width, pCodecCtx->height,
-
pCodecCtx->pix_fmt, 16);
-
if (ret < 0) {
-
printf("Could not allocate raw picture buffer\n");
-
return -1;
-
}
-
//Input raw data
-
fp_in = fopen(filename_in, "rb");
-
if (!fp_in) {
-
printf("Could not open %s\n", filename_in);
-
return -1;
-
}
-
//Output bitstream
-
fp_out = fopen(filename_out, "wb");
-
if (!fp_out) {
-
printf("Could not open %s\n", filename_out);
-
return -1;
-
}
-
y_size = pCodecCtx->width * pCodecCtx->height;
-
//Encode
-
for (i = 0; i < framenum; i++) {
-
av_init_packet(&pkt);
-
pkt.data = NULL; // packet data will be allocated by the encoder
-
pkt.size = 0;
-
//Read raw YUV data
-
if (fread(pFrame->data[0],1,y_size,fp_in)<= 0|| // Y
-
fread(pFrame->data[1],1,y_size/4,fp_in)<= 0|| // U
-
fread(pFrame->data[2],1,y_size/4,fp_in)<= 0){ // V
-
return -1;
-
}else if(feof(fp_in)){
-
break;
-
}
-
pFrame->pts = i;
-
/* encode the image */
-
ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_output);
-
if (ret < 0) {
-
printf("Error encoding frame\n");
-
return -1;
-
}
-
if (got_output) {
-
printf("Succeed to encode frame: %5d\tsize:%5d\n",framecnt,pkt.size);
-
framecnt++;
-
fwrite(pkt.data, 1, pkt.size, fp_out);
-
av_free_packet(&pkt);
-
}
-
}
-
//Flush Encoder
-
for (got_output = 1; got_output; i++) {
-
ret = avcodec_encode_video2(pCodecCtx, &pkt, NULL, &got_output);
-
if (ret < 0) {
-
printf("Error encoding frame\n");
-
return -1;
-
}
-
if (got_output) {
-
printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",pkt.size);
-
fwrite(pkt.data, 1, pkt.size, fp_out);
-
av_free_packet(&pkt);
-
}
-
}
-
fclose(fp_out);
-
avcodec_close(pCodecCtx);
-
av_free(pCodecCtx);
-
av_freep(&pFrame->data[0]);
-
av_frame_free(&pFrame);
-
return 0;
-
}