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*

  

posted @ 2024-06-01 21:21  NAVYSUMMER  阅读(206)  评论(0编辑  收藏  举报
交流群 编程书籍