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>
44
45// Mythmusic Headers
46#include "avfdecoder.h"
47#include "decoderhandler.h"
48#include "musicplayer.h"
50
51extern "C" {
52 #include <libavformat/avio.h>
53 #include <libavutil/opt.h>
54}
55
56/****************************************************************************/
57
58using 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;
74};
75
76void 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
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
174static 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
392void 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
595bool 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
603const QString &avfDecoderFactory::extension() const
604{
606}
607
608const QString &avfDecoderFactory::description() const
609{
610 static QString s_desc(tr("Internal Decoder"));
611 return s_desc;
612}
613
614Decoder *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}
@ FORMAT_NONE
static void myth_av_log(void *ptr, int level, const char *fmt, va_list vl)
Definition: avfdecoder.cpp:174
QMap< QString, QString > ShoutCastMetaMap
Definition: avfdecoder.cpp:58
static AudioFormat AVSampleFormatToFormat(AVSampleFormat format, int bits=0)
Return AVSampleFormat closest equivalent to AudioFormat.
virtual bool AddData(void *buffer, int len, std::chrono::milliseconds timecode, int frames)=0
Add data to the audiobuffer for playback.
virtual void Drain(void)=0
virtual std::chrono::milliseconds GetAudioBufferedTime(void)
report amount of audio buffered in milliseconds.
Definition: audiooutput.h:142
virtual void PauseUntilBuffered(void)=0
virtual int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
Utility routine.
virtual void Reconfigure(const AudioSettings &settings)=0
virtual void SetSourceBitrate(int)
Definition: audiooutput.h:144
static const Type kStopped
Definition: decoder.h:46
static const Type kDecoding
Definition: decoder.h:45
static const Type kFinished
Definition: decoder.h:47
Events sent by the DecoderHandler and it's helper classes.
static const Type kBufferStatus
static const Type kMeta
MusicMetadata & getMetadata()
void error(const QString &e)
Definition: decoder.cpp:51
QString getURL(void) const
Definition: decoder.h:91
void setURL(const QString &url)
Definition: decoder.h:83
AudioOutput * output()
Definition: decoder.h:81
QString m_url
Definition: decoder.h:105
void setOutput(AudioOutput *o)
Definition: decoder.cpp:44
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
void setObjectName(const QString &name)
Definition: mthread.cpp:238
static const QString kValidFileExtensions
Definition: metaio.h:160
void setLength(T llength)
void setTitle(const QString &ltitle, const QString &ltitle_sort=nullptr)
QString MetadataFormat(void)
void setAlbum(const QString &lalbum, const QString &lalbum_sort=nullptr)
void setArtist(const QString &lartist, const QString &lartist_sort=nullptr)
DecoderHandler * getDecoderHandler(void)
Definition: musicplayer.h:127
AVCodecContext * GetCodecContext(const AVStream *Stream, const AVCodec *Codec=nullptr, bool NullCodec=false)
Definition: mythavutil.cpp:288
void FreeCodecContext(const AVStream *Stream)
Definition: mythavutil.cpp:333
void dispatch(const MythEvent &event)
Dispatch an event to all listeners.
AVFormatContext * getContext(void)
~ShoutCastMetaParser(void)=default
ShoutCastMetaMap parseMeta(const QString &mdata)
Definition: avfdecoder.cpp:138
ShoutCastMetaParser(void)=default
void setMetaFormat(const QString &metaformat)
Definition: avfdecoder.cpp:76
bool supports(const QString &source) const override
Definition: avfdecoder.cpp:595
Decoder * create(const QString &file, AudioOutput *output, bool deletable) override
Definition: avfdecoder.cpp:614
const QString & description() const override
Definition: avfdecoder.cpp:608
const QString & extension() const override
Definition: avfdecoder.cpp:603
void checkMetatdata(void)
Definition: avfdecoder.cpp:549
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
bool initialize() override
Definition: avfdecoder.cpp:260
void stop() override
Definition: avfdecoder.cpp:255
QTimer * m_mdataTimer
Definition: avfdecoder.h:64
class RemoteAVFormatContext * m_inputContext
Definition: avfdecoder.h:58
int m_stat
Definition: avfdecoder.h:46
void seek(double pos) override
Definition: avfdecoder.cpp:392
double m_seekTime
Definition: avfdecoder.h:53
MythCodecMap m_codecMap
Definition: avfdecoder.h:60
long m_bitrate
Definition: avfdecoder.h:51
void deinit()
Definition: avfdecoder.cpp:401
~avfDecoder(void) override
Definition: avfdecoder.cpp:242
uint8_t * m_outputBuffer
Definition: avfdecoder.h:47
AVCodecContext * m_audioDec
Definition: avfdecoder.h:59
QString m_lastMetadataParsed
Definition: avfdecoder.h:66
const AVInputFormat * m_inputFormat
Definition: avfdecoder.h:57
QString m_lastMetadata
Definition: avfdecoder.h:65
bool m_finish
Definition: avfdecoder.h:49
long m_freq
Definition: avfdecoder.h:50
bool m_inited
Definition: avfdecoder.h:44
avfDecoder(const QString &file, DecoderFactory *d, AudioOutput *o)
Definition: avfdecoder.cpp:230
bool m_userStop
Definition: avfdecoder.h:45
int m_channels
Definition: avfdecoder.h:52
unsigned int uint
Definition: freesurround.h:24
static const iso6937table * d
MusicPlayer * gPlayer
Definition: musicplayer.cpp:38
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
static bool VERBOSE_LEVEL_NONE()
Definition: mythlogging.h:28
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define output
VERBOSE_PREAMBLE Most debug(nodatabase, notimestamp, noextra)") VERBOSE_MAP(VB_GENERAL