MythTV master
mythinteractivebuffer.cpp
Go to the documentation of this file.
1// Std
2#include <cstdio>
3
4// Qt
5#include <QChar> // Fix Qt6 GCC SFINAE warning
6#include <QWriteLocker>
7
8// Mythtv
10
12#include "mheg/netstream.h"
13
14#define LOC QString("InteractiveBuf: ")
15
18 m_parent(Parent)
19{
20 m_startReadAhead = true;
22}
23
25{
27 delete m_stream;
28 delete m_parent;
29}
30
32{
33 return m_stream ? m_stream->IsOpen() : false;
34}
35
42bool MythInteractiveBuffer::OpenFile(const QString &UrlStr, std::chrono::milliseconds /*Retry*/)
43{
44 QUrl Url { UrlStr };
45 if (!Url.isValid())
46 {
47 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Invalid URL '%1'").arg(UrlStr));
48 return false;
49 }
50 if (!NetStream::IsSupported(Url))
51 {
52 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unsupported URL '%1'").arg(UrlStr));
53 return false;
54 }
55
56 std::unique_ptr<NetStream> stream(new NetStream(Url, NetStream::kNeverCache));
57 if (!stream || !stream->IsOpen())
58 {
59 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to open '%1'").arg(UrlStr));
60 return false;
61 }
62
63 if (!stream->WaitTillReady(30s))
64 {
65 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Stream not ready '%1'").arg(UrlStr));
66 return false;
67 }
68
69 if (m_parent)
70 m_parent->Pause();
71
72 QWriteLocker locker(&m_rwLock);
73
74 m_safeFilename = UrlStr;
75 m_filename = UrlStr;
76
77 delete m_stream;
78 m_stream = stream.release();
79
80 // The initial bitrate needs to be set with consideration for low bit rate
81 // streams (e.g. radio @ 64Kbps) such that fill_min bytes are received
82 // in a reasonable time period to enable decoders to peek the first few KB
83 // to determine type & settings.
84 m_rawBitrate = 128; // remotefile
86
87 locker.unlock();
88 Reset(true, false, true);
89
90 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Opened '%1'").arg(UrlStr));
91 return true;
92}
93
95{
96 return m_stream ? m_stream->GetReadPosition() : 0;
97}
98
99long long MythInteractiveBuffer::SeekInternal(long long Position, int Whence)
100{
101 long long result = -1;
102 if (!m_stream)
103 return result;
104
105 QWriteLocker locker(&m_posLock);
106
107 // Optimize no-op seeks
108 if (m_readAheadRunning && ((Whence == SEEK_SET && Position == m_readPos) ||
109 (Whence == SEEK_CUR && Position == 0)))
110 {
111 result = m_readPos;
112 return result;
113 }
114
115 switch (Whence)
116 {
117 case SEEK_SET: break;
118 case SEEK_CUR:
119 Position += m_stream->GetReadPosition();
120 break;
121 case SEEK_END:
122 Position += m_stream->GetSize();
123 break;
124 default:
125 errno = EINVAL;
126 m_generalWait.wakeAll();
127 return result;
128 }
129
130 result = m_stream->Seek(Position);
131 if (result >= 0)
132 {
133 m_readPos = result;
134 m_ignoreReadPos = -1;
137 m_readAdjust = 0;
138 }
139
140 m_generalWait.wakeAll();
141 return result;
142}
143
145{
146 if (m_stream)
147 return m_stream->safe_read(Buffer, Size, 1000);
148 m_ateof = true;
149 return 0;
150}
151
153{
154 return m_stream ? m_stream->GetSize() : -1;
155}
156
158{
159 MythMediaBuffer *parent = m_parent;
160 if (parent && IsOpen())
161 parent->Unpause();
162 m_parent = nullptr;
163 return parent;
164}
MythMediaBuffer * TakeBuffer(void)
long long SeekInternal(long long Position, int Whence) override
bool OpenFile(const QString &Url, std::chrono::milliseconds Retry=kDefaultOpenTimeout) override
Opens a BBC NetStream for reading.
int SafeRead(void *Buffer, uint Size) override
MythMediaBuffer * m_parent
bool IsOpen(void) const override
long long GetReadPosition(void) const override
long long GetRealFileSizeInternal(void) const override
void Reset(bool Full=false, bool ToAdjust=false, bool ResetInternal=false)
Resets the read-ahead thread and our position in the file.
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
long long m_ignoreReadPos
void Pause(void)
Pauses the read-ahead thread.
long long m_readAdjust
QReadWriteLock m_posLock
friend class MythInteractiveBuffer
void Unpause(void)
Unpauses the read-ahead thread.
QReadWriteLock m_rwLock
void ResetReadAhead(long long NewInternal)
Restart the read-ahead thread at the 'newinternal' position.
void CalcReadAheadThresh(void)
Calculates m_fillMin, m_fillThreshold, and m_readBlockSize from the estimated effective bitrate of th...
QWaitCondition m_generalWait
Condition to signal that the read ahead thread is running.
Stream content from a URI.
Definition: netstream.h:32
qlonglong GetSize() const
Definition: netstream.cpp:630
qlonglong Seek(qlonglong pos)
Definition: netstream.cpp:602
int safe_read(void *data, unsigned sz, unsigned millisecs=0)
Definition: netstream.cpp:570
bool IsOpen() const
Definition: netstream.cpp:539
@ kNeverCache
Definition: netstream.h:36
static bool IsSupported(const QUrl &url)
RingBuffer interface.
Definition: netstream.cpp:531
qlonglong GetReadPosition() const
Definition: netstream.cpp:623
unsigned int uint
Definition: compat.h:60
#define LOC
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
@ kMythBufferMHEG