为什么avcodec_send_frame会出现无效参数错误?

问题描述 投票:0回答:1

我正试图学习如何使用FFmpeg的libav库。当我运行我的代码时,它给出了 "无效参数",当我第一次尝试编码一帧。我使用mp4作为输入,输出为mp4。它为什么会给出这个错误的可能性是什么?它在寻找什么参数可能是错误的?

#include <libavformat/avformat.h>
#include <stdio.h>
#include <stdlib.h>

void die(const char *msg)
{
    printf("ERROR: %s\n", msg);
    exit(1);
}

void checkRC(int rc, const char *msg)
{
    if (rc != 0) {
        char avErrMsg[1024];
        av_strerror(rc, avErrMsg, sizeof(avErrMsg));

        int length = strlen(avErrMsg) + strlen(msg) + 2 + 1;
        char *errMsg = (char *)malloc(length);
        sprintf(errMsg, "%s: %s", msg, avErrMsg);

        die(errMsg);
    }
}

void checkNull(void *ptr, const char *msg)
{
    if (ptr == NULL) {
        die(msg);
    }
}

char *copyString(const char *str)
{
    int length = strlen(str);
    char *newStr = (char *)malloc(length + 1);

    strcpy(newStr, str);

    return newStr;
}

int main(int argc, char const *argv[])
{
    argc--;
    argv++;

    if (argc != 2) {
        die("Please give an input file and output file");
    }

    int rc = 0;
    const char *inputFile = argv[0];
    const char *outputFile = argv[1];

    AVFormatContext *inputFmtCtx = NULL;
    AVFormatContext *outputFmtCtx = NULL;
    AVIOContext *ioCtx = NULL;
    AVStream *inputStream = NULL;
    AVStream *outputStream = NULL;
    AVCodec *decoder = NULL;
    AVCodec *encoder = NULL;
    AVCodecContext *inputCodecCtx = NULL;
    AVCodecContext *outputCodecCtx = NULL;
    AVFrame *frame = NULL;
    AVPacket inPacket;

    rc = avformat_open_input(&inputFmtCtx, inputFile, NULL, NULL);
    checkRC(rc, "Failed to open input format");

    rc = avformat_find_stream_info(inputFmtCtx, NULL);
    checkRC(rc, "Failed to find input streams");

    rc = avio_open(&ioCtx, outputFile, AVIO_FLAG_WRITE);
    checkRC(rc, "Failed to open output IO context");

    outputFmtCtx = avformat_alloc_context();
    checkNull(outputFmtCtx, "Failed to allocate output format context");

    outputFmtCtx->pb = ioCtx;
    outputFmtCtx->oformat = av_guess_format(NULL, outputFile, NULL);
    outputFmtCtx->url = copyString(outputFile);

    inputStream = inputFmtCtx->streams[0];
    decoder = avcodec_find_decoder(inputStream->codecpar->codec_id);
    checkNull(decoder, "Failed to find decoder");

    inputCodecCtx = avcodec_alloc_context3(decoder);
    checkNull(inputCodecCtx, "Failed to allocate codec context");

    rc = avcodec_parameters_to_context(inputCodecCtx, inputStream->codecpar);
    checkRC(rc, "Failed to copy parameters to context");

    rc = avcodec_open2(inputCodecCtx, decoder, NULL);
    checkRC(rc, "Failed to open codec");

    outputStream = avformat_new_stream(outputFmtCtx, NULL);
    checkNull(outputStream, "Failed to create new stream");

    encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
    checkNull(encoder, "Failed to find encoder");

    outputCodecCtx = avcodec_alloc_context3(encoder);
    checkNull(outputCodecCtx, "Failed to allocate encoder context");

    outputCodecCtx->bit_rate = inputCodecCtx->bit_rate;
    outputCodecCtx->width = inputCodecCtx->width;
    outputCodecCtx->height = inputCodecCtx->height;
    outputCodecCtx->time_base = (AVRational){1, 25};
    outputCodecCtx->framerate = (AVRational){25, 1};
    outputCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
    outputCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

    rc = avcodec_parameters_from_context(outputStream->codecpar, outputCodecCtx);
    checkRC(rc, "Failed to copy parameters from context");

    frame = av_frame_alloc();
    checkNull(frame, "Failed to allocate frame");

    rc = avformat_write_header(outputFmtCtx, NULL);
    checkRC(rc, "Failed to write header");

    rc = av_read_frame(inputFmtCtx, &inPacket);
    checkRC(rc, "Failed to read frame");

    rc = avcodec_send_packet(inputCodecCtx, &inPacket);
    checkRC(rc, "Failed to send packet");

    rc = avcodec_receive_frame(inputCodecCtx, frame);
    checkRC(rc, "Failed to receive frame");

    rc = avcodec_send_frame(outputCodecCtx, frame);
    checkRC(rc, "Faied to send frame");

    return 0;
}
ffmpeg libav
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.