20static std::optional<qint64> streamDuration(
const AVStream &
stream)
22 const auto &factor =
stream.time_base;
24 if (
stream.duration > 0 && factor.num > 0 && factor.den > 0) {
25 return qint64(1000000) *
stream.duration * factor.num / factor.den;
33 <<
"is invalid. Taking it from the metadata";
36 if (
const auto duration = av_dict_get(
stream.metadata,
"DURATION",
nullptr, 0)) {
48 const auto *codecPar =
stream->codecpar;
55 codecPar->codec_id)));
64 codecPar->codec_id)));
71static int readQIODevice(
void *opaque, uint8_t *
buf,
int buf_size)
73 auto *dev =
static_cast<QIODevice *
>(opaque);
76 return dev->
read(
reinterpret_cast<char *
>(
buf), buf_size);
79static int64_t seekQIODevice(
void *opaque, int64_t
offset,
int whence)
84 return AVERROR(EINVAL);
86 if (whence & AVSEEK_SIZE)
89 whence &= ~AVSEEK_FORCE;
91 if (whence == SEEK_CUR)
93 else if (whence == SEEK_END)
97 return AVERROR(EINVAL);
104 case AVMEDIA_TYPE_AUDIO:
106 case AVMEDIA_TYPE_VIDEO:
108 case AVMEDIA_TYPE_SUBTITLE:
115std::optional<MediaDataHolder::ContextError>
118 *
this = MediaDataHolder{};
122 AVFormatContext *
context =
nullptr;
130 if (!
stream->isSequential())
132 context = avformat_alloc_context();
134 constexpr int bufferSize = 32768;
135 unsigned char *
buffer = (
unsigned char *)av_malloc(bufferSize);
136 context->pb = avio_alloc_context(
buffer, bufferSize,
false,
stream, &readQIODevice,
nullptr, &seekQIODevice);
139 int ret = avformat_open_input(&
context,
url.constData(),
nullptr,
nullptr);
142 if (
ret == AVERROR(EACCES))
144 else if (
ret == AVERROR(EINVAL))
147 return ContextError{ code, QMediaPlayer::tr(
"Could not open file") };
150 ret = avformat_find_stream_info(
context,
nullptr);
152 avformat_close_input(&
context);
154 QMediaPlayer::tr(
"Could not find stream information for media file") };
158 av_dump_format(
context, 0,
url.constData(), 0);
161 m_isSeekable = !(
context->ctx_flags & AVFMTCTX_UNSEEKABLE);
170void MediaDataHolder::updateStreams()
173 m_requestedStreams = { -1, -1, -1 };
174 m_currentAVStreamIndex = { -1, -1, -1 };
181 for (
unsigned int i = 0;
i < m_context->nb_streams; ++
i) {
183 const auto *
stream = m_context->streams[
i];
184 const auto trackType = trackTypeFromMediaType(
stream->codecpar->codec_type);
190 const bool isDefault =
stream->disposition & AV_DISPOSITION_DEFAULT;
193 insertMediaData(metaData, trackType,
stream);
195 if (isDefault && m_requestedStreams[trackType] < 0)
196 m_requestedStreams[trackType] = m_streamMap[trackType].size();
199 if (
auto duration = streamDuration(*
stream)) {
200 m_duration =
qMax(m_duration, *duration);
204 m_streamMap[trackType].append({ (int)
i, isDefault, metaData });
207 for (
auto trackType :
209 auto &requestedStream = m_requestedStreams[trackType];
210 auto &streamMap = m_streamMap[trackType];
212 if (requestedStream < 0 && !streamMap.empty())
215 if (requestedStream >= 0)
216 m_currentAVStreamIndex[trackType] = streamMap[requestedStream].avStreamIndex;
220void MediaDataHolder::updateMetaData()
230 m_context->iformat)));
233 for (
auto trackType :
235 const auto streamIndex = m_currentAVStreamIndex[trackType];
236 if (streamIndex >= 0)
237 insertMediaData(m_metaData, trackType, m_context->streams[streamIndex]);
246 if (streamNumber < 0 || streamNumber >= m_streamMap[
type].
size())
248 if (m_requestedStreams[
type] == streamNumber)
250 m_requestedStreams[
type] = streamNumber;
251 const int avStreamIndex = m_streamMap[
type].value(streamNumber).avStreamIndex;
253 const int oldIndex = m_currentAVStreamIndex[
type];
254 qCDebug(qLcMediaDataHolder) <<
">>>>> change track" <<
type <<
"from" << oldIndex <<
"to"
258 m_currentAVStreamIndex[
type] = avStreamIndex;
275 return m_streamMap[trackType];
\inmodule QtCore \reentrant
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from.
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success,...
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray toUtf8() const &
constexpr int msecsSinceStartOfDay() const
Returns the number of msecs since the start of the day, i.e.
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Combined button and popup list for selecting options.
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLuint GLintptr offset
QLatin1StringView QLatin1String
QUrl url("example.com")
[constructor-url-reference]