MythTV  master
httplivestreambuffer.h
Go to the documentation of this file.
1 /*****************************************************************************
2  * httplivestreambuffer.cpp
3  * MythTV
4  *
5  * Created by Jean-Yves Avenard on 6/05/12.
6  * Copyright (c) 2012 Bubblestuff Pty Ltd. All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22 
23 #ifndef MythXCode_hlsbuffer_h
24 #define MythXCode_hlsbuffer_h
25 
26 #include "mythcorecontext.h"
27 #include "ringbuffer.h"
28 
29 extern "C" {
30 #include "libavformat/avformat.h"
31 #include "libavformat/url.h"
32 }
33 
35 class HLSStream;
36 class HLSSegment;
37 class StreamWorker;
38 class PlaylistWorker;
39 class HLSPlayback;
40 
41 using StreamsList = QList<HLSStream*>;
42 
43 class HLSRingBuffer : public RingBuffer
44 {
45 public:
46  explicit HLSRingBuffer(const QString &lfilename);
47  HLSRingBuffer(const QString &lfilename, bool open);
48  ~HLSRingBuffer() override;
49 
50  bool IsOpen(void) const override; // RingBuffer
51  long long GetReadPosition(void) const override; // RingBuffer
52  bool OpenFile(const QString &lfilename,
53  uint retry_ms = kDefaultOpenTimeout) override; // RingBuffer
54  bool IsStreamed(void) override { return false; } // RingBuffer
55  bool IsSeekingAllowed(void) override { return !m_error; } // RingBuffer
56  bool IsBookmarkAllowed(void) override { return true; } // RingBuffer
57  static bool IsHTTPLiveStreaming(QByteArray *s);
58  static bool TestForHTTPLiveStreaming(const QString &filename);
59  bool SaveToDisk(const QString &filename, int segstart = 0, int segend = -1);
60  int NumStreams(void) const;
61  int Read(void *data, uint i_read) { return safe_read(data, i_read); }
62  void Interrupt(void);
63  void Continue(void);
64  int DurationForBytes(uint size);
65 
66 protected:
67  int safe_read(void *data, uint sz) override; // RingBuffer
68  long long GetRealFileSizeInternal(void) const override; // RingBuffer
69  long long SeekInternal(long long pos, int whence) override; // RingBuffer
70 
71 private:
72  void FreeStreamsList(QList<HLSStream*> *streams) const;
73  HLSStream *GetStreamForSegment(int segnum) const;
74  HLSStream *GetStream(int wanted, const StreamsList *streams = nullptr) const;
75  HLSStream *GetFirstStream(const StreamsList *streams = nullptr) const;
76  HLSStream *GetLastStream(const StreamsList *streams = nullptr) const;
77  HLSStream *FindStream(const HLSStream *hls_new, const StreamsList *streams = nullptr) const;
78  HLSStream *GetCurrentStream(void) const;
79  static QString ParseAttributes(const QString &line, const char *attr);
80  static int ParseDecimalValue(const QString &line, int &target);
81  static int ParseSegmentInformation(const HLSStream *hls, const QString &line,
82  int &duration, QString &title);
83  static int ParseTargetDuration(HLSStream *hls, const QString &line);
84  HLSStream *ParseStreamInformation(const QString &line, const QString &uri) const;
85  static int ParseMediaSequence(HLSStream *hls, const QString &line);
86  int ParseKey(HLSStream *hls, const QString &line);
87  static int ParseProgramDateTime(HLSStream *hls, const QString &line);
88  static int ParseAllowCache(HLSStream *hls, const QString &line);
89  static int ParseVersion(const QString &line, int &version);
90  static int ParseEndList(HLSStream *hls);
91  static int ParseDiscontinuity(HLSStream *hls, const QString &line);
92  int ParseM3U8(const QByteArray *buffer, StreamsList *streams = nullptr);
93  int Prefetch(int count);
94  void SanityCheck(const HLSStream *hls) const;
95  HLSSegment *GetSegment(int segnum, int timeout = 1000);
96  int NumSegments(void) const;
97  int ChooseSegment(int stream) const;
98  int64_t SizeMedia(void) const;
99  void WaitUntilBuffered(void);
100  void SanitizeStreams(StreamsList *streams = nullptr);
101 
102  // private member variables
103  QString m_m3u8; // M3U8 url
104  QByteArray m_peeked;
105 
107 
108  /* state */
109  StreamsList m_streams; // bandwidth adaptation
110  mutable QMutex m_lock; // protect general class members
111  bool m_meta {false}; // meta playlist
112  bool m_error {false}; // parsing error
113  bool m_aesmsg {false}; // only print one time that the media is encrypted
114  int m_startup {0}; // starting segment (where seek start)
120  int64_t m_bitrate {0};
126  bool m_seektoend {false};
127 
128  friend class StreamWorker;
130  friend class PlaylistWorker;
132  FILE *m_fd {nullptr};
133  bool m_interrupted {false};
134  bool m_killed {false};
135 };
136 
137 #endif
static const int kDefaultOpenTimeout
HLSRingBuffer(const QString &lfilename)
StreamWorker * m_streamworker
int ChooseSegment(int stream) const
int NumStreams(void) const
int64_t SizeMedia(void) const
int64_t m_bitrate
assumed bitrate of playback used for the purpose of calculating length and seek position.
bool IsStreamed(void) override
static bool IsHTTPLiveStreaming(QByteArray *s)
bool OpenFile(const QString &lfilename, uint retry_ms=kDefaultOpenTimeout) override
Opens an HTTP Live Stream for reading.
bool IsOpen(void) const override
Returns true if open for either reading or writing.
static bool TestForHTTPLiveStreaming(const QString &filename)
void FreeStreamsList(QList< HLSStream * > *streams) const
HLSSegment * GetSegment(int segnum, int timeout=1000)
Retrieve segment [segnum] from any available streams.
static int ParseDiscontinuity(HLSStream *hls, const QString &line)
int DurationForBytes(uint size)
returns an estimated duration in ms for size amount of data returns 0 if we can't estimate the durati...
void SanityCheck(const HLSStream *hls) const
static int ParseDecimalValue(const QString &line, int &target)
Return the decimal argument in a line of type: blah:<decimal> presence of value <decimal> is compulso...
HLSStream * GetStream(int wanted, const StreamsList *streams=nullptr) const
bool m_seektoend
FFmpeg seek to the end of the stream in order to determine the length of the video.
bool SaveToDisk(const QString &filename, int segstart=0, int segend=-1)
static int ParseMediaSequence(HLSStream *hls, const QString &line)
int ParseKey(HLSStream *hls, const QString &line)
long long SeekInternal(long long pos, int whence) override
static int ParseAllowCache(HLSStream *hls, const QString &line)
int Read(void *data, uint i_read)
HLSStream * ParseStreamInformation(const QString &line, const QString &uri) const
static int ParseSegmentInformation(const HLSStream *hls, const QString &line, int &duration, QString &title)
int safe_read(void *data, uint sz) override
long long GetRealFileSizeInternal(void) const override
bool IsBookmarkAllowed(void) override
void WaitUntilBuffered(void)
Wait until we have enough segments buffered to allow smooth playback Do not wait if VOD and at end of...
static int ParseVersion(const QString &line, int &version)
static int ParseEndList(HLSStream *hls)
QList< HLSStream * > StreamsList
PlaylistWorker * m_playlistworker
unsigned int uint
Definition: compat.h:140
static QString ParseAttributes(const QString &line, const char *attr)
HLSStream * GetFirstStream(const StreamsList *streams=nullptr) const
int FILE
Definition: mythburn.py:110
int NumSegments(void) const
bool IsSeekingAllowed(void) override
long long GetReadPosition(void) const override
Returns how far into the file we have read.
static int ParseTargetDuration(HLSStream *hls, const QString &line)
int ParseM3U8(const QByteArray *buffer, StreamsList *streams=nullptr)
HLSStream * GetCurrentStream(void) const
return the stream we are currently streaming from
Implements a file/stream reader/writer.
HLSPlayback * m_playback
int Prefetch(int count)
Preferetch the first x segments of the stream.
HLSStream * FindStream(const HLSStream *hls_new, const StreamsList *streams=nullptr) const
HLSStream * GetLastStream(const StreamsList *streams=nullptr) const
void SanitizeStreams(StreamsList *streams=nullptr)
Streams may not be all starting at the same sequence number, so attempt to align their starting seque...
HLSStream * GetStreamForSegment(int segnum) const
static int ParseProgramDateTime(HLSStream *hls, const QString &line)