MythTV master
mythstreamingbuffer.cpp
Go to the documentation of this file.
2
3// Qt
4#include <QUrl>
5
6// MythTV
8
9// FFmpeg
10extern "C" {
11#include "libavformat/avio.h"
12}
13
14#define LOC QString("StreamRingBuf(%1): ").arg(m_filename)
15
18{
19 m_startReadAhead = false;
21}
22
24{
26
27 m_rwLock.lockForWrite();
28 if (m_context)
29 avio_closep(&m_context);
30 m_rwLock.unlock();
31}
32
34{
35 m_rwLock.lockForRead();
36 bool result = m_context;
37 m_rwLock.unlock();
38 return result;
39}
40
42{
43 return 0;
44}
45
54bool MythStreamingBuffer::OpenFile(const QString &Filename, std::chrono::milliseconds /*Retry*/)
55{
57
58 m_rwLock.lockForWrite();
59
60 m_safeFilename = Filename;
61 m_filename = Filename;
62
63 // TODO check whether local area file
64
65 QUrl url { m_filename };
66 if (!url.isValid())
67 {
68 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Invalid URL (%1)").arg(m_filename));
69 m_lastError = QObject::tr("Invalid URL (%1)").arg(m_filename);
70 m_rwLock.unlock();
71 return false;
72 }
73
74 if (url.path().endsWith(QLatin1String("m3u8"), Qt::CaseInsensitive))
75 url.setScheme("hls+http");
76
77 int res = avio_open(&m_context, url.toString().toLatin1().constData(),
78 AVIO_FLAG_READ);
79 if (res < 0 || !m_context)
80 {
81 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to open stream (%1) (error %2)")
82 .arg(m_filename, QString::number(res)));
83 m_lastError = QObject::tr("Failed to open stream (%1)").arg(res);
84 m_rwLock.unlock();
85 return false;
86 }
87
88 m_streamed = (m_context->seekable & AVIO_SEEKABLE_NORMAL) == 0;
89 m_allowSeeks = !m_streamed && avio_seek(m_context, 0, SEEK_SET) >= 0;
90
91 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Opened %1 (allow seeks: %2")
93
94 m_rwLock.unlock();
95 return true;
96}
97
98long long MythStreamingBuffer::SeekInternal(long long Position, int Whence)
99{
100 if (!m_context)
101 return 0;
102
103 m_posLock.lockForWrite();
104 int64_t seek = avio_seek(m_context, Position, Whence);
105 m_posLock.unlock();
106
107 if (seek < 0)
108 {
109 m_ateof = true;
110 return 0;
111 }
112 return seek;
113}
114
116{
117 int len = 0;
118
119 if (m_context)
120 {
121 while (len < static_cast<int>(Size))
122 {
123 int ret = avio_read(m_context, static_cast<unsigned char*>(Buffer) + len,
124 static_cast<int>(Size) - len);
125 if (ret < 0)
126 {
127 if (ret == AVERROR_EOF)
128 m_ateof = true;
129 errno = ret;
130 break;
131 }
132 if (ret == 0) // nothing read, exit early
133 break; // should EOF be set ??
134 len += ret;
135 }
136 }
137 return len;
138}
139
141{
142 long long result = -1;
143 m_rwLock.lockForRead();
144 if (m_context)
145 result = avio_size(m_context);
146 m_rwLock.unlock();
147 return result;
148}
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
QReadWriteLock m_posLock
static void AVFormatInitNetwork(void)
QReadWriteLock m_rwLock
long long GetReadPosition(void) const override
bool OpenFile(const QString &Filename, std::chrono::milliseconds Retry=kDefaultOpenTimeout) override
bool IsOpen(void) const override
MythStreamingBuffer(const QString &Filename)
long long GetRealFileSizeInternal(void) const override
struct AVIOContext * m_context
int SafeRead(void *Buffer, uint Size) override
long long SeekInternal(long long Position, int Whence) override
unsigned int uint
Definition: compat.h:60
QString boolToQString(bool val)
This is equivalent to QVariant(bool).toString()
Definition: mythlogging.h:86
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
@ kMythBufferHTTP
#define LOC