MythTV  master
mytharchive/mytharchive/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 #include <QString>
7 
8 #include <remotefile.h>
9 #include <mythlogging.h>
10 
11 extern "C" {
12 #include <libavformat/avformat.h>
13 #include <libavformat/avio.h>
14 }
15 
17 {
18  public:
19  explicit RemoteAVFormatContext(const QString &filename = "")
20  { if (!filename.isEmpty()) Open(filename); }
21 
23  {
24  Close();
25  if (m_buffer)
27  }
28 
29  bool Open(const QString &filename)
30  {
31  if (isOpen())
32  return false;
33 
34  if (m_inputFC)
35  avformat_free_context(m_inputFC);
36  m_inputFC = avformat_alloc_context();
37 
38  delete m_rf;
39 
40  m_inputIsRemote = filename.startsWith("myth://");
41  if (m_inputIsRemote)
42  {
43  m_rf = new RemoteFile(filename);
44 
45  if (!m_rf->isOpen())
46  return false;
47 
48  const int BUFFER_SIZE = 0x8000;
49  if (!m_buffer)
50  {
51  m_buffer = (unsigned char*)av_malloc(BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
52  if (!m_buffer)
53  return false;
54  }
55  m_byteIOContext = avio_alloc_context(m_buffer, BUFFER_SIZE, 0,
57 
58  m_byteIOContext->seekable = 1;
59 
60  // probe the stream
61  AVProbeData probe_data;
62  memset(&probe_data, 0, sizeof(AVProbeData));
63  probe_data.filename = "stream";
64  probe_data.buf_size = m_rf->Read(m_buffer, BUFFER_SIZE);
65  probe_data.buf = m_buffer;
66 
67  AVInputFormat *fmt = av_probe_input_format(&probe_data, 1);
68  if (!fmt)
69  return false;
70 
71  m_rf->Seek(0, SEEK_SET);
72 
74 
75  int ret = avformat_open_input(&m_inputFC, "stream", fmt, nullptr);
76  if (ret)
77  return false;
78  }
79  else
80  {
81  int ret = avformat_open_input(&m_inputFC, qPrintable(filename), nullptr, nullptr);
82  if (ret)
83  return false;
84  }
85 
86  return true;
87  }
88 
89  void Close()
90  {
91  if (m_inputFC)
92  {
93  avformat_close_input(&m_inputFC);
94  m_inputFC = nullptr;
95  }
96 
97  if (m_rf)
98  {
99  delete m_rf;
100  m_rf = nullptr;
101  }
102  }
103 
104  bool isOpen() const
105  {
106  if (m_inputIsRemote)
107  return (m_inputFC != nullptr && m_rf != nullptr && m_rf->isOpen());
108  return (m_inputFC != nullptr);
109  }
110 
111  operator AVFormatContext * () const { return m_inputFC; }
112  AVFormatContext * operator -> () const { return m_inputFC; }
113 
114  private:
115  static int ReadFunc(void *opaque, uint8_t *buf, int buf_size)
116  {
117  auto *rf = reinterpret_cast< RemoteFile* >(opaque);
118  return rf->Read(buf, buf_size);
119  }
120 
121  static int WriteFunc(void */*opaque*/, uint8_t */*buf*/, int /*buf_size*/)
122  { return -1; }
123 
124  static int64_t SeekFunc(void *opaque, int64_t offset, int whence)
125  {
126  auto *rf = reinterpret_cast< RemoteFile* >(opaque);
127  if (whence == AVSEEK_SIZE)
128  return rf->GetFileSize();
129 
130  return rf->Seek(offset, whence);
131  }
132 
133  private:
134  AVFormatContext *m_inputFC { nullptr };
135  bool m_inputIsRemote { false };
136  RemoteFile *m_rf { nullptr };
137  AVIOContext *m_byteIOContext { nullptr };
138  unsigned char *m_buffer { nullptr };
139 };
140 #endif // REMOTEAVFORMATCONTEXT_H
static int ReadFunc(void *opaque, uint8_t *buf, int buf_size)
int Read(void *data, int size)
Definition: remotefile.cpp:937
#define BUFFER_SIZE
void * av_malloc(unsigned int size)
static int64_t SeekFunc(void *opaque, int64_t offset, int whence)
bool isOpen(void) const
Definition: remotefile.cpp:247
void av_free(void *ptr)
long long Seek(long long pos, int whence, long long curpos=-1)
Definition: remotefile.cpp:760
static int WriteFunc(void *, uint8_t *, int)