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 <QFile>
26 #include <QIODevice>
27 #include <QObject>
28 #include <QRegularExpression>
29 #include <QTimer>
30 
31 // MythTV headers
32 #include <mythconfig.h>
35 #include <libmyth/mythcontext.h>
37 #include <libmythmetadata/metaio.h>
44 #include <libmythtv/mythavutil.h>
45 
46 // Mythmusic Headers
47 #include "avfdecoder.h"
48 #include "decoderhandler.h"
49 #include "musicplayer.h"
50 
51 extern "C" {
52  #include <libavformat/avio.h>
53  #include <libavutil/opt.h>
54 }
55 
56 /****************************************************************************/
57 
58 using ShoutCastMetaMap = QMap<QString,QString>;
59 
61 {
62  public:
63  ShoutCastMetaParser(void) = default;
64  ~ShoutCastMetaParser(void) = default;
65 
66  void setMetaFormat(const QString &metaformat);
67  ShoutCastMetaMap parseMeta(const QString &mdata);
68 
69  private:
70  QString m_metaFormat;
71  int m_metaArtistPos {-1};
72  int m_metaTitlePos {-1};
73  int m_metaAlbumPos {-1};
74 };
75 
76 void ShoutCastMetaParser::setMetaFormat(const QString &metaformat)
77 {
78 /*
79  We support these metatags :
80  %a - artist
81  %t - track
82  %b - album
83  %r - random bytes
84  */
85  m_metaFormat = metaformat;
86 
87  m_metaArtistPos = 0;
88  m_metaTitlePos = 0;
89  m_metaAlbumPos = 0;
90 
91  int assign_index = 1;
92  int pos = 0;
93 
94  pos = m_metaFormat.indexOf("%", pos);
95  while (pos >= 0)
96  {
97  pos++;
98 
99  QChar ch;
100 
101  if (pos < m_metaFormat.length())
102  ch = m_metaFormat.at(pos);
103 
104  if (!ch.isNull() && ch == '%')
105  {
106  pos++;
107  }
108  else if (!ch.isNull() && (ch == 'r' || ch == 'a' || ch == 'b' || ch == 't'))
109  {
110  if (ch == 'a')
111  m_metaArtistPos = assign_index;
112 
113  if (ch == 'b')
114  m_metaAlbumPos = assign_index;
115 
116  if (ch == 't')
117  m_metaTitlePos = assign_index;
118 
119  assign_index++;
120  }
121  else
122  {
123  LOG(VB_GENERAL, LOG_ERR,
124  QString("ShoutCastMetaParser: malformed metaformat '%1'")
125  .arg(m_metaFormat));
126  }
127 
128  pos = m_metaFormat.indexOf("%", pos);
129  }
130 
131  m_metaFormat.replace("%a", "(.*)");
132  m_metaFormat.replace("%t", "(.*)");
133  m_metaFormat.replace("%b", "(.*)");
134  m_metaFormat.replace("%r", "(.*)");
135  m_metaFormat.replace("%%", "%");
136 }
137 
139 {
140  ShoutCastMetaMap result;
141  int title_begin_pos = mdata.indexOf("StreamTitle='");
142 
143  if (title_begin_pos >= 0)
144  {
145  title_begin_pos += 13;
146  int title_end_pos = mdata.indexOf("';", title_begin_pos);
147  QString title = mdata.mid(title_begin_pos, title_end_pos - title_begin_pos);
148  QRegularExpression rx { m_metaFormat };
149  auto match = rx.match(title);
150  if (match.hasMatch())
151  {
152  LOG(VB_PLAYBACK, LOG_DEBUG, QString("ShoutCast: Meta : '%1'")
153  .arg(mdata));
154  LOG(VB_PLAYBACK, LOG_DEBUG,
155  QString("ShoutCast: Parsed as: '%1' by '%2' on '%3'")
156  .arg(m_metaTitlePos ? match.captured(m_metaTitlePos) : "",
157  m_metaArtistPos ? match.captured(m_metaArtistPos) : "",
158  m_metaAlbumPos ? match.captured(m_metaAlbumPos) : ""));
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::vasprintf(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  m_outputBuffer((uint8_t *)av_malloc(AudioOutput::kMaxSizeBuffer))
233 {
234  MThread::setObjectName("avfDecoder");
235  setURL(file);
236 
237  bool debug = VERBOSE_LEVEL_CHECK(VB_LIBAV, LOG_ANY);
238  av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR);
239  av_log_set_callback(myth_av_log);
240 }
241 
243 {
244  delete m_mdataTimer;
245 
246  if (m_inited)
247  deinit();
248 
249  if (m_outputBuffer)
250  av_freep(reinterpret_cast<void*>(&m_outputBuffer));
251 
252  delete m_inputContext;
253 }
254 
256 {
257  m_userStop = true;
258 }
259 
261 {
262  m_inited = m_userStop = m_finish = false;
263  m_freq = m_bitrate = 0;
264  m_stat = m_channels = 0;
265  m_seekTime = -1.0;
266 
267  // give up if we dont have an audiooutput set
268  if (!output())
269  {
270  error("avfDecoder: initialise called with a NULL audiooutput");
271  return false;
272  }
273 
274  if (!m_outputBuffer)
275  {
276  error("avfDecoder: couldn't allocate memory");
277  return false;
278  }
279 
281 
282  delete m_inputContext;
284 
285  if (!m_inputContext->isOpen())
286  {
287  error(QString("Could not open url (%1)").arg(m_url));
288  deinit();
289  return false;
290  }
291 
292  // if this is a ice/shoutcast or MMS stream start polling for metadata changes and buffer status
293  if (getURL().startsWith("http://") || getURL().startsWith("mmsh://"))
294  {
295  m_mdataTimer = new QTimer;
296  m_mdataTimer->setSingleShot(false);
298 
299  m_mdataTimer->start(500ms);
300 
301  // we don't get metadata updates for MMS streams so grab the metadata from the headers
302  if (getURL().startsWith("mmsh://"))
303  {
304  AVDictionaryEntry *tag = nullptr;
306 
307  tag = av_dict_get(m_inputContext->getContext()->metadata, "title", tag, AV_DICT_IGNORE_SUFFIX);
308  mdata.setTitle(tag->value);
309 
310  tag = av_dict_get(m_inputContext->getContext()->metadata, "artist", tag, AV_DICT_IGNORE_SUFFIX);
311  mdata.setArtist(tag->value);
312 
313  mdata.setAlbum("");
314  mdata.setLength(-1ms);
315 
317  dispatch(ev);
318  }
319  }
320 
321  // determine the stream format
322  // this also populates information needed for metadata
323  if (avformat_find_stream_info(m_inputContext->getContext(), nullptr) < 0)
324  {
325  error("Could not determine the stream format.");
326  deinit();
327  return false;
328  }
329 
330  // let FFmpeg finds the best audio stream (should only be one), also catter
331  // should the file/stream not be an audio one
332  const AVCodec *codec = nullptr;
333  int selTrack = av_find_best_stream(m_inputContext->getContext(), AVMEDIA_TYPE_AUDIO,
334  -1, -1, &codec, 0);
335 
336  if (selTrack < 0)
337  {
338  error(QString("Could not find audio stream."));
339  deinit();
340  return false;
341  }
342 
343  // Store the audio codec of the stream
345  (m_inputContext->getContext()->streams[selTrack]);
346 
347  // Store the input format of the context
349 
350  if (avcodec_open2(m_audioDec, codec, nullptr) < 0)
351  {
352  error(QString("Could not open audio codec: %1")
353  .arg(m_audioDec->codec_id));
354  deinit();
355  return false;
356  }
357 
358  m_freq = m_audioDec->sample_rate;
359  m_channels = m_audioDec->ch_layout.nb_channels;
360 
361  if (m_channels <= 0)
362  {
363  error(QString("AVCodecContext tells us %1 channels are "
364  "available, this is bad, bailing.")
365  .arg(m_channels));
366  deinit();
367  return false;
368  }
369 
370  AudioFormat format =
372  m_audioDec->bits_per_raw_sample);
373  if (format == FORMAT_NONE)
374  {
375  error(QString("Error: Unsupported sample format: %1")
376  .arg(av_get_sample_fmt_name(m_audioDec->sample_fmt)));
377  deinit();
378  return false;
379  }
380 
381  const AudioSettings settings(format, m_audioDec->ch_layout.nb_channels,
382  m_audioDec->codec_id,
383  m_audioDec->sample_rate, false);
384 
385  output()->Reconfigure(settings);
386  output()->SetSourceBitrate(m_audioDec->bit_rate);
387 
388  m_inited = true;
389  return true;
390 }
391 
392 void avfDecoder::seek(double pos)
393 {
395  m_inputContext->getContext()->pb->seekable)
396  {
397  m_seekTime = pos;
398  }
399 }
400 
402 {
403  m_inited = m_userStop = m_finish = false;
404  m_freq = m_bitrate = 0;
405  m_stat = m_channels = 0;
406  setOutput(nullptr);
407 
408  // Cleanup here
410  {
411  for (uint i = 0; i < m_inputContext->getContext()->nb_streams; i++)
412  {
413  AVStream *st = m_inputContext->getContext()->streams[i];
415  }
416  }
417 
418  m_audioDec = nullptr;
419  m_inputFormat = nullptr;
420 }
421 
423 {
424  RunProlog();
425  if (!m_inited)
426  {
427  RunEpilog();
428  return;
429  }
430 
431  AVPacket *pkt = av_packet_alloc();
432  AVPacket *tmp_pkt = av_packet_alloc();
433  if ((pkt == nullptr) || (tmp_pkt == nullptr))
434  {
435  LOG(VB_GENERAL, LOG_ERR, "packet allocation failed");
436  return;
437  }
438 
440  {
441  DecoderEvent e((DecoderEvent::Type) m_stat);
442  dispatch(e);
443  }
444 
445  av_read_play(m_inputContext->getContext());
446 
447  while (!m_finish && !m_userStop)
448  {
449  // Look to see if user has requested a seek
450  if (m_seekTime >= 0.0)
451  {
452  LOG(VB_GENERAL, LOG_INFO, QString("avfdecoder.o: seek time %1")
453  .arg(m_seekTime));
454 
455  if (av_seek_frame(m_inputContext->getContext(), -1,
456  (int64_t)(m_seekTime * AV_TIME_BASE), 0) < 0)
457  LOG(VB_GENERAL, LOG_ERR, "Error seeking");
458 
459  m_seekTime = -1.0;
460  // Play all pending and restart buffering, else REW/FFWD
461  // takes 1 second per keypress at the "buffered" wait below.
462  output()->Drain(); // (see issue #784)
463  }
464 
465  while (!m_finish && !m_userStop && m_seekTime <= 0.0)
466  {
467  // Read a packet from the input context
468  int res = av_read_frame(m_inputContext->getContext(), pkt);
469  if (res < 0)
470  {
471  if (res != AVERROR_EOF)
472  {
473  LOG(VB_GENERAL, LOG_ERR, QString("Read frame failed: %1").arg(res));
474  LOG(VB_FILE, LOG_ERR, ("... for file '" + m_url) + "'");
475  }
476 
477  m_finish = true;
478  break;
479  }
480 
481  av_packet_ref(tmp_pkt, pkt);
482 
483  while (tmp_pkt->size > 0 && !m_finish &&
484  !m_userStop && m_seekTime <= 0.0)
485  {
486  int data_size = 0;
487 
488  int ret = output()->DecodeAudio(m_audioDec,
490  data_size,
491  tmp_pkt);
492 
493  if (ret < 0)
494  break;
495 
496  // Increment the output pointer and count
497  tmp_pkt->size -= ret;
498  tmp_pkt->data += ret;
499 
500  if (data_size <= 0)
501  continue;
502 
503  output()->AddData(m_outputBuffer, data_size, -1ms, 0);
504  }
505 
506  av_packet_unref(pkt);
507 
508  // Wait until we need to decode or supply more samples
509  while (!m_finish && !m_userStop && m_seekTime <= 0.0)
510  {
511  std::chrono::milliseconds buffered = output()->GetAudioBufferedTime();
512  // never go below 1s buffered
513  if (buffered < 1s)
514  break;
515  // wait
516  long count = buffered.count();
517  const struct timespec ns {0, (count - 1000) * 1000000};
518  nanosleep(&ns, nullptr);
519  }
520  }
521  }
522 
523  if (m_userStop)
524  {
525  m_inited = false;
526  }
527  else
528  {
529  // Drain ao buffer, making sure we play all remaining audio samples
530  output()->Drain();
531  }
532 
533  if (m_finish)
535  else if (m_userStop)
537 
538  {
539  DecoderEvent e((DecoderEvent::Type) m_stat);
540  dispatch(e);
541  }
542 
543  av_packet_free(&pkt);
544  av_packet_free(&tmp_pkt);
545  deinit();
546  RunEpilog();
547 }
548 
550 {
551  uint8_t *pdata = nullptr;
552 
553  if (av_opt_get(m_inputContext->getContext(), "icy_metadata_packet", AV_OPT_SEARCH_CHILDREN, &pdata) >= 0)
554  {
555  QString shout = QString::fromUtf8((const char*) pdata);
556 
557  if (m_lastMetadata != shout)
558  {
559  m_lastMetadata = shout;
562  ShoutCastMetaMap meta_map = parser.parseMeta(shout);
563 
564  QString parsed = meta_map["title"] + "\\" + meta_map["artist"] + "\\" + meta_map["album"];
565  if (m_lastMetadataParsed != parsed)
566  {
567  m_lastMetadataParsed = parsed;
568 
569  LOG(VB_PLAYBACK, LOG_INFO, QString("avfDecoder: shoutcast metadata changed - %1").arg(shout));
570  LOG(VB_PLAYBACK, LOG_INFO, QString("avfDecoder: new metadata (%1)").arg(parsed));
571 
573  mdata.setTitle(meta_map["title"]);
574  mdata.setArtist(meta_map["artist"]);
575  mdata.setAlbum(meta_map["album"]);
576  mdata.setLength(-1ms);
577 
579  dispatch(ev);
580  }
581  }
582 
583  av_free(pdata);
584  }
585 
586  if (m_inputContext->getContext()->pb)
587  {
588  int available = (int) (m_inputContext->getContext()->pb->buf_end - m_inputContext->getContext()->pb->buffer);
589  int maxSize = m_inputContext->getContext()->pb->buffer_size;
591  dispatch(ev);
592  }
593 }
594 
595 bool avfDecoderFactory::supports(const QString &source) const
596 {
597  QStringList list = extension().split("|", Qt::SkipEmptyParts);
598  return std::any_of(list.cbegin(), list.cend(),
599  [source](const auto& str)
600  { return str == source.right(str.length()).toLower(); } );
601 }
602 
603 const QString &avfDecoderFactory::extension() const
604 {
606 }
607 
608 const QString &avfDecoderFactory::description() const
609 {
610  static QString s_desc(tr("Internal Decoder"));
611  return s_desc;
612 }
613 
614 Decoder *avfDecoderFactory::create(const QString &file, AudioOutput *output, bool deletable)
615 {
616  if (deletable)
617  return new avfDecoder(file, this, output);
618 
619  static avfDecoder *s_decoder = nullptr;
620  if (!s_decoder)
621  {
622  s_decoder = new avfDecoder(file, this, output);
623  }
624  else
625  {
626  s_decoder->setOutput(output);
627  }
628 
629  return s_decoder;
630 }
avfDecoder::m_inited
bool m_inited
Definition: avfdecoder.h:41
AudioOutput::AddData
virtual bool AddData(void *buffer, int len, std::chrono::milliseconds timecode, int frames)=0
Add data to the audiobuffer for playback.
RemoteAVFormatContext::isOpen
bool isOpen() const
Definition: remoteavformatcontext.h:129
avfDecoder::m_codecMap
MythCodecMap m_codecMap
Definition: avfdecoder.h:57
gPlayer
MusicPlayer * gPlayer
Definition: musicplayer.cpp:37
AudioOutputSettings::AVSampleFormatToFormat
static AudioFormat AVSampleFormatToFormat(AVSampleFormat format, int bits=0)
Return AVSampleFormat closest equivalent to AudioFormat.
Definition: audiooutputsettings.cpp:198
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
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:422
MythCodecMap::GetCodecContext
AVCodecContext * GetCodecContext(const AVStream *Stream, const AVCodec *Codec=nullptr, bool NullCodec=false)
Definition: mythavutil.cpp:288
audiooutpututil.h
ShoutCastMetaParser::m_metaTitlePos
int m_metaTitlePos
Definition: avfdecoder.cpp:72
MusicMetadata::MetadataFormat
QString MetadataFormat(void)
Definition: musicmetadata.h:278
decoderhandler.h
ShoutCastMetaMap
QMap< QString, QString > ShoutCastMetaMap
Definition: avfdecoder.cpp:58
RemoteAVFormatContext::getContext
AVFormatContext * getContext(void)
Definition: remoteavformatcontext.h:35
VERBOSE_LEVEL_CHECK
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
MThread::setObjectName
void setObjectName(const QString &name)
Definition: mthread.cpp:238
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:42
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
MusicMetadata
Definition: musicmetadata.h:81
metaioflacvorbis.h
avfDecoder::m_seekTime
double m_seekTime
Definition: avfdecoder.h:50
DecoderFactory
Definition: decoder.h:117
build_compdb.parser
parser
Definition: build_compdb.py:7
avfDecoder::stop
void stop() override
Definition: avfdecoder.cpp:255
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:70
avfDecoder::initialize
bool initialize() override
Definition: avfdecoder.cpp:260
avfDecoder::m_mdataTimer
QTimer * m_mdataTimer
Definition: avfdecoder.h:61
avfDecoder::m_inputContext
RemoteAVFormatContext * m_inputContext
Definition: avfdecoder.h:55
avfDecoder::m_outputBuffer
uint8_t * m_outputBuffer
Definition: avfdecoder.h:44
AudioOutput::GetAudioBufferedTime
virtual std::chrono::milliseconds GetAudioBufferedTime(void)
report amount of audio buffered in milliseconds.
Definition: audiooutput.h:143
AudioOutput::Drain
virtual void Drain(void)=0
AudioSettings
Definition: audiosettings.h:28
AudioOutput
Definition: audiooutput.h:25
DecoderHandlerEvent
Events sent by the DecoderHandler and it's helper classes.
Definition: decoderhandler.h:25
Decoder
Definition: decoder.h:70
RemoteAVFormatContext
Definition: remoteavformatcontext.h:22
mythlogging.h
avfDecoder
Definition: avfdecoder.h:20
avfDecoderFactory::supports
bool supports(const QString &source) const override
Definition: avfdecoder.cpp:595
FORMAT_NONE
@ FORMAT_NONE
Definition: audiooutputsettings.h:25
MusicMetadata::setLength
void setLength(T llength)
Definition: musicmetadata.h:207
AudioOutput::SetSourceBitrate
virtual void SetSourceBitrate(int)
Definition: audiooutput.h:145
DecoderEvent
Definition: decoder.h:29
avfDecoderFactory::description
const QString & description() const override
Definition: avfdecoder.cpp:608
avfDecoder::m_finish
bool m_finish
Definition: avfdecoder.h:46
avfDecoder::deinit
void deinit()
Definition: avfdecoder.cpp:401
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:76
avfDecoder::m_freq
long m_freq
Definition: avfdecoder.h:47
MythCodecMap::FreeCodecContext
void FreeCodecContext(const AVStream *Stream)
Definition: mythavutil.cpp:336
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
avfDecoder::m_inputFormat
const AVInputFormat * m_inputFormat
Definition: avfdecoder.h:54
AudioOutput::DecodeAudio
virtual int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
Utility routine.
Definition: audiooutput.cpp:595
avfDecoderFactory::extension
const QString & extension() const override
Definition: avfdecoder.cpp:603
Decoder::getURL
QString getURL(void) const
Definition: decoder.h:91
DecoderEvent::kStopped
static const Type kStopped
Definition: decoder.h:46
ShoutCastMetaParser::~ShoutCastMetaParser
~ShoutCastMetaParser(void)=default
DecoderHandlerEvent::kMeta
static const Type kMeta
Definition: decoderhandler.h:47
ShoutCastMetaParser::m_metaAlbumPos
int m_metaAlbumPos
Definition: avfdecoder.cpp:73
ShoutCastMetaParser
Definition: avfdecoder.cpp:60
Decoder::setURL
void setURL(const QString &url)
Definition: decoder.h:83
avfDecoderFactory::create
Decoder * create(const QString &file, AudioOutput *output, bool deletable) override
Definition: avfdecoder.cpp:614
Decoder::error
void error(const QString &e)
Definition: decoder.cpp:52
avfDecoder::m_audioDec
AVCodecContext * m_audioDec
Definition: avfdecoder.h:56
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:127
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
DecoderEvent::kFinished
static const Type kFinished
Definition: decoder.h:47
DecoderEvent::kDecoding
static const Type kDecoding
Definition: decoder.h:45
metaio.h
ShoutCastMetaParser::parseMeta
ShoutCastMetaMap parseMeta(const QString &mdata)
Definition: avfdecoder.cpp:138
avfDecoder::m_stat
int m_stat
Definition: avfdecoder.h:43
audiooutput.h
Decoder::setOutput
void setOutput(AudioOutput *o)
Definition: decoder.cpp:45
DecoderHandler::getMetadata
MusicMetadata & getMetadata()
Definition: decoderhandler.h:102
mythavutil.h
DecoderHandlerEvent::kBufferStatus
static const Type kBufferStatus
Definition: decoderhandler.h:48
AudioFormat
AudioFormat
Definition: audiooutputsettings.h:24
mythcontext.h
VERBOSE_LEVEL_NONE
static bool VERBOSE_LEVEL_NONE()
Definition: mythlogging.h:28
metaioid3.h
metaiomp4.h
avfDecoder::m_lastMetadataParsed
QString m_lastMetadataParsed
Definition: avfdecoder.h:63
avfDecoder::m_channels
int m_channels
Definition: avfdecoder.h:49
avfDecoder::seek
void seek(double pos) override
Definition: avfdecoder.cpp:392
avfDecoder::m_lastMetadata
QString m_lastMetadata
Definition: avfdecoder.h:62
ShoutCastMetaParser::ShoutCastMetaParser
ShoutCastMetaParser(void)=default
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
avfDecoder::m_bitrate
long m_bitrate
Definition: avfdecoder.h:48
Decoder::output
AudioOutput * output()
Definition: decoder.h:81
ShoutCastMetaParser::m_metaArtistPos
int m_metaArtistPos
Definition: avfdecoder.cpp:71
MetaIO::kValidFileExtensions
static const QString kValidFileExtensions
Definition: metaio.h:161
output
#define output
Definition: synaesthesia.cpp:223
avfDecoder::~avfDecoder
~avfDecoder(void) override
Definition: avfdecoder.cpp:242
AudioOutput::PauseUntilBuffered
virtual void PauseUntilBuffered(void)=0
metaiooggvorbis.h
avfDecoder::checkMetatdata
void checkMetatdata(void)
Definition: avfdecoder.cpp:549
uint
unsigned int uint
Definition: freesurround.h:24
musicplayer.h