【问题标题】:Combining planar RGB images into lossless video with ffmpeg使用ffmpeg将平面RGB图像组合成无损视频
【发布时间】:2017-08-15 07:24:39
【问题描述】:

我的内存中已经有一系列图像。图像是 RGB 的,但是是平面的,即非交错的。我希望使用 ffmpeg 将这些无损压缩成视频。

目前我有这个(注意:我已经排除了错误检查和清理):

av_register_all();

AVCodec* codec = avcodec_find_encoder_by_name("libx264rgb");

AVCodecContext* context = avcodec_alloc_context3(codec);
context->width = width;
context->height = paddedHeight;//height padded to a multiple of 8
context->time_base = AVRational { 1,25 };
context->gop_size = 10;
context->max_b_frames = 1;
context->pix_fmt = AV_PIX_FMT_RGB24;
av_opt_set(context->priv_data, "preset", "ultrafast", 0);
av_opt_set(context->priv_data, "crf", 0, 0);//lossless

avcodec_open2(context, codec, NULL);

AVFrame* avFrame = av_frame_alloc();
for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
    avFrame->data[i] = NULL;
}
avFrame->data[0] = new uint8_t[width*paddedHeight];
avFrame->data[1] = new uint8_t[width*paddedHeight];
avFrame->data[2] = new uint8_t[width*paddedHeight];

AVFormatContext* outputContext;
avformat_alloc_output_context2(&outputContext, NULL, NULL, "filename.webm");

AVStream* outputStream = avformat_new_stream(outputContext, codec);
outputStream->codecpar->width = width;
outputStream->codecpar->height = paddedHeight;
outputStream->codecpar->format = AV_PIX_FMT_GBRP;
outputStream->time_base = AVRational { 1,25 };

outputContext->video_codec = codec;
avio_open2(&outputContext->pb, "filepath\filename.webm", AVIO_FLAG_WRITE, NULL, NULL);//obviously a real filepath is being used

avformat_write_header(outputContext, NULL);

uint8_t* R, G, B;
while(GetNextImageChannels(&R, &G, &B)){
    memcpy(R, avFrame->data[0], width * height * sizeof(uint8_t));
    memcpy(G, avFrame->data[1], width * height * sizeof(uint8_t));
    memcpy(B, avFrame->data[2], width * height * sizeof(uint8_t));

    avcodec_send_frame(context, avFrame);

    AVPacket encodedPacket;
    avcodec_receive_packet(context, &encodedPacket);
    av_interleaved_write_frame(outputContext, &encodedPacket);
}

av_write_trailer(outputContext);

目前在 avformat_write_header 失败,给我一个错误代码 -22,我认为这意味着某种无效参数?

我尝试使用 filename.mkv,但在 avformat_alloc_output_context2 失败,错误代码为 -22

我尝试使用AV_PIX_FMT_GBRP 格式,但在avcodec_open2 失败,错误代码也为-22。

我在 ffmpeg 上找到了各种资源,但其中大多数都使用命令行应用程序。少数不是很通用,而且大多已经过时(使用不推荐使用的函数),并且通常从一种视频格式转换为另一种视频格式,而且它们都不是处理平面图像。

如果你能帮我解决我的问题吗?

编辑:修正了数组索引中的错字

【问题讨论】:

    标签: c++ image video ffmpeg video-encoding


    【解决方案1】:

    终于有时间安装和构建它了。 所以我们开始:

    1) 激活调试日志记录。很有用。

    av_log_set_level(AV_LOG_DEBUG);
    

    你打电话登记吗?

    avcodec_register_all();
    av_register_all();
    

    2) 您要使用的编解码器似乎不支持平面 RGB 格式。
    对我来说 AV_PIX_FMT_GBRP 因“无效参数”错误而失败。
    您需要指定一些打包的 RGB 格式(AV_PIX_FMT_RGB24 可以),并将您单独的颜色通道转换为单个数组。

    avFrame->data[0] = new uint8_t[3*width*paddedHeight];
    . . .
    uint8_t* R, G, B;
    uint8_t* row = avFrame->data[0];
    while(GetNextImageChannels(&R, &G, &B)){
        for(int iy=0; iy<height; ++iy){
            for(int ix=0; ix<width; ++ix){
                row[3*ix+0] = R[ix];
                row[3*ix+1] = G[ix];
                row[3*ix+2] = B[ix];
            }
            R += width;
            G += width;
            B += width;
            row += 3*width;
        }
    

    3) WebM 不支持 h264。所以又回到了mkv。
    您需要创建视频流:

    AVFormatContext* outputContext;
    avformat_alloc_output_context2(&outputContext, NULL, "h264", "filename.mkv");
    AVStream* video_stream = avformat_new_stream(outputContext, codec);
    video_stream->codec = c;
    avio_open(&outputContext->pb, "filename.mkv", AVIO_FLAG_WRITE);
    avformat_write_header(outputContext, NULL);
    

    【讨论】:

    • 哦,天哪,是的,这是一个错字。但是我刚刚修复了它,我得到了与以前完全相同的结果(两种格式都试过)
    • 填充呢?
    • 我刚刚尝试过,将高度和宽度都填充到 8、16 和 32。不幸的是它没有工作
    • 打包的 RGB 怎么样?
    • 记住它在到达循环之前就出错了。我相信这与我设置整个事情的方式有关,比如我可能错过了一些设置,或者我没有正确地将两个结构连接在一起。只是为了确认这不是数据缓冲区的数量,我还是尝试了这个,它没有工作
    猜你喜欢
    • 1970-01-01
    • 2022-01-21
    • 2021-07-08
    • 1970-01-01
    • 2011-08-18
    • 2021-01-16
    • 1970-01-01
    • 2017-10-12
    • 2023-01-30
    相关资源
    最近更新 更多