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 {
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  const 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->ch_layout.nb_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->ch_layout.nb_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  // Play all pending and restart buffering, else REW/FFWD
463  // takes 1 second per keypress at the "buffered" wait below.
464  output()->Drain(); // (see issue #784)
465  }
466 
467  while (!m_finish && !m_userStop && m_seekTime <= 0.0)
468  {
469  // Read a packet from the input context
470  int res = av_read_frame(m_inputContext->getContext(), pkt);
471  if (res < 0)
472  {
473  if (res != AVERROR_EOF)
474  {
475  LOG(VB_GENERAL, LOG_ERR, QString("Read frame failed: %1").arg(res));
476  LOG(VB_FILE, LOG_ERR, ("... for file '" + m_url) + "'");
477  }
478 
479  m_finish = true;
480  break;
481  }
482 
483  av_packet_ref(tmp_pkt, pkt);
484 
485  while (tmp_pkt->size > 0 && !m_finish &&
486  !m_userStop && m_seekTime <= 0.0)
487  {
488  int data_size = 0;
489 
490  int ret = output()->DecodeAudio(m_audioDec,
492  data_size,
493  tmp_pkt);
494 
495  if (ret < 0)
496  break;
497 
498  // Increment the output pointer and count
499  tmp_pkt->size -= ret;
500  tmp_pkt->data += ret;
501 
502  if (data_size <= 0)
503  continue;
504 
505  output()->AddData(m_outputBuffer, data_size, -1ms, 0);
506  }
507 
508  av_packet_unref(pkt);
509 
510  // Wait until we need to decode or supply more samples
511  while (!m_finish && !m_userStop && m_seekTime <= 0.0)
512  {
513  std::chrono::milliseconds buffered = output()->GetAudioBufferedTime();
514  // never go below 1s buffered
515  if (buffered < 1s)
516  break;
517  // wait
518  long count = buffered.count();
519  const struct timespec ns {0, (count - 1000) * 1000000};
520  nanosleep(&ns, nullptr);
521  }
522  }
523  }
524 
525  if (m_userStop)
526  {
527  m_inited = false;
528  }
529  else
530  {
531  // Drain ao buffer, making sure we play all remaining audio samples
532  output()->Drain();
533  }
534 
535  if (m_finish)
537  else if (m_userStop)
539 
540  {
541  DecoderEvent e((DecoderEvent::Type) m_stat);
542  dispatch(e);
543  }
544 
545  av_packet_free(&pkt);
546  av_packet_free(&tmp_pkt);
547  deinit();
548  RunEpilog();
549 }
550 
552 {
553  uint8_t *pdata = nullptr;
554 
555  if (av_opt_get(m_inputContext->getContext(), "icy_metadata_packet", AV_OPT_SEARCH_CHILDREN, &pdata) >= 0)
556  {
557  QString shout = QString::fromUtf8((const char*) pdata);
558 
559  if (m_lastMetadata != shout)
560  {
561  m_lastMetadata = shout;
564  ShoutCastMetaMap meta_map = parser.parseMeta(shout);
565 
566  QString parsed = meta_map["title"] + "\\" + meta_map["artist"] + "\\" + meta_map["album"];
567  if (m_lastMetadataParsed != parsed)
568  {
569  m_lastMetadataParsed = parsed;
570 
571  LOG(VB_PLAYBACK, LOG_INFO, QString("avfDecoder: shoutcast metadata changed - %1").arg(shout));
572  LOG(VB_PLAYBACK, LOG_INFO, QString("avfDecoder: new metadata (%1)").arg(parsed));
573 
575  mdata.setTitle(meta_map["title"]);
576  mdata.setArtist(meta_map["artist"]);
577  mdata.setAlbum(meta_map["album"]);
578  mdata.setLength(-1ms);
579 
581  dispatch(ev);
582  }
583  }
584 
585  av_free(pdata);
586  }
587 
588  if (m_inputContext->getContext()->pb)
589  {
590  int available = (int) (m_inputContext->getContext()->pb->buf_end - m_inputContext->getContext()->pb->buffer);
591  int maxSize = m_inputContext->getContext()->pb->buffer_size;
593  dispatch(ev);
594  }
595 }
596 
597 bool avfDecoderFactory::supports(const QString &source) const
598 {
599  QStringList list = extension().split("|", Qt::SkipEmptyParts);
600  return std::any_of(list.cbegin(), list.cend(),
601  [source](const auto& str)
602  { return str == source.right(str.length()).toLower(); } );
603 }
604 
605 const QString &avfDecoderFactory::extension() const
606 {
608 }
609 
610 const QString &avfDecoderFactory::description() const
611 {
612  static QString s_desc(tr("Internal Decoder"));
613  return s_desc;
614 }
615 
616 Decoder *avfDecoderFactory::create(const QString &file, AudioOutput *output, bool deletable)
617 {
618  if (deletable)
619  return new avfDecoder(file, this, output);
620 
621  static avfDecoder *s_decoder = nullptr;
622  if (!s_decoder)
623  {
624  s_decoder = new avfDecoder(file, this, output);
625  }
626  else
627  {
628  s_decoder->setOutput(output);
629  }
630 
631  return s_decoder;
632 }
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.
FORMAT_NONE
@ FORMAT_NONE
Definition: audiooutputsettings.h:25
AudioOutput::kMaxSizeBuffer
static const int kMaxSizeBuffer
kMaxSizeBuffer is the maximum size of a buffer to be used with DecodeAudio
Definition: audiooutput.h:197
RemoteAVFormatContext::isOpen
bool isOpen() const
Definition: mythmusic/mythmusic/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:424
MythCodecMap::GetCodecContext
AVCodecContext * GetCodecContext(const AVStream *Stream, const AVCodec *Codec=nullptr, bool NullCodec=false)
Definition: mythavutil.cpp:287
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: mythmusic/mythmusic/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:80
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:257
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:262
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:144
AudioOutput::Drain
virtual void Drain(void)=0
AudioSettings
Definition: audiosettings.h:28
AudioOutput
Definition: audiooutput.h:26
DecoderHandlerEvent
Events sent by the DecoderHandler and it's helper classes.
Definition: decoderhandler.h:25
Decoder
Definition: decoder.h:70
RemoteAVFormatContext
Definition: mythmusic/mythmusic/remoteavformatcontext.h:22
mythlogging.h
avfDecoder
Definition: avfdecoder.h:20
avfDecoderFactory::supports
bool supports(const QString &source) const override
Definition: avfdecoder.cpp:597
MusicMetadata::setLength
void setLength(T llength)
Definition: musicmetadata.h:207
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:610
avfDecoder::m_finish
bool m_finish
Definition: avfdecoder.h:46
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:76
avfDecoder::m_freq
long m_freq
Definition: avfdecoder.h:47
MythCodecMap::FreeCodecContext
void FreeCodecContext(const AVStream *Stream)
Definition: mythavutil.cpp:335
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:590
avfDecoderFactory::extension
const QString & extension() const override
Definition: avfdecoder.cpp:605
Decoder::getURL
QString getURL(void) const
Definition: decoder.h:91
DecoderEvent::kStopped
static const Type kStopped
Definition: decoder.h:46
uint
unsigned int uint
Definition: compat.h:81
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:616
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
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:394
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
AudioFormat
AudioFormat
Definition: audiooutputsettings.h:24
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: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:551
musicplayer.h