mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Play webm stickers only once if looping is disabled.
This commit is contained in:
parent
b4a49de819
commit
95e806cb89
12 changed files with 95 additions and 38 deletions
|
@ -415,9 +415,21 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
|||
activeOwnPlaying->frozenFrame = QImage();
|
||||
activeOwnPlaying->frozenStatusText = QString();
|
||||
}
|
||||
p.drawImage(rthumb, streamed->frame(request));
|
||||
if (!paused) {
|
||||
streamed->markFrameShown();
|
||||
|
||||
const auto frame = streamed->frameWithInfo(request);
|
||||
const auto playOnce = sticker
|
||||
&& !Core::App().settings().loopAnimatedStickers();
|
||||
const auto switchToNext = !playOnce
|
||||
|| (frame.index != 0)
|
||||
|| !_stickerOncePlayed;
|
||||
p.drawImage(rthumb, frame.image);
|
||||
if (!paused
|
||||
&& switchToNext
|
||||
&& streamed->markFrameShown()
|
||||
&& playOnce
|
||||
&& !_stickerOncePlayed) {
|
||||
_stickerOncePlayed = true;
|
||||
_parent->delegate()->elementStartStickerLoop(_parent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,10 @@ public:
|
|||
QPoint resolveCustomInfoRightBottom() const override;
|
||||
QString additionalInfoString() const override;
|
||||
|
||||
void stickerClearLoopPlayed() override {
|
||||
_stickerOncePlayed = false;
|
||||
}
|
||||
|
||||
bool skipBubbleTail() const override {
|
||||
return isRoundedInBubbleBottom() && _caption.isEmpty();
|
||||
}
|
||||
|
@ -192,6 +196,7 @@ private:
|
|||
ClickHandlerPtr _stickerLink;
|
||||
|
||||
QString _downloadSize;
|
||||
mutable bool _stickerOncePlayed = false;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ struct FrameYUV420 {
|
|||
};
|
||||
|
||||
struct FrameWithInfo {
|
||||
QImage original;
|
||||
QImage image;
|
||||
FrameYUV420 *yuv420 = nullptr;
|
||||
FrameFormat format = FrameFormat::None;
|
||||
int index = -1;
|
||||
|
|
|
@ -172,6 +172,10 @@ QImage Instance::frame(const FrameRequest &request) const {
|
|||
return player().frame(request, this);
|
||||
}
|
||||
|
||||
FrameWithInfo Instance::frameWithInfo(const FrameRequest &request) const {
|
||||
return player().frameWithInfo(request, this);
|
||||
}
|
||||
|
||||
FrameWithInfo Instance::frameWithInfo() const {
|
||||
return player().frameWithInfo(this);
|
||||
}
|
||||
|
|
|
@ -69,6 +69,8 @@ public:
|
|||
void callWaitingCallback();
|
||||
|
||||
[[nodiscard]] QImage frame(const FrameRequest &request) const;
|
||||
[[nodiscard]] FrameWithInfo frameWithInfo(
|
||||
const FrameRequest &request) const;
|
||||
[[nodiscard]] FrameWithInfo frameWithInfo() const;
|
||||
bool markFrameShown() const;
|
||||
|
||||
|
|
|
@ -884,6 +884,14 @@ QImage Player::frame(
|
|||
return _video->frame(request, instance);
|
||||
}
|
||||
|
||||
FrameWithInfo Player::frameWithInfo(
|
||||
const FrameRequest &request,
|
||||
const Instance *instance) const {
|
||||
Expects(_video != nullptr);
|
||||
|
||||
return _video->frameWithInfo(request, instance);
|
||||
}
|
||||
|
||||
FrameWithInfo Player::frameWithInfo(const Instance *instance) const {
|
||||
Expects(_video != nullptr);
|
||||
|
||||
|
|
|
@ -64,7 +64,9 @@ public:
|
|||
[[nodiscard]] QImage frame(
|
||||
const FrameRequest &request,
|
||||
const Instance *instance = nullptr) const;
|
||||
|
||||
[[nodiscard]] FrameWithInfo frameWithInfo(
|
||||
const FrameRequest &request,
|
||||
const Instance *instance = nullptr) const;
|
||||
[[nodiscard]] FrameWithInfo frameWithInfo(
|
||||
const Instance *instance = nullptr) const; // !requireARGB32
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ private:
|
|||
Fn<void(Error)> _error;
|
||||
crl::time _pausedTime = kTimeUnknown;
|
||||
crl::time _resumedTime = kTimeUnknown;
|
||||
int _frameIndex = 0;
|
||||
int _durationByLastPacket = 0;
|
||||
mutable TimePoint _syncTimePoint;
|
||||
crl::time _loopingShift = 0;
|
||||
|
@ -330,6 +331,7 @@ bool VideoTrackObject::loopAround() {
|
|||
return false;
|
||||
}
|
||||
avcodec_flush_buffers(_stream.codec.get());
|
||||
_frameIndex = 0;
|
||||
_loopingShift += duration;
|
||||
_readTillEnd = false;
|
||||
return true;
|
||||
|
@ -372,6 +374,7 @@ auto VideoTrackObject::readFrame(not_null<Frame*> frame) -> FrameResult {
|
|||
return FrameResult::Error;
|
||||
}
|
||||
std::swap(frame->decoded, _stream.frame);
|
||||
frame->index = _frameIndex++;
|
||||
frame->position = position;
|
||||
frame->displayed = kTimeUnknown;
|
||||
return FrameResult::Done;
|
||||
|
@ -651,6 +654,7 @@ void VideoTrackObject::callReady() {
|
|||
Expects(_ready != nullptr);
|
||||
|
||||
const auto frame = _shared->frameForPaint();
|
||||
++_frameIndex;
|
||||
|
||||
auto data = VideoInformation();
|
||||
data.size = FFmpeg::CorrectByAspect(
|
||||
|
@ -961,9 +965,6 @@ bool VideoTrack::Shared::markFrameShown() {
|
|||
if (frame->displayed == kTimeUnknown) {
|
||||
return false;
|
||||
}
|
||||
if (counter == 2 * kFramesCount - 1) {
|
||||
++_counterCycle;
|
||||
}
|
||||
_counter.store(
|
||||
next,
|
||||
std::memory_order_release);
|
||||
|
@ -995,7 +996,7 @@ VideoTrack::FrameWithIndex VideoTrack::Shared::frameForPaintWithIndex() {
|
|||
Assert(frame->displayed != kTimeUnknown);
|
||||
return {
|
||||
.frame = frame,
|
||||
.index = (_counterCycle * 2 * kFramesCount) + index,
|
||||
.index = frame->index,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1101,7 +1102,44 @@ bool VideoTrack::markFrameShown() {
|
|||
QImage VideoTrack::frame(
|
||||
const FrameRequest &request,
|
||||
const Instance *instance) {
|
||||
const auto frame = _shared->frameForPaint();
|
||||
return frameImage(_shared->frameForPaint(), request, instance);
|
||||
}
|
||||
|
||||
FrameWithInfo VideoTrack::frameWithInfo(
|
||||
const FrameRequest &request,
|
||||
const Instance *instance) {
|
||||
const auto data = _shared->frameForPaintWithIndex();
|
||||
return {
|
||||
.image = frameImage(data.frame, request, instance),
|
||||
.format = FrameFormat::ARGB32,
|
||||
.index = data.index,
|
||||
};
|
||||
}
|
||||
|
||||
FrameWithInfo VideoTrack::frameWithInfo(const Instance *instance) {
|
||||
const auto data = _shared->frameForPaintWithIndex();
|
||||
const auto i = data.frame->prepared.find(instance);
|
||||
const auto none = (i == data.frame->prepared.end());
|
||||
if (none || i->second.request.requireARGB32) {
|
||||
_wrapped.with([=](Implementation &unwrapped) {
|
||||
unwrapped.updateFrameRequest(
|
||||
instance,
|
||||
{ .requireARGB32 = false });
|
||||
});
|
||||
}
|
||||
return {
|
||||
.image = data.frame->original,
|
||||
.yuv420 = &data.frame->yuv420,
|
||||
.format = data.frame->format,
|
||||
.index = data.index,
|
||||
.alpha = data.frame->alpha,
|
||||
};
|
||||
}
|
||||
|
||||
QImage VideoTrack::frameImage(
|
||||
not_null<Frame*> frame,
|
||||
const FrameRequest &request,
|
||||
const Instance *instance) {
|
||||
const auto i = frame->prepared.find(instance);
|
||||
const auto none = (i == frame->prepared.end());
|
||||
const auto preparedFor = frame->prepared.empty()
|
||||
|
@ -1151,26 +1189,6 @@ QImage VideoTrack::frame(
|
|||
return i->second.image;
|
||||
}
|
||||
|
||||
FrameWithInfo VideoTrack::frameWithInfo(const Instance *instance) {
|
||||
const auto data = _shared->frameForPaintWithIndex();
|
||||
const auto i = data.frame->prepared.find(instance);
|
||||
const auto none = (i == data.frame->prepared.end());
|
||||
if (none || i->second.request.requireARGB32) {
|
||||
_wrapped.with([=](Implementation &unwrapped) {
|
||||
unwrapped.updateFrameRequest(
|
||||
instance,
|
||||
{ .requireARGB32 = false });
|
||||
});
|
||||
}
|
||||
return {
|
||||
.original = data.frame->original,
|
||||
.yuv420 = &data.frame->yuv420,
|
||||
.format = data.frame->format,
|
||||
.index = data.index,
|
||||
.alpha = data.frame->alpha,
|
||||
};
|
||||
}
|
||||
|
||||
QImage VideoTrack::currentFrameImage() {
|
||||
const auto frame = _shared->frameForPaint();
|
||||
if (frame->original.isNull() && frame->format == FrameFormat::YUV420) {
|
||||
|
|
|
@ -58,6 +58,9 @@ public:
|
|||
[[nodiscard]] QImage frame(
|
||||
const FrameRequest &request,
|
||||
const Instance *instance);
|
||||
[[nodiscard]] FrameWithInfo frameWithInfo(
|
||||
const FrameRequest &request,
|
||||
const Instance *instance);
|
||||
[[nodiscard]] FrameWithInfo frameWithInfo(const Instance *instance);
|
||||
[[nodiscard]] QImage currentFrameImage();
|
||||
void unregisterInstance(not_null<const Instance*> instance);
|
||||
|
@ -88,6 +91,7 @@ private:
|
|||
|
||||
base::flat_map<const Instance*, Prepared> prepared;
|
||||
|
||||
int index = 0;
|
||||
bool alpha = false;
|
||||
};
|
||||
struct FrameWithIndex {
|
||||
|
@ -141,9 +145,6 @@ private:
|
|||
static constexpr auto kCounterUninitialized = -1;
|
||||
std::atomic<int> _counter = kCounterUninitialized;
|
||||
|
||||
// Main thread.
|
||||
int _counterCycle = 0;
|
||||
|
||||
static constexpr auto kFramesCount = 4;
|
||||
std::array<Frame, kFramesCount> _frames;
|
||||
|
||||
|
@ -160,6 +161,11 @@ private:
|
|||
not_null<const Frame*> frame,
|
||||
crl::time trackTime);
|
||||
|
||||
[[nodiscard]] QImage frameImage(
|
||||
not_null<Frame*> frame,
|
||||
const FrameRequest &request,
|
||||
const Instance *instance);
|
||||
|
||||
const int _streamIndex = 0;
|
||||
const AVRational _streamTimeBase;
|
||||
const crl::time _streamDuration = 0;
|
||||
|
|
|
@ -188,9 +188,9 @@ void OverlayWidget::RendererGL::paintTransformedVideoFrame(
|
|||
if (data.format == Streaming::FrameFormat::None) {
|
||||
return;
|
||||
} else if (data.format == Streaming::FrameFormat::ARGB32) {
|
||||
Assert(!data.original.isNull());
|
||||
Assert(!data.image.isNull());
|
||||
paintTransformedStaticContent(
|
||||
data.original,
|
||||
data.image,
|
||||
geometry,
|
||||
data.alpha,
|
||||
data.alpha);
|
||||
|
|
|
@ -610,7 +610,7 @@ Streaming::FrameWithInfo OverlayWidget::videoFrameWithInfo() const {
|
|||
return _streamed->instance.player().ready()
|
||||
? _streamed->instance.frameWithInfo()
|
||||
: Streaming::FrameWithInfo{
|
||||
.original = _streamed->instance.info().video.cover,
|
||||
.image = _streamed->instance.info().video.cover,
|
||||
.format = Streaming::FrameFormat::ARGB32,
|
||||
.index = -2,
|
||||
.alpha = _streamed->instance.info().video.alpha,
|
||||
|
|
|
@ -285,8 +285,8 @@ void Pip::RendererGL::paintTransformedVideoFrame(
|
|||
}
|
||||
geometry.rotation = (geometry.rotation + geometry.videoRotation) % 360;
|
||||
if (data.format == Streaming::FrameFormat::ARGB32) {
|
||||
Assert(!data.original.isNull());
|
||||
paintTransformedStaticContent(data.original, geometry);
|
||||
Assert(!data.image.isNull());
|
||||
paintTransformedStaticContent(data.image, geometry);
|
||||
return;
|
||||
}
|
||||
Assert(data.format == Streaming::FrameFormat::YUV420);
|
||||
|
|
Loading…
Add table
Reference in a new issue