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  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 = av_packet_alloc();
434  AVPacket *tmp_pkt = av_packet_alloc();
435  if ((pkt == nullptr) || (tmp_pkt == nullptr))
436  {
437  LOG(VB_GENERAL, LOG_ERR, "packet allocation failed");
438  return;
439  }
440 
442  {
443  DecoderEvent e((DecoderEvent::Type) m_stat);
444  dispatch(e);
445  }
446 
447  av_read_play(m_inputContext->getContext());
448 
449  while (!m_finish && !m_userStop)
450  {
451  // Look to see if user has requested a seek
452  if (m_seekTime >= 0.0)
453  {
454  LOG(VB_GENERAL, LOG_INFO, QString("avfdecoder.o: seek time %1")
455  .arg(m_seekTime));
456 
457  if (av_seek_frame(m_inputContext->getContext(), -1,
458  (int64_t)(m_seekTime * AV_TIME_BASE), 0) < 0)
459  LOG(VB_GENERAL, LOG_ERR, "Error seeking");
460 
461  m_seekTime = -1.0;
462  }
463 
464  while (!m_finish && !m_userStop && m_seekTime <= 0.0)
465  {
466  // Read a packet from the input context
467  int res = av_read_frame(m_inputContext->getContext(), pkt);
468  if (res < 0)
469  {
470  if (res != AVERROR_EOF)
471  {
472  LOG(VB_GENERAL, LOG_ERR, QString("Read frame failed: %1").arg(res));
473  LOG(VB_FILE, LOG_ERR, ("... for file '" + m_url) + "'");
474  }
475 
476  m_finish = true;
477  break;
478  }
479 
480  av_packet_ref(tmp_pkt, pkt);
481 
482  while (tmp_pkt->size > 0 && !m_finish &&
483  !m_userStop && m_seekTime <= 0.0)
484  {
485  int data_size = 0;
486 
487  int ret = output()->DecodeAudio(m_audioDec,
489  data_size,
490  tmp_pkt);
491 
492  if (ret < 0)
493  break;
494 
495  // Increment the output pointer and count
496  tmp_pkt->size -= ret;
497  tmp_pkt->data += ret;
498 
499  if (data_size <= 0)
500  continue;
501 
502  output()->AddData(m_outputBuffer, data_size, -1ms, 0);
503  }
504 
505  av_packet_unref(pkt);
506 
507  // Wait until we need to decode or supply more samples
508  while (!m_finish && !m_userStop && m_seekTime <= 0.0)
509  {
510  std::chrono::milliseconds buffered = output()->GetAudioBufferedTime();
511  // never go below 1s buffered
512  if (buffered < 1s)
513  break;
514  // wait
515  const struct timespec ns {0, (buffered.count() - 1000) * 1000000};
516  nanosleep(&ns, nullptr);
517  }
518  }
519  }
520 
521  if (m_userStop)
522  {
523  m_inited = false;
524  }
525  else
526  {
527  // Drain ao buffer, making sure we play all remaining audio samples
528  output()->Drain();
529  }
530 
531  if (m_finish)
533  else if (m_userStop)
535 
536  {
537  DecoderEvent e((DecoderEvent::Type) m_stat);
538  dispatch(e);
539  }
540 
541  av_packet_free(&pkt);
542  av_packet_free(&tmp_pkt);
543  deinit();
544  RunEpilog();
545 }
546 
548 {
549  uint8_t *pdata = nullptr;
550 
551  if (av_opt_get(m_inputContext->getContext(), "icy_metadata_packet", AV_OPT_SEARCH_CHILDREN, &pdata) >= 0)
552  {
553  QString s = QString::fromUtf8((const char*) pdata);
554 
555  if (m_lastMetadata != s)
556  {
557  m_lastMetadata = s;
558 
559  LOG(VB_PLAYBACK, LOG_INFO, QString("avfDecoder: shoutcast metadata changed - %1").arg(m_lastMetadata));
560 
563 
564  ShoutCastMetaMap meta_map = parser.parseMeta(m_lastMetadata);
565 
567  mdata.setTitle(meta_map["title"]);
568  mdata.setArtist(meta_map["artist"]);
569  mdata.setAlbum(meta_map["album"]);
570  mdata.setLength(-1ms);
571 
573  dispatch(ev);
574  }
575 
576  av_free(pdata);
577  }
578 
579  if (m_inputContext->getContext()->pb)
580  {
581  int available = (int) (m_inputContext->getContext()->pb->buf_end - m_inputContext->getContext()->pb->buffer);
582  int maxSize = m_inputContext->getContext()->pb->buffer_size;
584  dispatch(ev);
585  }
586 }
587 
588 bool avfDecoderFactory::supports(const QString &source) const
589 {
590 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
591  QStringList list = extension().split("|", QString::SkipEmptyParts);
592 #else
593  QStringList list = extension().split("|", Qt::SkipEmptyParts);
594 #endif
595  return std::any_of(list.cbegin(), list.cend(),
596  [source](const auto& str)
597  { return str == source.right(str.length()).toLower(); } );
598 }
599 
600 const QString &avfDecoderFactory::extension() const
601 {
603 }
604 
605 const QString &avfDecoderFactory::description() const
606 {
607  static QString s_desc(tr("Internal Decoder"));
608  return s_desc;
609 }
610 
611 Decoder *avfDecoderFactory::create(const QString &file, AudioOutput *output, bool deletable)
612 {
613  if (deletable)
614  return new avfDecoder(file, this, output);
615 
616  static avfDecoder *s_decoder = nullptr;
617  if (!s_decoder)
618  {
619  s_decoder = new avfDecoder(file, this, output);
620  }
621  else
622  {
623  s_decoder->setOutput(output);
624  }
625 
626  return s_decoder;
627 }
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:280
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:153
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:81
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:209
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:588
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:605
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:165
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:593
avfDecoderFactory::extension
const QString & extension() const override
Definition: avfdecoder.cpp:600
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:144
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:611
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:129
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:547
musicplayer.h