我已经在内存中有一系列图像。图像是 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 上找到了各种资源,但其中大多数都使用命令行应用程序。少数不是很通用的,而且大多是过时的(使用不推荐使用的函数),并且通常从一种视频格式转换为另一种视频格式,而且它们都没有处理平面图像。
如果你能帮我解决我做错了什么?
编辑:修复了数组索引中的错字
最佳答案
终于有时间安装和构建它了。
所以我们开始:
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 可以),并将您单独的颜色 channel 转换为单个数组。
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);
关于c++ - 使用ffmpeg将平面RGB图像组合成无损视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42964210/