16 m_absSeekPos(absSeekPos),
19 qCDebug(qLcStreamDecoder) <<
"Create stream decoder, trackType" << m_trackType
20 <<
"absSeekPos:" << absSeekPos;
26 avcodec_flush_buffers(m_codec.
context());
36 m_absSeekPos = trackPos;
41 m_packets.enqueue(packet);
48 auto packet = m_packets.dequeue();
50 auto decodePacket = [
this](
Packet packet) {
52 decodeSubtitle(packet);
57 if (packet.isValid() && packet.loopOffset().index != m_offset.
index) {
60 qCDebug(qLcStreamDecoder) <<
"flush buffers due to new loop:" << packet.loopOffset().index;
62 avcodec_flush_buffers(m_codec.
context());
63 m_offset = packet.loopOffset();
92 Q_UNREACHABLE_RETURN(-1);
98 if (
frame.sourceId() !=
id())
101 --m_pendingFramesCount;
102 Q_ASSERT(m_pendingFramesCount >= 0);
111 return !m_packets.empty() && m_pendingFramesCount <
maxCount
117 if (
frame.isValid() &&
frame.absoluteEnd() < m_absSeekPos)
120 Q_ASSERT(m_pendingFramesCount >= 0);
121 ++m_pendingFramesCount;
125void StreamDecoder::decodeMedia(Packet packet)
127 auto sendPacketResult = sendAVPacket(packet);
129 if (sendPacketResult == AVERROR(EAGAIN)) {
136 sendPacketResult = sendAVPacket(packet);
138 if (sendPacketResult != AVERROR(EAGAIN))
139 qWarning() <<
"Unexpected FFmpeg behavior";
142 if (sendPacketResult == 0)
146int StreamDecoder::sendAVPacket(Packet packet)
148 return avcodec_send_packet(m_codec.
context(), packet.isValid() ? packet.avPacket() :
nullptr);
151void StreamDecoder::receiveAVFrames()
156 const auto receiveFrameResult = avcodec_receive_frame(m_codec.
context(), avFrame.get());
158 if (receiveFrameResult == AVERROR_EOF || receiveFrameResult == AVERROR(EAGAIN))
161 if (receiveFrameResult < 0) {
166 onFrameFound({ m_offset, std::move(avFrame), m_codec, 0,
id() });
170void StreamDecoder::decodeSubtitle(Packet packet)
172 if (!packet.isValid())
177 memset(&subtitle, 0,
sizeof(subtitle));
181 avcodec_decode_subtitle2(m_codec.
context(), &subtitle, &gotSubtitle, packet.avPacket());
184 if (
res < 0 || !gotSubtitle)
190 if (subtitle.pts == AV_NOPTS_VALUE) {
191 start = m_codec.
toUs(packet.avPacket()->pts);
192 end =
start + m_codec.
toUs(packet.avPacket()->duration);
194 auto pts =
timeStampUs(subtitle.pts, AVRational{ 1, AV_TIME_BASE });
195 start = *pts +
qint64(subtitle.start_display_time) * 1000;
196 end = *pts +
qint64(subtitle.end_display_time) * 1000;
200 qWarning() <<
"Invalid subtitle time";
205 for (
uint i = 0;
i < subtitle.num_rects; ++
i) {
206 const auto *
r = subtitle.rects[
i];
213 const char *ass =
r->ass;
240#include "moc_qffmpegstreamdecoder_p.cpp"
AVCodecContext * context() const
qint64 toUs(qint64 ts) const
virtual bool canDoNextStep() const
void setAtEnd(bool isAtEnd)
void scheduleNextStep(bool allowDoImmediatelly=true)
std::chrono::steady_clock::time_point TimePoint
StreamDecoder(const Codec &codec, qint64 absSeekPos)
bool canDoNextStep() const override
static qint32 maxQueueSize(QPlatformMediaPlayer::TrackType type)
void doNextStep() override
void onFrameProcessed(Frame frame)
void packetProcessed(Packet)
void setInitialPosition(TimePoint tp, qint64 trackPos)
void onFinalPacketReceived()
void requestHandleFrame(Frame frame)
QPlatformMediaPlayer::TrackType trackType() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString & replace(qsizetype i, qsizetype len, QChar after)
void chop(qsizetype n)
Removes n characters from the end of the string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
AVFrameUPtr makeAVFrame()
QString err2str(int errnum)
std::optional< qint64 > timeStampUs(qint64 ts, AVRational base)
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
QLatin1StringView QLatin1String
\inmodule QtCore \reentrant