通过ffmpeg的demo修改的
Mingw Cygwin 皆可编译通过
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
}
static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
FILE *outfile)
{
int ret;
/* send the frame to the encoder */
if (frame)
fprintf(stderr, "Send frame %3lld\n", frame->pts);
ret = avcodec_send_frame(enc_ctx, frame);
if (ret < 0) {
fprintf(stderr, "Error sending a frame for encoding\n");
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_packet(enc_ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return;
else if (ret < 0) {
fprintf(stderr, "Error during encoding\n");
exit(1);
}
fprintf(stderr, "Write packet %3lld(size=%5d)\n", pkt->pts, pkt->size);
fwrite(pkt->data, 1, pkt->size, outfile);
av_packet_unref(pkt);
}
}
int main(int argc, char **argv)
{
const AVCodec *codec;
AVCodecContext *pCodecCtx= NULL;
int i, ret, x, y;
FILE *outfp, *infp;
AVFrame *pFrame;
AVPacket *packet;
const char *infile = "D:\\test.yuv";
const char *outfile = "D:\\out.264";
int width = 768, height = 432; //输入yuv的分辨率
if(width%2 != 0 || height %2 != 0) {
fprintf(stderr, "resolution must be a multiple of two\n");
exit(0);
}
/* find the encoder */
// codec = avcodec_find_encoder_by_name("h264_amf"); //amd 硬编码
// codec = avcodec_find_encoder_by_name("h264_nvenc"); //nvdia 硬编码
// codec = avcodec_find_encoder_by_name("h264_qsv"); //intel 硬编码
codec = avcodec_find_encoder(AV_CODEC_ID_H264); //软编码
if (!codec) {
fprintf(stderr, "Codec not found\n");
exit(1);
}
printf("fullname = %s\n", codec->long_name);
pCodecCtx = avcodec_alloc_context3(codec);
if (!pCodecCtx) {
fprintf(stderr, "Could not allocate video codec context\n");
exit(1);
}
packet = av_packet_alloc();
if (!packet)
exit(1);
/* put sample parameters */
pCodecCtx->bit_rate = 2000000;
/* resolution must be a multiple of two */
pCodecCtx->width = width;
pCodecCtx->height = height;
/* frames per second */
pCodecCtx->time_base = (AVRational){1, 25};
pCodecCtx->framerate = (AVRational){25, 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
*/
pCodecCtx->gop_size = 20;
pCodecCtx->max_b_frames = 0;
#if 1
//YUV420P格式
pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
#else
//intel硬编时选择NV12格式
pCodecCtx->pix_fmt = AV_PIX_FMT_NV12;
#endif
//ultrafast superfast veryfast faster fast medium slow slower veryslow placebo 速度越慢质量越好
if (codec->id == AV_CODEC_ID_H264)
av_opt_set(pCodecCtx->priv_data, "preset", "veryslow", 0);
/* open it */
ret = avcodec_open2(pCodecCtx, codec, NULL);
if (ret < 0) {
fprintf(stderr, "Could not open codec, ret = %d\n", ret);
exit(1);
}
infp = fopen(infile, "rb");
if (!infp) {
fprintf(stderr, "Could not open %s\n", infile);
exit(1);
}
outfp = fopen(outfile, "wb");
if (!outfp) {
fprintf(stderr, "Could not open %s\n", outfile);
fclose(infp);
exit(1);
}
pFrame = av_frame_alloc();
if (!pFrame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
pFrame->format = pCodecCtx->pix_fmt;
pFrame->width = pCodecCtx->width;
pFrame->height = pCodecCtx->height;
ret = av_frame_get_buffer(pFrame, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate the video frame data\n");
exit(1);
}
int rsize = width*height + width*height/2;
uint8_t * rbuf = new uint8_t[rsize];
for (i = 0; ; i++) {
fflush(stdout);
memset(rbuf, 0, rsize);
uint8_t *ptr = rbuf;
ret = fread(rbuf, 1, rsize, infp);
if(ret != rsize) {
break;
}
/* make sure the frame data is writable */
ret = av_frame_make_writable(pFrame);
if (ret < 0)
exit(1);
/* prepare a dummy image */
memcpy(pFrame->data[0], rbuf, width*height);
#if 1
//YUV420P格式
memcpy(pFrame->data[1], rbuf+width*height, width*height/4);
memcpy(pFrame->data[2], rbuf+width*height+width*height/4, width*height/4);
#else
//NV12格式
uint8_t *uptr = rbuf + width*height, *vptr = rbuf + width*height*5/4;
uint8_t *dst = &pFrame->data[1][0];
for (int ii = 0; ii < height*width/4; ii++) {
*dst++ = *uptr++;
*dst++ = *vptr++;
}
#endif
pFrame->pts = i;
/* encode the image */
encode(pCodecCtx, pFrame, packet, outfp);
}
/* flush the encoder */
encode(pCodecCtx, NULL, packet, outfp);
fclose(outfp);
fclose(infp);
avcodec_free_context(&pCodecCtx);
av_frame_free(&pFrame);
av_packet_free(&packet);
return 0;
}