init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "media/clip/media_clip_check_streaming.h"
|
||||
|
||||
#include "core/file_location.h"
|
||||
#include "base/bytes.h"
|
||||
#include "logs.h"
|
||||
|
||||
#include <QtCore/QtEndian>
|
||||
#include <QtCore/QBuffer>
|
||||
#include <QtCore/QFile>
|
||||
|
||||
namespace Media {
|
||||
namespace Clip {
|
||||
namespace {
|
||||
|
||||
constexpr auto kHeaderSize = 8;
|
||||
constexpr auto kFindMoovBefore = 128 * 1024;
|
||||
|
||||
template <typename Type>
|
||||
Type ReadBigEndian(bytes::const_span data) {
|
||||
const auto bytes = data.subspan(0, sizeof(Type)).data();
|
||||
return qFromBigEndian(*reinterpret_cast<const Type*>(bytes));
|
||||
}
|
||||
|
||||
bool IsAtom(bytes::const_span header, const char (&atom)[5]) {
|
||||
return bytes::compare(
|
||||
header.subspan(4, 4),
|
||||
bytes::make_span(atom).subspan(0, 4)) == 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool CheckStreamingSupport(
|
||||
const Core::FileLocation &location,
|
||||
QByteArray data) {
|
||||
QBuffer buffer;
|
||||
QFile file;
|
||||
if (data.isEmpty()) {
|
||||
file.setFileName(location.name());
|
||||
} else {
|
||||
buffer.setBuffer(&data);
|
||||
}
|
||||
const auto size = data.isEmpty()
|
||||
? file.size()
|
||||
: data.size();
|
||||
const auto device = data.isEmpty()
|
||||
? static_cast<QIODevice*>(&file)
|
||||
: static_cast<QIODevice*>(&buffer);
|
||||
|
||||
if (size < kHeaderSize || !device->open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto lastReadPosition = 0;
|
||||
char atomHeader[kHeaderSize] = { 0 };
|
||||
auto atomHeaderBytes = bytes::make_span(atomHeader);
|
||||
while (true) {
|
||||
const auto position = device->pos();
|
||||
if (device->read(atomHeader, kHeaderSize) != kHeaderSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (lastReadPosition >= kFindMoovBefore) {
|
||||
return false;
|
||||
} else if (IsAtom(atomHeaderBytes, "moov")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto length = [&] {
|
||||
const auto result = ReadBigEndian<uint32>(atomHeaderBytes);
|
||||
if (result != 1) {
|
||||
return uint64(result);
|
||||
}
|
||||
char atomSize64[kHeaderSize] = { 0 };
|
||||
if (device->read(atomSize64, kHeaderSize) != kHeaderSize) {
|
||||
return uint64(-1);
|
||||
}
|
||||
auto atomSize64Bytes = bytes::make_span(atomSize64);
|
||||
return ReadBigEndian<uint64>(atomSize64Bytes);
|
||||
}();
|
||||
if (position + length > size) {
|
||||
break;
|
||||
}
|
||||
device->seek(position + length);
|
||||
lastReadPosition = position;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Clip
|
||||
} // namespace Media
|
||||
Reference in New Issue
Block a user