opengltexture: align all data to 16

Fixes crash if frame is not aligned to 16. This should probably
be folded into the Frame class itself at some point.
This commit is contained in:
itsmattkc
2020-04-22 15:08:36 +10:00
parent 1d7c29c6d8
commit c8da59a45e
3 changed files with 57 additions and 13 deletions
+9 -4
View File
@@ -303,8 +303,8 @@ FramePtr FFmpegDecoder::RetrieveVideo(const rational &timecode, const int &divid
// Create frame to return
FramePtr copy = Frame::Create();
copy->set_video_params(VideoRenderingParams(vs->width() / divider,
vs->height() / divider,
copy->set_video_params(VideoRenderingParams(GetScaledDimension(vs->width(), divider),
GetScaledDimension(vs->height(), divider),
native_pix_fmt_));
copy->set_timestamp(Timecode::timestamp_to_time(target_ts, time_base_));
copy->set_sample_aspect_ratio(aspect_ratio_);
@@ -649,6 +649,11 @@ QString FFmpegDecoder::GetIndexFilename()
.append(QString::number(stream()->index()));
}
int FFmpegDecoder::GetScaledDimension(int dim, int divider)
{
return dim / divider;
}
void FFmpegDecoder::UnconditionalAudioIndex(const QAtomicInt* cancelled)
{
// Iterate through each audio frame and extract the PCM data
@@ -1082,8 +1087,8 @@ void FFmpegDecoder::InitScaler(int divider)
scale_ctx_ = sws_getContext(vs->width(),
vs->height(),
src_pix_fmt_,
vs->width() / divider,
vs->height() / divider,
GetScaledDimension(vs->width(), divider),
GetScaledDimension(vs->height(), divider),
ideal_pix_fmt_,
SWS_FAST_BILINEAR,
nullptr,
+2
View File
@@ -175,6 +175,8 @@ private:
void InitScaler(int divider);
void FreeScaler();
static int GetScaledDimension(int dim, int divider);
SwsContext* scale_ctx_;
int scale_divider_;
AVPixelFormat src_pix_fmt_;
+46 -9
View File
@@ -22,6 +22,7 @@
#include <QDateTime>
#include <QDebug>
#include <QtMath>
#include "openglrenderfunctions.h"
#include "render/pixelformat.h"
@@ -123,15 +124,51 @@ void OpenGLTexture::Upload(const void *data)
Bind();
created_ctx_->functions()->glTexSubImage2D(GL_TEXTURE_2D,
0,
0,
0,
width_,
height_,
OpenGLRenderFunctions::GetPixelFormat(format_),
OpenGLRenderFunctions::GetPixelType(format_),
data);
if (width_ % 16 != 0) {
// Align to a multiple of 16
// FIXME: We should probably fold linesizes into the Frame class proper for optimization
int new_width = qCeil(static_cast<double>(width_) / 16.0) * 16;
Frame f;
f.set_video_params(VideoRenderingParams(new_width, height_, format_));
f.allocate();
int src_linesize = PixelFormat::GetBufferSize(format_, width_, 1);
int dst_linesize = PixelFormat::GetBufferSize(format_, new_width, 1);
for (int i=0;i<height_;i++) {
memcpy(f.data() + (i*dst_linesize),
reinterpret_cast<const char*>(data) + i*src_linesize,
src_linesize);
}
created_ctx_->functions()->glPixelStorei(GL_UNPACK_ROW_LENGTH, new_width);
created_ctx_->functions()->glTexSubImage2D(GL_TEXTURE_2D,
0,
0,
0,
width_,
height_,
OpenGLRenderFunctions::GetPixelFormat(format_),
OpenGLRenderFunctions::GetPixelType(format_),
f.data());
created_ctx_->functions()->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
} else {
created_ctx_->functions()->glTexSubImage2D(GL_TEXTURE_2D,
0,
0,
0,
width_,
height_,
OpenGLRenderFunctions::GetPixelFormat(format_),
OpenGLRenderFunctions::GetPixelType(format_),
data);
}
Release();
}