00001 #include <QUrl>
00002 #include "mythcorecontext.h"
00003 #include "mythlogging.h"
00004
00005 #include "streamingringbuffer.h"
00006
00007 #define LOC QString("StreamRingBuf(%1): ").arg(filename)
00008
00009 StreamingRingBuffer::StreamingRingBuffer(const QString &lfilename)
00010 : RingBuffer(kRingBuffer_HTTP), m_context(NULL), m_streamed(true),
00011 m_allowSeeks(false)
00012 {
00013 startreadahead = false;
00014 OpenFile(lfilename);
00015 }
00016
00017 StreamingRingBuffer::~StreamingRingBuffer()
00018 {
00019 rwlock.lockForWrite();
00020 if (m_context)
00021 ffurl_close(m_context);
00022 rwlock.unlock();
00023 }
00024
00025 bool StreamingRingBuffer::IsOpen(void) const
00026 {
00027 bool result;
00028 rwlock.lockForRead();
00029 result = (bool)m_context;
00030 rwlock.unlock();
00031 return result;
00032 }
00033
00034 long long StreamingRingBuffer::GetReadPosition(void) const
00035 {
00036 return 0;
00037 }
00038
00039 bool StreamingRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
00040 {
00041 avcodeclock->lock();
00042 av_register_all();
00043 avcodeclock->unlock();
00044
00045 rwlock.lockForWrite();
00046
00047 safefilename = lfilename;
00048 filename = lfilename;
00049
00050
00051
00052 QUrl url = filename;
00053 if (url.path().endsWith(QLatin1String("m3u8"), Qt::CaseInsensitive))
00054 {
00055 url.setScheme("hls+http");
00056 }
00057
00058 int res = ffurl_open(&m_context, url.toString().toAscii(), AVIO_FLAG_READ,
00059 NULL, NULL);
00060 if (res >=0 && m_context &&
00061 !m_context->is_streamed && ffurl_seek(m_context, 0, SEEK_SET) >= 0)
00062 {
00063 m_streamed = false;
00064 m_allowSeeks = true;
00065 }
00066
00067 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Trying %1 (allow seeks: %2")
00068 .arg(filename).arg(m_allowSeeks));
00069
00070 rwlock.unlock();
00071
00072 if (res < 0 || !m_context)
00073 {
00074 LOG(VB_GENERAL, LOG_ERR, LOC +
00075 QString("Failed to open stream (error %1)") .arg(res));
00076 return false;
00077 }
00078
00079 return true;
00080 }
00081
00082 long long StreamingRingBuffer::Seek(long long pos, int whence, bool has_lock)
00083 {
00084 if (!m_context)
00085 return 0;
00086
00087 poslock.lockForWrite();
00088 int seek = ffurl_seek(m_context, pos, whence);
00089 poslock.unlock();
00090
00091 if (seek < 0)
00092 {
00093 ateof = true;
00094 return 0;
00095 }
00096 return pos;
00097 }
00098
00099 int StreamingRingBuffer::safe_read(void *data, uint sz)
00100 {
00101 if (m_context)
00102 return ffurl_read_complete(m_context, (unsigned char*)data, sz);
00103 return 0;
00104 }
00105
00106 long long StreamingRingBuffer::GetRealFileSize(void) const
00107 {
00108 long long result = -1;
00109 rwlock.lockForRead();
00110 if (m_context)
00111 result = ffurl_size(m_context);
00112 rwlock.unlock();
00113 return result;
00114 }