一、源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
}
static int encode(AVCodecContext* enc_ctx, AVFrame* frame, AVPacket* pkt,FILE* outfile){
int ret;
/* send the frame to the encoder */
if (frame){
printf("Send frame %lld\n", frame->pts);
}
ret = avcodec_send_frame(enc_ctx, frame);
if (ret < 0) {
char errorBuf[512]={0};
av_strerror(ret,errorBuf,sizeof(errorBuf));
// printf("Error sending a frame for encoding ,ret=%d,%s\n",ret,errorBuf);
return -1;
}
while (ret >= 0) {
ret = avcodec_receive_packet(enc_ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){
printf("Error AVERROR\n");
return -1;
}
else if (ret < 0) {
printf("Error during encoding\n");
return -1;
}
printf("Write packet size=%d\n", pkt->size);
fwrite(pkt->data, 1, pkt->size, outfile);
av_packet_unref(pkt);
}
return 0;
}
int encode_file(const char *input_file,const char *filename){
AVCodecContext* c = NULL;
int ret=-1;
AVFrame* frame=NULL;
AVPacket* pkt;
int frame_num=0;
int nv12_frameSize;
int r_size=0;
FILE *out_fp ;
void *buffer;
uint8_t endcode[] = { 0, 0, 1, 0xb7 };
FILE *in_fp = fopen(input_file,"rb");
if(in_fp==NULL){
return -1;
}
AVCodec* codec = (AVCodec*)avcodec_find_encoder(AV_CODEC_ID_H264);//查找编解码器
if(NULL == codec){
printf("find AV_CODEC_ID_H264 fail! \n");
goto exit0;
}
c = avcodec_alloc_context3(codec);
if (!c) {
printf("Could not allocate video codec context\n");
goto exit0;
}
pkt = av_packet_alloc();
if (!pkt){
printf("av_packet_alloc failed");
goto exit1;
}
/* put sample parameters */
c->bit_rate = 400000;
/* resolution must be a multiple of two */
c->width = 1920;
c->height = 1080;
/* frames per second */
c->time_base.num =1;
c->time_base.den =25;
c->time_base.num =25;
c->time_base.den =1;
/* emit one intra frame every ten frames
* check frame pict_type before passing frame
* to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
* then gop_size is ignored and the output of encoder
* will always be I frame irrespective to gop_size
*/
c->gop_size = 10;
c->max_b_frames = 1;
c->pix_fmt = AV_PIX_FMT_NV12;
if (codec->id == AV_CODEC_ID_H264){
printf("av_opt_set h264 preset slow\n");
av_opt_set(c->priv_data, "preset", "slow", 0);
}
/* open it */
ret = avcodec_open2(c, codec, NULL);
if (ret < 0) {
printf("Could not open codec: %d\n", ret);
goto exit2;
}
out_fp = fopen(filename, "wb");
if (!out_fp) {
printf( "Could not open %s\n", filename);
goto exit2;
}
frame = av_frame_alloc();
if (!frame) {
printf("Could not allocate video frame\n");
goto exit3;
}
frame->format = c->pix_fmt;
frame->width = c->width;
frame->height = c->height;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
printf( "Could not allocate the video frame data\n");
goto exit4;
}
nv12_frameSize = av_image_get_buffer_size(c->pix_fmt, frame->width, frame->height, 1);
printf("nv12_frameSize=%d\n",nv12_frameSize);
buffer = (void *)calloc(1,nv12_frameSize);
if(buffer==NULL){
goto exit4;
}
while(1){
r_size = fread(buffer,1,nv12_frameSize,in_fp);
if(r_size<=0){
printf("read file end\n");
break;
}
av_image_fill_arrays(frame->data, frame->linesize, (const uint8_t *)buffer,(enum AVPixelFormat)frame->format,frame->width,frame->height, 1);
frame_num++;
frame->pts = frame_num;
encode(c, frame, pkt, out_fp);
}
encode(c, NULL, pkt, out_fp);
exit5:
free(buffer);
exit4:
av_frame_free(&frame);
exit3:
fclose(out_fp);
exit2:
av_packet_free(&pkt);
exit1:
avcodec_free_context(&c);
exit0:
fclose(in_fp);
return ret;
}
int main(int argc,char **argv){
if(argc<2){
printf("input yuv file and output.h264");
}
encode_file((const char *)argv[1],(const char *)argv[2]);
return 0;
}
二、Makefile 文件
AR=encode
CC=$(CROSS_COMPILE)gcc
STRIP=$(CROSS_COMPILE)strip
CC=$(CROSS_COMPILE)gcc
CPP=$(CROSS_COMPILE)g++
CFLAGS = -Wall -I /home/share/ffmpeg4.4/output/x86/include/
all +=test_encode.o
export CC
$(TAR): $(all)
$(CC) $(CFLAGS) $(all) -o $(TAR) -lpthread -lm -L/usr/local/ffmpeg_x264/lib/ -lavcodec-59 -lavdev
ice-59 -lavfilter-8 -lavformat-59 -lavutil-57 -lswresample-4 -lswscale-6
$(RM) -f *.gch *.bak $(all)
%.o:%.c
$(CC) $(CFLAGS) -c -o $@ $<
%.o:%.cpp
$(CPP) $(CFLAGS) -c -o $@ $<
.PHONY: clean
clean:
rm -f $(TAR) $(all)