code cleanups and fixed gif export #360

This commit is contained in:
itsmattkc
2019-01-30 21:36:07 +11:00
parent 6f3a826da7
commit c19a2dad7d
8 changed files with 67 additions and 51 deletions
+24 -15
View File
@@ -38,7 +38,6 @@ ExportThread::ExportThread(QObject *parent) :
vcodec = nullptr;
vcodec_ctx = nullptr;
video_frame = nullptr;
sws_frame = nullptr;
sws_ctx = nullptr;
audio_stream = nullptr;
acodec = nullptr;
@@ -125,18 +124,17 @@ bool ExportThread::setupVideo() {
vcodec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
if (vcodec_ctx->codec_id == AV_CODEC_ID_H264) {
/*char buffer[50];
itoa(vcodec_ctx, buffer, 10);*/
//av_opt_set(vcodec_ctx->priv_data, "preset", "fast", AV_OPT_SEARCH_CHILDREN);
//av_opt_set(vcodec_ctx->priv_data, "x264opts", "opencl", AV_OPT_SEARCH_CHILDREN);
switch (vcodec_ctx->codec_id) {
case AV_CODEC_ID_H264:
switch (video_compression_type) {
case COMPRESSION_TYPE_CFR:
av_opt_set(vcodec_ctx->priv_data, "crf", QString::number(static_cast<int>(video_bitrate)).toUtf8(), AV_OPT_SEARCH_CHILDREN);
break;
}
break;
case AV_CODEC_ID_GIF:
av_opt_set(vcodec_ctx->priv_data, "image", "1", AV_OPT_SEARCH_CHILDREN);
break;
}
AVDictionary* opts = nullptr;
@@ -180,12 +178,6 @@ bool ExportThread::setupVideo() {
nullptr
);
sws_frame = av_frame_alloc();
sws_frame->format = vcodec_ctx->pix_fmt;
sws_frame->width = video_width;
sws_frame->height = video_height;
av_frame_get_buffer(sws_frame, 0);
return true;
}
@@ -369,12 +361,30 @@ void ExportThread::run() {
// encode last frame while rendering next frame
double timecode_secs = (double) (sequence->playhead-start_frame) / sequence->frame_rate;
if (video_enabled) {
// create sws_frame for converting pixel format
//
// - I'm not sure why, but we have to alloc/free sws_frame every frame, or it breaks GIF exporting.
// - (i.e. GIFs get stuck on the first frame)
// - The same problem/solution can be seen here: https://stackoverflow.com/a/38997739
// - Perhaps this is the intended way to use swscale, but it seems inefficient.
// - Anyway, here we are.
//
sws_frame = av_frame_alloc();
sws_frame->format = vcodec_ctx->pix_fmt;
sws_frame->width = video_width;
sws_frame->height = video_height;
av_frame_get_buffer(sws_frame, 0);
// change pixel format
sws_scale(sws_ctx, video_frame->data, video_frame->linesize, 0, video_frame->height, sws_frame->data, sws_frame->linesize);
sws_frame->pts = qRound(timecode_secs/av_q2d(video_stream->time_base));
// send to encoder
if (!encode(fmt_ctx, vcodec_ctx, sws_frame, &video_pkt, video_stream, false)) continueEncode = false;
av_frame_free(&sws_frame);
}
if (audio_enabled) {
// do we need to encode more audio samples?
@@ -481,7 +491,6 @@ void ExportThread::run() {
if (sws_ctx != nullptr) {
sws_freeContext(sws_ctx);
av_frame_free(&sws_frame);
}
if (swr_ctx != nullptr) {
swr_free(&swr_ctx);