mirror of https://github.com/procxx/kepka.git
				
				
				
			Add limits on video frame size.
Any video that starts streaming is limited to 4K. Any in-chat streaming is limited to full hd. Any GIF panel animation is limited to 720p.
This commit is contained in:
		
							parent
							
								
									2c0b852dad
								
							
						
					
					
						commit
						01c79f917e
					
				| 
						 | 
				
			
			@ -40,6 +40,7 @@ namespace {
 | 
			
		|||
 | 
			
		||||
constexpr auto kMaxGifForwardedBarLines = 4;
 | 
			
		||||
constexpr auto kUseNonBlurredThreshold = 240;
 | 
			
		||||
constexpr auto kMaxInlineArea = 1920 * 1080;
 | 
			
		||||
 | 
			
		||||
int gifMaxStatusWidth(DocumentData *document) {
 | 
			
		||||
	auto result = st::normalFont->width(formatDownloadText(document->size, document->size));
 | 
			
		||||
| 
						 | 
				
			
			@ -47,6 +48,11 @@ int gifMaxStatusWidth(DocumentData *document) {
 | 
			
		|||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[[nodiscard]] bool CanPlayInline(not_null<DocumentData*> document) {
 | 
			
		||||
	const auto dimensions = document->dimensions;
 | 
			
		||||
	return dimensions.width() * dimensions.height() <= kMaxInlineArea;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
 | 
			
		||||
struct Gif::Streamed {
 | 
			
		||||
| 
						 | 
				
			
			@ -261,7 +267,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
 | 
			
		|||
	const auto selected = (selection == FullSelection);
 | 
			
		||||
	const auto autoPaused = App::wnd()->sessionController()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
 | 
			
		||||
	const auto cornerDownload = downloadInCorner();
 | 
			
		||||
	const auto canBePlayed = _data->canBePlayed();
 | 
			
		||||
	const auto canBePlayed = _data->canBePlayed() && CanPlayInline(_data);
 | 
			
		||||
	const auto autoplay = autoplayEnabled() && canBePlayed;
 | 
			
		||||
	const auto activeRoundPlaying = activeRoundStreamed();
 | 
			
		||||
	const auto startPlay = autoplay
 | 
			
		||||
| 
						 | 
				
			
			@ -865,7 +871,7 @@ void Gif::drawGrouped(
 | 
			
		|||
	const auto autoPaused = App::wnd()->sessionController()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
 | 
			
		||||
	const auto fullFeatured = fullFeaturedGrouped(sides);
 | 
			
		||||
	const auto cornerDownload = fullFeatured && downloadInCorner();
 | 
			
		||||
	const auto canBePlayed = _data->canBePlayed();
 | 
			
		||||
	const auto canBePlayed = _data->canBePlayed() && CanPlayInline(_data);;
 | 
			
		||||
	const auto autoplay = fullFeatured && autoplayEnabled() && canBePlayed;
 | 
			
		||||
	const auto startPlay = autoplay && !_streamed;
 | 
			
		||||
	if (startPlay) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1404,7 +1410,13 @@ void Gif::repaintStreamedContent() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void Gif::streamingReady(::Media::Streaming::Information &&info) {
 | 
			
		||||
	if (info.video.size.width() * info.video.size.height()
 | 
			
		||||
		> kMaxInlineArea) {
 | 
			
		||||
		_data->dimensions = info.video.size;
 | 
			
		||||
		stopAnimation();
 | 
			
		||||
	} else {
 | 
			
		||||
		history()->owner().requestViewResize(_parent);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gif::stopAnimation() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,13 @@ namespace internal {
 | 
			
		|||
 | 
			
		||||
using TextState = HistoryView::TextState;
 | 
			
		||||
 | 
			
		||||
constexpr auto kMaxInlineArea = 1280 * 720;
 | 
			
		||||
 | 
			
		||||
[[nodiscard]] bool CanPlayInline(not_null<DocumentData*> document) {
 | 
			
		||||
	const auto dimensions = document->dimensions;
 | 
			
		||||
	return dimensions.width() * dimensions.height() <= kMaxInlineArea;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileBase::FileBase(not_null<Context*> context, not_null<Result*> result)
 | 
			
		||||
: ItemBase(context, result) {
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +148,10 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons
 | 
			
		|||
	document->automaticLoad(fileOrigin(), nullptr);
 | 
			
		||||
 | 
			
		||||
	bool loaded = document->loaded(), loading = document->loading(), displayLoading = document->displayLoading();
 | 
			
		||||
	if (loaded && !_gif && !_gif.isBad()) {
 | 
			
		||||
	if (loaded
 | 
			
		||||
		&& !_gif
 | 
			
		||||
		&& !_gif.isBad()
 | 
			
		||||
		&& CanPlayInline(document)) {
 | 
			
		||||
		auto that = const_cast<Gif*>(this);
 | 
			
		||||
		that->_gif = Media::Clip::MakeReader(document, FullMsgId(), [that](Media::Clip::Notification notification) {
 | 
			
		||||
			that->clipCallback(notification);
 | 
			
		||||
| 
						 | 
				
			
			@ -371,9 +381,16 @@ void Gif::clipCallback(Media::Clip::Notification notification) {
 | 
			
		|||
				_gif.setBad();
 | 
			
		||||
				getShownDocument()->unload();
 | 
			
		||||
			} else if (_gif->ready() && !_gif->started()) {
 | 
			
		||||
				if (_gif->width() * _gif->height() > kMaxInlineArea) {
 | 
			
		||||
					getShownDocument()->dimensions = QSize(
 | 
			
		||||
						_gif->width(),
 | 
			
		||||
						_gif->height());
 | 
			
		||||
					unloadAnimation();
 | 
			
		||||
				} else {
 | 
			
		||||
					auto height = st::inlineMediaHeight;
 | 
			
		||||
					auto frame = countFrameSize();
 | 
			
		||||
					_gif->start(frame.width(), frame.height(), _width, height, ImageRoundRadius::None, RectPart::None);
 | 
			
		||||
				}
 | 
			
		||||
			} else if (_gif->autoPausedGif() && !context()->inlineItemVisible(this)) {
 | 
			
		||||
				unloadAnimation();
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ namespace internal {
 | 
			
		|||
namespace {
 | 
			
		||||
 | 
			
		||||
constexpr auto kSkipInvalidDataPackets = 10;
 | 
			
		||||
constexpr auto kMaxInlineArea = 1280 * 720;
 | 
			
		||||
 | 
			
		||||
// See https://github.com/telegramdesktop/tdesktop/issues/7225
 | 
			
		||||
constexpr auto kAlignImageBy = 64;
 | 
			
		||||
| 
						 | 
				
			
			@ -59,6 +60,9 @@ ReaderImplementation::ReadResult FFMpegReaderImplementation::readNextFrame() {
 | 
			
		|||
	do {
 | 
			
		||||
		int res = avcodec_receive_frame(_codecContext, _frame.get());
 | 
			
		||||
		if (res >= 0) {
 | 
			
		||||
			if (_frame->width * _frame->height > kMaxInlineArea) {
 | 
			
		||||
				return ReadResult::Error;
 | 
			
		||||
			}
 | 
			
		||||
			processReadFrame();
 | 
			
		||||
			return ReadResult::Success;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@ namespace Media {
 | 
			
		|||
namespace Streaming {
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
constexpr auto kMaxFrameArea = 3840 * 2160; // usual 4K
 | 
			
		||||
constexpr auto kDisplaySkipped = crl::time(-1);
 | 
			
		||||
constexpr auto kFinishedPosition = std::numeric_limits<crl::time>::max();
 | 
			
		||||
static_assert(kDisplaySkipped != kTimeUnknown);
 | 
			
		||||
| 
						 | 
				
			
			@ -511,6 +512,9 @@ bool VideoTrackObject::tryReadFirstFrame(FFmpeg::Packet &&packet) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
bool VideoTrackObject::processFirstFrame() {
 | 
			
		||||
	if (_stream.frame->width * _stream.frame->height >= kMaxFrameArea) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	auto frame = ConvertFrame(
 | 
			
		||||
		_stream,
 | 
			
		||||
		_stream.frame.get(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue