Fix GIFs with alpha display.

This commit is contained in:
John Preston 2020-02-24 17:48:23 +04:00
parent 5937b24799
commit c2f58d3ab5
5 changed files with 37 additions and 13 deletions

View File

@ -212,6 +212,7 @@ void PaintFrameInner(
QPainter &p, QPainter &p,
QRect to, QRect to,
const QImage &original, const QImage &original,
bool alpha,
int rotation) { int rotation) {
const auto rotated = [](QRect rect, int rotation) { const auto rotated = [](QRect rect, int rotation) {
switch (rotation) { switch (rotation) {
@ -239,22 +240,32 @@ void PaintFrameInner(
if (rotation) { if (rotation) {
p.rotate(rotation); p.rotate(rotation);
} }
p.drawImage(rotated(to, rotation), original); const auto rect = rotated(to, rotation);
if (alpha) {
p.fillRect(rect, Qt::white);
}
p.drawImage(rect, original);
} }
void PaintFrameContent( void PaintFrameContent(
QPainter &p, QPainter &p,
const QImage &original, const QImage &original,
bool alpha,
int rotation, int rotation,
const FrameRequest &request) { const FrameRequest &request) {
const auto full = request.outer; const auto full = request.outer.isEmpty()
? original.size()
: request.outer;
const auto size = request.resize.isEmpty()
? original.size()
: request.resize;
const auto to = QRect( const auto to = QRect(
(full.width() - request.resize.width()) / 2, (full.width() - size.width()) / 2,
(full.height() - request.resize.height()) / 2, (full.height() - size.height()) / 2,
request.resize.width(), size.width(),
request.resize.height()); size.height());
PaintFrameOuter(p, to, full); PaintFrameOuter(p, to, full);
PaintFrameInner(p, to, original, rotation); PaintFrameInner(p, to, original, alpha, rotation);
} }
void ApplyFrameRounding(QImage &storage, const FrameRequest &request) { void ApplyFrameRounding(QImage &storage, const FrameRequest &request) {
@ -267,17 +278,21 @@ void ApplyFrameRounding(QImage &storage, const FrameRequest &request) {
QImage PrepareByRequest( QImage PrepareByRequest(
const QImage &original, const QImage &original,
bool alpha,
int rotation, int rotation,
const FrameRequest &request, const FrameRequest &request,
QImage storage) { QImage storage) {
Expects(!request.outer.isEmpty()); Expects(!request.outer.isEmpty() || alpha);
if (!FFmpeg::GoodStorageForFrame(storage, request.outer)) { const auto outer = request.outer.isEmpty()
storage = FFmpeg::CreateFrameStorage(request.outer); ? original.size()
: request.outer;
if (!FFmpeg::GoodStorageForFrame(storage, outer)) {
storage = FFmpeg::CreateFrameStorage(outer);
} }
QPainter p(&storage); QPainter p(&storage);
PaintFrameContent(p, original, rotation, request); PaintFrameContent(p, original, alpha, rotation, request);
p.end(); p.end();
ApplyFrameRounding(storage, request); ApplyFrameRounding(storage, request);

View File

@ -60,6 +60,7 @@ struct Stream {
QImage storage); QImage storage);
[[nodiscard]] QImage PrepareByRequest( [[nodiscard]] QImage PrepareByRequest(
const QImage &original, const QImage &original,
bool alpha,
int rotation, int rotation,
const FrameRequest &request, const FrameRequest &request,
QImage storage); QImage storage);

View File

@ -361,6 +361,7 @@ void VideoTrackObject::presentFrameIfNeeded() {
Expects(frame->position != kFinishedPosition); Expects(frame->position != kFinishedPosition);
fillRequests(frame); fillRequests(frame);
frame->alpha = (frame->decoded->format == AV_PIX_FMT_BGRA);
frame->original = ConvertFrame( frame->original = ConvertFrame(
_stream, _stream,
frame->decoded.get(), frame->decoded.get(),
@ -982,7 +983,8 @@ QImage VideoTrack::frame(
unwrapped.updateFrameRequest(instance, useRequest); unwrapped.updateFrameRequest(instance, useRequest);
}); });
} }
if (GoodForRequest(frame->original, _streamRotation, useRequest)) { if (!frame->alpha
&& GoodForRequest(frame->original, _streamRotation, useRequest)) {
return frame->original; return frame->original;
} else if (changed || none || i->second.image.isNull()) { } else if (changed || none || i->second.image.isNull()) {
const auto j = none const auto j = none
@ -1002,6 +1004,7 @@ QImage VideoTrack::frame(
} }
j->second.image = PrepareByRequest( j->second.image = PrepareByRequest(
frame->original, frame->original,
frame->alpha,
_streamRotation, _streamRotation,
useRequest, useRequest,
std::move(j->second.image)); std::move(j->second.image));
@ -1025,7 +1028,8 @@ void VideoTrack::PrepareFrameByRequests(
const auto end = frame->prepared.end(); const auto end = frame->prepared.end();
for (auto i = begin; i != end; ++i) { for (auto i = begin; i != end; ++i) {
auto &prepared = i->second; auto &prepared = i->second;
if (!GoodForRequest(frame->original, rotation, prepared.request)) { if (frame->alpha
|| !GoodForRequest(frame->original, rotation, prepared.request)) {
auto j = begin; auto j = begin;
for (; j != i; ++j) { for (; j != i; ++j) {
if (j->second.request == prepared.request) { if (j->second.request == prepared.request) {
@ -1036,6 +1040,7 @@ void VideoTrack::PrepareFrameByRequests(
if (j == i) { if (j == i) {
prepared.image = PrepareByRequest( prepared.image = PrepareByRequest(
frame->original, frame->original,
frame->alpha,
rotation, rotation,
prepared.request, prepared.request,
std::move(prepared.image)); std::move(prepared.image));

View File

@ -83,6 +83,8 @@ private:
crl::time display = kTimeUnknown; crl::time display = kTimeUnknown;
base::flat_map<const Instance*, Prepared> prepared; base::flat_map<const Instance*, Prepared> prepared;
bool alpha = false;
}; };
class Shared { class Shared {

View File

@ -1391,6 +1391,7 @@ QImage Pip::videoFrame(const FrameRequest &request) const {
if (state == ThumbState::Cover) { if (state == ThumbState::Cover) {
_preparedCoverStorage = Streaming::PrepareByRequest( _preparedCoverStorage = Streaming::PrepareByRequest(
_instance.info().video.cover, _instance.info().video.cover,
false,
_instance.info().video.rotation, _instance.info().video.rotation,
request, request,
std::move(_preparedCoverStorage)); std::move(_preparedCoverStorage));