ffmpeg编码之实现YUV转换成H264
方法1:命令转换
# 转换 ffmpeg -s 720*1280 -pix_fmt yuv420p -i input.yuv -vcodec libx264 -b:v 4096k -bf 0 -g 10 -r 30 output.h264 # 播放 ffplay output.h264
方法2:代码转换

main.c
#include "libavutil/log.h"
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
#include "libavutil/parseutils.h"
#include "libavutil/imgutils.h"
int writeFrameCount = 0;
int encodeVideo(AVCodecContext *encodeCtx, AVFrame *frame, AVPacket *packet, FILE *dest) {
int ret = avcodec_send_frame(encodeCtx, frame);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "avcodec_send_frame failed: %s\n", av_err2str(ret));
return ret;
}
else{
ret = avcodec_receive_packet(encodeCtx, packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return 0;
} else if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "avcodec_receive_packet failed: %s\n", av_err2str(ret));
return ret;
}
fwrite(packet->data, 1, packet->size, dest);
av_log(NULL,AV_LOG_INFO,"write frame index = %d\n",writeFrameCount);
writeFrameCount ++;
av_packet_unref(packet);
}
return 0;
}
int main(int argc, char **argv) {
av_log_set_level(AV_LOG_DEBUG);
if (argc < 5) {
av_log(NULL, AV_LOG_ERROR, "Usage: %s inputFile outputFile encoderName <width*height>\n", argv[0]);
return -1;
}
const char *inputFile = argv[1];
const char *outputFile = argv[2];
const char *encodeName = argv[3];
const char *dstVideoSizeString = argv[4];
int ret;
int dstHeight = 0;
int dstWidth = 0;
ret = av_parse_video_size(&dstWidth, &dstHeight, dstVideoSizeString);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "av_parse_video_size failed: %s\n", av_err2str(ret));
return -1;
}
AVCodec *encoder = avcodec_find_encoder_by_name(encodeName);
if (encoder == NULL) {
av_log(NULL, AV_LOG_ERROR, "avcodec_find_encoder_by_name failed\n");
return -1;
}
AVCodecContext *encodeCtx = avcodec_alloc_context3(encoder);
if (encodeCtx == NULL) {
av_log(NULL, AV_LOG_ERROR, "avcodec_alloc_context3 failed\n");
return -1;
}
enum AVPixelFormat pix_fmt = AV_PIX_FMT_YUV420P;
encodeCtx->codec_type = AVMEDIA_TYPE_VIDEO;
encodeCtx->pix_fmt = pix_fmt;
encodeCtx->width = dstWidth;
encodeCtx->height = dstHeight;
encodeCtx->time_base = (AVRational) {1, 30};
encodeCtx->max_b_frames = 0;
encodeCtx->gop_size = 10;
ret = avcodec_open2(encodeCtx, encoder, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "avcodec_open2 failed: %s\n", av_err2str(ret));
avcodec_free_context(&encodeCtx);
return -1;
}
FILE *inFp = fopen(inputFile, "rb");
if (inFp == NULL) {
av_log(NULL, AV_LOG_ERROR, "open inputFile failed\n");
avcodec_free_context(&encodeCtx);
return -1;
}
FILE *destFp = fopen(outputFile, "wb");
if (destFp == NULL) {
av_log(NULL, AV_LOG_ERROR, "open outputFile failed\n");
avcodec_free_context(&encodeCtx);
fclose(inFp);
return -1;
}
AVFrame *frame = av_frame_alloc();
int frameSize = av_image_get_buffer_size(pix_fmt, dstWidth, dstHeight, 1);
uint8_t *frameBuffer = av_malloc(frameSize);
if (frameBuffer == NULL) {
av_log(NULL, AV_LOG_ERROR, "av_malloc failed\n");
av_frame_free(&frame);
avcodec_free_context(&encodeCtx);
fclose(inFp);
fclose(destFp);
return -1;
}
av_image_fill_arrays(frame->data, frame->linesize, frameBuffer, pix_fmt, dstWidth, dstHeight, 1);
frame->format = pix_fmt;
frame->width = dstWidth;
frame->height = dstHeight;
int pictureSize = dstWidth * dstHeight;
AVPacket *packet = av_packet_alloc();
if (packet==NULL){
av_frame_free(&frame);
avcodec_free_context(&encodeCtx);
fclose(inFp);
fclose(destFp);
return -1;
}
int readFrameCount = 0;
while (fread(frameBuffer, 1, pictureSize * 3 / 2, inFp) == pictureSize * 3 / 2) {
frame->data[0] = frameBuffer;
frame->data[1] = frameBuffer + pictureSize;
frame->data[2] = frameBuffer + pictureSize + pictureSize / 4;
frame->pts = readFrameCount;
readFrameCount++;
av_log(NULL,AV_LOG_INFO,"read frame index = %d\n",readFrameCount);
encodeVideo(encodeCtx, frame, packet, destFp);
}
encodeVideo(encodeCtx, NULL, packet, destFp);
avcodec_free_context(&encodeCtx);
fclose(inFp);
fclose(destFp);
av_frame_free(&frame);
av_freep(&frameBuffer);
av_packet_free(&packet);
return 0;
}
Makefile
TARGET=main SRC=main.c CC=gcc CFLAGS=-I /usr/local/ffmpeg/include LDFLAGS=-L /usr/local/ffmpeg/lib LDFLAGS+= -lavutil -lavformat -lavcodec -lswscale all:$(TARGET) $(TARGET):$(SRC) $(CC) $(SRC) $(CFLAGS) $(LDFLAGS) -o $(TARGET) clean: rm -rf $(TARGET) rm -rf ../output*

浙公网安备 33010602011771号