c++ - 使用 ffmpeg 从 QImages 创建 GIF

标签 c++ qt ffmpeg gif



我想使用 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_GIFAV_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(右)
Generated in command line with ffmpeg enter image description here

看起来有些选项没有定义......也可能是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/

相关文章:

c++ - C++ 中的回调,模板成员?

video - FFmpeg 并不总是完全连接视频?

ffmpeg - php exec ffmpeg如何获取错误

video - 使用 ffmpeg 流式传输会杀死我的互联网连接

c++ - 每次保存后如何进行自动g++编译?

c++ - 跨多个文件共享枚举的正确方法是什么?

c++ - 关于C++ rest sdk和同步调用

c++ - Qt WebKit 和永久 Cookie

c++ - 尝试在构造函数中设置成员变量时代码中断

c++ - Qt全局快捷方式扩展劫持快捷方式