方法1:命令解码

# 解码命令
ffmpeg -i input.mp4 -f rawvideo output.yuv 

# 播放命令
ffplay -s 720x1280 -pix_fmt yuv420p output.yuv

方法2:代码解码

ffmpeg解码YUV_#include

 main.c

#include "libavutil/log.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"

int decodeVideo(AVCodecContext *codecCtx, AVPacket *packet, FILE *dst) {
    int ret = avcodec_send_packet(codecCtx, packet);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_send_packet failed: %s\n", av_err2str(ret));
        av_packet_unref(packet);
        return ret;
    }
    AVFrame *frame = av_frame_alloc();
    while ((ret = avcodec_receive_frame(codecCtx, frame)) == 0) {
//        写入YUV数据方法1
        fwrite(frame->data[0], 1, codecCtx->width * codecCtx->height, dst); // Y data
        fwrite(frame->data[1], 1, codecCtx->width * codecCtx->height / 4, dst); // U data
        fwrite(frame->data[2], 1, codecCtx->width * codecCtx->height / 4, dst); // V data
//        写入YUV数据方法2
//        for (int i = 0; i < codecCtx->height; i++) {
//            fwrite(frame->data[0] + i * frame->linesize[0], 1, codecCtx->width, dst); // Y data
//        }
//        for (int i = 0; i < codecCtx->height / 2; i++) {
//            fwrite(frame->data[1] + i * frame->linesize[1], 1, codecCtx->width / 2, dst); // U data
//        }
//        for (int i = 0; i < codecCtx->height / 2; i++) {
//            fwrite(frame->data[2] + i * frame->linesize[2], 1, codecCtx->width / 2, dst); // V data
//        }
    }
    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
        av_frame_free(&frame);
        return 0;
    } else if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_receive_frame failed: %s\n", av_err2str(ret));
        av_frame_free(&frame);
        return ret;
    }
    av_frame_free(&frame);
    return 0;
}

int main(int argc, char **argv) {
    av_log_set_level(AV_LOG_DEBUG);
    if (argc < 3) {
        av_log(NULL, AV_LOG_ERROR, "Usage: %s inputFile outputFile\n", argv[0]);
        return -1;
    }
    const char *inputFile = argv[1];
    const char *outputFile = argv[2];
    AVFormatContext *fCtx = NULL;
    int ret;

    if ((ret = avformat_open_input(&fCtx, inputFile, NULL, NULL)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "Open input file %s failed: %s\n", inputFile, av_err2str(ret));
        return -1;
    }
    if ((ret = avformat_find_stream_info(fCtx, NULL)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "Find input file stream info failed: %s\n", av_err2str(ret));
        avformat_close_input(&fCtx);
        return -1;
    }

    ret = av_find_best_stream(fCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "av_find_best_stream failed: %s\n", av_err2str(ret));
        avformat_close_input(&fCtx);
        return -1;
    }
    int videoIndex = ret;

    AVCodecContext *codecCtx = avcodec_alloc_context3(NULL);
    if (codecCtx == NULL) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_alloc_context3 failed\n");
        avformat_close_input(&fCtx);
        return -1;
    }
    if ((ret = avcodec_parameters_to_context(codecCtx, fCtx->streams[videoIndex]->codecpar)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_parameters_to_context failed: %s\n", av_err2str(ret));
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }

    AVCodec *decoder = avcodec_find_decoder(codecCtx->codec_id);
    if (decoder == NULL) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_find_decoder failed\n");
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }
    if ((ret = avcodec_open2(codecCtx, decoder, NULL)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_open2 failed: %s\n", av_err2str(ret));
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }

    FILE *dst = fopen(outputFile, "wb");
    if (dst == NULL) {
        av_log(NULL, AV_LOG_ERROR, "open outputFile failed\n");
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }

    AVPacket *packet = av_packet_alloc();
    if (!packet) {
        av_log(NULL, AV_LOG_ERROR, "Could not allocate AVPacket\n");
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        fclose(dst);
        return -1;
    }

    while (av_read_frame(fCtx, packet) == 0) {
        if (packet->stream_index == videoIndex) {
            if (decodeVideo(codecCtx, packet, dst) < 0) {
                av_packet_unref(packet);
                break;
            }
        }
        av_packet_unref(packet);
    }
    decodeVideo(codecCtx, NULL, dst);

    // Cleanup
    av_packet_free(&packet);
    avformat_close_input(&fCtx);
    avcodec_free_context(&codecCtx);
    fclose(dst);

    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
all:$(TARGET)
$(TARGET):$(SRC)
    $(CC) $(SRC) $(CFLAGS) $(LDFLAGS) -o $(TARGET)
clean:
    rm -rf $(TARGET)