最近在学习ffmpeg于是查了一些资料写了一个简单的编码并且用h264进行编码,其代码如下:
#include <stdio.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
#include "libavutil/common.h"
//SDL
#include "SDL/SDL.h"
#include "SDL/SDL_thread.h"
static char inputfile[256];
static char outputfile[256];
static int bitRate; //ÊÓƵÊä³öÂëÂÊ
static int yuvWidth;
static int yuvHeight;
static int totalFrame;
static FILE *pfin;
static FILE *pfout;
static AVCodec *pcodec;
static AVFrame *pframe;
static AVCodecContext *pcodecCtx;
static AVPacket packet;
/*
./ffmpegApp source.yuv out.h264 120000 352 288 50
*/
static int parse_input_param(int argc, char **argv)
{
if (argc != 7)
{
printf("usage: %s <inputfile> <outputfile> <bitrate> <width> <height> <totalframe>", argv[0]);
return -1;
}
strcpy(inputfile, argv[1]);
printf("inputfile = %s\n", inputfile);
strcpy(outputfile, argv[2]);
printf("outputfile = %s\n", outputfile);
bitRate = atoi(argv[3]);
yuvWidth = atoi(argv[4]);
yuvHeight = atoi(argv[5]);
totalFrame = atoi(argv[6]);
printf("bitrate = %d width = %d height = %d totalframe = %d\n",
bitRate, yuvWidth, yuvHeight, totalFrame);
return 0;
}
static int open_file(void)
{
pfin = fopen(inputfile, "rb");
if (pfin == NULL)
{
printf("input file open failed.\n");
return -1;
}
pfout = fopen(outputfile, "wb");
if (pfout == NULL)
{
printf("input file open failed.\n");
return -1;
}
return 0;
}
static void close_file(void)
{
fclose(pfin);
fclose(pfout);
}
static int open_encoder(void)
{
int ret;
//×¢²áËùÓеÄffmpeg±àœâÂëÆ÷
avcodec_register_all();
//²éÕÒ×ÔŒºÏëÒªµÄ±àÂëÆ÷
pcodec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!pcodec)
{
printf("could not found codec\n");
return -1;
}
//·ÖÅäcontexÊÂÀý
pcodecCtx = avcodec_alloc_context3(pcodec);
if (!pcodecCtx)
{
printf("could not allocate video codec context\n");
return -1;
}
//ÉèÖñàÂëÆ÷²ÎÊý
pcodecCtx->bit_rate = bitRate;
pcodecCtx->width = yuvWidth;
pcodecCtx->height = yuvHeight;
AVRational rational = {1, 25}; //ÉèÖÃÖ¡ÂÊ 1ÃëÖÓ25Ö¡
pcodecCtx->time_base = rational;
pcodecCtx->gop_size = 12;
pcodecCtx->max_b_frames = 1;
pcodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
//ÉèÖÃËœÓÐÊýŸÝ
av_opt_set(pcodecCtx->priv_data, "preset", "slow", 0);
//Žò¿ª±àÂëÆ÷
ret = avcodec_open2(pcodecCtx, pcodec, NULL);
if (ret < 0)
{
printf("could not open codec ret = %d.\n", ret);
return -1;
}
//·ÖÅäAVFRAMEÒÔŒ°ÏóË؎探¿ÕŒä
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, pframe->width, pframe->height, pframe->format, 32);
if (ret < 0)
{
printf("could not allocte raw picture buffer.\n");
return -1;
}
return 0;
}
static void close_encoder(void)
{
avcodec_close(pcodecCtx);
av_free(pcodecCtx);
av_freep(&(pframe->data[0]));
av_frame_free(&pframe);
}
static int read_yuv_data(int color)
{
int frame_height = color == 0 ? pframe->height : pframe->height / 2;
int frame_width = color == 0 ? pframe->width : pframe->width / 2;
int frame_size = frame_height * frame_width;
int frame_stride = pframe->linesize[color];
//±íÊŸÁ¬ÐøŽæŽ¢
if (frame_width == frame_stride)
{
if (fread(pframe->data[color], 1, frame_size, pfin) == 0)
{
printf("read data error.\n");
return -1;
}
}
else
{
int row;
for (row = 0; row < frame_height; row++)
{
if (fread(pframe->data[color]+row*frame_stride, 1, frame_width, pfin) == 0)
{
printf("read data error.\n");
return -1;
}
}
}
return frame_size;
}
int main(int argc, char* argv[])
{
int ret;
int got_output;
int packIndex = 0;
if (parse_input_param(argc, argv) < 0)
{
printf("fail to parse input param\n");
return -1;
}
if (open_file() < 0)
{
printf("open file faile\n");
return -1;
}
if (open_encoder() < 0)
{
printf("open encoder faile\n");
return -1;
}
int frameIndex;
for (frameIndex = 0; frameIndex < totalFrame; frameIndex++)
{
//³õÊŒ»¯°üÓÉÓÚ×°ÔرàÂëºóµÄÂëÁ÷
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
fflush(stdout);
//¶ÁÈ¡ÊýŸÝµœAVFRAMEÖÐ
read_yuv_data(0);
read_yuv_data(1);
read_yuv_data(2);
pframe->pts = frameIndex;
//encode the image
ret = avcodec_encode_video2(pcodecCtx, &packet, pframe, &got_output);
if (ret < 0)
{
printf("error encoding frame\n");
return -1;
}
printf("encode frame index: %d, frame pts: %ld\n", frameIndex, pframe->pts);
if (got_output) //ÊÇ·ñ±àÂë³öÒ»žöÍêÕûµÄ°ü
{
printf("write packet %3d (size = %5d) packet pts %ld\n",packIndex++, packet.size, packet.pts);
fwrite(packet.data, 1, packet.size, pfout);
av_packet_unref(&packet);
}
}
//œ«±àÂëÆ÷ÖÐÊ£ÓàµÄÊýŸÝÊä³ö
for (got_output = 1; got_output; frameIndex++)
{
fflush(stdout);
ret = avcodec_encode_video2(pcodecCtx, &packet, NULL, &got_output);
if (ret < 0)
{
printf("error encoding frame\n");
return -1;
}
if (got_output)
{
printf("cached frame: write packkets %3d (size=%5d) packet pts %ld\n", packIndex++, packet.size, packet.pts);
fwrite(packet.data, 1, packet.size, pfout);
av_packet_unref(&packet);
}
}
close_encoder();
close_file();
return 0;
}
编写完后进行编译一直提示“could found codec”,找不到h264编码器,在网上搜索了一下原来是h264依赖libx264,于是修改了ffmpeg编译时的配置文件
将--enable-libx264加上。加上后重新配置但是此时配置是又提示:
查看日志文件如下:
这下应该是PC下没有安装x264的库,于是安装x264的库顺便也安装了其他的几个依赖库
suto apt-get install libx264-dev
sudo apt-get install libfaac-dev
sudo apt-get install libmp3lame-dev
sudo apt-get install libtheora-dev
sudo apt-get install libxfixes-dev