MythTV  master
mythmusic/mythmusic/remoteavformatcontext.h
Go to the documentation of this file.
1 // Wrapper for AVFormatContext (av_open_input_file/stream)
2 // supporting myth remote files
3 #ifndef REMOTEAVFORMATCONTEXT_H
4 #define REMOTEAVFORMATCONTEXT_H
5 
6 // C++
7 #include <iostream>
8 
9 // Qt
10 #include <QString>
11 
12 // MythTV
14 #include <libmythbase/remotefile.h>
15 
16 extern "C" {
17 #include <libavformat/avformat.h>
18 #include <libavformat/avio.h>
19 #include <libavutil/opt.h>
20 }
21 
23 {
24  public:
25  explicit RemoteAVFormatContext(const QString &filename = "")
26  { if (!filename.isEmpty()) Open(filename); }
27 
29  {
30  Close();
31  if (m_buffer)
32  av_free(m_buffer);
33  }
34 
35  AVFormatContext *getContext(void) { return m_inputFC; }
36 
37  bool Open(const QString &filename)
38  {
39  LOG(VB_PLAYBACK, LOG_ERR, QString("RemoteAVFormatContext::Open: Opening %1").arg(filename));
40  if (isOpen())
41  return false;
42 
43  if (m_inputFC)
44  avformat_free_context(m_inputFC);
45  m_inputFC = avformat_alloc_context();
46 
47  delete m_rf;
48 
49  m_inputIsRemote = filename.startsWith("myth://");
50  if (m_inputIsRemote)
51  {
52  m_rf = new RemoteFile(filename);
53 
54  if (!m_rf->isOpen())
55  return false;
56 
57  const int BUFFER_SIZE = 0x20000;
58  if (!m_buffer)
59  {
60  m_buffer = (unsigned char*)av_malloc(BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
61  if (!m_buffer)
62  return false;
63  }
64  m_byteIOContext = avio_alloc_context(m_buffer, BUFFER_SIZE, 0,
66 
67  m_byteIOContext->seekable = 1;
68 
69  // probe the stream
70  AVProbeData probe_data;
71  memset(&probe_data, 0, sizeof(AVProbeData));
72  probe_data.filename = "stream";
73  probe_data.buf_size = m_rf->Read(m_buffer, BUFFER_SIZE);
74  probe_data.buf = m_buffer;
75 
76  const AVInputFormat *fmt = av_probe_input_format(&probe_data, 1);
77  if (!fmt)
78  {
79  LOG(VB_GENERAL, LOG_ERR, QString("RemoteAVFormatContext::Open: Failed to probe file: %1").arg(filename));
80  return false;
81  }
82  LOG(VB_PLAYBACK, LOG_INFO, QString("RemoteAVFormatContext::Open: probed file as %1").arg(fmt->name));
83 
84  m_rf->Seek(0, SEEK_SET);
85 
87 
88  int ret = avformat_open_input(&m_inputFC, "stream", fmt, nullptr);
89  if (ret)
90  {
91  LOG(VB_GENERAL, LOG_ERR, QString("RemoteAVFormatContext::Open: Failed to open input: %1").arg(filename));
92  return false;
93  }
94  }
95  else
96  {
97  // if this is a ice/shoutcast stream setup grabbing the inline metadata
98  AVDictionary *options = nullptr;
99 
100  if (filename.startsWith("http://"))
101  av_dict_set(&options, "icy", "1", 0);
102 
103  int ret = avformat_open_input(&m_inputFC, qPrintable(filename), nullptr, &options);
104  if (ret)
105  {
106  LOG(VB_GENERAL, LOG_ERR, QString("RemoteAVFormatContext::Open: Failed to open input: %1").arg(filename));
107  return false;
108  }
109  }
110 
111  m_isOpen = true;
112  return m_isOpen;
113  }
114 
115  void Close()
116  {
117  if (m_inputFC)
118  {
119  avformat_close_input(&m_inputFC);
120  m_inputFC = nullptr;
121  }
122 
123  delete m_rf;
124  m_rf = nullptr;
125 
126  m_isOpen = false;
127  }
128 
129  bool isOpen() const { return m_isOpen; }
130 
131  operator AVFormatContext * () const { return m_inputFC; }
132  //operator AVFormatContext & () const { return m_inputFC; }
133  AVFormatContext * operator -> () const { return m_inputFC; }
134 
135  private:
136  static int ReadFunc(void *opaque, uint8_t *buf, int buf_size)
137  {
138  auto *rf = reinterpret_cast< RemoteFile* >(opaque);
139  int len = rf->Read(buf, buf_size);
140  int ret = ((len == 0) && (buf_size > 0)) ? AVERROR_EOF : len;
141  return ret;
142  }
143 
144  static int WriteFunc(void */*opaque*/, uint8_t */*buf*/, int/*buf_size*/)
145  { return -1; }
146 
147  static int64_t SeekFunc(void *opaque, int64_t offset, int whence)
148  {
149  auto *rf = reinterpret_cast< RemoteFile* >(opaque);
150  if (whence == AVSEEK_SIZE)
151  return rf->GetFileSize();
152 
153  return rf->Seek(offset, whence);
154  }
155 
156  private:
157  AVFormatContext *m_inputFC { nullptr };
158  bool m_inputIsRemote { false };
159  bool m_isOpen { false };
160  RemoteFile *m_rf { nullptr };
161  AVIOContext *m_byteIOContext { nullptr };
162  unsigned char *m_buffer { nullptr };
163 };
164 #endif // REMOTEAVFORMATCONTEXT_H
RemoteAVFormatContext::isOpen
bool isOpen() const
Definition: mythmusic/mythmusic/remoteavformatcontext.h:129
RemoteFile::GetFileSize
long long GetFileSize(void) const
GetFileSize: returns the remote file's size at the time it was first opened Will query the server in ...
Definition: remotefile.cpp:1084
RemoteAVFormatContext::RemoteAVFormatContext
RemoteAVFormatContext(const QString &filename="")
Definition: mythmusic/mythmusic/remoteavformatcontext.h:25
RemoteAVFormatContext::getContext
AVFormatContext * getContext(void)
Definition: mythmusic/mythmusic/remoteavformatcontext.h:35
RemoteFile
Definition: remotefile.h:17
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
RemoteFile::isOpen
bool isOpen(void) const
Definition: remotefile.cpp:238
RemoteAVFormatContext::Open
bool Open(const QString &filename)
Definition: mythmusic/mythmusic/remoteavformatcontext.h:37
RemoteAVFormatContext::m_inputFC
AVFormatContext * m_inputFC
Definition: mythmusic/mythmusic/remoteavformatcontext.h:157
RemoteAVFormatContext::ReadFunc
static int ReadFunc(void *opaque, uint8_t *buf, int buf_size)
Definition: mythmusic/mythmusic/remoteavformatcontext.h:136
RemoteAVFormatContext
Definition: mythmusic/mythmusic/remoteavformatcontext.h:22
mythlogging.h
RemoteFile::Seek
long long Seek(long long pos, int whence, long long curpos=-1)
Definition: remotefile.cpp:752
remotefile.h
RemoteAVFormatContext::m_buffer
unsigned char * m_buffer
Definition: mythmusic/mythmusic/remoteavformatcontext.h:162
RemoteAVFormatContext::m_rf
RemoteFile * m_rf
Definition: mythmusic/mythmusic/remoteavformatcontext.h:160
RemoteAVFormatContext::WriteFunc
static int WriteFunc(void *, uint8_t *, int)
Definition: mythmusic/mythmusic/remoteavformatcontext.h:144
RemoteAVFormatContext::Close
void Close()
Definition: mythmusic/mythmusic/remoteavformatcontext.h:115
RemoteAVFormatContext::m_inputIsRemote
bool m_inputIsRemote
Definition: mythmusic/mythmusic/remoteavformatcontext.h:158
RemoteAVFormatContext::~RemoteAVFormatContext
~RemoteAVFormatContext()
Definition: mythmusic/mythmusic/remoteavformatcontext.h:28
BUFFER_SIZE
static constexpr qint64 BUFFER_SIZE
Definition: hlsstreamhandler.cpp:20
RemoteAVFormatContext::operator->
AVFormatContext * operator->() const
Definition: mythmusic/mythmusic/remoteavformatcontext.h:133
RemoteAVFormatContext::m_byteIOContext
AVIOContext * m_byteIOContext
Definition: mythmusic/mythmusic/remoteavformatcontext.h:161
build_compdb.filename
filename
Definition: build_compdb.py:21
build_compdb.options
options
Definition: build_compdb.py:11
RemoteAVFormatContext::SeekFunc
static int64_t SeekFunc(void *opaque, int64_t offset, int whence)
Definition: mythmusic/mythmusic/remoteavformatcontext.h:147
RemoteFile::Read
int Read(void *data, int size)
Definition: remotefile.cpp:929
RemoteAVFormatContext::m_isOpen
bool m_isOpen
Definition: mythmusic/mythmusic/remoteavformatcontext.h:159