我想使用 ffmpeg 从 QImage 生成 GIF - 所有这些都是以编程方式 (C++)。我正在使用 Qt 5.6 和 ffmpeg 的最新版本(build git-0a9e781 (2016-06-10))。
我已经能够将这些 QImage 转换为 .mp4 并且它可以工作。我尝试对 GIF 使用相同的原理,更改格式像素和编解码器。 GIF 由两张图片(每张 1 秒)生成,帧率为 15 FPS。
## INITIALIZATION
#####################################################################
// Filepath : "C:/Users/.../qt_temp.Jv7868.gif"
// Allocating an AVFormatContext for an output format...
avformat_alloc_output_context2(formatContext, NULL, NULL, filepath);
...
// Adding the video streams using the default format codecs and initializing the codecs.
stream = avformat_new_stream(formatContext, *codec);
AVCodecContext * codecContext = avcodec_alloc_context3(*codec);
context->codec_id = codecId;
context->bit_rate = 400000;
...
context->pix_fmt = AV_PIX_FMT_BGR8;
...
// Opening the codec...
avcodec_open2(codecContext, codec, NULL);
...
frame = allocPicture(codecContext->width, codecContext->height, codecContext->pix_fmt);
tmpFrame = allocPicture(codecContext->width, codecContext->height, AV_PIX_FMT_RGBA);
...
avformat_write_header(formatContext, NULL);
## ADDING A NEW FRAME
#####################################################################
// Getting in parameter the QImage: newFrame(const QImage & image)
const qint32 width = image.width();
const qint32 height = image.height();
// Converting QImage into AVFrame
for (qint32 y = 0; y < height; y++) {
const uint8_t * scanline = image.scanLine(y);
for (qint32 x = 0; x < width * 4; x++) {
tmpFrame->data[0][y * tmpFrame->linesize[0] + x] = scanline[x];
}
}
...
// Scaling...
if (codec->pix_fmt != AV_PIX_FMT_BGRA) {
if (!swsCtx) {
swsCtx = sws_getContext(codec->width, codec->height,
AV_PIX_FMT_BGRA,
codec->width, codec->height,
codec->pix_fmt,
SWS_BICUBIC, NULL, NULL, NULL);
}
sws_scale(swsCtx,
(const uint8_t * const *)tmpFrame->data,
tmpFrame->linesize,
0,
codec->height,
frame->data,
frame->linesize);
}
frame->pts = nextPts++;
...
int gotPacket = 0;
AVPacket packet = {0};
av_init_packet(&packet);
avcodec_encode_video2(codec, &packet, frame, &gotPacket);
if (gotPacket) {
av_packet_rescale_ts(paket, *codec->time_base, stream->time_base);
paket->stream_index = stream->index;
av_interleaved_write_frame(formatContext, paket);
}
但是当我尝试修改视频编解码器和像素格式以匹配 GIF 规范时,我遇到了一些问题。
我尝试了几种编解码器,例如 AV_CODEC_ID_GIF
和 AV_CODEC_ID_RAWVIDEO
但它们似乎都不起作用。在初始化阶段,avcodec_open2()
总是返回这样的错误:
Specified pixel format rgb24 is invalid or not supported
Could not open video codec: gif
编辑 2016 年 6 月 17 日
再深入一点,avcodec_open2()
返回 -22:
#define EINVAL 22 /* Invalid argument */
编辑 22/06/2016
以下是用于编译 ffmpeg 的标志:
"FFmpeg/Libav configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --disable-w32threads --enable-nvenc --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmfx --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib"
我是否错过了 GIF 的关键部分?
编辑 27/06/2016
感谢 Gwen,我得到了第一个输出:我将 context->pix_fmt
设置为 AV_PIX_FMT_BGR8
。顺便说一句,我仍然面临生成的 GIF 的一些问题。它没有播放,编码似乎失败。
在命令行中使用 ffmpeg(左)生成 GIF。 . . 以编程方式生成的 GIF(右)
看起来有些选项没有定义......也可能是QImage和AVFrame之间的错误转换?我更新了上面的代码。它代表了很多代码,所以我尽量保持简短。不要犹豫,询问更多详情。
编辑结束
我对 ffmpeg 不是很熟悉,非常感谢任何形式的帮助。谢谢。
最佳答案
GIF 只能支持 256 色位图(每像素 8 位)。这可能是您遇到 指定的像素格式 rgb24 无效或不受支持
错误的原因。
您需要使用的像素格式是 AV_PIX_FMT_PAL8
( 8 bit with RGB32 palette )。
关于c++ - 使用 ffmpeg 从 QImages 创建 GIF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37861764/