MythTV  master
avfdecoder.cpp
Go to the documentation of this file.
1 /*
2  MythMusic libav* Decoder
3  Originally written by Kevin Kuphal with contributions and updates from
4  many others
5 
6  Special thanks to
7  ffmpeg team for libavcodec and libavformat
8  qemacs team for their av support which I used to understand the libraries
9  getid3.sourceforget.net project for the ASF information used here
10 
11  This library decodes various media files into PCM data
12  returned to the MythMusic output buffer.
13 
14  Revision History
15  - Initial release
16  - 1/9/2004 - Improved seek support
17  - ?/?/2009 - Extended to support many more filetypes and bug fixes
18  - ?/7/2010 - Add streaming support
19 */
20 
21 // C++ headers
22 #include <chrono>
23 
24 // QT headers
25 #include <QObject>
26 #include <QIODevice>
27 #include <QFile>
28 #include <QRegularExpression>
29 #include <QTimer>
30 
31 // Myth headers
32 #include <mythconfig.h>
33 #include <mythcontext.h>
34 #include <audiooutput.h>
35 #include <audiooutpututil.h>
36 #include <mythlogging.h>
37 #include <decoderhandler.h>
38 #include <mythavutil.h>
39 
40 // Mythmusic Headers
41 #include "avfdecoder.h"
42 #include "metaio.h"
43 #include "metaioavfcomment.h"
44 #include "metaioid3.h"
45 #include "metaioflacvorbis.h"
46 #include "metaiooggvorbis.h"
47 #include "metaiomp4.h"
48 #include "metaiowavpack.h"
49 #include "decoderhandler.h"
50 #include "musicplayer.h"
51 
52 extern "C" {
53 #include "libavformat/avio.h"
54 #include "libavutil/opt.h"
55 }
56 
57 /****************************************************************************/
58 
59 using ShoutCastMetaMap = QMap<QString,QString>;
60 
62 {
63  public:
64  ShoutCastMetaParser(void) = default;
65  ~ShoutCastMetaParser(void) = default;
66 
67  void setMetaFormat(const QString &metaformat);
68  ShoutCastMetaMap parseMeta(const QString &mdata);
69 
70  private:
71  QString m_metaFormat;
72  int m_metaArtistPos {-1};
73  int m_metaTitlePos {-1};
74  int m_metaAlbumPos {-1};
75 };
76 
77 void ShoutCastMetaParser::setMetaFormat(const QString &metaformat)
78 {
79 /*
80  We support these metatags :
81  %a - artist
82  %t - track
83  %b - album
84  %r - random bytes
85  */
86  m_metaFormat = metaformat;
87 
88  m_metaArtistPos = 0;
89  m_metaTitlePos = 0;
90  m_metaAlbumPos = 0;
91 
92  int assign_index = 1;
93  int pos = 0;
94 
95  pos = m_metaFormat.indexOf("%", pos);
96  while (pos >= 0)
97  {
98  pos++;
99 
100  QChar ch;
101 
102  if (pos < m_metaFormat.length())
103  ch = m_metaFormat.at(pos);
104 
105  if (!ch.isNull() && ch == '%')
106  {
107  pos++;
108  }
109  else if (!ch.isNull() && (ch == 'r' || ch == 'a' || ch == 'b' || ch == 't'))
110  {
111  if (ch == 'a')
112  m_metaArtistPos = assign_index;
113 
114  if (ch == 'b')
115  m_metaAlbumPos = assign_index;
116 
117  if (ch == 't')
118  m_metaTitlePos = assign_index;
119 
120  assign_index++;
121  }
122  else
123  {
124  LOG(VB_GENERAL, LOG_ERR,
125  QString("ShoutCastMetaParser: malformed metaformat '%1'")
126  .arg(m_metaFormat));
127  }
128 
129  pos = m_metaFormat.indexOf("%", pos);
130  }
131 
132  m_metaFormat.replace("%a", "(.*)");
133  m_metaFormat.replace("%t", "(.*)");
134  m_metaFormat.replace("%b", "(.*)");
135  m_metaFormat.replace("%r", "(.*)");
136  m_metaFormat.replace("%%", "%");
137 }
138 
140 {
141  ShoutCastMetaMap result;
142  int title_begin_pos = mdata.indexOf("StreamTitle='");
143 
144  if (title_begin_pos >= 0)
145  {
146  title_begin_pos += 13;
147  int title_end_pos = mdata.indexOf("';", title_begin_pos);
148  QString title = mdata.mid(title_begin_pos, title_end_pos - title_begin_pos);
149  QRegularExpression rx { m_metaFormat };
150  auto match = rx.match(title);
151  if (match.hasMatch())
152  {
153  LOG(VB_PLAYBACK, LOG_INFO, QString("ShoutCast: Meta : '%1'")
154  .arg(mdata));
155  LOG(VB_PLAYBACK, LOG_INFO,
156  QString("ShoutCast: Parsed as: '%1' by '%2'")
157  .arg(match.captured(m_metaTitlePos))
158  .arg(match.captured(m_metaArtistPos)));
159 
160  if (m_metaTitlePos > 0)
161  result["title"] = match.captured(m_metaTitlePos);
162 
163  if (m_metaArtistPos > 0)
164  result["artist"] = match.captured(m_metaArtistPos);
165 
166  if (m_metaAlbumPos > 0)
167  result["album"] = match.captured(m_metaAlbumPos);
168  }
169  }
170 
171  return result;
172 }
173 
174 static void myth_av_log(void *ptr, int level, const char* fmt, va_list vl)
175 {
176  if (VERBOSE_LEVEL_NONE)
177  return;
178 
179  static QString s_fullLine("");
180  static QMutex s_stringLock;
181  uint64_t verbose_mask = VB_GENERAL;
182  LogLevel_t verbose_level = LOG_DEBUG;
183 
184  // determine mythtv debug level from av log level
185  switch (level)
186  {
187  case AV_LOG_PANIC:
188  verbose_level = LOG_EMERG;
189  break;
190  case AV_LOG_FATAL:
191  verbose_level = LOG_CRIT;
192  break;
193  case AV_LOG_ERROR:
194  verbose_level = LOG_ERR;
195  verbose_mask |= VB_LIBAV;
196  break;
197  case AV_LOG_DEBUG:
198  case AV_LOG_VERBOSE:
199  case AV_LOG_INFO:
200  verbose_level = LOG_DEBUG;
201  verbose_mask |= VB_LIBAV;
202  break;
203  case AV_LOG_WARNING:
204  verbose_mask |= VB_LIBAV;
205  break;
206  default:
207  return;
208  }
209 
210  if (!VERBOSE_LEVEL_CHECK(verbose_mask, verbose_level))
211  return;
212 
213  s_stringLock.lock();
214  if (s_fullLine.isEmpty() && ptr) {
215  AVClass* avc = *(AVClass**)ptr;
216  s_fullLine = QString("[%1 @ %2] ")
217  .arg(avc->item_name(ptr))
218  .arg(reinterpret_cast<size_t>(avc),QT_POINTER_SIZE,8,QChar('0'));
219  }
220 
221  s_fullLine += QString::asprintf(fmt, vl);
222  if (s_fullLine.endsWith("\n"))
223  {
224  LOG(verbose_mask, verbose_level, s_fullLine.trimmed());
225  s_fullLine.truncate(0);
226  }
227  s_stringLock.unlock();
228 }
229 
231  Decoder(d, o)
232 {
233  MThread::setObjectName("avfDecoder");
234  setURL(file);
235 
237  (uint8_t *)av_malloc(AudioOutput::kMaxSizeBuffer);
238 
239  bool debug = VERBOSE_LEVEL_CHECK(VB_LIBAV, LOG_ANY);
240  av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR);
241  av_log_set_callback(myth_av_log);
242 }
243 
245 {
246  delete m_mdataTimer;
247 
248  if (m_inited)
249  deinit();
250 
251  if (m_outputBuffer)
252  av_freep(&m_outputBuffer);
253 
254  delete m_inputContext;
255 }
256 
258 {
259  m_userStop = true;
260 }
261 
263 {
264  m_inited = m_userStop = m_finish = false;
265  m_freq = m_bitrate = 0;
266  m_stat = m_channels = 0;
267  m_seekTime = -1.0;
268 
269  // give up if we dont have an audiooutput set
270  if (!output())
271  {
272  error("avfDecoder: initialise called with a NULL audiooutput");
273  return false;
274  }
275 
276  if (!m_outputBuffer)
277  {
278  error("avfDecoder: couldn't allocate memory");
279  return false;
280  }
281 
283 
284  delete m_inputContext;
286 
287  if (!m_inputContext->isOpen())
288  {
289  error(QString("Could not open url (%1)").arg(m_url));
290  deinit();
291  return false;
292  }
293 
294  // if this is a ice/shoutcast or MMS stream start polling for metadata changes and buffer status
295  if (getURL().startsWith("http://") || getURL().startsWith("mmsh://"))
296  {
297  m_mdataTimer = new QTimer;
298  m_mdataTimer->setSingleShot(false);
300 
301  m_mdataTimer->start(500ms);
302 
303  // we don't get metadata updates for MMS streams so grab the metadata from the headers
304  if (getURL().startsWith("mmsh://"))
305  {
306  AVDictionaryEntry *tag = nullptr;
308 
309  tag = av_dict_get(m_inputContext->getContext()->metadata, "title", tag, AV_DICT_IGNORE_SUFFIX);
310  mdata.setTitle(tag->value);
311 
312  tag = av_dict_get(m_inputContext->getContext()->metadata, "artist", tag, AV_DICT_IGNORE_SUFFIX);
313  mdata.setArtist(tag->value);
314 
315  mdata.setAlbum("");
316  mdata.setLength(-1ms);
317 
319  dispatch(ev);
320  }
321  }
322 
323  // determine the stream format
324  // this also populates information needed for metadata
325  if (avformat_find_stream_info(m_inputContext->getContext(), nullptr) < 0)
326  {
327  error("Could not determine the stream format.");
328  deinit();
329  return false;
330  }
331 
332  // let FFmpeg finds the best audio stream (should only be one), also catter
333  // should the file/stream not be an audio one
334  AVCodec *codec = nullptr;
335  int selTrack = av_find_best_stream(m_inputContext->getContext(), AVMEDIA_TYPE_AUDIO,
336  -1, -1, &codec, 0);
337 
338  if (selTrack < 0)
339  {
340  error(QString("Could not find audio stream."));
341  deinit();
342  return false;
343  }
344 
345  // Store the audio codec of the stream
347  (m_inputContext->getContext()->streams[selTrack]);
348 
349  // Store the input format of the context
351 
352  if (avcodec_open2(m_audioDec, codec, nullptr) < 0)
353  {
354  error(QString("Could not open audio codec: %1")
355  .arg(m_audioDec->codec_id));
356  deinit();
357  return false;
358  }
359 
360  m_freq = m_audioDec->sample_rate;
361  m_channels = m_audioDec->channels;
362 
363  if (m_channels <= 0)
364  {
365  error(QString("AVCodecContext tells us %1 channels are "
366  "available, this is bad, bailing.")
367  .arg(m_channels));
368  deinit();
369  return false;
370  }
371 
372  AudioFormat format =
374  m_audioDec->bits_per_raw_sample);
375  if (format == FORMAT_NONE)
376  {
377  error(QString("Error: Unsupported sample format: %1")
378  .arg(av_get_sample_fmt_name(m_audioDec->sample_fmt)));
379  deinit();
380  return false;
381  }
382 
383  const AudioSettings settings(format, m_audioDec->channels,
384  m_audioDec->codec_id,
385  m_audioDec->sample_rate, false);
386 
387  output()->Reconfigure(settings);
388  output()->SetSourceBitrate(m_audioDec->bit_rate);
389 
390  m_inited = true;
391  return true;
392 }
393 
394 void avfDecoder::seek(double pos)
395 {
397  m_inputContext->getContext()->pb->seekable)
398  {
399  m_seekTime = pos;
400  }
401 }
402 
404 {
405  m_inited = m_userStop = m_finish = false;
406  m_freq = m_bitrate = 0;
407  m_stat = m_channels = 0;
408  setOutput(nullptr);
409 
410  // Cleanup here
412  {
413  for (uint i = 0; i < m_inputContext->getContext()->nb_streams; i++)
414  {
415  AVStream *st = m_inputContext->getContext()->streams[i];
417  }
418  }
419 
420  m_audioDec = nullptr;
421  m_inputFormat = nullptr;
422 }
423 
425 {
426  RunProlog();
427  if (!m_inited)
428  {
429  RunEpilog();
430  return;
431  }
432 
433  AVPacket pkt;
434  AVPacket tmp_pkt;
435  memset(&pkt, 0, sizeof(AVPacket));
436  av_init_packet(&pkt);
437 
439  {
440  DecoderEvent e((DecoderEvent::Type) m_stat);
441  dispatch(e);
442  }
443 
444  av_read_play(m_inputContext->getContext());
445 
446  while (!m_finish && !m_userStop)
447  {
448  // Look to see if user has requested a seek
449  if (m_seekTime >= 0.0)
450  {
451  LOG(VB_GENERAL, LOG_INFO, QString("avfdecoder.o: seek time %1")
452  .arg(m_seekTime));
453 
454  if (av_seek_frame(m_inputContext->getContext(), -1,
455  (int64_t)(m_seekTime * AV_TIME_BASE), 0) < 0)
456  LOG(VB_GENERAL, LOG_ERR, "Error seeking");
457 
458  m_seekTime = -1.0;
459  }
460 
461  while (!m_finish && !m_userStop && m_seekTime <= 0.0)
462  {
463  // Read a packet from the input context
464  int res = av_read_frame(m_inputContext->getContext(), &pkt);
465  if (res < 0)
466  {
467  if (res != AVERROR_EOF)
468  {
469  LOG(VB_GENERAL, LOG_ERR, QString("Read frame failed: %1").arg(res));
470  LOG(VB_FILE, LOG_ERR, ("... for file '" + m_url) + "'");
471  }
472 
473  m_finish = true;
474  break;
475  }
476 
477  av_init_packet(&tmp_pkt);
478  tmp_pkt.data = pkt.data;
479  tmp_pkt.size = pkt.size;
480 
481  while (tmp_pkt.size > 0 && !m_finish &&
482  !m_userStop && m_seekTime <= 0.0)
483  {
484  int data_size = 0;
485 
486  int ret = output()->DecodeAudio(m_audioDec,
488  data_size,
489  &tmp_pkt);
490 
491  if (ret < 0)
492  break;
493 
494  // Increment the output pointer and count
495  tmp_pkt.size -= ret;
496  tmp_pkt.data += ret;
497 
498  if (data_size <= 0)
499  continue;
500 
501  output()->AddData(m_outputBuffer, data_size, -1ms, 0);
502  }
503 
504  av_packet_unref(&pkt);
505 
506  // Wait until we need to decode or supply more samples
507  while (!m_finish && !m_userStop && m_seekTime <= 0.0)
508  {
509  std::chrono::milliseconds buffered = output()->GetAudioBufferedTime();
510  // never go below 1s buffered
511  if (buffered < 1s)
512  break;
513  // wait
514  const struct timespec ns {0, (buffered.count() - 1000) * 1000000};
515  nanosleep(&ns, nullptr);
516  }
517  }
518  }
519 
520  if (m_userStop)
521  {
522  m_inited = false;
523  }
524  else
525  {
526  // Drain ao buffer, making sure we play all remaining audio samples
527  output()->Drain();
528  }
529 
530  if (m_finish)
532  else if (m_userStop)
534 
535  {
536  DecoderEvent e((DecoderEvent::Type) m_stat);
537  dispatch(e);
538  }
539 
540  deinit();
541  RunEpilog();
542 }
543 
545 {
546  uint8_t *pdata = nullptr;
547 
548  if (av_opt_get(m_inputContext->getContext(), "icy_metadata_packet", AV_OPT_SEARCH_CHILDREN, &pdata) >= 0)
549  {
550  QString s = QString::fromUtf8((const char*) pdata);
551 
552  if (m_lastMetadata != s)
553  {
554  m_lastMetadata = s;
555 
556  LOG(VB_PLAYBACK, LOG_INFO, QString("avfDecoder: shoutcast metadata changed - %1").arg(m_lastMetadata));
557 
560 
561  ShoutCastMetaMap meta_map = parser.parseMeta(m_lastMetadata);
562 
564  mdata.setTitle(meta_map["title"]);
565  mdata.setArtist(meta_map["artist"]);
566  mdata.setAlbum(meta_map["album"]);
567  mdata.setLength(-1ms);
568 
570  dispatch(ev);
571  }
572 
573  av_free(pdata);
574  }
575 
576  if (m_inputContext->getContext()->pb)
577  {
578  int available = (int) (m_inputContext->getContext()->pb->buf_end - m_inputContext->getContext()->pb->buffer);
579  int maxSize = m_inputContext->getContext()->pb->buffer_size;
581  dispatch(ev);
582  }
583 }
584 
585 bool avfDecoderFactory::supports(const QString &source) const
586 {
587 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
588  QStringList list = extension().split("|", QString::SkipEmptyParts);
589 #else
590  QStringList list = extension().split("|", Qt::SkipEmptyParts);
591 #endif
592  return std::any_of(list.cbegin(), list.cend(),
593  [source](const auto& str)
594  { return str == source.right(str.length()).toLower(); } );
595 }
596 
597 const QString &avfDecoderFactory::extension() const
598 {
600 }
601 
602 const QString &avfDecoderFactory::description() const
603 {
604  static QString s_desc(tr("Internal Decoder"));
605  return s_desc;
606 }
607 
608 Decoder *avfDecoderFactory::create(const QString &file, AudioOutput *output, bool deletable)
609 {
610  if (deletable)
611  return new avfDecoder(file, this, output);
612 
613  static avfDecoder *s_decoder = nullptr;
614  if (!s_decoder)
615  {
616  s_decoder = new avfDecoder(file, this, output);
617  }
618  else
619  {
620  s_decoder->setOutput(output);
621  }
622 
623  return s_decoder;
624 }
avfDecoder::m_inited
bool m_inited
Definition: avfdecoder.h:36
AudioOutput::AddData
virtual bool AddData(void *buffer, int len, std::chrono::milliseconds timecode, int frames)=0
Add data to the audiobuffer for playback.
FORMAT_NONE
@ FORMAT_NONE
Definition: audiooutputsettings.h:26
AudioOutput::kMaxSizeBuffer
static const int kMaxSizeBuffer
kMaxSizeBuffer is the maximum size of a buffer to be used with DecodeAudio
Definition: audiooutput.h:197
DecoderHandlerEvent::BufferStatus
static Type BufferStatus
Definition: decoderhandler.h:49
RemoteAVFormatContext::isOpen
bool isOpen() const
Definition: mytharchive/mytharchive/remoteavformatcontext.h:104
avfDecoder::m_codecMap
MythCodecMap m_codecMap
Definition: avfdecoder.h:52
gPlayer
MusicPlayer * gPlayer
Definition: musicplayer.cpp:35
AudioOutputSettings::AVSampleFormatToFormat
static AudioFormat AVSampleFormatToFormat(AVSampleFormat format, int bits=0)
Return AVSampleFormat closest equivalent to AudioFormat.
Definition: audiooutputsettings.cpp:197
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
avfDecoder::run
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: avfdecoder.cpp:424
MythCodecMap::GetCodecContext
AVCodecContext * GetCodecContext(const AVStream *Stream, const AVCodec *Codec=nullptr, bool NullCodec=false)
Definition: mythavutil.cpp:250
audiooutpututil.h
ShoutCastMetaParser::m_metaTitlePos
int m_metaTitlePos
Definition: avfdecoder.cpp:73
MusicMetadata::MetadataFormat
QString MetadataFormat(void)
Definition: musicmetadata.h:279
decoderhandler.h
ShoutCastMetaMap
QMap< QString, QString > ShoutCastMetaMap
Definition: avfdecoder.cpp:59
RemoteAVFormatContext::getContext
AVFormatContext * getContext(void)
Definition: mythmusic/mythmusic/remoteavformatcontext.h:31
MThread::setObjectName
void setObjectName(const QString &name)
Definition: mthread.cpp:241
MusicMetadata::setAlbum
void setAlbum(const QString &lalbum, const QString &lalbum_sort=nullptr)
Definition: musicmetadata.h:152
avfDecoder::m_userStop
bool m_userStop
Definition: avfdecoder.h:37
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
MusicMetadata
Definition: musicmetadata.h:80
metaioflacvorbis.h
avfDecoder::m_seekTime
double m_seekTime
Definition: avfdecoder.h:45
DecoderFactory
Definition: decoder.h:117
build_compdb.parser
parser
Definition: build_compdb.py:7
avfDecoder::m_inputFormat
AVInputFormat * m_inputFormat
Definition: avfdecoder.h:49
avfDecoder::stop
void stop() override
Definition: avfdecoder.cpp:257
DecoderHandlerEvent::Meta
static Type Meta
Definition: decoderhandler.h:48
build_compdb.file
file
Definition: build_compdb.py:55
avfdecoder.h
Decoder::m_url
QString m_url
Definition: decoder.h:105
MythObservable::dispatch
void dispatch(const MythEvent &event)
Dispatch an event to all listeners.
Definition: mythobservable.cpp:73
ShoutCastMetaParser::m_metaFormat
QString m_metaFormat
Definition: avfdecoder.cpp:71
avfDecoder::initialize
bool initialize() override
Definition: avfdecoder.cpp:262
avfDecoder::m_mdataTimer
QTimer * m_mdataTimer
Definition: avfdecoder.h:56
avfDecoder::m_inputContext
RemoteAVFormatContext * m_inputContext
Definition: avfdecoder.h:50
avfDecoder::m_outputBuffer
uint8_t * m_outputBuffer
Definition: avfdecoder.h:39
AudioOutput::GetAudioBufferedTime
virtual std::chrono::milliseconds GetAudioBufferedTime(void)
report amount of audio buffered in milliseconds.
Definition: audiooutput.h:144
AudioOutput::Drain
virtual void Drain(void)=0
AudioSettings
Definition: audiosettings.h:28
MusicMetadata::setLength
std::enable_if_t< std::chrono::__is_duration< T >::value, void > setLength(T llength)
Definition: musicmetadata.h:208
AudioOutput
Definition: audiooutput.h:26
DecoderHandlerEvent
Events sent by the DecoderHandler and it's helper classes.
Definition: decoderhandler.h:26
Decoder
Definition: decoder.h:70
RemoteAVFormatContext
Definition: mytharchive/mytharchive/remoteavformatcontext.h:16
mythlogging.h
avfDecoder
Definition: avfdecoder.h:15
avfDecoderFactory::supports
bool supports(const QString &source) const override
Definition: avfdecoder.cpp:585
AudioOutput::SetSourceBitrate
virtual void SetSourceBitrate(int)
Definition: audiooutput.h:146
DecoderEvent
Definition: decoder.h:29
avfDecoderFactory::description
const QString & description() const override
Definition: avfdecoder.cpp:602
avfDecoder::m_finish
bool m_finish
Definition: avfdecoder.h:41
avfDecoder::deinit
void deinit()
Definition: avfdecoder.cpp:403
debug
VERBOSE_PREAMBLE Most debug(nodatabase, notimestamp, noextra)") VERBOSE_MAP(VB_GENERAL
MusicMetadata::setTitle
void setTitle(const QString &ltitle, const QString &ltitle_sort=nullptr)
Definition: musicmetadata.h:164
ShoutCastMetaParser::setMetaFormat
void setMetaFormat(const QString &metaformat)
Definition: avfdecoder.cpp:77
avfDecoder::m_freq
long m_freq
Definition: avfdecoder.h:42
MythCodecMap::FreeCodecContext
void FreeCodecContext(const AVStream *Stream)
Definition: mythavutil.cpp:298
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
avfDecoder::avfDecoder
avfDecoder(const QString &file, DecoderFactory *d, AudioOutput *o)
Definition: avfdecoder.cpp:230
metaioavfcomment.h
metaiowavpack.h
AudioOutput::DecodeAudio
virtual int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
Utility routine.
Definition: audiooutput.cpp:594
avfDecoderFactory::extension
const QString & extension() const override
Definition: avfdecoder.cpp:597
Decoder::getURL
QString getURL(void) const
Definition: decoder.h:91
DecoderEvent::Decoding
static Type Decoding
Definition: decoder.h:45
uint
unsigned int uint
Definition: compat.h:140
ShoutCastMetaParser::~ShoutCastMetaParser
~ShoutCastMetaParser(void)=default
VERBOSE_LEVEL_NONE
#define VERBOSE_LEVEL_NONE
Definition: mythlogging.h:13
ShoutCastMetaParser::m_metaAlbumPos
int m_metaAlbumPos
Definition: avfdecoder.cpp:74
ShoutCastMetaParser
Definition: avfdecoder.cpp:61
Decoder::setURL
void setURL(const QString &url)
Definition: decoder.h:83
DecoderEvent::Finished
static Type Finished
Definition: decoder.h:47
avfDecoderFactory::create
Decoder * create(const QString &file, AudioOutput *output, bool deletable) override
Definition: avfdecoder.cpp:608
Decoder::error
void error(const QString &e)
Definition: decoder.cpp:53
avfDecoder::m_audioDec
AVCodecContext * m_audioDec
Definition: avfdecoder.h:51
DecoderEvent::Stopped
static Type Stopped
Definition: decoder.h:46
myth_av_log
static void myth_av_log(void *ptr, int level, const char *fmt, va_list vl)
Definition: avfdecoder.cpp:174
MusicPlayer::getDecoderHandler
DecoderHandler * getDecoderHandler(void)
Definition: musicplayer.h:124
VERBOSE_LEVEL_CHECK
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
Definition: mythlogging.h:14
MusicMetadata::setArtist
void setArtist(const QString &lartist, const QString &lartist_sort=nullptr)
Definition: musicmetadata.h:128
AudioOutput::Reconfigure
virtual void Reconfigure(const AudioSettings &settings)=0
metaio.h
ShoutCastMetaParser::parseMeta
ShoutCastMetaMap parseMeta(const QString &mdata)
Definition: avfdecoder.cpp:139
avfDecoder::m_stat
int m_stat
Definition: avfdecoder.h:38
audiooutput.h
Decoder::setOutput
void setOutput(AudioOutput *o)
Definition: decoder.cpp:46
DecoderHandler::getMetadata
MusicMetadata & getMetadata()
Definition: decoderhandler.h:103
mythavutil.h
mythcontext.h
metaioid3.h
metaiomp4.h
avfDecoder::m_channels
int m_channels
Definition: avfdecoder.h:44
avfDecoder::seek
void seek(double pos) override
Definition: avfdecoder.cpp:394
avfDecoder::m_lastMetadata
QString m_lastMetadata
Definition: avfdecoder.h:57
ShoutCastMetaParser::ShoutCastMetaParser
ShoutCastMetaParser(void)=default
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
avfDecoder::m_bitrate
long m_bitrate
Definition: avfdecoder.h:43
AudioFormat
AudioFormat
Definition: audiooutputsettings.h:25
Decoder::output
AudioOutput * output()
Definition: decoder.h:81
ShoutCastMetaParser::m_metaArtistPos
int m_metaArtistPos
Definition: avfdecoder.cpp:72
MetaIO::kValidFileExtensions
static const QString kValidFileExtensions
Definition: metaio.h:173
output
#define output
Definition: synaesthesia.cpp:220
avfDecoder::~avfDecoder
~avfDecoder(void) override
Definition: avfdecoder.cpp:244
AudioOutput::PauseUntilBuffered
virtual void PauseUntilBuffered(void)=0
metaiooggvorbis.h
avfDecoder::checkMetatdata
void checkMetatdata(void)
Definition: avfdecoder.cpp:544
musicplayer.h