MythTV master
avformatdecoder.cpp
Go to the documentation of this file.
1#include "avformatdecoder.h"
2
3#include <unistd.h>
4
5// C++ headers
6#include <algorithm>
7#include <array>
8#include <cmath>
9#include <cstdint>
10#include <cstring>
11#include <iostream>
12#include <set>
13
14extern "C" {
15#include "libavutil/avutil.h"
16#include "libavutil/error.h"
17#include "libavutil/intreadwrite.h" // for AV_RB32 and AV_RB24
18#include "libavutil/log.h"
19#include "libavutil/opt.h"
20#include "libavcodec/avcodec.h"
21#include "libavformat/avformat.h"
22#include "libavformat/avio.h"
23#include "libswscale/swscale.h"
24#include "libavutil/stereo3d.h"
25#include "libavutil/imgutils.h"
26#include "libavutil/display.h"
27}
28
29#if CONFIG_MEDIACODEC // Android
30extern "C" {
31#include "libavcodec/jni.h"
32}
33#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
34#include <QtAndroidExtras>
35#else
36#include <QJniEnvironment>
37#define QAndroidJniEnvironment QJniEnvironment
38#endif
39#endif // Android
40
41// regardless of building with V4L2 or not, enable IVTV VBI data
42// from <linux/videodev2.h> under SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause)
43/*
44 * V4L2_MPEG_STREAM_VBI_FMT_IVTV:
45 *
46 * Structure of payload contained in an MPEG 2 Private Stream 1 PES Packet in an
47 * MPEG-2 Program Pack that contains V4L2_MPEG_STREAM_VBI_FMT_IVTV Sliced VBI
48 * data
49 *
50 * Note, the MPEG-2 Program Pack and Private Stream 1 PES packet header
51 * definitions are not included here. See the MPEG-2 specifications for details
52 * on these headers.
53 */
54
55/* Line type IDs */
56enum V4L2_MPEG_LINE_TYPES : std::uint8_t {
61};
62// comments for each ID from ivtv_myth.h
63
64#include <QFileInfo>
65#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
66#include <QTextCodec>
67#else
68#include <QStringDecoder>
69#endif // Qt 6
70
71#ifdef _WIN32
72# undef mkdir
73#endif
74
75// MythTV headers
78#include "libmyth/mythaverror.h"
79#include "libmyth/mythavframe.h"
80#include "libmythbase/iso639.h"
83#include "libmythbase/mythconfig.h"
90
91#include "mythtvexp.h"
92
93#include "Bluray/mythbdbuffer.h"
94#include "DVD/mythdvdbuffer.h"
99#include "io/mythmediabuffer.h"
100#include "mheg/interactivetv.h"
101#include "mpeg/atscdescriptors.h"
102#include "mpeg/dvbdescriptors.h"
103#include "mpeg/mpegtables.h"
104#include "bytereader.h"
105#include "mythavbufferref.h"
106#include "mythavutil.h"
107#include "mythframe.h"
108#include "mythhdrvideometadata.h"
109#include "mythvideoprofile.h"
110#include "remoteencoder.h"
111
112using namespace std::string_view_literals;
113
114#define LOC QString("AFD: ")
115
116// Maximum number of sequential invalid data packet errors before we try
117// switching to software decoder. Packet errors are often seen when using
118// hardware contexts and, for example, seeking. Hence this needs to be high and
119// is probably best removed as it is treating the symptoms and not the cause.
120// See also comment in MythCodecMap::freeCodecContext re trying to free an
121// active hardware context when it is errored.
122static constexpr int SEQ_PKT_ERR_MAX { 50 };
123
124#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
125static constexpr int16_t kMaxVideoQueueSize = 220;
126#else
127static constexpr ssize_t kMaxVideoQueueSize = 220;
128#endif
129
130static QSize get_video_dim(const AVCodecContext &ctx)
131{
132 return {ctx.width >> ctx.lowres, ctx.height >> ctx.lowres};
133}
134static float get_aspect(const AVCodecContext &ctx)
135{
136 float aspect_ratio = 0.0F;
137
138 if (ctx.sample_aspect_ratio.num && ctx.height)
139 {
140 aspect_ratio = av_q2d(ctx.sample_aspect_ratio) *
141 static_cast<double>(ctx.width);
142 aspect_ratio /= (float) ctx.height;
143 }
144
145 if (aspect_ratio <= 0.0F || aspect_ratio > 6.0F)
146 {
147 if (ctx.height)
148 aspect_ratio = (float)ctx.width / (float)ctx.height;
149 else
150 aspect_ratio = 4.0F / 3.0F;
151 }
152
153 return aspect_ratio;
154}
155static float get_aspect(AVCParser &p)
156{
157 static constexpr float kDefaultAspect = 4.0F / 3.0F;
158 int asp = p.aspectRatio();
159 switch (asp)
160 {
161 case 0: return kDefaultAspect;
162 case 2: return 4.0F / 3.0F;
163 case 3: return 16.0F / 9.0F;
164 case 4: return 2.21F;
165 default: break;
166 }
167
168 float aspect_ratio = asp * 0.000001F;
169 if (aspect_ratio <= 0.0F || aspect_ratio > 6.0F)
170 {
171 if (p.pictureHeight() && p.pictureWidth())
172 {
173 aspect_ratio =
174 (float) p.pictureWidth() /(float) p.pictureHeight();
175 }
176 else
177 {
178 aspect_ratio = kDefaultAspect;
179 }
180 }
181 return aspect_ratio;
182}
183
184
185int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic, int flags);
186
187// currently unused
188//static int determinable_frame_size(struct AVCodecContext *avctx)
189//{
190// if (/*avctx->codec_id == AV_CODEC_ID_AAC ||*/
191// avctx->codec_id == AV_CODEC_ID_MP1 ||
192// avctx->codec_id == AV_CODEC_ID_MP2 ||
193// avctx->codec_id == AV_CODEC_ID_MP3/* ||
194// avctx->codec_id == AV_CODEC_ID_CELT*/)
195// return 1;
196// return 0;
197//}
198
199#define FAIL(errmsg) do { \
200 LOG(VB_PLAYBACK, LOG_INFO, LOC + (errmsg)); \
201 return false; \
202} while (false)
203
209static bool StreamHasRequiredParameters(AVCodecContext *Context, AVStream *Stream)
210{
211 switch (Stream->codecpar->codec_type)
212 {
213 // We fail on video first as this is generally the most serious error
214 // and if we have video, we usually have everything else
215 case AVMEDIA_TYPE_VIDEO:
216 if (!Context)
217 FAIL("No codec for video stream");
218 if (!Stream->codecpar->width || !Stream->codecpar->height)
219 FAIL("Unspecified video size");
220 if (Stream->codecpar->format == AV_PIX_FMT_NONE)
221 FAIL("Unspecified video pixel format");
222 // The proprietary RealVideo codecs are not used for TV broadcast
223 // and codec_info_nb_frames was moved to FFStream as it is an internal, private value.
224 //if (Context->codec_id == AV_CODEC_ID_RV30 || Context->codec_id == AV_CODEC_ID_RV40)
225 // if (!Stream->sample_aspect_ratio.num && !Context->sample_aspect_ratio.num && !Stream->codec_info_nb_frames)
226 // FAIL("No frame in rv30/40 and no sar");
227 break;
228 case AVMEDIA_TYPE_AUDIO:
229 if (!Context)
230 FAIL("No codec for audio stream");
231
232 // These checks are currently disabled as they continually fail but
233 // codec initialisation is fine - which just delays live tv startup.
234 // The worst offender appears to be audio description channel...
235
236 //if (!Stream->codecpar->frame_size && determinable_frame_size(avctx))
237 // FAIL("Unspecified audio frame size");
238 //if (Stream->codecpar->format == AV_SAMPLE_FMT_NONE)
239 // FAIL("Unspecified audio sample format");
240 //if (!Stream->codecpar->sample_rate)
241 // FAIL("Unspecified audio sample rate");
242 //if (!Stream->codecpar->channels)
243 // FAIL("Unspecified number of audio channels");
244 // if (!Stream->internal->nb_decoded_frames && Context->codec_id == AV_CODEC_ID_DTS)
245 // FAIL("No decodable DTS frames");
246 break;
247
248 case AVMEDIA_TYPE_SUBTITLE:
249 if (Stream->codecpar->codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE && !Stream->codecpar->width)
250 FAIL("Unspecified subtitle size");
251 break;
252 case AVMEDIA_TYPE_DATA:
253 if (Stream->codecpar->codec_id == AV_CODEC_ID_NONE)
254 return true;
255 break;
256 default:
257 break;
258 }
259
260 if (Stream->codecpar->codec_id == AV_CODEC_ID_NONE)
261 FAIL("Unknown codec");
262 return true;
263}
264
265static void myth_av_log(void *ptr, int level, const char* fmt, va_list vl)
266{
267 if (VERBOSE_LEVEL_NONE())
268 return;
269
270 static QString s_fullLine("");
271 static QMutex s_stringLock;
272 uint64_t verbose_mask = VB_LIBAV;
273 LogLevel_t verbose_level = LOG_EMERG;
274
275 // determine mythtv debug level from av log level
276 switch (level)
277 {
278 case AV_LOG_PANIC:
279 verbose_level = LOG_EMERG;
280 verbose_mask |= VB_GENERAL;
281 break;
282 case AV_LOG_FATAL:
283 verbose_level = LOG_CRIT;
284 verbose_mask |= VB_GENERAL;
285 break;
286 case AV_LOG_ERROR:
287 verbose_level = LOG_ERR;
288 break;
289 case AV_LOG_WARNING:
290 verbose_level = LOG_WARNING;
291 break;
292 case AV_LOG_INFO:
293 verbose_level = LOG_INFO;
294 break;
295 case AV_LOG_VERBOSE:
296 case AV_LOG_DEBUG:
297 verbose_level = LOG_DEBUG;
298 break;
299 case AV_LOG_TRACE:
300 verbose_level = LOG_TRACE;
301 break;
302 default:
303 return;
304 }
305
306 if (!VERBOSE_LEVEL_CHECK(verbose_mask, verbose_level))
307 return;
308
309 s_stringLock.lock();
310 if (s_fullLine.isEmpty() && ptr) {
311 AVClass* avc = *(AVClass**)ptr;
312 s_fullLine = QString("[%1 @ %2] ")
313 .arg(avc->item_name(ptr))
314 .arg((quintptr)avc, QT_POINTER_SIZE * 2, 16, QChar('0'));
315 }
316
317 s_fullLine += QString::vasprintf(fmt, vl);
318 if (s_fullLine.endsWith("\n"))
319 {
320 LOG(verbose_mask, verbose_level, s_fullLine.trimmed());
321 s_fullLine.truncate(0);
322 }
323 s_stringLock.unlock();
324}
325
326static int get_canonical_lang(const char *lang_cstr)
327{
328 if (lang_cstr[0] == '\0' || lang_cstr[1] == '\0')
329 {
330 return iso639_str3_to_key("und");
331 }
332 if (lang_cstr[2] == '\0')
333 {
334 QString tmp2 = lang_cstr;
335 QString tmp3 = iso639_str2_to_str3(tmp2);
336 int lang = iso639_str3_to_key(tmp3);
337 return iso639_key_to_canonical_key(lang);
338 }
339 int lang = iso639_str3_to_key(lang_cstr);
340 return iso639_key_to_canonical_key(lang);
341}
342
348static const char* AVMediaTypeToString(enum AVMediaType codec_type)
349{
350 switch (codec_type)
351 {
352 case AVMEDIA_TYPE_UNKNOWN: return "Unknown";
353 case AVMEDIA_TYPE_VIDEO: return "Video";
354 case AVMEDIA_TYPE_AUDIO: return "Audio";
355 case AVMEDIA_TYPE_DATA: return "Data";
356 case AVMEDIA_TYPE_SUBTITLE: return "Subtitle";
357 case AVMEDIA_TYPE_ATTACHMENT: return "Attachment";
358 default: return "Invalid Codec Type";
359 }
360}
361
363 const ProgramInfo &pginfo,
364 PlayerFlags flags)
365 : DecoderBase(parent, pginfo),
366 m_isDbIgnored(gCoreContext->IsDatabaseIgnored()),
367 m_avcParser(new AVCParser()),
368 m_playerFlags(flags),
369 // Closed Caption & Teletext decoders
370 m_ccd608(new CC608Decoder(parent->GetCC608Reader())),
371 m_ccd708(new CC708Decoder(parent->GetCC708Reader())),
372 m_ttd(new TeletextDecoder(parent->GetTeletextReader())),
373 m_itv(parent->GetInteractiveTV()),
374 m_audioSamples((uint8_t *)av_mallocz(AudioOutput::kMaxSizeBuffer))
375{
376 // this will be deleted and recreated once decoder is set up
378
380
381 av_log_set_callback(myth_av_log);
382
383 m_audioIn.m_sampleSize = -32;// force SetupAudioStream to run once
384
386 m_audioReadAhead = gCoreContext->GetDurSetting<std::chrono::milliseconds>("AudioReadAhead", 100ms);
387
388 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PlayerFlags: 0x%1, AudioReadAhead: %2 msec")
389 .arg(m_playerFlags, 0, 16).arg(m_audioReadAhead.count()));
390}
391
393{
394 while (!m_storedPackets.isEmpty())
395 {
396 AVPacket *pkt = m_storedPackets.takeFirst();
397 av_packet_free(&pkt);
398 }
399
400 CloseContext();
401 delete m_ccd608;
402 delete m_ccd708;
403 delete m_ttd;
404 delete m_avcParser;
405 delete m_mythCodecCtx;
406
407 sws_freeContext(m_swsCtx);
408
409 av_freep(reinterpret_cast<void*>(&m_audioSamples));
410
411 delete m_avfRingBuffer;
412
413 if (LCD *lcd = LCD::Get())
414 {
415 lcd->setAudioFormatLEDs(AUDIO_AC3, false);
416 lcd->setVideoFormatLEDs(VIDEO_MPG, false);
417 lcd->setVariousLEDs(VARIOUS_HDTV, false);
418 lcd->setVariousLEDs(VARIOUS_SPDIF, false);
419 lcd->setSpeakerLEDs(SPEAKER_71, false); // should clear any and all speaker LEDs
420 }
421}
422
424{
425 return &m_codecMap;
426}
427
429{
430 if (m_ic)
431 {
432 m_avCodecLock.lock();
433 for (uint i = 0; i < m_ic->nb_streams; i++)
434 {
435 AVStream *st = m_ic->streams[i];
437 }
438 m_avCodecLock.unlock();
439 }
440}
441
443{
444 if (m_ic)
445 {
446 CloseCodecs();
447
448 delete m_avfRingBuffer;
449 m_avfRingBuffer = nullptr;
450 m_ic->pb = nullptr;
451 avformat_close_input(&m_ic);
452 m_ic = nullptr;
453 }
455}
456
457static int64_t lsb3full(int64_t lsb, int64_t base_ts, int lsb_bits)
458{
459 int64_t mask = (lsb_bits < 64) ? (1LL<<lsb_bits)-1 : -1LL;
460 return ((lsb - base_ts)&mask);
461}
462
463std::chrono::milliseconds AvFormatDecoder::NormalizeVideoTimecode(std::chrono::milliseconds timecode)
464{
465 int64_t start_pts = 0;
466
467 AVStream *st = nullptr;
468 for (uint i = 0; i < m_ic->nb_streams; i++)
469 {
470 AVStream *st1 = m_ic->streams[i];
471 if (st1 && st1->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
472 {
473 st = st1;
474 break;
475 }
476 }
477 if (!st)
478 return 0ms;
479
480 if (m_ic->start_time != AV_NOPTS_VALUE)
481 {
482 start_pts = av_rescale(m_ic->start_time,
483 st->time_base.den,
484 AV_TIME_BASE * (int64_t)st->time_base.num);
485 }
486
487 int64_t pts = av_rescale(timecode.count() / 1000.0,
488 st->time_base.den,
489 st->time_base.num);
490
491 // adjust for start time and wrap
492 pts = lsb3full(pts, start_pts, st->pts_wrap_bits);
493
494 return millisecondsFromFloat(av_q2d(st->time_base) * pts * 1000);
495}
496
497std::chrono::milliseconds AvFormatDecoder::NormalizeVideoTimecode(AVStream *st,
498 std::chrono::milliseconds timecode)
499{
500 int64_t start_pts = 0;
501
502 if (m_ic->start_time != AV_NOPTS_VALUE)
503 {
504 start_pts = av_rescale(m_ic->start_time,
505 st->time_base.den,
506 AV_TIME_BASE * (int64_t)st->time_base.num);
507 }
508
509 int64_t pts = av_rescale(timecode.count() / 1000.0,
510 st->time_base.den,
511 st->time_base.num);
512
513 // adjust for start time and wrap
514 pts = lsb3full(pts, start_pts, st->pts_wrap_bits);
515
516 return millisecondsFromFloat(av_q2d(st->time_base) * pts * 1000);
517}
518
520{
521 if (m_ic && m_ic->nb_chapters > 1)
522 return m_ic->nb_chapters;
523 return 0;
524}
525
526void AvFormatDecoder::GetChapterTimes(QList<std::chrono::seconds> &times)
527{
528 int total = GetNumChapters();
529 if (!total)
530 return;
531
532 for (int i = 0; i < total; i++)
533 {
534 int num = m_ic->chapters[i]->time_base.num;
535 int den = m_ic->chapters[i]->time_base.den;
536 int64_t start = m_ic->chapters[i]->start;
537 long double total_secs = (long double)start * (long double)num /
538 (long double)den;
539 times.push_back(std::chrono::seconds((long long)total_secs));
540 }
541}
542
543int AvFormatDecoder::GetCurrentChapter(long long framesPlayed)
544{
545 if (!GetNumChapters())
546 return 0;
547
548 for (int i = (m_ic->nb_chapters - 1); i > -1 ; i--)
549 {
550 int num = m_ic->chapters[i]->time_base.num;
551 int den = m_ic->chapters[i]->time_base.den;
552 int64_t start = m_ic->chapters[i]->start;
553 long double total_secs = (long double)start * (long double)num /
554 (long double)den;
555 auto framenum = (long long)(total_secs * m_fps);
556 if (framesPlayed >= framenum)
557 {
558 LOG(VB_PLAYBACK, LOG_INFO, LOC +
559 QString("GetCurrentChapter(selected chapter %1 framenum %2)")
560 .arg(i + 1).arg(framenum));
561 return i + 1;
562 }
563 }
564 return 0;
565}
566
567long long AvFormatDecoder::GetChapter(int chapter)
568{
569 if (chapter < 1 || chapter > GetNumChapters())
570 return -1;
571
572 int num = m_ic->chapters[chapter - 1]->time_base.num;
573 int den = m_ic->chapters[chapter - 1]->time_base.den;
574 int64_t start = m_ic->chapters[chapter - 1]->start;
575 long double total_secs = (long double)start * (long double)num /
576 (long double)den;
577 auto framenum = (long long)(total_secs * m_fps);
578 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("GetChapter %1: framenum %2")
579 .arg(chapter).arg(framenum));
580 return framenum;
581}
582
583bool AvFormatDecoder::DoRewind(long long desiredFrame, bool discardFrames)
584{
585 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DoRewind(%1, %2 discard frames)")
586 .arg(desiredFrame).arg( discardFrames ? "do" : "don't" ));
587
589 return DecoderBase::DoRewind(desiredFrame, discardFrames);
590
591 // avformat-based seeking
592 return do_av_seek(desiredFrame, discardFrames, AVSEEK_FLAG_BACKWARD);
593}
594
595bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames)
596{
597 LOG(VB_PLAYBACK, LOG_INFO, LOC +
598 QString("DoFastForward(%1 (%2), %3 discard frames)")
599 .arg(desiredFrame).arg(m_framesPlayed)
600 .arg((discardFrames) ? "do" : "don't"));
601
603 return DecoderBase::DoFastForward(desiredFrame, discardFrames);
604
605 int seekDelta = desiredFrame - m_framesPlayed;
606
607 // avoid using av_frame_seek if we are seeking frame-by-frame when paused
608 if (seekDelta >= 0 && seekDelta < 2 && m_parent->GetPlaySpeed() == 0.0F)
609 {
610 SeekReset(m_framesPlayed, seekDelta, false, true);
612 return true;
613 }
614 return do_av_seek(desiredFrame, discardFrames, 0);
615}
616
617bool AvFormatDecoder::do_av_seek(long long desiredFrame, bool discardFrames, int flags)
618{
619 long long ts = 0;
620 if (m_ic->start_time != AV_NOPTS_VALUE)
621 ts = m_ic->start_time;
622
623 // convert framenumber to normalized timestamp
624 long double seekts = desiredFrame * AV_TIME_BASE / m_fps;
625 ts += (long long)seekts;
626
627 // XXX figure out how to do snapping in this case
628 bool exactseeks = DecoderBase::GetSeekSnap() == 0U;
629
630 if (exactseeks)
631 {
632 flags |= AVSEEK_FLAG_BACKWARD;
633 }
634
635 int ret = av_seek_frame(m_ic, -1, ts, flags);
636 if (ret < 0)
637 {
638 LOG(VB_GENERAL, LOG_ERR, LOC +
639 QString("av_seek_frame(m_ic, -1, %1, 0b%2) error: %3").arg(
640 QString::number(ts),
641 QString::number(flags, 2),
642 QString::fromStdString(av_make_error_stdstring(ret))
643 )
644 );
645 return false;
646 }
647 if (auto* reader = m_parent->GetSubReader(); reader)
648 reader->SeekFrame(ts, flags);
649
650 int normalframes = 0;
651
652 {
653 m_framesPlayed = desiredFrame;
654 m_fpsSkip = 0;
655 m_framesRead = desiredFrame;
656 normalframes = 0;
657 }
658
659 SeekReset(m_lastKey, normalframes, true, discardFrames);
660
661 if (discardFrames)
663
664 return true;
665}
666
667void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames,
668 bool doflush, bool discardFrames)
669{
670 if (!m_ringBuffer)
671 return; // nothing to reset...
672
673 LOG(VB_PLAYBACK, LOG_INFO, LOC +
674 QString("SeekReset(%1, %2, %3 flush, %4 discard)")
675 .arg(newKey).arg(skipFrames)
676 .arg((doflush) ? "do" : "don't",
677 (discardFrames) ? "do" : "don't"));
678
679 DecoderBase::SeekReset(newKey, skipFrames, doflush, discardFrames);
680
681 QMutexLocker locker(&m_avCodecLock);
682
683 // Discard all the queued up decoded frames
684 if (discardFrames)
685 {
686 bool releaseall = m_mythCodecCtx ? (m_mythCodecCtx->DecoderWillResetOnFlush() ||
687 m_mythCodecCtx->DecoderNeedsReset(nullptr)) : false;
688 m_parent->DiscardVideoFrames(doflush, doflush && releaseall);
689 }
690
691 if (doflush)
692 {
693 m_lastAPts = 0ms;
694 m_lastVPts = 0ms;
695 m_lastCcPtsu = 0us;
696
697 avformat_flush(m_ic);
698
699 // Only reset the internal state if we're using our seeking,
700 // not when using libavformat's seeking
702 {
703 m_ic->pb->pos = m_ringBuffer->GetReadPosition();
704 m_ic->pb->buf_ptr = m_ic->pb->buffer;
705 m_ic->pb->buf_end = m_ic->pb->buffer;
706 m_ic->pb->eof_reached = 0;
707 }
708
709 // Flush the avcodec buffers
710 LOG(VB_PLAYBACK, LOG_INFO, LOC + "SeekReset() flushing");
711 for (uint i = 0; i < m_ic->nb_streams; i++)
712 {
713 AVCodecContext *codecContext = m_codecMap.FindCodecContext(m_ic->streams[i]);
714 // note that contexts that have not been opened have
715 // codecContext->internal = nullptr and cause a segfault in
716 // avcodec_flush_buffers
717 if (codecContext && codecContext->internal)
718 avcodec_flush_buffers(codecContext);
719 }
720
721 // Free up the stored up packets
722 while (!m_storedPackets.isEmpty())
723 {
724 AVPacket *pkt = m_storedPackets.takeFirst();
725 av_packet_free(&pkt);
726 }
727
728 m_prevGopPos = 0;
729 m_gopSet = false;
730 }
731
732 // Skip all the desired number of skipFrames
733
734 // Some seeks can be very slow. The most common example comes
735 // from HD-PVR recordings, where keyframes are 128 frames apart
736 // and decoding (even hardware decoding) may not be much faster
737 // than realtime, causing some exact seeks to take 2-4 seconds.
738 // If exact seeking is not required, we take some shortcuts.
739 // First, we impose an absolute maximum time we are willing to
740 // spend (maxSeekTimeMs) on the forward frame-by-frame skip.
741 // After that much time has elapsed, we give up and stop the
742 // frame-by-frame seeking. Second, after skipping a few frames,
743 // we predict whether the situation is hopeless, i.e. the total
744 // skipping would take longer than giveUpPredictionMs, and if so,
745 // stop skipping right away.
746 bool exactSeeks = GetSeekSnap() == 0U;
747 static constexpr std::chrono::milliseconds maxSeekTimeMs { 200ms };
748 int profileFrames = 0;
750 for (; (skipFrames > 0 && !m_atEof &&
751 (exactSeeks || begin.elapsed() < maxSeekTimeMs));
752 --skipFrames, ++profileFrames)
753 {
754 // TODO this won't work well in conjunction with the MythTimer
755 // above...
756 QElapsedTimer getframetimer;
757 getframetimer.start();
758 bool retry = true;
759 while (retry && !getframetimer.hasExpired(100))
760 {
761 retry = false;
762 GetFrame(kDecodeVideo, retry);
763 if (retry)
764 std::this_thread::sleep_for(1ms);
765 }
766
768 {
770 m_decodedVideoFrame = nullptr;
771 }
772 if (!exactSeeks && profileFrames >= 5 && profileFrames < 10)
773 {
774 const int giveUpPredictionMs = 400;
775 int remainingTimeMs =
776 skipFrames * (float)begin.elapsed().count() / profileFrames;
777 if (remainingTimeMs > giveUpPredictionMs)
778 {
779 LOG(VB_PLAYBACK, LOG_DEBUG,
780 QString("Frame-by-frame seeking would take "
781 "%1 ms to finish, skipping.").arg(remainingTimeMs));
782 break;
783 }
784 }
785 }
786
787 if (doflush)
788 {
789 m_firstVPts = 0ms;
790 m_firstVPtsInuse = true;
791 }
792}
793
795{
796 if (!eof && m_ic && m_ic->pb)
797 {
798 LOG(VB_GENERAL, LOG_NOTICE, LOC +
799 QString("Resetting byte context eof (livetv %1 was eof %2)")
800 .arg(m_livetv).arg(m_ic->pb->eof_reached));
801 m_ic->pb->eof_reached = 0;
802 }
804}
805
806void AvFormatDecoder::Reset(bool reset_video_data, bool seek_reset,
807 bool reset_file)
808{
809 LOG(VB_PLAYBACK, LOG_INFO, LOC +
810 QString("Reset: Video %1, Seek %2, File %3")
811 .arg(reset_video_data).arg(seek_reset).arg(reset_file));
812
813 if (seek_reset)
814 SeekReset(0, 0, true, false);
815
816 DecoderBase::Reset(reset_video_data, false, reset_file);
817
818 if (reset_video_data)
819 {
820 m_seenGop = false;
821 m_seqCount = 0;
822 }
823}
824
825bool AvFormatDecoder::CanHandle(TestBufferVec & testbuf, const QString &filename)
826{
827 AVProbeData probe;
828 memset(&probe, 0, sizeof(AVProbeData));
829
830 QByteArray fname = filename.toLatin1();
831 probe.filename = fname.constData();
832 probe.buf = (unsigned char *)testbuf.data();
833 probe.buf_size = testbuf.size();
834
835 int score = AVPROBE_SCORE_MAX/4;
836
837 if (testbuf.size() + AVPROBE_PADDING_SIZE > kDecoderProbeBufferSize)
838 {
839 probe.buf_size = kDecoderProbeBufferSize - AVPROBE_PADDING_SIZE;
840 score = 0;
841 }
842 else if (testbuf.size()*2 >= kDecoderProbeBufferSize)
843 {
844 score--;
845 }
846
847 memset(probe.buf + probe.buf_size, 0, AVPROBE_PADDING_SIZE);
848
849 return av_probe_input_format2(&probe, static_cast<int>(true), &score) != nullptr;
850}
851
852void AvFormatDecoder::streams_changed(void *data, int avprogram_id)
853{
854 auto *decoder = reinterpret_cast<AvFormatDecoder*>(data);
855
856 int cnt = decoder->m_ic->nb_streams;
857
858 LOG(VB_PLAYBACK, LOG_INFO, LOC +
859 QString("streams_changed 0x%1 -- program_number %2 stream count %3")
860 .arg((uint64_t)data,0,16).arg(QString::number(avprogram_id), QString::number(cnt)));
861
862 auto* program = decoder->get_current_AVProgram();
863 if (program != nullptr && program->id != avprogram_id)
864 {
865 return;
866 }
867 decoder->m_streamsChanged = true;
868}
869
870extern "C"
871{
872 static void HandleStreamChange(void *data, int avprogram_id)
873 {
874 AvFormatDecoder::streams_changed(data, avprogram_id);
875 }
876}
877
893 TestBufferVec & testbuf)
894{
895 CloseContext();
896
898
899 // Process frames immediately unless we're decoding
900 // a DVD, in which case don't so that we don't show
901 // anything whilst probing the data streams.
903
904 const AVInputFormat *fmt = nullptr;
905 QString fnames = m_ringBuffer->GetFilename();
906 QByteArray fnamea = fnames.toLatin1();
907 const char *filename = fnamea.constData();
908
909 AVProbeData probe;
910 memset(&probe, 0, sizeof(AVProbeData));
911 probe.filename = filename;
912 probe.buf = reinterpret_cast<unsigned char *>(testbuf.data());
913 if (testbuf.size() + AVPROBE_PADDING_SIZE <= kDecoderProbeBufferSize)
914 probe.buf_size = testbuf.size();
915 else
916 probe.buf_size = kDecoderProbeBufferSize - AVPROBE_PADDING_SIZE;
917 memset(probe.buf + probe.buf_size, 0, AVPROBE_PADDING_SIZE);
918
919 fmt = av_probe_input_format(&probe, static_cast<int>(true));
920 if (!fmt)
921 {
922 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Probe failed for '%1'").arg(filename));
923 return -1;
924 }
925
926 if (strcmp(fmt->name, "mpegts") == 0 &&
927 gCoreContext->GetBoolSetting("FFMPEGTS", false))
928 {
929 const AVInputFormat *fmt2 = av_find_input_format("mpegts-ffmpeg");
930 if (fmt2)
931 {
932 fmt = fmt2;
933 LOG(VB_GENERAL, LOG_INFO, LOC + "Using FFmpeg MPEG-TS demuxer (forced)");
934 }
935 }
936
937 int err = 0;
938 bool scancomplete = false;
939 int remainingscans = 5;
940
941 while (!scancomplete && remainingscans--)
942 {
943 bool found = false;
944
945 // With live tv, the ringbufer may contain insufficient data for complete
946 // initialisation so we try a few times with a slight pause each time to
947 // allow extra data to become available. In the worst case scenarios, the
948 // stream may not have a keyframe for 4-5 seconds.
949 // As a last resort, we will try and fallback to the original FFmpeg MPEG-TS
950 // demuxer if it is not already used.
951 // For regular videos, this shouldn't be an issue as the complete file
952 // should be available - though we try a little harder for streamed formats
953 int retries = m_livetv || m_ringBuffer->IsStreamed() ? 50 : 10;
954
955 while (!found && --retries)
956 {
957 m_ic = avformat_alloc_context();
958 if (!m_ic)
959 {
960 LOG(VB_GENERAL, LOG_ERR, LOC + "Could not allocate format context.");
961 return -1;
962 }
963
964 delete m_avfRingBuffer;
967 LOG(VB_PLAYBACK, LOG_INFO, LOC +
968 QString("Buffer size: %1 Streamed %2 Seekable %3 Available %4")
970 .arg(m_ringBuffer->IsStreamed())
971 .arg(m_ic->pb->seekable)
974
975 err = avformat_open_input(&m_ic, filename, fmt, nullptr);
976 if (err < 0)
977 {
978 std::string error;
979 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Failed to open input ('%1')")
980 .arg(av_make_error_stdstring(error, err)));
981
982 // note - m_ic (AVFormatContext) is freed on failure
983 if (retries > 2)
984 {
985 // wait a little to buffer more data
986 // 50*0.1 = 5 seconds max
987 QThread::usleep(100000);
988 // resets the read position
990 continue;
991 }
992
993 if (strcmp(fmt->name, "mpegts") == 0)
994 {
995 fmt = av_find_input_format("mpegts-ffmpeg");
996 if (fmt)
997 {
998 LOG(VB_GENERAL, LOG_ERR, LOC + "Attempting to use original FFmpeg MPEG-TS demuxer.");
999 // resets the read position
1000 m_avfRingBuffer->SetInInit(false);
1001 continue;
1002 }
1003 break;
1004 }
1005 }
1006 found = true;
1007 }
1008
1009 if (err < 0)
1010 {
1011 LOG(VB_GENERAL, LOG_ERR, LOC + "Fatal error opening input. Aborting");
1012 m_ic = nullptr;
1013 return -1;
1014 }
1015
1016 // With certain streams, we don't get a complete stream analysis and the video
1017 // codec/frame format is not fully detected. This can have various consequences - from
1018 // failed playback to not enabling hardware decoding (as the frame formt is not valid).
1019 // Bump the duration (FFmpeg defaults to 5 seconds) to 60 seconds. This should
1020 // not impact performance as in the vast majority of cases the scan is completed
1021 // within a second or two (seconds in this case referring to stream duration - not the time
1022 // it takes to complete the scan).
1023 m_ic->max_analyze_duration = 60LL * AV_TIME_BASE;
1024
1026 m_avCodecLock.lock();
1027 err = avformat_find_stream_info(m_ic, nullptr);
1028 m_avCodecLock.unlock();
1029 if (err < 0)
1030 {
1031 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Could not find codec parameters for '%1'").arg(filename));
1032 CloseContext();
1033 return -1;
1034 }
1035 m_avfRingBuffer->SetInInit(false);
1036
1037 // final sanity check that scanned streams are valid for live tv
1038 scancomplete = true;
1039 for (uint i = 0; m_livetv && (i < m_ic->nb_streams); i++)
1040 {
1041 if (!StreamHasRequiredParameters(m_codecMap.GetCodecContext(m_ic->streams[i]), m_ic->streams[i]))
1042 {
1043 scancomplete = false;
1044 if (remainingscans)
1045 {
1046 CloseContext();
1047 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Stream scan incomplete - retrying");
1048 QThread::usleep(250000); // wait 250ms
1049 }
1050 break;
1051 }
1052 }
1053 }
1054
1055 if (!scancomplete)
1056 LOG(VB_GENERAL, LOG_WARNING, LOC + "Scan incomplete - playback may not work");
1057
1058 m_ic->streams_changed = HandleStreamChange;
1059 m_ic->stream_change_data = this;
1060
1061 if (!m_livetv && !m_ringBuffer->IsDisc())
1062 {
1063 // generate timings based on the video stream to avoid bogus ffmpeg
1064 // values for duration and bitrate
1066 }
1067
1068 // FLAC, MP3 or M4A file may contains an artwork image, a single frame MJPEG,
1069 // we need to ignore it as we don't handle single frames or images in place of video
1070 // TODO: display single frame
1071 QString extension = QFileInfo(fnames).suffix();
1072 if (strcmp(fmt->name, "mp3") == 0 || strcmp(fmt->name, "flac") == 0 ||
1073 strcmp(fmt->name, "ogg") == 0 ||
1074 (extension.compare("m4a", Qt::CaseInsensitive) == 0))
1075 {
1076 novideo = true;
1077 }
1078
1079 // Scan for the initial A/V streams
1080 err = ScanStreams(novideo);
1081 if (-1 == err)
1082 {
1083 CloseContext();
1084 return err;
1085 }
1086
1087#if CONFIG_MHEG
1088 {
1089 int initialAudio = -1;
1090 int initialVideo = -1;
1091 if (m_itv == nullptr)
1093 if (m_itv != nullptr)
1094 m_itv->GetInitialStreams(initialAudio, initialVideo);
1095 if (initialAudio >= 0)
1096 SetAudioByComponentTag(initialAudio);
1097 if (initialVideo >= 0)
1098 SetVideoByComponentTag(initialVideo);
1099 }
1100#endif // CONFIG_MHEG
1101
1102 // Try to get a position map from the recorder if we don't have one yet.
1104 {
1106 {
1109 {
1110 m_hasFullPositionMap = true;
1111 m_gopSet = true;
1112 }
1113 }
1114 }
1115
1116 // If watching pre-recorded television or video use the marked duration
1117 // from the db if it exists, else ffmpeg duration
1118 std::chrono::seconds dur = 0s;
1119
1120 if (m_playbackInfo)
1121 {
1122 dur = duration_cast<std::chrono::seconds>(m_playbackInfo->QueryTotalDuration());
1123 }
1124
1125 if (dur == 0s)
1126 {
1127 dur = duration_cast<std::chrono::seconds>(av_duration(m_ic->duration));
1128 }
1129
1130 if (dur > 0s && !m_livetv && !m_watchingRecording)
1131 {
1132 m_parent->SetDuration(dur);
1133 }
1134
1135 // If we don't have a position map, set up ffmpeg for seeking
1137 {
1138 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1139 "Recording has no position -- using libavformat seeking.");
1140
1141 if (dur > 0s)
1142 {
1143 m_parent->SetFileLength(dur, (int)(dur.count() * m_fps));
1144 }
1145 else
1146 {
1147 // the pvr-250 seems to over report the bitrate by * 2
1148 float bytespersec = (float)m_bitrate / 8 / 2;
1149 float secs = m_ringBuffer->GetRealFileSize() * 1.0F / bytespersec;
1151 (int)(secs * static_cast<float>(m_fps)));
1152 }
1153
1154 // we will not see a position map from db or remote encoder,
1155 // set the gop interval to 15 frames. if we guess wrong, the
1156 // auto detection will change it.
1157 m_keyframeDist = 15;
1159
1160 if (strcmp(fmt->name, "avi") == 0)
1161 {
1162 // avi keyframes are too irregular
1163 m_keyframeDist = 1;
1164 }
1165
1166 m_dontSyncPositionMap = true;
1167 }
1168
1169 av_dump_format(m_ic, 0, filename, 0);
1170
1171 // print some useful information if playback debugging is on
1173 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Position map found");
1175 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Partial position map found");
1176 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1177 QString("Successfully opened decoder for file: \"%1\". novideo(%2)")
1178 .arg(filename).arg(novideo));
1179
1180 // Print AVChapter information
1181 for (unsigned int i=0; i < m_ic->nb_chapters; i++)
1182 {
1183 int num = m_ic->chapters[i]->time_base.num;
1184 int den = m_ic->chapters[i]->time_base.den;
1185 int64_t start = m_ic->chapters[i]->start;
1186 auto total_secs = static_cast<long double>(start) * static_cast<long double>(num) /
1187 static_cast<long double>(den);
1188 auto msec = millisecondsFromFloat(total_secs * 1000);
1189 auto framenum = static_cast<long long>(total_secs * static_cast<long double>(m_fps));
1190 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1191 QString("Chapter %1 found @ [%2]->%3")
1193 MythDate::formatTime(msec, "HH:mm:ss.zzz"),
1194 QString::number(framenum)));
1195 }
1196
1197 if (m_ringBuffer->IsDVD())
1198 {
1199 // Reset DVD playback and clear any of
1200 // our buffers so that none of the data
1201 // parsed so far to determine decoders
1202 // gets shown.
1204 return -1;
1206
1207 Reset(true, true, true);
1208
1209 // Now we're ready to process and show frames
1210 m_processFrames = true;
1211 }
1212
1213
1214 // Return true if recording has position map
1215 return static_cast<int>(m_recordingHasPositionMap);
1216}
1217
1218float AvFormatDecoder::GetVideoFrameRate(AVStream *Stream, AVCodecContext *Context, bool Sanitise)
1219{
1220 // MKV default_duration
1221 double avg_fps = (Stream->avg_frame_rate.den == 0) ? 0.0 : av_q2d(Stream->avg_frame_rate);
1222 double codec_fps = av_q2d(Context->framerate); // {0, 1} when unknown
1223 double container_fps = (Stream->time_base.num == 0) ? 0.0 : av_q2d(av_inv_q(Stream->time_base));
1224 // least common multiple of all framerates in a stream; this is a guess
1225 double estimated_fps = (Stream->r_frame_rate.den == 0) ? 0.0 : av_q2d(Stream->r_frame_rate);
1226
1227 // build a list of possible rates, best first
1228 std::vector<double> rates;
1229 rates.reserve(7);
1230
1231 // matroska demuxer sets the default_duration to avg_frame_rate
1232 // mov,mp4,m4a,3gp,3g2,mj2 demuxer sets avg_frame_rate
1233 if (QString(m_ic->iformat->name).contains("matroska") ||
1234 QString(m_ic->iformat->name).contains("mov"))
1235 {
1236 rates.emplace_back(avg_fps);
1237 }
1238
1239 // avi uses container fps for timestamps
1240 if (QString(m_ic->iformat->name).contains("avi"))
1241 {
1242 rates.emplace_back(container_fps);
1243 }
1244
1245 rates.emplace_back(codec_fps);
1246 rates.emplace_back(container_fps);
1247 rates.emplace_back(avg_fps);
1248 // certain H.264 interlaced streams are detected at 2x using estimated (i.e. wrong)
1249 rates.emplace_back(estimated_fps);
1250 // last resort, default to NTSC
1251 rates.emplace_back(30000.0 / 1001.0);
1252
1253 auto invalid_fps = [](double rate) { return rate < 3.0 || rate > 121.0; };
1254 rates.erase(std::remove_if(rates.begin(), rates.end(), invalid_fps), rates.end());
1255
1256 auto FuzzyEquals = [](double First, double Second) { return std::abs(First - Second) < 0.03; };
1257
1258 // debug
1259 if (!FuzzyEquals(rates.front(), m_fps))
1260 {
1261 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1262 QString("Selected FPS: %1 (Avg:%2 Mult:%3 Codec:%4 Container:%5 Estimated:%6)")
1263 .arg(static_cast<double>(rates.front())).arg(avg_fps)
1264 .arg(m_fpsMultiplier).arg(codec_fps).arg(container_fps).arg(estimated_fps));
1265 }
1266
1267 auto IsStandard = [&FuzzyEquals](double Rate)
1268 {
1269 // List of known, standards based frame rates
1270 static const std::set<double> k_standard_rates =
1271 {
1272 24000.0 / 1001.0,
1273 23.976,
1274 24.0,
1275 25.0,
1276 30000.0 / 1001.0,
1277 29.97,
1278 30.0,
1279 50.0,
1280 60000.0 / 1001.0,
1281 59.94,
1282 60.0,
1283 100.0,
1284 120000.0 / 1001.0,
1285 119.88,
1286 120.0
1287 };
1288
1289 if (Rate > 23.0 && Rate < 121.0)
1290 {
1291 for (auto standard_rate : k_standard_rates)
1292 if (FuzzyEquals(Rate, standard_rate))
1293 return true;
1294 }
1295 return false;
1296 // TODO do not convert AVRational to double
1297 //return k_standard_rates.find(rate) != k_standard_rates.end();
1298 };
1299
1300 // If the first choice rate is unusual, see if there is something more 'usual'
1301 double detected = rates.front();
1302 if (Sanitise && !IsStandard(detected))
1303 {
1304 for (auto rate : rates)
1305 {
1306 if (IsStandard(rate))
1307 {
1308 LOG(VB_GENERAL, LOG_INFO, LOC + QString("%1 is non-standard - using %2 instead.")
1309 .arg(rates.front()).arg(rate));
1310
1311 // The most common problem here is mpegts files where the average
1312 // rate is slightly out and the estimated rate is the fallback.
1313 // As noted above, however, the estimated rate is sometimes twice
1314 // the actual for interlaced content. Try and detect and fix this
1315 // so that we don't throw out deinterlacing and video mode switching.
1316 // Assume anything under 30 may be interlaced - with +-10% error.
1317 if (rate > 33.0 && detected < 33.0)
1318 {
1319 double half = rate / 2.0;
1320 if (std::abs(half - detected) < (half * 0.1))
1321 {
1322 LOG(VB_GENERAL, LOG_INFO, LOC +
1323 QString("Assuming %1 is a better choice than %2")
1324 .arg(half).arg(rate));
1325 return static_cast<float>(half);
1326 }
1327 }
1328 return static_cast<float>(rate);
1329 }
1330 }
1331 }
1332
1333 return static_cast<float>(detected);
1334}
1335
1336int AvFormatDecoder::GetMaxReferenceFrames(AVCodecContext *Context)
1337{
1338 switch (Context->codec_id)
1339 {
1340 case AV_CODEC_ID_H264:
1341 {
1342 int result = 16;
1343 if (Context->extradata && (Context->extradata_size >= 7))
1344 {
1345 uint8_t offset = 0;
1346 if (Context->extradata[0] == 1)
1347 offset = 9; // avCC
1348 else if (AV_RB24(Context->extradata) == 0x01) // Annex B - 3 byte startcode 0x000001
1349 offset = 4;
1350 else if (AV_RB32(Context->extradata) == 0x01) // Annex B - 4 byte startcode 0x00000001
1351 offset= 5;
1352
1353 if (offset)
1354 {
1356 bool dummy = false;
1357 parser.parse_SPS(Context->extradata + offset,
1358 static_cast<uint>(Context->extradata_size - offset), dummy, result);
1359 }
1360 }
1361 return result;
1362 }
1363 case AV_CODEC_ID_H265: return 16;
1364 case AV_CODEC_ID_VP9: return 8;
1365 case AV_CODEC_ID_VP8: return 3;
1366 default: return 2;
1367 }
1368}
1369
1370void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *codecContext,
1371 bool selectedStream)
1372{
1373 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1374 QString("InitVideoCodec ID:%1 Type:%2 Size:%3x%4")
1375 .arg(avcodec_get_name(codecContext->codec_id),
1376 AVMediaTypeToString(codecContext->codec_type))
1377 .arg(codecContext->width).arg(codecContext->height));
1378
1380 m_directRendering = false;
1381
1382 codecContext->opaque = static_cast<void*>(this);
1383 codecContext->get_buffer2 = get_avf_buffer;
1384 codecContext->slice_flags = 0;
1385
1386 codecContext->err_recognition = AV_EF_COMPLIANT;
1387 codecContext->workaround_bugs = FF_BUG_AUTODETECT;
1388 codecContext->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
1389 codecContext->idct_algo = FF_IDCT_AUTO;
1390 codecContext->debug = 0;
1391 // codecContext->error_rate = 0;
1392
1393 const AVCodec *codec1 = codecContext->codec;
1394
1395 if (selectedStream)
1396 m_directRendering = true;
1397
1398 // retrieve rotation information
1399 const AVPacketSideData *sd = av_packet_side_data_get(stream->codecpar->coded_side_data,
1400 stream->codecpar->nb_coded_side_data, AV_PKT_DATA_DISPLAYMATRIX);
1401 if (sd)
1402 m_videoRotation = static_cast<int>(-av_display_rotation_get(reinterpret_cast<int32_t*>(sd->data)));
1403 else
1404 m_videoRotation = 0;
1405
1406 // retrieve 3D type
1407 sd = av_packet_side_data_get(stream->codecpar->coded_side_data,
1408 stream->codecpar->nb_coded_side_data, AV_PKT_DATA_STEREO3D);
1409 if (sd)
1410 {
1411 auto * avstereo = reinterpret_cast<AVStereo3D*>(sd->data);
1412 m_stereo3D = avstereo->type;
1413 }
1414
1415 delete m_mythCodecCtx;
1417 m_mythCodecCtx->InitVideoCodec(codecContext, selectedStream, m_directRendering);
1418 if (m_mythCodecCtx->HwDecoderInit(codecContext) < 0)
1419 {
1420 // force it to switch to software decoding
1422 m_streamsChanged = true;
1423 }
1424 else
1425 {
1426 // Note: This is never going to work as expected in all circumstances.
1427 // It will not account for changes in the stream and/or display. For
1428 // MediaCodec, Android will do its own thing (and judging by the Android logs,
1429 // shouldn't double rate the deinterlacing if the display cannot support it).
1430 // NVDEC will probably move to the FFmpeg YADIF CUDA deinterlacer - which
1431 // will avoid the issue (video player deinterlacing) and maybe disable
1432 // decoder VAAPI deinterlacing. If we get it wrong and the display cannot
1433 // keep up, the player should just drop frames.
1434
1435 // FIXME - need a better way to handle this
1436 bool doublerate = true;//m_parent->CanSupportDoubleRate();
1437 m_mythCodecCtx->SetDeinterlacing(codecContext, &m_videoDisplayProfile, doublerate);
1438 }
1439
1440 if (codec1 && ((AV_CODEC_ID_MPEG2VIDEO == codec1->id) ||
1441 (AV_CODEC_ID_MPEG1VIDEO == codec1->id)))
1442 {
1444 {
1445 int total_blocks = (codecContext->height + 15) / 16;
1446 codecContext->skip_top = (total_blocks + 3) / 4;
1447 codecContext->skip_bottom = (total_blocks + 3) / 4;
1448 }
1449
1451 codecContext->lowres = 2; // 1 = 1/2 size, 2 = 1/4 size
1452 }
1453 else if (codec1 && (AV_CODEC_ID_H264 == codec1->id) && FlagIsSet(kDecodeNoLoopFilter))
1454 {
1455 codecContext->flags &= ~AV_CODEC_FLAG_LOOP_FILTER;
1456 codecContext->skip_loop_filter = AVDISCARD_ALL;
1457 }
1458
1460 codecContext->skip_idct = AVDISCARD_ALL;
1461
1462 if (selectedStream)
1463 {
1464 // m_fps is now set 'correctly' in ScanStreams so this additional call
1465 // to GetVideoFrameRate may now be redundant
1466 m_fps = GetVideoFrameRate(stream, codecContext, true);
1467 QSize dim = get_video_dim(*codecContext);
1468 int width = m_currentWidth = dim.width();
1469 int height = m_currentHeight = dim.height();
1470 m_currentAspect = get_aspect(*codecContext);
1471
1472 if (!width || !height)
1473 {
1474 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1475 "InitVideoCodec invalid dimensions, resetting decoder.");
1476 width = 640;
1477 height = 480;
1478 m_fps = 29.97F;
1479 m_currentAspect = 4.0F / 3.0F;
1480 }
1481
1483 const AVCodec *codec2 = codecContext->codec;
1484 QString codecName;
1485 if (codec2)
1486 codecName = codec2->name;
1487 m_parent->SetVideoParams(width, height, m_fps,
1488 m_currentAspect, false, GetMaxReferenceFrames(codecContext),
1489 kScan_Detect, codecName);
1490 if (LCD *lcd = LCD::Get())
1491 {
1492 LCDVideoFormatSet video_format = VIDEO_MPG;
1493
1494 switch (codecContext->codec_id)
1495 {
1496 case AV_CODEC_ID_H263:
1497 case AV_CODEC_ID_MPEG4:
1498 case AV_CODEC_ID_MSMPEG4V1:
1499 case AV_CODEC_ID_MSMPEG4V2:
1500 case AV_CODEC_ID_MSMPEG4V3:
1501 case AV_CODEC_ID_H263P:
1502 case AV_CODEC_ID_H263I:
1503 video_format = VIDEO_DIVX;
1504 break;
1505 case AV_CODEC_ID_WMV1:
1506 case AV_CODEC_ID_WMV2:
1507 video_format = VIDEO_WMV;
1508 break;
1509#if 0
1510 case AV_CODEC_ID_XVID:
1511 video_format = VIDEO_XVID;
1512 break;
1513#endif
1514 default:
1515 video_format = VIDEO_MPG;
1516 break;
1517 }
1518
1519 lcd->setVideoFormatLEDs(video_format, true);
1520
1521 if(height >= 720)
1522 lcd->setVariousLEDs(VARIOUS_HDTV, true);
1523 else
1524 lcd->setVariousLEDs(VARIOUS_HDTV, false);
1525 }
1526 }
1527}
1528
1530{
1531 static constexpr std::array<uint8_t, 256> odd_parity_LUT
1532 {
1533 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1534 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1535 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1536 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1537 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1538 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1539 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1540 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1541 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1542 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1543 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1544 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1545 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1546 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1547 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1548 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1549 };
1550 bool ret = (odd_parity_LUT[data & 0xff] == 1) &&
1551 (odd_parity_LUT[(data & 0xff00) >> 8] == 1);
1552 if (!ret)
1553 {
1554 LOG(VB_VBI, LOG_ERR, LOC +
1555 QString("VBI: Bad parity in EIA-608 data (%1)") .arg(data,0,16));
1556 }
1557 return ret;
1558}
1559
1560static AVBufferRef* get_pmt_section_from_AVProgram(const AVProgram *program)
1561{
1562 if (program == nullptr)
1563 {
1564 return nullptr;
1565 }
1566 return program->pmt_section;
1567}
1568
1569static AVBufferRef* get_pmt_section_for_AVStream_index(AVFormatContext *context, int stream_index)
1570{
1571 AVProgram* program = av_find_program_from_stream(context, nullptr, stream_index);
1572 return get_pmt_section_from_AVProgram(program);
1573}
1574
1576{
1577 QMutexLocker locker(&m_trackLock);
1578
1579 m_ccX08InPmt.fill(false);
1580 m_pmtTracks.clear();
1581 m_pmtTrackTypes.clear();
1582
1583 // Figure out languages of ATSC captions
1585 if (!pmt_buffer.has_buffer())
1586 {
1587 LOG(VB_GENERAL, LOG_DEBUG, LOC +
1588 "ScanATSCCaptionStreams() called with no PMT");
1589 return;
1590 }
1591 const ProgramMapTable pmt(PSIPTable(pmt_buffer.data()));
1592
1593 bool video_found = false;
1594 uint i = 0;
1595 for (i = 0; i < pmt.StreamCount(); i++)
1596 {
1597 // MythTV remaps OpenCable Video to normal video during recording
1598 // so "dvb" is the safest choice for system info type, since this
1599 // will ignore other uses of the same stream id in DVB countries.
1600 if (pmt.IsVideo(i, "dvb"))
1601 {
1602 video_found = true;
1603 break;
1604 }
1605 }
1606 if (!video_found)
1607 return;
1608
1610 pmt.StreamInfo(i), pmt.StreamInfoLength(i),
1612
1614 pmt.ProgramInfo(), pmt.ProgramInfoLength(),
1616
1617 desc_list.insert(desc_list.end(), desc_list2.begin(), desc_list2.end());
1618
1619 for (auto & desc : desc_list)
1620 {
1621 const CaptionServiceDescriptor csd(desc);
1622 if (!csd.IsValid())
1623 continue;
1624
1625 LOG(VB_VBI, LOG_DEBUG, LOC + csd.toString());
1626
1627 for (uint k = 0; k < csd.ServicesCount(); k++)
1628 {
1629 int lang = csd.CanonicalLanguageKey(k);
1630 int type = csd.Type(k) ? 1 : 0;
1631 if (type)
1632 {
1633 StreamInfo si {av_index, csd.CaptionServiceNumber(k), lang};
1634 uint key = csd.CaptionServiceNumber(k) + 4;
1635 m_ccX08InPmt[key] = true;
1636 m_pmtTracks.push_back(si);
1638 }
1639 else
1640 {
1641 int line21 = csd.Line21Field(k) ? 3 : 1;
1642 StreamInfo si {av_index, line21, lang};
1643 m_ccX08InPmt[line21-1] = true;
1644 m_pmtTracks.push_back(si);
1646 }
1647 }
1648 }
1649}
1650
1652{
1653 QMutexLocker locker(&m_trackLock);
1654
1655 m_tracks[kTrackTypeCC608].clear();
1656 m_tracks[kTrackTypeCC708].clear();
1657 m_ccX08InTracks.fill(false);
1658
1659 uint pidx = 0;
1660 uint sidx = 0;
1661 std::array<std::map<int,uint>,2> lang_cc_cnt;
1662 while (true)
1663 {
1664 bool pofr = pidx >= (uint)m_pmtTracks.size();
1665 bool sofr = sidx >= (uint)m_streamTracks.size();
1666 if (pofr && sofr)
1667 break;
1668
1669 // choose lowest available next..
1670 // stream_id's of 608 and 708 streams alias, but this
1671 // is ok as we just want each list to be ordered.
1672 StreamInfo const *si = nullptr;
1673 int type = 0; // 0 if 608, 1 if 708
1674 bool isp = true; // if true use m_pmtTracks next, else stream_tracks
1675
1676 if (pofr && !sofr)
1677 isp = false; // NOLINT(bugprone-branch-clone)
1678 else if (!pofr && sofr)
1679 isp = true;
1680 else if (m_streamTracks[sidx] < m_pmtTracks[pidx])
1681 isp = false;
1682
1683 if (isp)
1684 {
1685 si = &m_pmtTracks[pidx];
1686 type = kTrackTypeCC708 == m_pmtTrackTypes[pidx] ? 1 : 0;
1687 pidx++;
1688 }
1689 else
1690 {
1691 si = &m_streamTracks[sidx];
1692 type = kTrackTypeCC708 == m_streamTrackTypes[sidx] ? 1 : 0;
1693 sidx++;
1694 }
1695
1696 StreamInfo nsi(*si);
1697 int lang_indx = lang_cc_cnt[type][nsi.m_language];
1698 lang_cc_cnt[type][nsi.m_language]++;
1699 nsi.m_language_index = lang_indx;
1700 m_tracks[(type) ? kTrackTypeCC708 : kTrackTypeCC608].push_back(nsi);
1701 int key = nsi.m_stream_id + ((type) ? 4 : -1);
1702 if (key < 0)
1703 {
1704 LOG(VB_GENERAL, LOG_ERR, LOC + "in_tracks key too small");
1705 }
1706 else
1707 {
1708 m_ccX08InTracks[key] = true;
1709 }
1710 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1711 QString("%1 caption service #%2 is in the %3 language.")
1712 .arg((type) ? "EIA-708" : "EIA-608")
1713 .arg(nsi.m_stream_id)
1714 .arg(iso639_key_toName(nsi.m_language)));
1715 }
1718}
1719
1721{
1722 QMutexLocker locker(&m_trackLock);
1723
1724 // ScanStreams() calls m_tracks[kTrackTypeTeletextCaptions].clear()
1726 return;
1727
1728 AVStream* st = m_ic->streams[av_index];
1729 const AVDictionaryEntry* language_dictionary_entry =
1730 av_dict_get(st->metadata, "language", nullptr, 0);
1731
1732 if (language_dictionary_entry == nullptr ||
1733 language_dictionary_entry->value == nullptr ||
1734 st->codecpar->extradata == nullptr
1735 )
1736 {
1737 return;
1738 }
1739
1740 std::vector<std::string_view> languages {StringUtil::split_sv(language_dictionary_entry->value, ","sv)};
1741
1742 if (st->codecpar->extradata_size != static_cast<int>(languages.size() * 2))
1743 {
1744 return;
1745 }
1746 for (size_t i = 0; i < languages.size(); i++)
1747 {
1748 if (languages[i].size() != 3)
1749 {
1750 continue;
1751 }
1752 //NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
1753 int language = iso639_str3_to_key(languages[i].data());
1754 uint8_t teletext_type = st->codecpar->extradata[i * 2] >> 3;
1755 uint8_t teletext_magazine_number = st->codecpar->extradata[i * 2] & 0x7;
1756 if (teletext_magazine_number == 0)
1757 teletext_magazine_number = 8;
1758 uint8_t teletext_page_number = st->codecpar->extradata[(i * 2) + 1];
1759 if (teletext_type == 2 || teletext_type == 1)
1760 {
1761 TrackType track = (teletext_type == 2) ?
1764 m_tracks[track].emplace_back(av_index, 0, language,
1765 (static_cast<unsigned>(teletext_magazine_number) << 8) | teletext_page_number);
1766 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1767 QString("Teletext stream #%1 (%2) is in the %3 language on page %4 %5.")
1768 .arg(QString::number(i),
1769 (teletext_type == 2) ? "Caption" : "Menu",
1770 iso639_key_toName(language),
1771 QString::number(teletext_magazine_number),
1772 QString::number(teletext_page_number)));
1773 }
1774 }
1775}
1776
1778{
1779 QMutexLocker locker(&m_trackLock);
1780
1781 AVDictionaryEntry *metatag =
1782 av_dict_get(m_ic->streams[av_stream_index]->metadata, "language", nullptr,
1783 0);
1784 bool forced = (m_ic->streams[av_stream_index]->disposition & AV_DISPOSITION_FORCED) != 0;
1785 int lang = metatag ? get_canonical_lang(metatag->value) :
1786 iso639_str3_to_key("und");
1787 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1788 QString("Text Subtitle track #%1 is A/V stream #%2 "
1789 "and is in the %3 language(%4), forced=%5.")
1790 .arg(m_tracks[kTrackTypeRawText].size()).arg(av_stream_index)
1791 .arg(iso639_key_toName(lang)).arg(lang).arg(forced));
1792 StreamInfo si {av_stream_index, 0, lang, 0, forced};
1793 m_tracks[kTrackTypeRawText].push_back(si);
1794}
1795
1800void AvFormatDecoder::ScanDSMCCStreams(AVBufferRef* pmt_section)
1801{
1802 if (m_itv == nullptr)
1804 if (m_itv == nullptr)
1805 return;
1806
1807 MythAVBufferRef pmt_buffer {pmt_section};
1808 if (!pmt_buffer.has_buffer())
1809 {
1810 return;
1811 }
1812 const ProgramMapTable pmt(PSIPTable(pmt_buffer.data()));
1813
1814 for (uint i = 0; i < pmt.StreamCount(); i++)
1815 {
1817 continue;
1818
1819 LOG(VB_DSMCC, LOG_NOTICE, QString("ScanDSMCCStreams Found Object Carousel in Stream %1").arg(QString::number(i)));
1820
1822 pmt.StreamInfo(i), pmt.StreamInfoLength(i),
1824
1825 for (const auto *desc : desc_list)
1826 {
1827 desc++; // Skip tag
1828 uint length = *desc++;
1829 const unsigned char *endDesc = desc+length;
1830 uint dataBroadcastId = desc[0]<<8 | desc[1];
1831 LOG(VB_DSMCC, LOG_NOTICE, QString("ScanDSMCCStreams dataBroadcastId %1").arg(QString::number(dataBroadcastId)));
1832 if (dataBroadcastId != 0x0106) // ETSI/UK Profile
1833 continue;
1834 desc += 2; // Skip data ID
1835 while (desc != endDesc)
1836 {
1837 [[maybe_unused]] uint appTypeCode = desc[0]<<8 | desc[1];
1838 desc += 3; // Skip app type code and boot priority hint
1839 uint appSpecDataLen = *desc++;
1840#if CONFIG_MHEG
1841 LOG(VB_DSMCC, LOG_NOTICE, QString("ScanDSMCCStreams AppTypeCode %1").arg(QString::number(appTypeCode)));
1842 if (appTypeCode == 0x101) // UK MHEG profile
1843 {
1844 const unsigned char *subDescEnd = desc + appSpecDataLen;
1845 while (desc < subDescEnd)
1846 {
1847 uint sub_desc_tag = *desc++;
1848 uint sub_desc_len = *desc++;
1849 // Network boot info sub-descriptor.
1850 if (sub_desc_tag == 1)
1851 m_itv->SetNetBootInfo(desc, sub_desc_len);
1852 desc += sub_desc_len;
1853 }
1854 }
1855 else
1856#endif // CONFIG_MHEG
1857 {
1858 desc += appSpecDataLen;
1859 }
1860 }
1861 }
1862 }
1863}
1864
1866{
1867 m_tracks[kTrackTypeVideo].clear();
1868 m_selectedTrack[kTrackTypeVideo].m_av_stream_index = -1;
1870 m_fps = 0;
1871
1872 const AVCodec *codec = nullptr;
1873 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Trying to select best video track");
1874
1875 /*
1876 * Find the "best" stream in the file.
1877 *
1878 * The best stream is determined according to various heuristics as
1879 * the most likely to be what the user expects. If the decoder parameter
1880 * is not nullptr, av_find_best_stream will find the default decoder
1881 * for the stream's codec; streams for which no decoder can be found
1882 * are ignored.
1883 *
1884 * If av_find_best_stream returns successfully and decoder_ret is not nullptr,
1885 * then *decoder_ret is guaranteed to be set to a valid AVCodec.
1886 */
1887 int stream_index = av_find_best_stream(m_ic, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);
1888
1889 if (stream_index < 0)
1890 {
1891 LOG(VB_PLAYBACK, LOG_INFO, LOC + "No video track found/selected.");
1892 return stream_index;
1893 }
1894
1895 AVStream *stream = m_ic->streams[stream_index];
1898 AVCodecContext *codecContext = m_codecMap.GetCodecContext(stream, codec);
1899 StreamInfo si {stream_index, 0};
1900
1901 m_tracks[kTrackTypeVideo].push_back(si);
1904
1905 QString codectype(AVMediaTypeToString(codecContext->codec_type));
1906 if (codecContext->codec_type == AVMEDIA_TYPE_VIDEO)
1907 codectype += QString("(%1x%2)").arg(codecContext->width).arg(codecContext->height);
1908 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1909 QString("Selected track #%1: ID: 0x%2 Codec ID: %3 Profile: %4 Type: %5 Bitrate: %6")
1910 .arg(stream_index).arg(static_cast<uint64_t>(stream->id), 0, 16)
1911 .arg(avcodec_get_name(codecContext->codec_id),
1912 avcodec_profile_name(codecContext->codec_id, codecContext->profile),
1913 codectype,
1914 QString::number(codecContext->bit_rate)));
1915
1916 // If ScanStreams has been called on a stream change triggered by a
1917 // decoder error - because the decoder does not handle resolution
1918 // changes gracefully (NVDEC and maybe MediaCodec) - then the stream/codec
1919 // will still contain the old resolution but the AVCodecContext will
1920 // have been updated. This causes mayhem for a second or two.
1921 if ((codecContext->width != stream->codecpar->width) || (codecContext->height != stream->codecpar->height))
1922 {
1923 LOG(VB_GENERAL, LOG_INFO, LOC + QString(
1924 "Video resolution mismatch: Context: %1x%2 Stream: %3x%4 Codec: %5 Stream change: %6")
1925 .arg(codecContext->width).arg(codecContext->height)
1926 .arg(stream->codecpar->width).arg(stream->codecpar->height)
1928 }
1929
1930 m_avcParser->Reset();
1931
1932 QSize dim = get_video_dim(*codecContext);
1933 int width = std::max(dim.width(), 16);
1934 int height = std::max(dim.height(), 16);
1935 QString dec = "ffmpeg";
1936 uint thread_count = 1;
1937 QString codecName;
1938 if (codecContext->codec)
1939 codecName = codecContext->codec->name;
1940 // framerate appears to never be set - which is probably why
1941 // GetVideoFrameRate never uses it:)
1942 // So fallback to the GetVideoFrameRate call which should then ensure
1943 // the video display profile gets an accurate frame rate - instead of 0
1944 if (codecContext->framerate.den && codecContext->framerate.num)
1945 m_fps = float(codecContext->framerate.num) / float(codecContext->framerate.den);
1946 else
1947 m_fps = GetVideoFrameRate(stream, codecContext, true);
1948
1949 bool foundgpudecoder = false;
1950 QStringList unavailabledecoders;
1951 bool allowgpu = FlagIsSet(kDecodeAllowGPU);
1952
1954 {
1955 // TODO this could be improved by appending the decoder that has
1956 // failed to the unavailable list - but that could lead to circular
1957 // failures if there are 2 or more hardware decoders that fail
1958 if (FlagIsSet(kDecodeAllowGPU) && (dec != "ffmpeg"))
1959 {
1960 LOG(VB_GENERAL, LOG_WARNING, LOC + QString(
1961 "GPU/hardware decoder '%1' failed - forcing software decode")
1962 .arg(dec));
1963 }
1964 m_averrorCount = 0;
1965 allowgpu = false;
1966 }
1967
1968 while (unavailabledecoders.size() < 10)
1969 {
1970 if (!m_isDbIgnored)
1971 {
1972 if (!unavailabledecoders.isEmpty())
1973 {
1974 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Unavailable decoders: %1")
1975 .arg(unavailabledecoders.join(",")));
1976 }
1977 m_videoDisplayProfile.SetInput(QSize(width, height), m_fps, codecName, unavailabledecoders);
1979 thread_count = m_videoDisplayProfile.GetMaxCPUs();
1980 bool skip_loop_filter = m_videoDisplayProfile.IsSkipLoopEnabled();
1981 if (!skip_loop_filter)
1982 codecContext->skip_loop_filter = AVDISCARD_NONKEY;
1983 }
1984
1986 uint version = mpeg_version(codecContext->codec_id);
1987 if (version)
1988 m_videoCodecId = static_cast<MythCodecID>(kCodec_MPEG1 + version - 1);
1989
1990 if (version && allowgpu && dec != "ffmpeg")
1991 {
1992 // We need to set this so that MythyCodecContext can callback
1993 // to the player in use to check interop support.
1994 codecContext->opaque = static_cast<void*>(this);
1995 MythCodecID hwcodec = MythCodecContext::FindDecoder(dec, stream, &codecContext, &codec);
1996 if (hwcodec != kCodec_NONE)
1997 {
1998 // the context may have changed
1999 codecContext->opaque = static_cast<void*>(this);
2000 m_videoCodecId = hwcodec;
2001 foundgpudecoder = true;
2002 }
2003 else
2004 {
2005 // hardware decoder is not available - try the next best profile
2006 unavailabledecoders.append(dec);
2007 continue;
2008 }
2009 }
2010
2011 // default to mpeg2
2013 {
2014 LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown video codec - defaulting to MPEG2");
2016 }
2017
2018 break;
2019 }
2020
2022 thread_count = 1;
2023
2024 if (HAVE_THREADS)
2025 {
2026 // Only use a single thread for hardware decoding. There is no
2027 // performance improvement with multithreaded hardware decode
2028 // and asynchronous callbacks create issues with decoders that
2029 // use AVHWFrameContext where we need to release video resources
2030 // before they are recreated
2031 if (!foundgpudecoder)
2032 {
2033 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Using %1 CPUs for decoding")
2034 .arg(HAVE_THREADS ? thread_count : 1));
2035 codecContext->thread_count = static_cast<int>(thread_count);
2036 }
2037 }
2038
2039 InitVideoCodec(stream, codecContext, true);
2040
2041 ScanATSCCaptionStreams(stream_index);
2043
2044 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Using %1 for video decoding").arg(GetCodecDecoderName()));
2045 m_mythCodecCtx->SetDecoderOptions(codecContext, codec);
2046 if (!OpenAVCodec(codecContext, codec))
2047 {
2048 scanerror = -1;
2049 }
2050 return stream_index;
2051}
2052
2054{
2055 AVProgram* program = av_find_program_from_stream(m_ic, nullptr, stream_index);
2056 if (program == nullptr)
2057 {
2058 return;
2059 }
2060
2061 LOG(VB_PLAYBACK, LOG_INFO,
2062 QString("Removing streams not in Program %1 from track selection.")
2063 .arg(QString::number(program->id)));
2064
2065 const auto * const begin = program->stream_index;
2066 const auto * const end = program->stream_index + program->nb_stream_indexes;
2067
2068 for (auto & track_list : m_tracks)
2069 {
2070 LOG(VB_PLAYBACK, LOG_DEBUG,
2071 QString("Size before: %1").arg(QString::number(track_list.size())));
2072 track_list.erase(std::remove_if(track_list.begin(), track_list.end(),
2073 [&](const StreamInfo& i)
2074 {
2075 return std::find(begin, end, i.m_av_stream_index) == end;
2076 }), track_list.end());
2077 LOG(VB_PLAYBACK, LOG_DEBUG,
2078 QString("Size after: %1").arg(QString::number(track_list.size())));
2079 }
2080}
2081
2082static bool is_dual_mono(const AVChannelLayout& ch_layout)
2083{
2084 return (ch_layout.order == AV_CHANNEL_ORDER_CUSTOM) &&
2085 (ch_layout.nb_channels == 2) &&
2086 (ch_layout.u.map[0].id == AV_CHAN_FRONT_CENTER) &&
2087 (ch_layout.u.map[1].id == AV_CHAN_FRONT_CENTER);
2088}
2089
2091{
2092 QMutexLocker avlocker(&m_avCodecLock);
2093 QMutexLocker locker(&m_trackLock);
2094
2095 bool unknownbitrate = false;
2096 int scanerror = 0;
2097 m_bitrate = 0;
2098
2099 constexpr std::array<TrackType, 6> types {
2106 };
2107 for (const auto type : types)
2108 {
2109 m_tracks[type].clear();
2110 m_currentTrack[type] = -1;
2111 }
2112
2113 std::map<int,uint> lang_sub_cnt;
2114 uint subtitleStreamCount = 0;
2115 std::map<int,uint> lang_aud_cnt;
2116 uint audioStreamCount = 0;
2117
2118 if (m_ringBuffer && m_ringBuffer->IsDVD() &&
2120 {
2123 }
2124
2125 if (m_ic == nullptr)
2126 return -1;
2127
2128 for (uint strm = 0; strm < m_ic->nb_streams; strm++)
2129 {
2130 AVCodecParameters *par = m_ic->streams[strm]->codecpar;
2131
2132 QString codectype(AVMediaTypeToString(par->codec_type));
2133 if (par->codec_type == AVMEDIA_TYPE_VIDEO)
2134 codectype += QString("(%1x%2)").arg(par->width).arg(par->height);
2135 QString program_id = "null";
2136 if (av_find_program_from_stream(m_ic, nullptr, strm) != nullptr)
2137 {
2138 program_id = QString::number(av_find_program_from_stream(m_ic, nullptr, strm)->id);
2139 }
2140 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2141 QString("Stream #%1: ID: 0x%2 Program ID: %3 Codec ID: %4 Type: %5 Bitrate: %6").arg(
2142 QString::number(strm),
2143 QString::number(static_cast<uint64_t>(m_ic->streams[strm]->id), 16),
2144 program_id,
2145 avcodec_get_name(par->codec_id),
2146 codectype,
2147 QString::number(par->bit_rate))
2148 );
2149
2150 switch (par->codec_type)
2151 {
2152 case AVMEDIA_TYPE_VIDEO:
2153 {
2154 // reset any potentially errored hardware decoders
2156 {
2157 if (m_codecMap.FindCodecContext(m_ic->streams[strm]))
2158 {
2159 AVCodecContext* ctx = m_codecMap.GetCodecContext(m_ic->streams[strm]);
2160 if (ctx && (ctx->hw_frames_ctx || ctx->hw_device_ctx))
2161 m_codecMap.FreeCodecContext(m_ic->streams[strm]);
2162 }
2163 }
2164
2165 if (!par->codec_id)
2166 {
2167 LOG(VB_GENERAL, LOG_ERR, LOC +
2168 QString("Stream #%1 has an unknown video "
2169 "codec id, skipping.").arg(strm));
2170 continue;
2171 }
2172
2173 // ffmpeg does not return a bitrate for several codecs and
2174 // formats. Typically the same streams do not have a duration either
2175 // - so we cannot estimate a bitrate (which would be subject
2176 // to significant error anyway if there were multiple video streams).
2177 // So we need to guesstimate a value that avoids low bitrate optimisations
2178 // (which typically kick in around 500,000) and provides a read
2179 // chunk size large enough to avoid starving the decoder of data.
2180 // Trying to read a 20Mbs stream with a 16KB chunk size does not work:)
2181 if (par->bit_rate == 0)
2182 {
2183 static constexpr int64_t s_baseBitrate { 1000000LL };
2184 int multiplier = 1;
2185 if (par->width && par->height)
2186 {
2187 static const int s_baseSize = 1920 * 1080;
2188 multiplier = ((par->width * par->height) + s_baseSize - 1) / s_baseSize;
2189 multiplier = std::max(multiplier, 1);
2190 }
2191 par->bit_rate = s_baseBitrate * multiplier;
2192 unknownbitrate = true;
2193 }
2194 m_bitrate += par->bit_rate;
2195
2196 break;
2197 }
2198 case AVMEDIA_TYPE_AUDIO:
2199 {
2200 LOG(VB_GENERAL, LOG_INFO, LOC +
2201 QString("codec %1 has %2 channels")
2202 .arg(avcodec_get_name(par->codec_id))
2203 .arg(par->ch_layout.nb_channels));
2204
2205 m_bitrate += par->bit_rate;
2206 break;
2207 }
2208 case AVMEDIA_TYPE_SUBTITLE:
2209 {
2210 if (par->codec_id == AV_CODEC_ID_DVB_TELETEXT)
2211 ScanTeletextCaptions(static_cast<int>(strm));
2212 if (par->codec_id == AV_CODEC_ID_TEXT)
2213 ScanRawTextCaptions(static_cast<int>(strm));
2214 m_bitrate += par->bit_rate;
2215
2216 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("subtitle codec (%1)")
2217 .arg(AVMediaTypeToString(par->codec_type)));
2218 break;
2219 }
2220 case AVMEDIA_TYPE_DATA:
2221 {
2222 if (par->codec_id == AV_CODEC_ID_DVB_VBI)
2223 ScanTeletextCaptions(static_cast<int>(strm));
2224 m_bitrate += par->bit_rate;
2225 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("data codec (%1)")
2226 .arg(AVMediaTypeToString(par->codec_type)));
2227 break;
2228 }
2229 case AVMEDIA_TYPE_ATTACHMENT:
2230 {
2231 if (par->codec_id == AV_CODEC_ID_TTF)
2232 m_tracks[kTrackTypeAttachment].emplace_back(static_cast<int>(strm), m_ic->streams[strm]->id);
2233 m_bitrate += par->bit_rate;
2234 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2235 QString("Attachment codec (%1)")
2236 .arg(AVMediaTypeToString(par->codec_type)));
2237 break;
2238 }
2239 default:
2240 {
2241 m_bitrate += par->bit_rate;
2242 LOG(VB_PLAYBACK, LOG_ERR, LOC +
2243 QString("Unknown codec type (%1)")
2244 .arg(AVMediaTypeToString(par->codec_type)));
2245 break;
2246 }
2247 }
2248
2249 if (par->codec_type != AVMEDIA_TYPE_AUDIO &&
2250 par->codec_type != AVMEDIA_TYPE_SUBTITLE)
2251 continue;
2252
2253 // skip DVB teletext and text subs, there is no libavcodec decoder
2254 if (par->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2255 (par->codec_id == AV_CODEC_ID_DVB_TELETEXT ||
2256 par->codec_id == AV_CODEC_ID_TEXT))
2257 continue;
2258
2259 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Looking for decoder for %1")
2260 .arg(avcodec_get_name(par->codec_id)));
2261
2262 if (par->codec_id == AV_CODEC_ID_PROBE)
2263 {
2264 LOG(VB_GENERAL, LOG_ERR, LOC +
2265 QString("Probing of stream #%1 unsuccesful, ignoring.").arg(strm));
2266 continue;
2267 }
2268
2269 AVCodecContext* codecContext = m_codecMap.GetCodecContext(m_ic->streams[strm]);
2270
2271 if (codecContext == nullptr)
2272 {
2273 LOG(VB_GENERAL, LOG_WARNING, LOC +
2274 QString("Could not find decoder for codec (%1), ignoring.")
2275 .arg(avcodec_get_name(par->codec_id)));
2276 LOG(VB_LIBAV, LOG_INFO, "For a list of all codecs, run `mythffmpeg -codecs`.");
2277 continue;
2278 }
2279
2280 if (codecContext->codec && par->codec_id != codecContext->codec_id)
2281 {
2282 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2283 QString("Already opened codec not matching (%1 vs %2). Reopening")
2284 .arg(avcodec_get_name(codecContext->codec_id),
2285 avcodec_get_name(codecContext->codec->id)));
2286 m_codecMap.FreeCodecContext(m_ic->streams[strm]);
2287 codecContext = m_codecMap.GetCodecContext(m_ic->streams[strm]);
2288 }
2289 if (!OpenAVCodec(codecContext, codecContext->codec))
2290 continue;
2291 if (!codecContext)
2292 continue;
2293
2294 if (!IsValidStream(m_ic->streams[strm]->id))
2295 {
2296 /* Hide this stream if it's not valid in this context.
2297 * This can happen, for example, on a Blu-ray disc if there
2298 * are more physical streams than there is metadata about them.
2299 * (e.g. Despicable Me)
2300 */
2301 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2302 QString("Stream 0x%1 is not valid in this context - skipping")
2303 .arg(m_ic->streams[strm]->id, 4, 16));
2304 continue;
2305 }
2306
2307 if (par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2308 {
2309 bool forced = (m_ic->streams[strm]->disposition & AV_DISPOSITION_FORCED) != 0;
2310 int lang = GetSubtitleLanguage(subtitleStreamCount, strm);
2311 uint lang_indx = lang_sub_cnt[lang]++;
2312 subtitleStreamCount++;
2313
2314 m_tracks[kTrackTypeSubtitle].emplace_back(
2315 static_cast<int>(strm), m_ic->streams[strm]->id, lang, lang_indx, forced);
2316
2317 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2318 QString("Subtitle track #%1 is A/V stream #%2 "
2319 "and is in the %3 language(%4).")
2320 .arg(m_tracks[kTrackTypeSubtitle].size()).arg(strm)
2321 .arg(iso639_key_toName(lang)).arg(lang));
2322 }
2323
2324 if (par->codec_type == AVMEDIA_TYPE_AUDIO)
2325 {
2326 int lang = GetAudioLanguage(audioStreamCount, strm);
2328 uint lang_indx = lang_aud_cnt[lang]++;
2329 audioStreamCount++;
2330
2331 int stream_id = m_ic->streams[strm]->id;
2333 {
2334 stream_id = m_ringBuffer->DVD()->GetAudioTrackNum(stream_id);
2335 if (stream_id == -1)
2336 {
2337 // This stream isn't mapped, so skip it
2338 continue;
2339 }
2340 }
2341
2342 m_tracks[kTrackTypeAudio].emplace_back(
2343 static_cast<int>(strm), stream_id, lang, lang_indx, type);
2344
2345 if (is_dual_mono(codecContext->ch_layout))
2346 {
2347 lang_indx = lang_aud_cnt[lang]++;
2348 m_tracks[kTrackTypeAudio].emplace_back(
2349 static_cast<int>(strm), stream_id, lang, lang_indx, type);
2350 }
2351
2352 LOG(VB_AUDIO, LOG_INFO, LOC +
2353 QString("Audio Track #%1, of type (%2) is A/V stream #%3 (id=0x%4) "
2354 "and has %5 channels in the %6 language(%7).")
2355 .arg(m_tracks[kTrackTypeAudio].size()).arg(toString(type))
2356 .arg(strm).arg(m_ic->streams[strm]->id,0,16).arg(codecContext->ch_layout.nb_channels)
2357 .arg(iso639_key_toName(lang)).arg(lang));
2358 }
2359 }
2360
2361 // Now find best video track to play
2363 if (!novideo)
2364 {
2365 int stream_index = autoSelectVideoTrack(scanerror);
2367 }
2368
2369 m_bitrate = std::max(static_cast<uint>(m_ic->bit_rate), m_bitrate);
2370
2371 if (m_bitrate > 0)
2372 {
2373 m_bitrate = (m_bitrate + 999) / 1000;
2374 if (m_ringBuffer)
2376 }
2377
2378 // update RingBuffer buffer size
2379 if (m_ringBuffer)
2380 {
2381 m_ringBuffer->SetBufferSizeFactors(unknownbitrate,
2382 QString(m_ic->iformat->name).contains("matroska"));
2383 }
2384
2386
2387 for (const auto type : types)
2388 {
2390 }
2391
2392 // We have to do this here to avoid the NVP getting stuck
2393 // waiting on audio.
2394 if (m_audio->HasAudioIn() && m_tracks[kTrackTypeAudio].empty())
2395 {
2396 m_audio->SetAudioParams(FORMAT_NONE, -1, -1, AV_CODEC_ID_NONE, -1, false);
2399 m_audioIn = AudioInfo();
2400 }
2401
2402 // if we don't have a video stream we still need to make sure some
2403 // video params are set properly
2404 if (m_selectedTrack[kTrackTypeVideo].m_av_stream_index == -1)
2405 {
2406 m_fps = 23.97F; // minimum likey display refresh rate
2407 // N.B. we know longer need a 'dummy' frame to render overlays into
2408 m_parent->SetVideoParams(0, 0, 23.97, 1.0F, false, 0);
2409 }
2410
2411 if (m_parent->IsErrored())
2412 scanerror = -1;
2413
2414 if (!novideo && m_selectedTrack[kTrackTypeVideo].m_av_stream_index != -1)
2415 {
2418 }
2419 else
2420 {
2421 /* We don't yet know which AVProgram we want, so iterate through them
2422 all. This should be no more incorrect than using the last PMT when
2423 there are multiple programs. */
2424 for (unsigned i = 0; i < m_ic->nb_programs; i++)
2425 {
2426 ScanDSMCCStreams(m_ic->programs[i]->pmt_section);
2427 }
2428 }
2429
2430 return scanerror;
2431}
2432
2433bool AvFormatDecoder::OpenAVCodec(AVCodecContext *avctx, const AVCodec *codec)
2434{
2435 m_avCodecLock.lock();
2436#if CONFIG_MEDIACODEC
2437 if (QString("mediacodec") == codec->wrapper_name)
2438 av_jni_set_java_vm(QAndroidJniEnvironment::javaVM(), nullptr);
2439#endif
2440 int ret = avcodec_open2(avctx, codec, nullptr);
2441 m_avCodecLock.unlock();
2442 if (ret < 0)
2443 {
2444 std::string error;
2445 LOG(VB_GENERAL, LOG_ERR, LOC +
2446 QString("Could not open codec 0x%1, id(%2) type(%3) "
2447 "ignoring. reason %4").arg((uint64_t)avctx,0,16)
2448 .arg(avcodec_get_name(avctx->codec_id),
2449 AVMediaTypeToString(avctx->codec_type),
2451 return false;
2452 }
2453
2454 LOG(VB_GENERAL, LOG_INFO, LOC +
2455 QString("Opened codec 0x%1, id(%2) type(%3)")
2456 .arg((uint64_t)avctx,0,16)
2457 .arg(avcodec_get_name(avctx->codec_id),
2458 AVMediaTypeToString(avctx->codec_type)));
2459 return true;
2460}
2461
2463{
2465}
2466
2467bool AvFormatDecoder::DoRewindSeek(long long desiredFrame)
2468{
2469 return DecoderBase::DoRewindSeek(desiredFrame);
2470}
2471
2472void AvFormatDecoder::DoFastForwardSeek(long long desiredFrame, bool &needflush)
2473{
2474 DecoderBase::DoFastForwardSeek(desiredFrame, needflush);
2475}
2476
2479{
2480 QMutexLocker locker(&m_trackLock);
2481 for (const auto & si : m_tracks[kTrackTypeTeletextCaptions])
2482 if (si.m_language_index == Index)
2483 return si.m_language;
2484 return iso639_str3_to_key("und");
2485}
2486
2489{
2490 AVDictionaryEntry *metatag = av_dict_get(m_ic->streams[StreamIndex]->metadata, "language", nullptr, 0);
2491 return metatag ? get_canonical_lang(metatag->value) : iso639_str3_to_key("und");
2492}
2493
2496{
2497 // This doesn't strictly need write lock but it is called internally while
2498 // write lock is held. All other (external) uses are safe
2499 QMutexLocker locker(&m_trackLock);
2500
2501 int ret = -1;
2502 for (int i = 0; i < m_pmtTrackTypes.size(); i++)
2503 {
2504 if ((m_pmtTrackTypes[i] == TrackType) && (m_pmtTracks[i].m_stream_id == ServiceNum))
2505 {
2506 ret = m_pmtTracks[i].m_language;
2507 if (!iso639_is_key_undefined(ret))
2508 return ret;
2509 }
2510 }
2511
2512 for (int i = 0; i < m_streamTrackTypes.size(); i++)
2513 {
2514 if ((m_streamTrackTypes[i] == TrackType) && (m_streamTracks[i].m_stream_id == ServiceNum))
2515 {
2516 ret = m_streamTracks[i].m_language;
2517 if (!iso639_is_key_undefined(ret))
2518 return ret;
2519 }
2520 }
2521
2522 return ret;
2523}
2524
2525int AvFormatDecoder::GetAudioLanguage(uint AudioIndex, uint StreamIndex)
2526{
2527 return GetSubtitleLanguage(AudioIndex, StreamIndex);
2528}
2529
2531{
2533 AVStream *stream = m_ic->streams[StreamIndex];
2534
2535 {
2536 // We only support labelling/filtering of these two types for now
2537 if (stream->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
2539 else if (stream->disposition & AV_DISPOSITION_COMMENT)
2541 else if (stream->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
2543 else if (stream->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
2545 }
2546
2547 return type;
2548}
2549
2563{
2564 QMutexLocker locker(&m_trackLock);
2565
2566 // Find the position of the streaminfo in m_tracks[kTrackTypeAudio]
2567 auto current = m_tracks[kTrackTypeAudio].begin();
2568 for (; current != m_tracks[kTrackTypeAudio].end(); ++current)
2569 {
2570 if (current->m_av_stream_index == streamIndex)
2571 break;
2572 }
2573
2574 if (current == m_tracks[kTrackTypeAudio].end())
2575 {
2576 LOG(VB_GENERAL, LOG_WARNING, LOC +
2577 QString("Invalid stream index passed to "
2578 "SetupAudioStreamSubIndexes: %1").arg(streamIndex));
2579
2580 return;
2581 }
2582
2583 // Remove the extra substream or duplicate the current substream
2584 auto next = current + 1;
2585 if (current->m_av_substream_index == -1)
2586 {
2587 // Split stream in two (Language I + Language II)
2588 StreamInfo lang1 = *current;
2589 StreamInfo lang2 = *current;
2590 lang1.m_av_substream_index = 0;
2591 lang2.m_av_substream_index = 1;
2592 *current = lang1;
2593 m_tracks[kTrackTypeAudio].insert(next, lang2);
2594 return;
2595 }
2596
2597 if ((next == m_tracks[kTrackTypeAudio].end()) ||
2598 (next->m_av_stream_index != streamIndex))
2599 {
2600 QString msg = QString(
2601 "Expected substream 1 (Language I) of stream %1\n\t\t\t"
2602 "following substream 0, found end of list or another stream.")
2603 .arg(streamIndex);
2604
2605 LOG(VB_GENERAL, LOG_WARNING, LOC + msg);
2606
2607 return;
2608 }
2609
2610 // Remove extra stream info
2611 StreamInfo stream = *current;
2612 stream.m_av_substream_index = -1;
2613 *current = stream;
2614 m_tracks[kTrackTypeAudio].erase(next);
2615}
2616
2622{
2623 if (!m_audio->HasAudioIn())
2624 return;
2625
2626 m_avCodecLock.lock();
2627 bool do_flush = false;
2628 for (uint i = 0; i < m_ic->nb_streams; i++)
2629 {
2630 AVStream *st = m_ic->streams[i];
2631 st->index = i;
2632 AVCodecContext *avctx = m_codecMap.FindCodecContext(st);
2633 if (avctx && avctx->codec_type == AVMEDIA_TYPE_AUDIO)
2634 {
2636 LOG(VB_LIBAV, LOG_DEBUG, QString("removing audio stream (id: 0x%1, index: %2, nb_streams: %3)")
2637 .arg(QString::number(st->id, 16),
2638 QString::number(i),
2639 QString::number(m_ic->nb_streams)
2640 )
2641 );
2642 m_ic->nb_streams--;
2643 if ((m_ic->nb_streams - i) > 0) {
2644 std::memmove(reinterpret_cast<void*>(&m_ic->streams[i]),
2645 reinterpret_cast<const void*>(&m_ic->streams[i + 1]),
2646 (m_ic->nb_streams - i) * sizeof(AVFormatContext*));
2647 }
2648 else
2649 {
2650 m_ic->streams[i] = nullptr;
2651 }
2652 do_flush = true;
2653 i--;
2654 }
2655 }
2656 if (do_flush)
2657 {
2658 avformat_flush(m_ic);
2659 }
2660 m_avCodecLock.unlock();
2661}
2662
2663int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
2664{
2665 auto *decoder = static_cast<AvFormatDecoder*>(c->opaque);
2667 if (!std::any_of(decoder->m_renderFormats->cbegin(), decoder->m_renderFormats->cend(),
2668 [&type](auto Format) { return type == Format; }))
2669 {
2670 decoder->m_directRendering = false;
2671 return avcodec_default_get_buffer2(c, pic, flags);
2672 }
2673
2674 decoder->m_directRendering = true;
2675 MythVideoFrame *frame = decoder->GetPlayer()->GetNextVideoFrame();
2676 if (!frame)
2677 return -1;
2678
2679 // We pre-allocate frames to certain alignments. If the coded size differs from
2680 // those alignments then re-allocate the frame. Changes in frame type (e.g.
2681 // YV12 to NV12) are always reallocated.
2682 int width = (frame->m_width + MYTH_WIDTH_ALIGNMENT - 1) & ~(MYTH_WIDTH_ALIGNMENT - 1);
2683 int height = (frame->m_height + MYTH_HEIGHT_ALIGNMENT - 1) & ~(MYTH_HEIGHT_ALIGNMENT - 1);
2684
2685 if ((frame->m_type != type) || (pic->width > width) || (pic->height > height))
2686 {
2687 if (!VideoBuffers::ReinitBuffer(frame, type, decoder->m_videoCodecId, pic->width, pic->height))
2688 return -1;
2689 // NB the video frame may now have a new size which is currenly not an issue
2690 // as the underlying size has already been passed through to the player.
2691 // But may cause issues down the line. We should add coded_width/height to
2692 // VideoFrame as well to ensure consistentency through the rendering
2693 // pipeline.
2694 // NB remember to compare coded width/height - not 'true' values - otherwsie
2695 // we continually re-allocate the frame.
2696 //frame->width = c->width;
2697 //frame->height = c->height;
2698 }
2699
2700 frame->m_colorshifted = false;
2702 for (uint i = 0; i < 3; i++)
2703 {
2704 pic->data[i] = (i < max) ? (frame->m_buffer + frame->m_offsets[i]) : nullptr;
2705 pic->linesize[i] = frame->m_pitches[i];
2706 }
2707
2708 pic->opaque = frame;
2709
2710 // Set release method
2711 AVBufferRef *buffer = av_buffer_create(reinterpret_cast<uint8_t*>(frame), 0,
2712 [](void* Opaque, uint8_t* Data)
2713 {
2714 auto *avfd = static_cast<AvFormatDecoder*>(Opaque);
2715 auto *vf = reinterpret_cast<MythVideoFrame*>(Data);
2716 if (avfd && avfd->GetPlayer())
2717 avfd->GetPlayer()->DeLimboFrame(vf);
2718 }
2719 , decoder, 0);
2720 pic->buf[0] = buffer;
2721
2722 return 0;
2723}
2724
2725#if CONFIG_DXVA2
2726int get_avf_buffer_dxva2(struct AVCodecContext *c, AVFrame *pic, int /*flags*/)
2727{
2728 AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque);
2729 MythVideoFrame *frame = nd->GetPlayer()->GetNextVideoFrame();
2730
2731 for (int i = 0; i < 4; i++)
2732 {
2733 pic->data[i] = nullptr;
2734 pic->linesize[i] = 0;
2735 }
2736 pic->opaque = frame;
2737 frame->m_pixFmt = c->pix_fmt;
2738 pic->data[0] = (uint8_t*)frame->m_buffer;
2739 pic->data[3] = (uint8_t*)frame->m_buffer;
2740
2741 // Set release method
2742 AVBufferRef *buffer =
2743 av_buffer_create((uint8_t*)frame, 0,
2744 [](void* Opaque, uint8_t* Data)
2745 {
2746 AvFormatDecoder *avfd = static_cast<AvFormatDecoder*>(Opaque);
2747 MythVideoFrame *vf = reinterpret_cast<MythVideoFrame*>(Data);
2748 if (avfd && avfd->GetPlayer())
2749 avfd->GetPlayer()->DeLimboFrame(vf);
2750 }
2751 , nd, 0);
2752 pic->buf[0] = buffer;
2753
2754 return 0;
2755}
2756#endif
2757
2758void AvFormatDecoder::DecodeCCx08(const uint8_t *buf, uint buf_size)
2759{
2760 if (buf_size < 3)
2761 return;
2762
2763 bool had_608 = false;
2764 bool had_708 = false;
2765 for (uint cur = 0; cur + 2 < buf_size; cur += 3)
2766 {
2767 uint cc_code = buf[cur];
2768 bool cc_valid = (cc_code & 0x04) != 0U;
2769
2770 uint data1 = buf[cur+1];
2771 uint data2 = buf[cur+2];
2772 uint data = (data2 << 8) | data1;
2773 uint cc_type = cc_code & 0x03;
2774
2775 if (!cc_valid)
2776 {
2777 continue;
2778 }
2779
2780 if (cc_type <= 0x1) // EIA-608 field-1/2
2781 {
2782 if (cc608_good_parity(data))
2783 {
2784 had_608 = true;
2785 m_ccd608->FormatCCField(duration_cast<std::chrono::milliseconds>(m_lastCcPtsu), cc_type, data);
2786 }
2787 }
2788 else
2789 {
2790 had_708 = true;
2791 m_ccd708->decode_cc_data(cc_type, data1, data2);
2792 }
2793 }
2794 UpdateCaptionTracksFromStreams(had_608, had_708);
2795}
2796
2798 bool check_608, bool check_708)
2799{
2800 bool need_change_608 = false;
2801 CC608Seen seen_608;
2802 if (check_608)
2803 {
2804 m_ccd608->GetServices(15s, seen_608);
2805 for (uint i = 0; i < 4; i++)
2806 {
2807 need_change_608 |= (seen_608[i] && !m_ccX08InTracks[i]) ||
2808 (!seen_608[i] && m_ccX08InTracks[i] && !m_ccX08InPmt[i]);
2809 }
2810 }
2811
2812 bool need_change_708 = false;
2813 cc708_seen_flags seen_708;
2814 if (check_708 || need_change_608)
2815 {
2816 m_ccd708->services(15s, seen_708);
2817 for (uint i = 1; i < 64 && !need_change_608 && !need_change_708; i++)
2818 {
2819 need_change_708 |= (seen_708[i] && !m_ccX08InTracks[i+4]) ||
2820 (!seen_708[i] && m_ccX08InTracks[i+4] && !m_ccX08InPmt[i+4]);
2821 }
2822 if (need_change_708 && !check_608)
2823 m_ccd608->GetServices(15s, seen_608);
2824 }
2825
2826 if (!need_change_608 && !need_change_708)
2827 return;
2828
2829 m_trackLock.lock();
2830
2832
2833 m_streamTracks.clear();
2834 m_streamTrackTypes.clear();
2835 int av_index = m_selectedTrack[kTrackTypeVideo].m_av_stream_index;
2836 int lang = iso639_str3_to_key("und");
2837 for (int i = 1; i < 64; i++)
2838 {
2839 if (seen_708[i] && !m_ccX08InPmt[i+4])
2840 {
2841 StreamInfo si {av_index, i, lang};
2842 m_streamTracks.push_back(si);
2844 }
2845 }
2846 for (int i = 0; i < 4; i++)
2847 {
2848 if (seen_608[i] && !m_ccX08InPmt[i])
2849 {
2850 if (0==i)
2852 else if (2==i)
2854 else
2855 lang = iso639_str3_to_key("und");
2856
2857 StreamInfo si {av_index, i+1, lang};
2858 m_streamTracks.push_back(si);
2860 }
2861 }
2862 m_trackLock.unlock();
2864}
2865
2867 AVPacket *pkt, bool can_reliably_parse_keyframes)
2868{
2869 if (m_prevGopPos != 0 && m_keyframeDist != 1)
2870 {
2871 int tempKeyFrameDist = m_framesRead - 1 - m_prevGopPos;
2872 bool reset_kfd = false;
2873
2874 if (!m_gopSet || m_livetv) // gopset: we've seen 2 keyframes
2875 {
2876 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2877 "gopset not set, syncing positionMap");
2879 if (tempKeyFrameDist > 0 && !m_livetv)
2880 {
2881 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2882 QString("Initial key frame distance: %1.")
2883 .arg(m_keyframeDist));
2884 m_gopSet = true;
2885 reset_kfd = true;
2886 }
2887 }
2888 else if (m_keyframeDist != tempKeyFrameDist && tempKeyFrameDist > 0)
2889 {
2890 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2891 QString("Key frame distance changed from %1 to %2.")
2892 .arg(m_keyframeDist).arg(tempKeyFrameDist));
2893 reset_kfd = true;
2894 }
2895
2896 if (reset_kfd)
2897 {
2898 m_keyframeDist = tempKeyFrameDist;
2900
2902
2903#if 0
2904 // also reset length
2905 QMutexLocker locker(&m_positionMapLock);
2906 if (!m_positionMap.empty())
2907 {
2908 long long index = m_positionMap.back().index;
2909 long long totframes = index * m_keyframeDist;
2910 uint length = (uint)((totframes * 1.0F) / m_fps);
2911 m_parent->SetFileLength(length, totframes);
2912 }
2913#endif
2914 }
2915 }
2916
2918
2919 if (can_reliably_parse_keyframes &&
2921 {
2922 long long last_frame = 0;
2923 {
2924 QMutexLocker locker(&m_positionMapLock);
2925 if (!m_positionMap.empty())
2926 last_frame = m_positionMap.back().index;
2927 }
2928
2929#if 0
2930 LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
2931 QString("framesRead: %1 last_frame: %2 keyframedist: %3")
2932 .arg(m_framesRead) .arg(last_frame) .arg(m_keyframeDist));
2933#endif
2934
2935 // if we don't have an entry, fill it in with what we've just parsed
2936 if (m_framesRead > last_frame && m_keyframeDist > 0)
2937 {
2938 long long startpos = pkt->pos;
2939
2940 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
2941 QString("positionMap[ %1 ] == %2.")
2942 .arg(m_framesRead).arg(startpos));
2943
2944 PosMapEntry entry = {m_framesRead, m_framesRead, startpos};
2945
2946 QMutexLocker locker(&m_positionMapLock);
2947 // Create a dummy positionmap entry for frame 0 so that
2948 // seeking will work properly. (See
2949 // DecoderBase::FindPosition() which subtracts
2950 // DecoderBase::indexOffset from each frame number.)
2951 if (m_positionMap.empty())
2952 {
2953 PosMapEntry dur = {0, 0, 0};
2954 m_positionMap.push_back(dur);
2955 }
2956 m_positionMap.push_back(entry);
2958 {
2959 long long duration = m_totalDuration.toFixed(1000LL);
2960 m_frameToDurMap[m_framesRead] = duration;
2961 m_durToFrameMap[duration] = m_framesRead;
2962 }
2963 }
2964
2965#if 0
2966 // If we are > 150 frames in and saw no positionmap at all, reset
2967 // length based on the actual bitrate seen so far
2969 {
2970 m_bitrate = (int)((pkt->pos * 8 * m_fps) / (m_framesRead - 1));
2971 float bytespersec = (float)m_bitrate / 8;
2972 float secs = m_ringBuffer->GetRealFileSize() * 1.0F / bytespersec;
2973 m_parent->SetFileLength((int)(secs), (int)(secs * m_fps));
2974 }
2975#endif
2976 }
2977}
2978
2979static constexpr uint32_t SEQ_START { 0x000001b3 };
2980static constexpr uint32_t GOP_START { 0x000001b8 };
2981//static constexpr uint32_t PICTURE_START { 0x00000100 };
2982static constexpr uint32_t SLICE_MIN { 0x00000101 };
2983static constexpr uint32_t SLICE_MAX { 0x000001af };
2984//static constexpr uint32_t SEQ_END_CODE { 0x000001b7 };
2985
2986void AvFormatDecoder::MpegPreProcessPkt(AVCodecContext* context, AVStream *stream, AVPacket *pkt)
2987{
2988 const uint8_t *bufptr = pkt->data;
2989 const uint8_t *bufend = pkt->data + pkt->size;
2990
2991 while (bufptr < bufend)
2992 {
2994
2995 float aspect_override = -1.0F;
2996 if (m_ringBuffer->IsDVD())
2997 aspect_override = m_ringBuffer->DVD()->GetAspectOverride();
2998
3000 continue;
3001
3003 {
3004 if (bufptr + 11 >= pkt->data + pkt->size)
3005 continue; // not enough valid data...
3006 const auto *seq = reinterpret_cast<const SequenceHeader*>(bufptr);
3007
3008 int width = static_cast<int>(seq->width()) >> context->lowres;
3009 int height = static_cast<int>(seq->height()) >> context->lowres;
3010 float aspect = seq->aspect(context->codec_id == AV_CODEC_ID_MPEG1VIDEO);
3011 if (stream->sample_aspect_ratio.num)
3012 aspect = static_cast<float>(av_q2d(stream->sample_aspect_ratio) * width / height);
3013 if (aspect_override > 0.0F)
3014 aspect = aspect_override;
3015 float seqFPS = seq->fps();
3016
3017 bool changed = (width != m_currentWidth );
3018 changed |= (height != m_currentHeight);
3019 changed |= (seqFPS > static_cast<float>(m_fps)+0.01F) ||
3020 (seqFPS < static_cast<float>(m_fps)-0.01F);
3021
3022 // some hardware decoders (e.g. VAAPI MPEG2) will reset when the aspect
3023 // ratio changes
3024 bool forceaspectchange = !qFuzzyCompare(m_currentAspect + 10.0F, aspect + 10.0F) &&
3026 m_currentAspect = aspect;
3027
3028 if (changed || forceaspectchange)
3029 {
3030 // N.B. We now set the default scan to kScan_Ignore as interlaced detection based on frame
3031 // size and rate is extremely error prone and FFmpeg gets it right far more often.
3032 // As for H.264, if a decoder deinterlacer is in operation - the stream must be progressive
3033 bool doublerate = false;
3034 bool decoderdeint = m_mythCodecCtx && m_mythCodecCtx->IsDeinterlacing(doublerate, true);
3035 m_parent->SetVideoParams(width, height, static_cast<double>(seqFPS), m_currentAspect,
3036 forceaspectchange, 2,
3037 decoderdeint ? kScan_Progressive : kScan_Ignore);
3038
3039 if (context->hw_frames_ctx)
3040 if (context->internal)
3041 avcodec_flush_buffers(context);
3042
3043 m_currentWidth = width;
3044 m_currentHeight = height;
3045 m_fps = seqFPS;
3046
3047 m_gopSet = false;
3048 m_prevGopPos = 0;
3050 m_lastCcPtsu = 0us;
3051 m_firstVPtsInuse = true;
3052
3053 // fps debugging info
3054 float avFPS = GetVideoFrameRate(stream, context);
3055 if ((seqFPS > avFPS+0.01F) || (seqFPS < avFPS-0.01F))
3056 {
3057 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("avFPS(%1) != seqFPS(%2)")
3058 .arg(static_cast<double>(avFPS)).arg(static_cast<double>(seqFPS)));
3059 }
3060 }
3061
3062 m_seqCount++;
3063
3064 if (!m_seenGop && m_seqCount > 1)
3065 {
3066 HandleGopStart(pkt, true);
3067 pkt->flags |= AV_PKT_FLAG_KEY;
3068 }
3069 }
3070 else if (GOP_START == m_startCodeState)
3071 {
3072 HandleGopStart(pkt, true);
3073 m_seenGop = true;
3074 pkt->flags |= AV_PKT_FLAG_KEY;
3075 }
3076 }
3077}
3078
3079// Returns the number of frame starts identified in the packet.
3080int AvFormatDecoder::H264PreProcessPkt(AVCodecContext* context, AVStream *stream, AVPacket *pkt)
3081{
3082 const uint8_t *buf = pkt->data;
3083 const uint8_t *buf_end = pkt->data + pkt->size;
3084 int num_frames = 0;
3085
3086 // The parser only understands Annex B/bytestream format - so check for avCC
3087 // format (starts with 0x01) and rely on FFmpeg keyframe detection
3088 if (context->extradata && (context->extradata_size >= 7) && (context->extradata[0] == 0x01))
3089 {
3090 if (pkt->flags & AV_PKT_FLAG_KEY)
3091 HandleGopStart(pkt, false);
3092 return 1;
3093 }
3094
3095 while (buf < buf_end)
3096 {
3097 buf += m_avcParser->addBytes(buf, static_cast<unsigned int>(buf_end - buf), 0);
3098
3100 {
3102 {
3104 ++num_frames;
3105
3107 continue;
3108 }
3109 else
3110 {
3111 continue;
3112 }
3113 }
3114 else
3115 {
3116 continue;
3117 }
3118
3120 float aspect = get_aspect(*m_avcParser);
3121 int width = static_cast<int>(m_avcParser->pictureWidthCropped());
3122 int height = static_cast<int>(m_avcParser->pictureHeightCropped());
3123 double seqFPS = m_avcParser->frameRate();
3124
3125 bool res_changed = ((width != m_currentWidth) || (height != m_currentHeight));
3126 bool fps_changed = (seqFPS > 0.0) && ((seqFPS > m_fps + 0.01) ||
3127 (seqFPS < m_fps - 0.01));
3128 bool forcechange = !qFuzzyCompare(aspect + 10.0F, m_currentAspect) &&
3130 m_currentAspect = aspect;
3131
3132 if (fps_changed || res_changed || forcechange)
3133 {
3134 // N.B. we now set the default scan to kScan_Ignore as interlaced detection based on frame
3135 // size and rate is extremely error prone and FFmpeg gets it right far more often.
3136 // N.B. if a decoder deinterlacer is in use - the stream must be progressive
3137 bool doublerate = false;
3138 bool decoderdeint = m_mythCodecCtx ? m_mythCodecCtx->IsDeinterlacing(doublerate, true) : false;
3139 m_parent->SetVideoParams(width, height, seqFPS, m_currentAspect, forcechange,
3140 static_cast<int>(m_avcParser->getRefFrames()),
3141 decoderdeint ? kScan_Progressive : kScan_Ignore);
3142
3143 // the SetVideoParams call above will have released all held frames
3144 // when using a hardware frames context - but for H264 (as opposed to mpeg2)
3145 // the codec will still hold references for reference frames (decoded picture buffer).
3146 // Flushing the context will release these references and the old
3147 // hardware context is released correctly before a new one is created.
3148 // TODO check what is needed here when a device context is used
3149 // TODO check whether any codecs need to be flushed for a frame rate change (e.g. mediacodec?)
3150 if (context->hw_frames_ctx && (forcechange || res_changed))
3151 if (context->internal)
3152 avcodec_flush_buffers(context);
3153
3154 m_currentWidth = width;
3155 m_currentHeight = height;
3156
3157 if (seqFPS > 0.0)
3158 m_fps = static_cast<float>(seqFPS);
3159
3160 m_gopSet = false;
3161 m_prevGopPos = 0;
3163 m_lastCcPtsu = 0us;
3164 m_firstVPtsInuse = true;
3165
3166 // fps debugging info
3167 auto avFPS = static_cast<double>(GetVideoFrameRate(stream, context));
3168 if ((seqFPS > avFPS + 0.01) || (seqFPS < avFPS - 0.01))
3169 {
3170 LOG(VB_PLAYBACK, LOG_INFO, LOC +
3171 QString("avFPS(%1) != seqFPS(%2)").arg(avFPS).arg(seqFPS));
3172 }
3173 }
3174
3175 HandleGopStart(pkt, true);
3176 pkt->flags |= AV_PKT_FLAG_KEY;
3177 }
3178
3179 return num_frames;
3180}
3181
3182bool AvFormatDecoder::PreProcessVideoPacket(AVCodecContext* context, AVStream *curstream, AVPacket *pkt)
3183{
3184 int num_frames = 1;
3185
3186 if (CODEC_IS_MPEG(context->codec_id))
3187 {
3188 MpegPreProcessPkt(context, curstream, pkt);
3189 }
3190 else if (CODEC_IS_H264(context->codec_id))
3191 {
3192 num_frames = H264PreProcessPkt(context, curstream, pkt);
3193 }
3194 else
3195 {
3196 if (pkt->flags & AV_PKT_FLAG_KEY)
3197 {
3198 HandleGopStart(pkt, false);
3199 m_seenGop = true;
3200 }
3201 else
3202 {
3203 m_seqCount++;
3204 if (!m_seenGop && m_seqCount > 1)
3205 {
3206 HandleGopStart(pkt, false);
3207 }
3208 }
3209 }
3210
3211 if (m_framesRead == 0 && !m_justAfterChange &&
3212 !(pkt->flags & AV_PKT_FLAG_KEY))
3213 {
3214 av_packet_unref(pkt);
3215 return false;
3216 }
3217
3218 m_framesRead += num_frames;
3219
3221 {
3222 // The ffmpeg libraries represent a frame interval of a
3223 // 59.94fps video as 1501/90000 seconds, when it should
3224 // actually be 1501.5/90000 seconds.
3225 MythAVRational pkt_dur {static_cast<int>(pkt->duration)};
3226 pkt_dur *= MythAVRational(curstream->time_base);
3227 if (pkt_dur == MythAVRational(1501, 90000))
3228 pkt_dur = MythAVRational(1001, 60000); // 1501.5/90000
3229 m_totalDuration += pkt_dur;
3230 }
3231
3232 m_justAfterChange = false;
3233
3235 m_gotVideoFrame = true;
3236
3237 return true;
3238}
3239
3240bool AvFormatDecoder::ProcessVideoPacket(AVCodecContext* context, AVStream *curstream, AVPacket *pkt, bool &Retry)
3241{
3242 int ret = 0;
3243 int gotpicture = 0;
3244 MythAVFrame mpa_pic;
3245 if (!mpa_pic)
3246 return false;
3247
3248 bool sentPacket = false;
3249 int ret2 = 0;
3250
3251 m_avCodecLock.lock();
3252
3253 // SUGGESTION
3254 // Now that avcodec_decode_video2 is deprecated and replaced
3255 // by 2 calls (receive frame and send packet), this could be optimized
3256 // into separate routines or separate threads.
3257 // Also now that it always consumes a whole buffer some code
3258 // in the caller may be able to be optimized.
3259
3260 // FilteredReceiveFrame will call avcodec_receive_frame and
3261 // apply any codec-dependent filtering
3262 ret = m_mythCodecCtx->FilteredReceiveFrame(context, mpa_pic);
3263
3264 if (ret == 0)
3265 gotpicture = 1;
3266 else
3267 gotpicture = 0;
3268 if (ret == AVERROR(EAGAIN))
3269 ret = 0;
3270 // If we got a picture do not send the packet until we have
3271 // all available pictures
3272 if (ret==0 && !gotpicture)
3273 {
3274 ret2 = avcodec_send_packet(context, pkt);
3275 if (ret2 == AVERROR(EAGAIN))
3276 {
3277 Retry = true;
3278 ret2 = 0;
3279 }
3280 else
3281 {
3282 sentPacket = true;
3283 }
3284 }
3285 m_avCodecLock.unlock();
3286
3287 if (ret < 0 || ret2 < 0)
3288 {
3289 std::string error;
3290 if (ret < 0)
3291 {
3292 LOG(VB_GENERAL, LOG_ERR, LOC +
3293 QString("video avcodec_receive_frame error: %1 (%2) gotpicture:%3")
3294 .arg(av_make_error_stdstring(error, ret))
3295 .arg(ret).arg(gotpicture));
3296 }
3297
3298 if (ret2 < 0)
3299 {
3300 LOG(VB_GENERAL, LOG_ERR, LOC +
3301 QString("video avcodec_send_packet error: %1 (%2) gotpicture:%3")
3302 .arg(av_make_error_stdstring(error, ret2))
3303 .arg(ret2).arg(gotpicture));
3304 }
3305
3307 {
3308 // If erroring on GPU assist, try switching to software decode
3310 m_parent->SetErrored(QObject::tr("Video Decode Error"));
3311 else
3312 m_streamsChanged = true;
3313 }
3314
3315 if (m_mythCodecCtx->DecoderNeedsReset(context))
3316 {
3317 LOG(VB_GENERAL, LOG_INFO, LOC + "Decoder needs reset");
3319 }
3320
3321 if (ret == AVERROR_EXTERNAL || ret2 == AVERROR_EXTERNAL)
3322 {
3323 LOG(VB_PLAYBACK, LOG_INFO, LOC + "FFmpeg external library error - assuming streams changed");
3324 m_streamsChanged = true;
3325 }
3326
3327 return false;
3328 }
3329
3330 // averror_count counts sequential errors, so if you have a successful
3331 // packet then reset it
3332 m_averrorCount = 0;
3333 if (gotpicture)
3334 {
3335 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
3336 QString("video timecodes packet-pts:%1 frame-pts:%2 packet-dts: %3 frame-dts:%4")
3337 .arg(pkt->pts).arg(mpa_pic->pts).arg(pkt->dts)
3338 .arg(mpa_pic->pkt_dts));
3339
3340 ProcessVideoFrame(context, curstream, mpa_pic);
3341 }
3342
3343 if (!sentPacket)
3344 {
3345 // MythTV logic expects that only one frame is processed
3346 // Save the packet for later and return.
3347 auto *newPkt = av_packet_clone(pkt);
3348 if (newPkt)
3349 m_storedPackets.prepend(newPkt);
3350 }
3351 return true;
3352}
3353
3354bool AvFormatDecoder::ProcessVideoFrame(AVCodecContext* context, AVStream *Stream, AVFrame *AvFrame)
3355{
3356 // look for A53 captions
3357 auto * side_data = av_frame_get_side_data(AvFrame, AV_FRAME_DATA_A53_CC);
3358 if (side_data && (side_data->size > 0))
3359 DecodeCCx08(side_data->data, static_cast<uint>(side_data->size));
3360
3361 auto * frame = static_cast<MythVideoFrame*>(AvFrame->opaque);
3362 if (frame)
3364
3366 {
3367 // Do nothing, we just want the pts, captions, subtites, etc.
3368 // So we can release the unconverted blank video frame to the
3369 // display queue.
3370 if (frame)
3371 frame->m_directRendering = false;
3372 }
3373 else if (!m_directRendering)
3374 {
3375 MythVideoFrame *oldframe = frame;
3376 frame = m_parent->GetNextVideoFrame();
3377 frame->m_directRendering = false;
3378
3379 if (!m_mythCodecCtx->RetrieveFrame(context, frame, AvFrame))
3380 {
3381 AVFrame tmppicture;
3382 av_image_fill_arrays(tmppicture.data, tmppicture.linesize,
3383 frame->m_buffer, AV_PIX_FMT_YUV420P, AvFrame->width,
3384 AvFrame->height, IMAGE_ALIGN);
3385 tmppicture.data[0] = frame->m_buffer + frame->m_offsets[0];
3386 tmppicture.data[1] = frame->m_buffer + frame->m_offsets[1];
3387 tmppicture.data[2] = frame->m_buffer + frame->m_offsets[2];
3388 tmppicture.linesize[0] = frame->m_pitches[0];
3389 tmppicture.linesize[1] = frame->m_pitches[1];
3390 tmppicture.linesize[2] = frame->m_pitches[2];
3391
3392 QSize dim = get_video_dim(*context);
3393 m_swsCtx = sws_getCachedContext(m_swsCtx, AvFrame->width,
3394 AvFrame->height, static_cast<AVPixelFormat>(AvFrame->format),
3395 AvFrame->width, AvFrame->height,
3396 AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
3397 nullptr, nullptr, nullptr);
3398 if (!m_swsCtx)
3399 {
3400 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate sws context");
3401 return false;
3402 }
3403 sws_scale(m_swsCtx, AvFrame->data, AvFrame->linesize, 0, dim.height(),
3404 tmppicture.data, tmppicture.linesize);
3405 }
3406
3407 // Discard any old VideoFrames
3408 if (oldframe)
3409 {
3410 // Set the frame flags, but then discard it
3411 // since we are not using it for display.
3412 oldframe->m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3413 oldframe->m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3414 oldframe->m_colorspace = AvFrame->colorspace;
3415 oldframe->m_colorrange = AvFrame->color_range;
3416 oldframe->m_colorprimaries = AvFrame->color_primaries;
3417 oldframe->m_colortransfer = AvFrame->color_trc;
3418 oldframe->m_chromalocation = AvFrame->chroma_location;
3419 oldframe->m_frameNumber = m_framesPlayed;
3420 oldframe->m_frameCounter = m_frameCounter++;
3421 oldframe->m_aspect = m_currentAspect;
3422 oldframe->m_rotation = m_videoRotation;
3423 oldframe->m_stereo3D = m_stereo3D;
3424
3425 oldframe->m_dummy = false;
3426 oldframe->m_pauseFrame = false;
3427 oldframe->m_interlacedReverse = false;
3428 oldframe->m_newGOP = false;
3429 oldframe->m_deinterlaceInuse = DEINT_NONE;
3430 oldframe->m_deinterlaceInuse2x = false;
3431 oldframe->m_alreadyDeinterlaced = false;
3432
3433 m_parent->DiscardVideoFrame(oldframe);
3434 }
3435 }
3436
3437 if (!frame)
3438 {
3439 LOG(VB_GENERAL, LOG_ERR, LOC + "NULL videoframe - direct rendering not "
3440 "correctly initialized.");
3441 return false;
3442 }
3443
3444
3445 if (AvFrame->best_effort_timestamp == AV_NOPTS_VALUE)
3446 {
3447 LOG(VB_GENERAL, LOG_ERR, LOC + "No PTS found - unable to process video.");
3448 return false;
3449 }
3450 std::chrono::milliseconds pts = millisecondsFromFloat(av_q2d(Stream->time_base) *
3451 AvFrame->best_effort_timestamp * 1000);
3452 std::chrono::milliseconds temppts = pts;
3453 // Validate the video pts against the last pts. If it's
3454 // a little bit smaller, equal or missing, compute
3455 // it from the last. Otherwise assume a wraparound.
3456 if (!m_ringBuffer->IsDVD() &&
3457 temppts <= m_lastVPts &&
3458 (temppts + millisecondsFromFloat(1000 / m_fps) > m_lastVPts ||
3459 temppts <= 0ms))
3460 {
3461 temppts = m_lastVPts;
3462 temppts += millisecondsFromFloat(1000 / m_fps);
3463 // MPEG2/H264 frames can be repeated, update pts accordingly
3464 temppts += millisecondsFromFloat(AvFrame->repeat_pict * 500 / m_fps);
3465 }
3466
3467 // Calculate actual fps from the pts values.
3468 std::chrono::milliseconds ptsdiff = temppts - m_lastVPts;
3469 double calcfps = 1000.0 / ptsdiff.count();
3470 if (calcfps < 121.0 && calcfps > 3.0)
3471 {
3472 // If fps has doubled due to frame-doubling deinterlace
3473 // Set fps to double value.
3474 double fpschange = calcfps / m_fps;
3475 int prior = m_fpsMultiplier;
3476 if (fpschange > 1.9 && fpschange < 2.1)
3477 m_fpsMultiplier = 2;
3478 if (fpschange > 0.9 && fpschange < 1.1)
3479 m_fpsMultiplier = 1;
3480 if (m_fpsMultiplier != prior)
3482 }
3483
3484 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
3485 QString("video timecode %1 %2 %3 %4%5")
3486 .arg(AvFrame->best_effort_timestamp)
3487 .arg(pts.count()).arg(temppts.count()).arg(m_lastVPts.count())
3488 .arg((pts != temppts) ? " fixup" : ""));
3489
3490 frame->m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3491 frame->m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3492 frame->m_newGOP = m_nextDecodedFrameIsKeyFrame;
3493 frame->m_repeatPic = AvFrame->repeat_pict != 0;
3494 frame->m_displayTimecode = NormalizeVideoTimecode(Stream, std::chrono::milliseconds(temppts));
3495 frame->m_frameNumber = m_framesPlayed;
3496 frame->m_frameCounter = m_frameCounter++;
3497 frame->m_aspect = m_currentAspect;
3498 frame->m_colorspace = AvFrame->colorspace;
3499 frame->m_colorrange = AvFrame->color_range;
3500 frame->m_colorprimaries = AvFrame->color_primaries;
3501 frame->m_colortransfer = AvFrame->color_trc;
3502 frame->m_chromalocation = AvFrame->chroma_location;
3503 frame->m_pixFmt = AvFrame->format;
3504 frame->m_deinterlaceInuse = DEINT_NONE;
3505 frame->m_rotation = m_videoRotation;
3506 frame->m_stereo3D = m_stereo3D;
3507
3508 frame->m_dummy = false;
3509 frame->m_pauseFrame = false;
3510 frame->m_deinterlaceInuse2x = false;
3511 frame->m_alreadyDeinterlaced = false;
3512 frame->m_interlacedReverse = false;
3513
3514 // Retrieve HDR metadata
3515 MythHDRVideoMetadata::Populate(frame, AvFrame);
3516
3517 m_parent->ReleaseNextVideoFrame(frame, std::chrono::milliseconds(temppts));
3518 m_mythCodecCtx->PostProcessFrame(context, frame);
3519
3521 m_decodedVideoFrame = frame;
3522 m_gotVideoFrame = true;
3523 if (++m_fpsSkip >= m_fpsMultiplier)
3524 {
3526 m_fpsSkip = 0;
3527 }
3528
3529 m_lastVPts = temppts;
3530 if ((m_firstVPts == 0ms) && m_firstVPtsInuse)
3531 m_firstVPts = temppts;
3532
3533 return true;
3534}
3535
3542 [[maybe_unused]] const AVStream *stream, const AVPacket *pkt)
3543{
3544 const uint8_t *buf = pkt->data;
3545 uint64_t linemask = 0;
3546 std::chrono::microseconds utc = m_lastCcPtsu;
3547
3548 // [i]tv0 means there is a linemask
3549 // [I]TV0 means there is no linemask and all lines are present
3550 if ((buf[0]=='t') && (buf[1]=='v') && (buf[2] == '0'))
3551 {
3553 memcpy(&linemask, buf + 3, 8);
3554 buf += 11;
3555 }
3556 else if ((buf[0]=='T') && (buf[1]=='V') && (buf[2] == '0'))
3557 {
3558 linemask = 0xffffffffffffffffLL;
3559 buf += 3;
3560 }
3561 else
3562 {
3563 LOG(VB_VBI, LOG_ERR, LOC + QString("Unknown VBI data stream '%1%2%3'")
3564 .arg(QChar(buf[0])).arg(QChar(buf[1])).arg(QChar(buf[2])));
3565 return;
3566 }
3567
3568 static constexpr uint kMinBlank = 6;
3569 for (uint i = 0; i < 36; i++)
3570 {
3571 if (!((linemask >> i) & 0x1))
3572 continue;
3573
3574 const uint line = ((i < 18) ? i : i-18) + kMinBlank;
3575 const uint field = (i<18) ? 0 : 1;
3576 const uint id2 = *buf & 0xf;
3577 switch (id2)
3578 {
3580 // SECAM lines 6-23
3581 // PAL lines 6-22
3582 // NTSC lines 10-21 (rare)
3583 m_trackLock.lock();
3584 if (m_tracks[kTrackTypeTeletextMenu].empty())
3585 {
3586 StreamInfo si {pkt->stream_index, 0};
3587 m_trackLock.lock();
3588 m_tracks[kTrackTypeTeletextMenu].push_back(si);
3589 m_trackLock.unlock();
3591 }
3592 m_trackLock.unlock();
3593 m_ttd->Decode(buf+1, VBI_IVTV);
3594 break;
3596 // PAL line 22 (rare)
3597 // NTSC line 21
3598 if (21 == line)
3599 {
3600 int data = (buf[2] << 8) | buf[1];
3601 if (cc608_good_parity(data))
3602 m_ccd608->FormatCCField(duration_cast<std::chrono::milliseconds>(utc), field, data);
3603 utc += 33367us;
3604 }
3605 break;
3606 case V4L2_MPEG_VBI_IVTV_VPS: // Video Programming System
3607 // PAL line 16
3608 m_ccd608->DecodeVPS(buf+1); // a.k.a. PDC
3609 break;
3610 case V4L2_MPEG_VBI_IVTV_WSS_625: // Wide Screen Signal
3611 // PAL line 23
3612 // NTSC line 20
3613 m_ccd608->DecodeWSS(buf+1);
3614 break;
3615 }
3616 buf += 43;
3617 }
3618 m_lastCcPtsu = utc;
3619 UpdateCaptionTracksFromStreams(true, false);
3620}
3621
3627 const AVStream* /*stream*/, const AVPacket *pkt)
3628{
3629 // ETSI EN 301 775 V1.2.1 (2003-05)
3630 // Check data_identifier value
3631 // Defined in 4.4.2 Semantics for PES data field, Table 2
3632 // Support only the "low range" 0x10-0x1F because they have
3633 // the fixed data_unit_length of 0x2C (44) that the teletext
3634 // decoder expects.
3635 //
3636 const uint8_t *buf = pkt->data;
3637 const uint8_t *buf_end = pkt->data + pkt->size;
3638
3639 if (*buf >= 0x10 && *buf <= 0x1F)
3640 {
3641 buf++;
3642 }
3643 else
3644 {
3645 LOG(VB_VBI, LOG_WARNING, LOC +
3646 QString("VBI: Unknown data_identier: %1 discarded").arg(*buf));
3647 return;
3648 }
3649
3650 // Process data packets in the PES packet payload
3651 while (buf < buf_end)
3652 {
3653 if (*buf == 0x02) // data_unit_id 0x02 EBU Teletext non-subtitle data
3654 {
3655 buf += 4; // Skip data_unit_id, data_unit_length (0x2C, 44) and first two data bytes
3656 if ((buf_end - buf) >= 42)
3657 m_ttd->Decode(buf, VBI_DVB);
3658 buf += 42;
3659 }
3660 else if (*buf == 0x03) // data_unit_id 0x03 EBU Teletext subtitle data
3661 {
3662 buf += 4;
3663 if ((buf_end - buf) >= 42)
3665 buf += 42;
3666 }
3667 else if (*buf == 0xff) // data_unit_id 0xff stuffing
3668 {
3669 buf += 46; // data_unit_id, data_unit_length and 44 data bytes
3670 }
3671 else
3672 {
3673 LOG(VB_VBI, LOG_WARNING, LOC +
3674 QString("VBI: Unsupported data_unit_id: %1 discarded").arg(*buf));
3675 buf += 46;
3676 }
3677 }
3678}
3679
3683void AvFormatDecoder::ProcessDSMCCPacket([[maybe_unused]] const AVStream *str,
3684 [[maybe_unused]] const AVPacket *pkt)
3685{
3686#if CONFIG_MHEG
3687 if (m_itv == nullptr)
3689 if (m_itv == nullptr)
3690 return;
3691
3692 // The packet may contain several tables.
3693 uint8_t *data = pkt->data;
3694 int length = pkt->size;
3695 int componentTag = 0;
3696 int dataBroadcastId = 0;
3697 unsigned carouselId = 0;
3698 {
3699 m_avCodecLock.lock();
3700 componentTag = str->component_tag;
3701 dataBroadcastId = str->data_id;
3702 carouselId = (unsigned) str->carousel_id;
3703 m_avCodecLock.unlock();
3704 }
3705 while (length > 3)
3706 {
3707 uint16_t sectionLen = (((data[1] & 0xF) << 8) | data[2]) + 3;
3708
3709 if (sectionLen > length) // This may well be filler
3710 return;
3711
3712 m_itv->ProcessDSMCCSection(data, sectionLen,
3713 componentTag, carouselId,
3714 dataBroadcastId);
3715 length -= sectionLen;
3716 data += sectionLen;
3717 }
3718#endif // CONFIG_MHEG
3719}
3720
3721bool AvFormatDecoder::ProcessSubtitlePacket(AVCodecContext* codecContext, AVStream *curstream, AVPacket *pkt)
3722{
3723 if (!m_parent->GetSubReader(pkt->stream_index))
3724 return true;
3725
3726 long long pts = pkt->pts;
3727 if (pts == AV_NOPTS_VALUE)
3728 pts = pkt->dts;
3729 if (pts == AV_NOPTS_VALUE)
3730 {
3731 LOG(VB_GENERAL, LOG_ERR, LOC + "No PTS found - unable to process subtitle.");
3732 return false;
3733 }
3734 pts = static_cast<long long>(av_q2d(curstream->time_base) * pts * 1000);
3735
3736 m_trackLock.lock();
3737 int subIdx = m_selectedTrack[kTrackTypeSubtitle].m_av_stream_index;
3738 int forcedSubIdx = m_selectedForcedTrack[kTrackTypeSubtitle].m_av_stream_index;
3739 bool mainTrackIsForced = m_selectedTrack[kTrackTypeSubtitle].m_forced;
3740 bool isForcedTrack = false;
3741 m_trackLock.unlock();
3742
3743 int gotSubtitles = 0;
3744 AVSubtitle subtitle;
3745 memset(&subtitle, 0, sizeof(AVSubtitle));
3746
3747 if (m_ringBuffer->IsDVD())
3748 {
3749 if (m_ringBuffer->DVD()->NumMenuButtons() > 0)
3750 {
3751 m_ringBuffer->DVD()->GetMenuSPUPkt(pkt->data, pkt->size,
3752 curstream->id, pts);
3753 }
3754 else
3755 {
3756 if (pkt->stream_index == subIdx)
3757 {
3758 m_avCodecLock.lock();
3759 m_ringBuffer->DVD()->DecodeSubtitles(&subtitle, &gotSubtitles,
3760 pkt->data, pkt->size, pts);
3761 m_avCodecLock.unlock();
3762 }
3763 }
3764 }
3765 else if (m_decodeAllSubtitles || pkt->stream_index == subIdx
3766 || pkt->stream_index == forcedSubIdx)
3767 {
3768 m_avCodecLock.lock();
3769 avcodec_decode_subtitle2(codecContext, &subtitle, &gotSubtitles, pkt);
3770 m_avCodecLock.unlock();
3771
3772 subtitle.start_display_time += pts;
3773 subtitle.end_display_time += pts;
3774
3775 if (pkt->stream_index != subIdx)
3776 isForcedTrack = true;
3777 }
3778
3779 if (gotSubtitles)
3780 {
3781 if (isForcedTrack)
3782 {
3783 for (unsigned i = 0; i < subtitle.num_rects; i++)
3784 {
3785 subtitle.rects[i]->flags |= AV_SUBTITLE_FLAG_FORCED;
3786 }
3787 }
3788 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
3789 QString("subtl timecode %1 %2 %3 %4")
3790 .arg(pkt->pts).arg(pkt->dts)
3791 .arg(subtitle.start_display_time)
3792 .arg(subtitle.end_display_time));
3793
3794 bool forcedon = m_parent->GetSubReader(pkt->stream_index)->AddAVSubtitle(
3795 subtitle, curstream->codecpar->codec_id == AV_CODEC_ID_XSUB,
3796 isForcedTrack,
3797 (m_parent->GetAllowForcedSubtitles() && !mainTrackIsForced), false);
3798 m_parent->EnableForcedSubtitles(forcedon || isForcedTrack);
3799 }
3800
3801 return true;
3802}
3803
3805{
3806 if (!m_decodeAllSubtitles && m_selectedTrack[kTrackTypeRawText].m_av_stream_index != Packet->stream_index)
3807 return false;
3808
3809 auto id = static_cast<uint>(Packet->stream_index + 0x2000);
3810 if (!m_parent->GetSubReader(id))
3811 return false;
3812
3813#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
3814 const auto * codec = QTextCodec::codecForName("utf-8");
3815 auto text = codec->toUnicode(reinterpret_cast<const char *>(Packet->data), Packet->size - 1);
3816#else
3817 auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);
3818 QString text = toUtf16.decode(Packet->data);
3819#endif
3820 auto list = text.split('\n', Qt::SkipEmptyParts);
3821 m_parent->GetSubReader(id)->AddRawTextSubtitle(list, std::chrono::milliseconds(Packet->duration));
3822 return true;
3823}
3824
3825bool AvFormatDecoder::ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
3826 [[maybe_unused]] DecodeType decodetype)
3827{
3828 enum AVCodecID codec_id = curstream->codecpar->codec_id;
3829
3830 switch (codec_id)
3831 {
3832 case AV_CODEC_ID_MPEG2VBI:
3833 ProcessVBIDataPacket(curstream, pkt);
3834 break;
3835 case AV_CODEC_ID_DVB_VBI:
3836 ProcessDVBDataPacket(curstream, pkt);
3837 break;
3838 case AV_CODEC_ID_DSMCC_B:
3839 {
3840 ProcessDSMCCPacket(curstream, pkt);
3842 // Have to return regularly to ensure that the OSD is updated.
3843 // This applies both to MHEG and also channel browsing.
3844#if CONFIG_MHEG
3845 if (!(decodetype & kDecodeVideo))
3846 m_allowedQuit |= (m_itv && m_itv->ImageHasChanged());
3847#endif // CONFIG_MHEG:
3848 break;
3849 }
3850 default:
3851 break;
3852 }
3853 return true;
3854}
3855
3856int AvFormatDecoder::SetTrack(uint Type, int TrackNo)
3857{
3858 QMutexLocker locker(&m_trackLock);
3859 int ret = DecoderBase::SetTrack(Type, TrackNo);
3860 if (kTrackTypeAudio == Type)
3861 {
3862 QString msg = SetupAudioStream() ? "" : "not ";
3863 LOG(VB_AUDIO, LOG_INFO, LOC + "Audio stream type " + msg + "changed.");
3864 }
3865 return ret;
3866}
3867
3869{
3870 QMutexLocker locker(&m_trackLock);
3871
3872 if (!m_ic || TrackNo >= m_tracks[type].size())
3873 return "";
3874
3875 bool forced = m_tracks[type][TrackNo].m_forced;
3876 int lang_key = m_tracks[type][TrackNo].m_language;
3877 QString forcedString = forced ? QObject::tr(" (forced)") : "";
3878
3879 int av_index = m_tracks[type][TrackNo].m_av_stream_index;
3880 AVStream *stream { nullptr };
3881 if (av_index >= 0 && av_index < (int)m_ic->nb_streams)
3882 stream = m_ic->streams[av_index];
3883 AVDictionaryEntry *entry =
3884 stream ? av_dict_get(stream->metadata, "title", nullptr, 0) : nullptr;
3885 QString user_title = entry ? QString(R"( "%1")").arg(entry->value) : "";
3886
3887 if (kTrackTypeAudio == type)
3888 {
3889 QString msg = iso639_key_toName(lang_key);
3890
3891 switch (m_tracks[type][TrackNo].m_audio_type)
3892 {
3893 case kAudioTypeNormal :
3894 {
3895 if (stream)
3896 {
3897 AVCodecParameters *par = stream->codecpar;
3898 AVCodecContext *ctx = m_codecMap.GetCodecContext(stream);
3899 if (par->codec_id == AV_CODEC_ID_MP3)
3900 msg += QString(" MP3");
3901 else if (ctx && ctx->codec)
3902 msg += QString(" %1").arg(ctx->codec->name).toUpper();
3903 if (!user_title.isEmpty())
3904 msg += user_title;
3905
3906 int channels = par->ch_layout.nb_channels;
3907
3908 if (channels == 0)
3909 msg += QString(" ?ch");
3910 else if((channels > 4) && !(channels & 1))
3911 msg += QString(" %1.1ch").arg(channels - 1);
3912 else
3913 msg += QString(" %1ch").arg(channels);
3914 }
3915 break;
3916 }
3922 default :
3923 if (!user_title.isEmpty())
3924 msg += user_title;
3925 else
3926 msg += QString(" (%1)")
3927 .arg(toString(m_tracks[type][TrackNo].m_audio_type));
3928 break;
3929 }
3930 return QString("%1: %2").arg(TrackNo + 1).arg(msg);
3931 }
3932 if (kTrackTypeSubtitle == type)
3933 {
3934 return QObject::tr("Subtitle") + QString(" %1: %2%3%4")
3935 .arg(QString::number(TrackNo + 1),
3936 iso639_key_toName(lang_key),
3937 user_title,
3938 forcedString);
3939 }
3940 if (forced && kTrackTypeRawText == type)
3941 return DecoderBase::GetTrackDesc(type, TrackNo) + forcedString;
3942 return DecoderBase::GetTrackDesc(type, TrackNo);
3943}
3944
3946{
3947 return m_ttd->GetDecoderType();
3948}
3949
3950QString AvFormatDecoder::GetXDS(const QString &Key) const
3951{
3952 return m_ccd608->GetXDS(Key);
3953}
3954
3956{
3957 QMutexLocker locker(&m_trackLock);
3958 if (TrackNo >= m_tracks[kTrackTypeSubtitle].size())
3959 return {};
3960
3961 int index = m_tracks[kTrackTypeSubtitle][TrackNo].m_av_stream_index;
3962 AVCodecContext *ctx = m_codecMap.GetCodecContext(m_ic->streams[index]);
3963 return ctx ? QByteArray(reinterpret_cast<char*>(ctx->subtitle_header), ctx->subtitle_header_size) :
3964 QByteArray();
3965}
3966
3967void AvFormatDecoder::GetAttachmentData(uint TrackNo, QByteArray &Filename, QByteArray &Data)
3968{
3969 QMutexLocker locker(&m_trackLock);
3970 if (TrackNo >= m_tracks[kTrackTypeAttachment].size())
3971 return;
3972
3973 int index = m_tracks[kTrackTypeAttachment][TrackNo].m_av_stream_index;
3974 AVDictionaryEntry *tag = av_dict_get(m_ic->streams[index]->metadata, "filename", nullptr, 0);
3975 if (tag)
3976 Filename = QByteArray(tag->value);
3977 AVCodecParameters *par = m_ic->streams[index]->codecpar;
3978 Data = QByteArray(reinterpret_cast<char*>(par->extradata), par->extradata_size);
3979}
3980
3982{
3983 QMutexLocker locker(&m_trackLock);
3984 for (size_t i = 0; i < m_tracks[kTrackTypeAudio].size(); i++)
3985 {
3986 AVStream *stream = m_ic->streams[m_tracks[kTrackTypeAudio][i].m_av_stream_index];
3987 if (stream)
3988 if ((stream->component_tag == Tag) || ((Tag <= 0) && stream->component_tag <= 0))
3989 return SetTrack(kTrackTypeAudio, static_cast<int>(i)) != -1;
3990 }
3991 return false;
3992}
3993
3995{
3996 QMutexLocker locker(&m_trackLock);
3997 for (uint i = 0; i < m_ic->nb_streams; i++)
3998 {
3999 AVStream *stream = m_ic->streams[i];
4000 if (stream)
4001 {
4002 if (stream->component_tag == Tag)
4003 {
4004 StreamInfo si {static_cast<int>(i), 0};
4006 return true;
4007 }
4008 }
4009 }
4010 return false;
4011}
4012
4013// documented in decoderbase.cpp
4015{
4016 if (kTrackTypeAudio == type)
4017 return AutoSelectAudioTrack();
4018
4020 return -1;
4021
4023}
4024
4025static std::vector<int> filter_lang(const sinfo_vec_t &tracks, int lang_key,
4026 const std::vector<int> &ftype)
4027{
4028 std::vector<int> ret;
4029
4030 for (int index : ftype)
4031 {
4032 if ((lang_key < 0) || tracks[index].m_language == lang_key)
4033 ret.push_back(index);
4034 }
4035
4036 return ret;
4037}
4038
4039static std::vector<int> filter_type(const sinfo_vec_t &tracks, AudioTrackType type)
4040{
4041 std::vector<int> ret;
4042
4043 for (size_t i = 0; i < tracks.size(); i++)
4044 {
4045 if (tracks[i].m_audio_type == type)
4046 ret.push_back(i);
4047 }
4048
4049 return ret;
4050}
4051
4052int AvFormatDecoder::filter_max_ch(const AVFormatContext *ic,
4053 const sinfo_vec_t &tracks,
4054 const std::vector<int>&fs,
4055 enum AVCodecID codecId,
4056 int profile)
4057{
4058 int selectedTrack = -1;
4059 int max_seen = -1;
4060
4061 for (int f : fs)
4062 {
4063 const int stream_index = tracks[f].m_av_stream_index;
4064 AVCodecParameters *par = ic->streams[stream_index]->codecpar;
4065 if ((codecId == AV_CODEC_ID_NONE || codecId == par->codec_id) &&
4066 (max_seen < par->ch_layout.nb_channels))
4067 {
4068 if (codecId == AV_CODEC_ID_DTS && profile > 0)
4069 {
4070 // we cannot decode dts-hd, so only select it if passthrough
4071 if (!DoPassThrough(par, true) || par->profile != profile)
4072 continue;
4073 }
4074 selectedTrack = f;
4075 max_seen = par->ch_layout.nb_channels;
4076 }
4077 }
4078
4079 return selectedTrack;
4080}
4081
4082int AvFormatDecoder::selectBestAudioTrack(int lang_key, const std::vector<int> &ftype)
4083{
4084 const sinfo_vec_t &atracks = m_tracks[kTrackTypeAudio];
4085 int selTrack = -1;
4086
4087 std::vector<int> flang = filter_lang(atracks, lang_key, ftype);
4088
4089 if (m_audio->CanDTSHD())
4090 {
4091 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_DTS,
4092 FF_PROFILE_DTS_HD_MA);
4093 if (selTrack >= 0)
4094 return selTrack;
4095 }
4096 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_TRUEHD);
4097 if (selTrack >= 0)
4098 return selTrack;
4099
4100 if (m_audio->CanDTSHD())
4101 {
4102 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_DTS,
4103 FF_PROFILE_DTS_HD_HRA);
4104 if (selTrack >= 0)
4105 return selTrack;
4106 }
4107 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_EAC3);
4108 if (selTrack >= 0)
4109 return selTrack;
4110
4111 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_DTS);
4112 if (selTrack >= 0)
4113 return selTrack;
4114
4115 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_AC3);
4116 if (selTrack >= 0)
4117 return selTrack;
4118
4119 selTrack = filter_max_ch(m_ic, atracks, flang);
4120
4121 return selTrack;
4122}
4123
4171{
4172 QMutexLocker locker(&m_trackLock);
4173
4174 const sinfo_vec_t &atracks = m_tracks[kTrackTypeAudio];
4177 int &ctrack = m_currentTrack[kTrackTypeAudio];
4178
4179 uint numStreams = atracks.size();
4180 int selTrack = -1;
4181 if (numStreams > 0)
4182 {
4183 if ((ctrack >= 0) && (ctrack < (int)numStreams))
4184 return ctrack; // audio already selected
4185
4186 LOG(VB_AUDIO, LOG_DEBUG, QString("%1 available audio streams").arg(numStreams));
4187 for (const auto & track : atracks)
4188 {
4189 AVCodecParameters *codecpar = m_ic->streams[track.m_av_stream_index]->codecpar;
4190 LOG(VB_AUDIO, LOG_DEBUG, QString("%1: %2 bps, %3 Hz, %4 channels, passthrough(%5)")
4191 .arg(avcodec_get_name(codecpar->codec_id), QString::number(codecpar->bit_rate),
4192 QString::number(codecpar->sample_rate), QString::number(codecpar->ch_layout.nb_channels),
4193 (DoPassThrough(codecpar, true)) ? "true" : "false")
4194 );
4195 }
4196
4197 if (1 == numStreams)
4198 {
4199 selTrack = 0;
4200 }
4201 else
4202 {
4203 int wlang = wtrack.m_language;
4204
4205 if ((selTrack < 0) && (wtrack.m_av_substream_index >= 0))
4206 {
4207 LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to reselect audio sub-stream");
4208 // Dual stream without language information: choose
4209 // the previous substream that was kept in wtrack,
4210 // ignoring the stream index (which might have changed).
4211 int substream_index = wtrack.m_av_substream_index;
4212
4213 for (uint i = 0; i < numStreams; i++)
4214 {
4215 if (atracks[i].m_av_substream_index == substream_index)
4216 {
4217 selTrack = i;
4218 break;
4219 }
4220 }
4221 }
4222
4223 if ((selTrack < 0) && wlang >= -1)
4224 {
4225 LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to reselect audio track");
4226 // Try to reselect user selected audio stream.
4227 // This should find the stream after a commercial
4228 // break and in some cases after a channel change.
4229 uint windx = wtrack.m_language_index;
4230 for (uint i = 0; i < numStreams; i++)
4231 {
4232 if (wlang == atracks[i].m_language)
4233 {
4234 selTrack = i;
4235
4236 if (windx == atracks[i].m_language_index)
4237 break;
4238 }
4239 }
4240 }
4241
4242 if (selTrack < 0)
4243 {
4244 LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to select audio track (w/lang)");
4245
4246 // Filter out commentary and audio description tracks
4247 std::vector<int> ftype = filter_type(atracks, kAudioTypeNormal);
4248
4249 if (ftype.empty())
4250 {
4251 LOG(VB_AUDIO, LOG_WARNING, "No audio tracks matched the type filter, "
4252 "so trying all tracks.");
4253 for (int i = 0; i < static_cast<int>(atracks.size()); i++)
4254 ftype.push_back(i);
4255 }
4256
4257 // Try to get the language track for the preferred language for audio
4258 QString language_key_convert = iso639_str2_to_str3(gCoreContext->GetAudioLanguage());
4259 uint language_key = iso639_str3_to_key(language_key_convert);
4260 uint canonical_key = iso639_key_to_canonical_key(language_key);
4261
4262 selTrack = selectBestAudioTrack(canonical_key, ftype);
4263
4264 // Try to get best track for most preferred language for audio.
4265 // Set by the "Guide Data" "Audio Language" preference in Appearance.
4266 if (selTrack < 0)
4267 {
4268 auto it = m_languagePreference.begin();
4269 for (; it != m_languagePreference.end() && selTrack < 0; ++it)
4270 {
4271 selTrack = selectBestAudioTrack(*it, ftype);
4272 }
4273 }
4274
4275 // Could not select track based on user preferences (audio language)
4276 // Try to select the default track
4277 if (selTrack < 0)
4278 {
4279 LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to select default track");
4280 for (size_t i = 0; i < atracks.size(); i++) {
4281 int idx = atracks[i].m_av_stream_index;
4282 if (m_ic->streams[idx]->disposition & AV_DISPOSITION_DEFAULT)
4283 {
4284 selTrack = i;
4285 break;
4286 }
4287 }
4288 }
4289
4290 // Try to get best track for any language
4291 if (selTrack < 0)
4292 {
4293 LOG(VB_AUDIO, LOG_INFO, LOC +
4294 "Trying to select audio track (wo/lang)");
4295 selTrack = selectBestAudioTrack(-1, ftype);
4296 }
4297 }
4298 }
4299 }
4300
4301 if (selTrack < 0)
4302 {
4303 strack.m_av_stream_index = -1;
4304 if (ctrack != selTrack)
4305 {
4306 LOG(VB_AUDIO, LOG_INFO, LOC + "No suitable audio track exists.");
4307 ctrack = selTrack;
4308 }
4309 }
4310 else
4311 {
4312 ctrack = selTrack;
4313 strack = atracks[selTrack];
4314
4315 if (wtrack.m_av_stream_index < 0)
4316 wtrack = strack;
4317
4318 LOG(VB_AUDIO, LOG_INFO, LOC + QString("Selected track %1 (A/V Stream #%2)")
4319 .arg(static_cast<uint>(ctrack)).arg(strack.m_av_stream_index));
4320 }
4321
4323 return selTrack;
4324}
4325
4326static void extract_mono_channel(uint channel, AudioInfo *audioInfo,
4327 char *buffer, int bufsize)
4328{
4329 // Only stereo -> mono (left or right) is supported
4330 if (audioInfo->m_channels != 2)
4331 return;
4332
4333 if (channel >= (uint)audioInfo->m_channels)
4334 return;
4335
4336 const uint samplesize = audioInfo->m_sampleSize;
4337 const uint samples = bufsize / samplesize;
4338 const uint halfsample = samplesize >> 1;
4339
4340 const char *from = (channel == 1) ? buffer + halfsample : buffer;
4341 char *to = (channel == 0) ? buffer + halfsample : buffer;
4342
4343 for (uint sample = 0; sample < samples;
4344 (sample++), (from += samplesize), (to += samplesize))
4345 {
4346 memmove(to, from, halfsample);
4347 }
4348}
4349
4350bool AvFormatDecoder::ProcessAudioPacket(AVCodecContext* context, AVStream *curstream, AVPacket *pkt,
4351 DecodeType decodetype)
4352{
4353 int ret = 0;
4354 int data_size = 0;
4355 bool firstloop = true;
4356 int decoded_size = -1;
4357
4358 m_trackLock.lock();
4359 int audIdx = m_selectedTrack[kTrackTypeAudio].m_av_stream_index;
4360 int audSubIdx = m_selectedTrack[kTrackTypeAudio].m_av_substream_index;
4361 m_trackLock.unlock();
4362
4363 AVPacket *tmp_pkt = av_packet_alloc();
4364 tmp_pkt->data = pkt->data;
4365 tmp_pkt->size = pkt->size;
4366 while (tmp_pkt->size > 0)
4367 {
4368 bool reselectAudioTrack = false;
4369
4371 if (!m_audio->HasAudioIn())
4372 {
4373 LOG(VB_AUDIO, LOG_INFO, LOC +
4374 "Audio is disabled - trying to restart it");
4375 reselectAudioTrack = true;
4376 }
4378
4379 // detect switches between stereo and dual languages
4380 bool wasDual = audSubIdx != -1;
4381 bool isDual = is_dual_mono(context->ch_layout);
4382 if ((wasDual && !isDual) || (!wasDual && isDual))
4383 {
4385 reselectAudioTrack = true;
4386 }
4387
4388 // detect channels on streams that need
4389 // to be decoded before we can know this
4390 bool already_decoded = false;
4391 if (!context->ch_layout.nb_channels)
4392 {
4393 m_avCodecLock.lock();
4394 if (DoPassThrough(curstream->codecpar, false) || !DecoderWillDownmix(context))
4395 {
4396 // for passthru or codecs for which the decoder won't downmix
4397 // let the decoder set the number of channels. For other codecs
4398 // we downmix if necessary in audiooutputbase
4399 ;
4400 }
4401 else // No passthru, the decoder will downmix
4402 {
4403 AVChannelLayout channel_layout;
4404 av_channel_layout_default(&channel_layout, m_audio->GetMaxChannels());
4405 av_opt_set_chlayout(context->priv_data, "downmix", &channel_layout, 0);
4406
4407 if (context->codec_id == AV_CODEC_ID_AC3)
4408 context->ch_layout.nb_channels = m_audio->GetMaxChannels();
4409 }
4410
4411 ret = m_audio->DecodeAudio(context, m_audioSamples, data_size, tmp_pkt);
4412 decoded_size = data_size;
4413 already_decoded = true;
4414 reselectAudioTrack |= context->ch_layout.nb_channels;
4415 m_avCodecLock.unlock();
4416 }
4417
4418 if (reselectAudioTrack)
4419 {
4420 QMutexLocker locker(&m_trackLock);
4422 m_selectedTrack[kTrackTypeAudio].m_av_stream_index = -1;
4424 audIdx = m_selectedTrack[kTrackTypeAudio].m_av_stream_index;
4425 audSubIdx = m_selectedTrack[kTrackTypeAudio].m_av_substream_index;
4426 }
4427
4428 if (!(decodetype & kDecodeAudio) || (pkt->stream_index != audIdx)
4429 || !m_audio->HasAudioOut())
4430 break;
4431
4432 if (firstloop && pkt->pts != AV_NOPTS_VALUE)
4433 m_lastAPts = millisecondsFromFloat(av_q2d(curstream->time_base) * pkt->pts * 1000);
4434
4435 m_firstVPtsInuse = false;
4436 m_avCodecLock.lock();
4437 data_size = 0;
4438
4439 // Check if the number of channels or sampling rate have changed
4440 if (context->sample_rate != m_audioOut.m_sampleRate ||
4441 context->ch_layout.nb_channels != m_audioOut.m_channels ||
4443 context->bits_per_raw_sample) != m_audioOut.format)
4444 {
4445 LOG(VB_GENERAL, LOG_INFO, LOC + "Audio stream changed");
4446 if (context->ch_layout.nb_channels != m_audioOut.m_channels)
4447 {
4448 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Number of audio channels changed from %1 to %2")
4449 .arg(m_audioOut.m_channels).arg(context->ch_layout.nb_channels));
4450 }
4451 QMutexLocker locker(&m_trackLock);
4453 m_selectedTrack[kTrackTypeAudio].m_av_stream_index = -1;
4454 audIdx = -1;
4456 }
4457
4459 {
4460 if (!already_decoded)
4461 {
4463 {
4464 ret = m_audio->DecodeAudio(context, m_audioSamples, data_size, tmp_pkt);
4465 decoded_size = data_size;
4466 }
4467 else
4468 {
4469 decoded_size = -1;
4470 }
4471 }
4472 memcpy(m_audioSamples, tmp_pkt->data, tmp_pkt->size);
4473 data_size = tmp_pkt->size;
4474 // We have processed all the data, there can't be any left
4475 tmp_pkt->size = 0;
4476 }
4477 else
4478 {
4479 if (!already_decoded)
4480 {
4481 if (DecoderWillDownmix(context))
4482 {
4483 AVChannelLayout channel_layout;
4484 av_channel_layout_default(&channel_layout, m_audio->GetMaxChannels());
4485 av_opt_set_chlayout(context->priv_data, "downmix", &channel_layout, 0);
4486 }
4487
4488 ret = m_audio->DecodeAudio(context, m_audioSamples, data_size, tmp_pkt);
4489 decoded_size = data_size;
4490 }
4491 }
4492 m_avCodecLock.unlock();
4493
4494 if (ret < 0)
4495 {
4496 LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown audio decoding error");
4497 av_packet_free(&tmp_pkt);
4498 return false;
4499 }
4500
4501 if (data_size <= 0)
4502 {
4503 tmp_pkt->data += ret;
4504 tmp_pkt->size -= ret;
4505 continue;
4506 }
4507
4508 std::chrono::milliseconds temppts = m_lastAPts;
4509
4510 if (audSubIdx != -1 && !m_audioOut.m_doPassthru)
4511 extract_mono_channel(audSubIdx, &m_audioOut,
4512 (char *)m_audioSamples, data_size);
4513
4515 int frames = (context->ch_layout.nb_channels <= 0 || decoded_size < 0 || !samplesize) ? -1 :
4516 decoded_size / (context->ch_layout.nb_channels * samplesize);
4517 m_audio->AddAudioData((char *)m_audioSamples, data_size, temppts, frames);
4519 {
4521 }
4522 else
4523 {
4525 ((double)(frames * 1000) / context->sample_rate);
4526 }
4527
4528 LOG(VB_TIMESTAMP, LOG_INFO, LOC + QString("audio timecode %1 %2 %3 %4")
4529 .arg(pkt->pts).arg(pkt->dts).arg(temppts.count()).arg(m_lastAPts.count()));
4530
4533
4534 tmp_pkt->data += ret;
4535 tmp_pkt->size -= ret;
4536 firstloop = false;
4537 }
4538
4539 av_packet_free(&tmp_pkt);
4540 return true;
4541}
4542
4543// documented in decoderbase.h
4544bool AvFormatDecoder::GetFrame(DecodeType decodetype, bool &Retry)
4545{
4546 AVPacket *pkt = nullptr;
4547 bool have_err = false;
4548
4549 const DecodeType origDecodetype = decodetype;
4550
4551 m_gotVideoFrame = false;
4552
4553 m_frameDecoded = 0;
4554 m_decodedVideoFrame = nullptr;
4555
4556 m_allowedQuit = false;
4557 bool storevideoframes = false;
4558
4559 m_skipAudio = (m_lastVPts == 0ms);
4560
4561 if( !m_processFrames )
4562 {
4563 return false;
4564 }
4565
4566 m_hasVideo = HasVideo();
4567 m_needDummyVideoFrames = false;
4568
4569 if (!m_hasVideo && (decodetype & kDecodeVideo))
4570 {
4571 // NB This could be an issue if the video stream is not
4572 // detected initially as the video buffers will be filled.
4574 decodetype = (DecodeType)((int)decodetype & ~kDecodeVideo);
4575 m_skipAudio = false;
4576 }
4577
4579
4580 while (!m_allowedQuit)
4581 {
4582 if (decodetype & kDecodeAudio)
4583 {
4584 if (((m_currentTrack[kTrackTypeAudio] < 0) ||
4585 (m_selectedTrack[kTrackTypeAudio].m_av_stream_index < 0)))
4586 {
4587 // disable audio request if there are no audio streams anymore
4588 // and we have video, otherwise allow decoding to stop
4589 if (m_hasVideo)
4590 decodetype = (DecodeType)((int)decodetype & ~kDecodeAudio);
4591 else
4592 m_allowedQuit = true;
4593 }
4594 }
4595 else if ((origDecodetype & kDecodeAudio) &&
4597 (m_selectedTrack[kTrackTypeAudio].m_av_stream_index >= 0))
4598 {
4599 // Turn on audio decoding again if it was on originally
4600 // and an audio stream has now appeared. This can happen
4601 // in still DVD menus with audio
4602 decodetype = (DecodeType)((int)decodetype | kDecodeAudio);
4603 }
4604
4606
4607 if (m_gotVideoFrame)
4608 {
4609 if (decodetype == kDecodeNothing)
4610 {
4611 // no need to buffer audio or video if we
4612 // only care about building a keyframe map.
4613 // NB but allow for data only (MHEG) streams
4614 m_allowedQuit = true;
4615 }
4616 else if ((decodetype & kDecodeAV) == kDecodeAV &&
4617 (m_storedPackets.count() < kMaxVideoQueueSize) &&
4618 // buffer audio to prevent audio buffer
4619 // underruns in case you are setting negative values
4620 // in Adjust Audio Sync.
4623 {
4624 storevideoframes = true;
4625 }
4626 else if (decodetype & kDecodeVideo)
4627 {
4628 if (m_storedPackets.count() >= kMaxVideoQueueSize)
4629 {
4630 LOG(VB_GENERAL, LOG_WARNING, LOC +
4631 QString("Audio %1 ms behind video but already %2 "
4632 "video frames queued. AV-Sync might be broken.")
4633 .arg((m_lastVPts-m_lastAPts).count()).arg(m_storedPackets.count()));
4634 }
4635 m_allowedQuit = true;
4636 continue;
4637 }
4638 }
4639
4640 if (!storevideoframes && m_storedPackets.count() > 0)
4641 {
4642 if (pkt)
4643 av_packet_free(&pkt);
4644 pkt = m_storedPackets.takeFirst();
4645 }
4646 else
4647 {
4648 if (!pkt)
4649 pkt = av_packet_alloc();
4650
4651 int retval = 0;
4652 if (m_ic != nullptr)
4653 retval = ReadPacket(m_ic, pkt, storevideoframes);
4654 if ((m_ic == nullptr) || (retval < 0))
4655 {
4656 if (retval == -EAGAIN)
4657 continue;
4658
4659 SetEof(true);
4660 av_packet_free(&pkt);
4661
4662 LOG(VB_GENERAL, LOG_ERR, QString("decoding error %1 (%2)")
4663 .arg(QString::fromStdString(av_make_error_stdstring_unknown(retval)),
4664 QString::number(retval)));
4665 return false;
4666 }
4667
4668 if (m_waitingForChange && pkt->pos >= m_readAdjust)
4669 FileChanged();
4670
4671 if (pkt->pos > m_readAdjust)
4672 pkt->pos -= m_readAdjust;
4673 }
4674
4675 if (!m_ic)
4676 {
4677 LOG(VB_GENERAL, LOG_ERR, LOC + "No context");
4678 av_packet_unref(pkt);
4679 continue;
4680 }
4681
4682 if (pkt->stream_index >= (int)m_ic->nb_streams)
4683 {
4684 LOG(VB_GENERAL, LOG_ERR, LOC + "Bad stream");
4685 av_packet_unref(pkt);
4686 continue;
4687 }
4688
4689 AVStream *curstream = m_ic->streams[pkt->stream_index];
4690
4691 if (!curstream)
4692 {
4693 LOG(VB_GENERAL, LOG_ERR, LOC + "Bad stream (NULL)");
4694 av_packet_unref(pkt);
4695 continue;
4696 }
4697
4698 enum AVMediaType codec_type = curstream->codecpar->codec_type;
4699 const AVCodecID codec_id = curstream->codecpar->codec_id;
4700
4701 // Handle AVCodecID values that don't have an AVCodec decoder and
4702 // store video packets
4703 switch (codec_type)
4704 {
4705 case AVMEDIA_TYPE_VIDEO:
4706 if (storevideoframes)
4707 {
4708 m_storedPackets.append(pkt);
4709 pkt = nullptr;
4710 continue;
4711 }
4712 break;
4713 case AVMEDIA_TYPE_AUDIO:
4714 // FFmpeg does not currently have an AC-4 decoder
4715 if (codec_id == AV_CODEC_ID_AC4)
4716 {
4717 av_packet_unref(pkt);
4718 continue;
4719 }
4720 break;
4721 case AVMEDIA_TYPE_SUBTITLE:
4722 switch (codec_id)
4723 {
4724 case AV_CODEC_ID_TEXT:
4726 av_packet_unref(pkt);
4727 continue;
4728 case AV_CODEC_ID_DVB_TELETEXT:
4729 ProcessDVBDataPacket(curstream, pkt);
4730 av_packet_unref(pkt);
4731 continue;
4732 default:
4733 break;
4734 }
4735 break;
4736 case AVMEDIA_TYPE_DATA:
4737 ProcessDataPacket(curstream, pkt, decodetype);
4738 av_packet_unref(pkt);
4739 continue;
4740 default:
4741 break;
4742 }
4743
4744 // ensure there is an AVCodecContext for this stream
4745 AVCodecContext *context = m_codecMap.GetCodecContext(curstream);
4746 if (context == nullptr)
4747 {
4748 if (codec_type != AVMEDIA_TYPE_VIDEO)
4749 {
4750 LOG(VB_PLAYBACK, LOG_ERR, LOC +
4751 QString("No codec for stream index %1, type(%2) id(%3:%4)")
4752 .arg(QString::number(pkt->stream_index),
4753 AVMediaTypeToString(codec_type),
4754 avcodec_get_name(codec_id),
4755 QString::number(codec_id)
4756 )
4757 );
4758 // Process Stream Change in case we have no audio
4759 if (codec_type == AVMEDIA_TYPE_AUDIO && !m_audio->HasAudioIn())
4760 m_streamsChanged = true;
4761 }
4762 av_packet_unref(pkt);
4763 continue;
4764 }
4765
4766 have_err = false;
4767
4768 switch (codec_type)
4769 {
4770 case AVMEDIA_TYPE_AUDIO:
4771 {
4772 if (!ProcessAudioPacket(context, curstream, pkt, decodetype))
4773 have_err = true;
4774 else
4776 break;
4777 }
4778
4779 case AVMEDIA_TYPE_VIDEO:
4780 {
4781 if (pkt->stream_index != m_selectedTrack[kTrackTypeVideo].m_av_stream_index)
4782 {
4783 break;
4784 }
4785
4786 if (!PreProcessVideoPacket(context, curstream, pkt))
4787 continue;
4788
4789 // If the resolution changed in XXXPreProcessPkt, we may
4790 // have a fatal error, so check for this before continuing.
4791 if (m_parent->IsErrored())
4792 {
4793 av_packet_free(&pkt);
4794 return false;
4795 }
4796
4797 if (pkt->pts != AV_NOPTS_VALUE)
4798 {
4800 (av_q2d(curstream->time_base)*pkt->pts*1000000);
4801 }
4802
4803 if (!(decodetype & kDecodeVideo))
4804 {
4806 m_gotVideoFrame = true;
4807 break;
4808 }
4809
4810 if (!ProcessVideoPacket(context, curstream, pkt, Retry))
4811 have_err = true;
4812 break;
4813 }
4814
4815 case AVMEDIA_TYPE_SUBTITLE:
4816 {
4817 if (!ProcessSubtitlePacket(context, curstream, pkt))
4818 have_err = true;
4819 break;
4820 }
4821
4822 default:
4823 {
4824 LOG(VB_GENERAL, LOG_ERR, LOC +
4825 QString("Decoding - id(%1) type(%2)")
4826 .arg(avcodec_get_name(codec_id),
4827 AVMediaTypeToString(codec_type)));
4828 have_err = true;
4829 break;
4830 }
4831 }
4832
4833 if (!have_err && !Retry)
4834 m_frameDecoded = 1;
4835 av_packet_unref(pkt);
4836 if (Retry)
4837 break;
4838 }
4839
4840 av_packet_free(&pkt);
4841 return true;
4842}
4843
4845{
4846 if (m_streamsChanged)
4847 {
4848 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("StreamChangeCheck skip SeekReset"));
4849 // SeekReset(0, 0, true, true);
4850 ScanStreams(false);
4851 m_streamsChanged = false;
4852 }
4853}
4854
4855int AvFormatDecoder::ReadPacket(AVFormatContext *ctx, AVPacket *pkt, bool &/*storePacket*/)
4856{
4857 m_avCodecLock.lock();
4858 int result = av_read_frame(ctx, pkt);
4859 m_avCodecLock.unlock();
4860 return result;
4861}
4862
4864{
4866 if (pmt_buffer.has_buffer())
4867 {
4868 const ProgramMapTable pmt(PSIPTable(pmt_buffer.data()));
4869
4870 for (uint i = 0; i < pmt.StreamCount(); i++)
4871 {
4872 // MythTV remaps OpenCable Video to normal video during recording
4873 // so "dvb" is the safest choice for system info type, since this
4874 // will ignore other uses of the same stream id in DVB countries.
4875 if (pmt.IsVideo(i, "dvb"))
4876 return true;
4877
4878 // MHEG may explicitly select a private stream as video
4879 if ((i == (uint)m_selectedTrack[kTrackTypeVideo].m_av_stream_index) &&
4880 (pmt.StreamType(i) == StreamID::PrivData))
4881 {
4882 return true;
4883 }
4884 }
4885 }
4886
4887 return GetTrackCount(kTrackTypeVideo) != 0U;
4888}
4889
4891{
4893 {
4895 if (!frame)
4896 return false;
4897
4898 frame->ClearMetadata();
4899 frame->ClearBufferToBlank();
4900
4901 frame->m_dummy = true;
4903 frame->m_frameCounter = m_frameCounter++;
4904
4906 m_parent->DeLimboFrame(frame);
4907
4908 m_decodedVideoFrame = frame;
4910 m_gotVideoFrame = true;
4911 }
4912 return true;
4913}
4914
4916{
4918}
4919
4921{
4922 int stream = m_selectedTrack[kTrackTypeVideo].m_av_stream_index;
4923 if (stream < 0 || !m_ic)
4924 return {};
4925 return avcodec_get_name(m_ic->streams[stream]->codecpar->codec_id);
4926}
4927
4929{
4930 if (m_selectedTrack[kTrackTypeAudio].m_av_stream_index < 0)
4931 {
4932 m_disablePassthru = disable;
4933 return;
4934 }
4935
4936 if (disable != m_disablePassthru)
4937 {
4938 m_disablePassthru = disable;
4939 QString msg = (disable) ? "Disabling" : "Allowing";
4940 LOG(VB_AUDIO, LOG_INFO, LOC + msg + " pass through");
4941
4942 // Force pass through state to be reanalyzed
4944 }
4945}
4946
4948{
4949 QMutexLocker locker(&m_trackLock);
4951}
4952
4953inline bool AvFormatDecoder::DecoderWillDownmix(const AVCodecContext *ctx)
4954{
4955 // Until ffmpeg properly implements dialnorm
4956 // use Myth internal downmixer if machine has SSE2
4958 return false;
4959 // use ffmpeg only for dolby codecs if we have to
4960 //return av_opt_find(ctx->priv_data, "downmix", nullptr, 0, 0);
4961 // av_opt_find was causing segmentation faults, so explicitly list the
4962 // compatible decoders
4963 switch (ctx->codec_id)
4964 {
4965 case AV_CODEC_ID_AC3:
4966 case AV_CODEC_ID_TRUEHD:
4967 case AV_CODEC_ID_EAC3:
4968 case AV_CODEC_ID_MLP:
4969 case AV_CODEC_ID_DTS:
4970 return true;
4971 default:
4972 return false;
4973 }
4974}
4975
4976bool AvFormatDecoder::DoPassThrough(const AVCodecParameters *par, bool withProfile)
4977{
4978 bool passthru = false;
4979
4980 // if withProfile == false, we will accept any DTS stream regardless
4981 // of its profile. We do so, so we can bitstream DTS-HD as DTS core
4982 if (!withProfile && par->codec_id == AV_CODEC_ID_DTS && !m_audio->CanDTSHD())
4983 {
4984 passthru = m_audio->CanPassthrough(par->sample_rate, par->ch_layout.nb_channels,
4985 par->codec_id, FF_PROFILE_DTS);
4986 }
4987 else
4988 {
4989 passthru = m_audio->CanPassthrough(par->sample_rate, par->ch_layout.nb_channels,
4990 par->codec_id, par->profile);
4991 }
4992
4993 passthru &= !m_disablePassthru;
4994
4995 return passthru;
4996}
4997
5004{
5005 AudioInfo info; // no_audio
5006 AVStream *curstream = nullptr;
5007 AVCodecContext *ctx = nullptr;
5008 AudioInfo old_in = m_audioIn;
5009 int requested_channels = 0;
5010
5011 if ((m_currentTrack[kTrackTypeAudio] >= 0) && m_ic &&
5012 (m_selectedTrack[kTrackTypeAudio].m_av_stream_index <=
5013 (int) m_ic->nb_streams))
5014 {
5015 curstream = m_ic->streams[m_selectedTrack[kTrackTypeAudio]
5016 .m_av_stream_index];
5017 if (curstream != nullptr)
5018 ctx = m_codecMap.GetCodecContext(curstream);
5019 }
5020
5021 if (ctx == nullptr)
5022 {
5023 if (!m_tracks[kTrackTypeAudio].empty())
5024 LOG(VB_PLAYBACK, LOG_INFO, LOC + "No codec context. Returning false");
5025 return false;
5026 }
5027
5028 AudioFormat fmt =
5030 ctx->bits_per_raw_sample);
5031
5032 if (av_sample_fmt_is_planar(ctx->sample_fmt))
5033 {
5034 LOG(VB_AUDIO, LOG_INFO, LOC + QString("Audio data is planar"));
5035 }
5036
5037 if (fmt == FORMAT_NONE)
5038 {
5039 int bps = av_get_bytes_per_sample(ctx->sample_fmt) << 3;
5040 if (ctx->sample_fmt == AV_SAMPLE_FMT_S32 &&
5041 ctx->bits_per_raw_sample)
5042 bps = ctx->bits_per_raw_sample;
5043 LOG(VB_GENERAL, LOG_ERR, LOC +
5044 QString("Unsupported sample format with %1 bits").arg(bps));
5045 return false;
5046 }
5047
5048 bool using_passthru = DoPassThrough(curstream->codecpar, false);
5049
5050 requested_channels = ctx->ch_layout.nb_channels;
5051
5052 if (!using_passthru &&
5053 ctx->ch_layout.nb_channels > (int)m_audio->GetMaxChannels() &&
5054 DecoderWillDownmix(ctx))
5055 {
5056 requested_channels = m_audio->GetMaxChannels();
5057
5058 AVChannelLayout channel_layout;
5059 av_channel_layout_default(&channel_layout, requested_channels);
5060 av_opt_set_chlayout(ctx->priv_data, "downmix", &channel_layout, 0);
5061 }
5062
5063 info = AudioInfo(ctx->codec_id, fmt, ctx->sample_rate,
5064 requested_channels, using_passthru, ctx->ch_layout.nb_channels,
5065 ctx->codec_id == AV_CODEC_ID_DTS ? ctx->profile : 0);
5066 if (info == m_audioIn)
5067 return false;
5068
5069 LOG(VB_AUDIO, LOG_INFO, LOC + "Initializing audio parms from " +
5070 QString("audio track #%1").arg(m_currentTrack[kTrackTypeAudio]+1));
5071
5073
5074 LOG(VB_AUDIO, LOG_INFO, LOC + "Audio format changed " +
5075 QString("\n\t\t\tfrom %1 to %2")
5076 .arg(old_in.toString(), m_audioOut.toString()));
5077
5078 m_audio->SetAudioParams(m_audioOut.format, ctx->ch_layout.nb_channels,
5079 requested_channels,
5083 AudioOutput *audioOutput = m_audio->GetAudioOutput();
5084 if (audioOutput)
5085 audioOutput->SetSourceBitrate(ctx->bit_rate);
5086
5087 if (LCD *lcd = LCD::Get())
5088 {
5089 LCDAudioFormatSet audio_format = AUDIO_MP3;
5090
5091 switch (ctx->codec_id)
5092 {
5093 case AV_CODEC_ID_MP2:
5094 audio_format = AUDIO_MPEG2;
5095 break;
5096 case AV_CODEC_ID_MP3:
5097 audio_format = AUDIO_MP3;
5098 break;
5099 case AV_CODEC_ID_AC3:
5100 audio_format = AUDIO_AC3;
5101 break;
5102 case AV_CODEC_ID_DTS:
5103 audio_format = AUDIO_DTS;
5104 break;
5105 case AV_CODEC_ID_VORBIS:
5106 audio_format = AUDIO_OGG;
5107 break;
5108 case AV_CODEC_ID_WMAV1:
5109 audio_format = AUDIO_WMA;
5110 break;
5111 case AV_CODEC_ID_WMAV2:
5112 audio_format = AUDIO_WMA2;
5113 break;
5114 default:
5115 audio_format = AUDIO_WAV;
5116 break;
5117 }
5118
5119 lcd->setAudioFormatLEDs(audio_format, true);
5120
5122 lcd->setVariousLEDs(VARIOUS_SPDIF, true);
5123 else
5124 lcd->setVariousLEDs(VARIOUS_SPDIF, false);
5125
5126 switch (m_audioIn.m_channels)
5127 {
5128 case 0:
5129 /* nb: aac and mp3 seem to be coming up 0 here, may point to an
5130 * avformatdecoder audio channel handling bug, per janneg */
5131 case 1:
5132 case 2:
5133 /* all audio codecs have at *least* one channel, but
5134 * LR is the fewest LED we can light up */
5135 lcd->setSpeakerLEDs(SPEAKER_LR, true);
5136 break;
5137 case 3:
5138 case 4:
5139 case 5:
5140 case 6:
5141 lcd->setSpeakerLEDs(SPEAKER_51, true);
5142 break;
5143 default:
5144 lcd->setSpeakerLEDs(SPEAKER_71, true);
5145 break;
5146 }
5147
5148 }
5149 return true;
5150}
5151
5153{
5154 int64_t start_time = INT64_MAX;
5155 int64_t end_time = INT64_MIN;
5156 AVStream *st = nullptr;
5157
5158 for (uint i = 0; i < ic->nb_streams; i++)
5159 {
5160 AVStream *st1 = ic->streams[i];
5161 if (st1 && st1->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5162 {
5163 st = st1;
5164 break;
5165 }
5166 }
5167 if (!st)
5168 return;
5169
5170 int64_t duration = INT64_MIN;
5171 if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {
5172 int64_t start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
5173 start_time = std::min(start_time1, start_time);
5174 if (st->duration != AV_NOPTS_VALUE) {
5175 int64_t end_time1 = start_time1 +
5176 av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
5177 end_time = std::max(end_time1, end_time);
5178 }
5179 }
5180 if (st->duration != AV_NOPTS_VALUE) {
5181 int64_t duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
5182 duration = std::max(duration1, duration);
5183 }
5184 if (start_time != INT64_MAX) {
5185 ic->start_time = start_time;
5186 if (end_time != INT64_MIN) {
5187 duration = std::max(end_time - start_time, duration);
5188 }
5189 }
5190 if (duration != INT64_MIN) {
5191 ic->duration = duration;
5192 if (!ic->pb)
5193 return;
5194 int64_t filesize = avio_size(ic->pb);
5195 if (filesize > 0) {
5196 /* compute the bitrate */
5197 ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE /
5198 (double)ic->duration;
5199 }
5200 }
5201}
5202
5204{
5205 if (m_currentTrack[type] < 0 || static_cast<size_t>(m_currentTrack[type]) >= m_tracks[type].size())
5206 {
5207 return -1;
5208 }
5209 return m_tracks[type][m_currentTrack[type]].m_av_stream_index;
5210}
5211
5213{
5214 if (m_ic == nullptr)
5215 {
5216 return nullptr;
5217 }
5218 AVProgram* program = av_find_program_from_stream(m_ic, nullptr, get_current_AVStream_index(kTrackTypeAudio));
5219 if (program == nullptr)
5220 {
5221 program = av_find_program_from_stream(m_ic, nullptr, get_current_AVStream_index(kTrackTypeVideo));
5222 }
5223 return program;
5224}
5225
5226/* vim: set expandtab tabstop=4 shiftwidth=4: */
AVFrame AVFrame
@ FORMAT_NONE
static int get_canonical_lang(const char *lang_cstr)
#define LOC
static constexpr ssize_t kMaxVideoQueueSize
static int64_t lsb3full(int64_t lsb, int64_t base_ts, int lsb_bits)
static void myth_av_log(void *ptr, int level, const char *fmt, va_list vl)
static constexpr uint32_t SLICE_MAX
#define FAIL(errmsg)
static bool StreamHasRequiredParameters(AVCodecContext *Context, AVStream *Stream)
Determine if we have enough live TV data to initialize hardware decoders.
int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
static constexpr uint32_t GOP_START
static QSize get_video_dim(const AVCodecContext &ctx)
static const char * AVMediaTypeToString(enum AVMediaType codec_type)
returns a human readable string for the AVMediaType enum.
static bool is_dual_mono(const AVChannelLayout &ch_layout)
static std::vector< int > filter_lang(const sinfo_vec_t &tracks, int lang_key, const std::vector< int > &ftype)
V4L2_MPEG_LINE_TYPES
@ V4L2_MPEG_VBI_IVTV_CAPTION_525
Closed Captions (line 21 NTSC, line 22 PAL)
@ V4L2_MPEG_VBI_IVTV_VPS
Video Programming System (PAL) (line 16)
@ V4L2_MPEG_VBI_IVTV_WSS_625
Wide Screen Signal (line 20 NTSC, line 23 PAL)
@ V4L2_MPEG_VBI_IVTV_TELETEXT_B
Teletext (uses lines 6-22 for PAL, 10-21 for NTSC)
static constexpr uint32_t SEQ_START
static AVBufferRef * get_pmt_section_from_AVProgram(const AVProgram *program)
static void HandleStreamChange(void *data, int avprogram_id)
static constexpr uint32_t SLICE_MIN
static std::vector< int > filter_type(const sinfo_vec_t &tracks, AudioTrackType type)
static bool cc608_good_parity(uint16_t data)
static float get_aspect(const AVCodecContext &ctx)
static void extract_mono_channel(uint channel, AudioInfo *audioInfo, char *buffer, int bufsize)
static constexpr int SEQ_PKT_ERR_MAX
static AVBufferRef * get_pmt_section_for_AVStream_index(AVFormatContext *context, int stream_index)
This is in libmythtv because that is where the parsers, which are its main users, are.
std::array< bool, 4 > CC608Seen
Definition: cc608decoder.h:59
std::array< bool, 64 > cc708_seen_flags
Definition: cc708decoder.h:12
uint pictureWidthCropped(void) const override
Definition: AVCParser.cpp:1027
uint32_t addBytes(const uint8_t *bytes, uint32_t byte_count, uint64_t stream_offset) override
Definition: AVCParser.cpp:285
uint pictureHeightCropped(void) const override
Definition: AVCParser.cpp:1039
field_type getFieldType(void) const override
Definition: AVCParser.cpp:1050
double frameRate(void) const
Definition: AVCParser.cpp:1069
void Reset(void) override
Definition: AVCParser.cpp:88
uint getRefFrames(void) const
Definition: AVCParser.h:112
QString toString() const
AVCodecID m_codecId
int m_codecProfile
bool m_doPassthru
AudioFormat format
static int SampleSize(AudioFormat format)
static AudioFormat AVSampleFormatToFormat(AVSampleFormat format, int bits=0)
Return AVSampleFormat closest equivalent to AudioFormat.
static bool has_optimized_SIMD()
Returns true if the processor supports MythTV's optimized SIMD for AudioOutputUtil/AudioConvert.
virtual void SetSourceBitrate(int)
Definition: audiooutput.h:144
AudioOutput * GetAudioOutput(void) const
Return internal AudioOutput object.
Definition: audioplayer.h:102
QString ReinitAudio(void)
bool CanPassthrough(int samplerate, int channels, AVCodecID codec, int profile)
uint GetMaxChannels(void)
int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
DecodeAudio Utility routine.
void AddAudioData(char *buffer, int len, std::chrono::milliseconds timecode, int frames)
bool CanDownmix(void)
AudioFormat GetFormat(void) const
Definition: audioplayer.h:79
std::chrono::milliseconds LengthLastData(void)
bool NeedDecodingBeforePassthrough(void)
void SetAudioParams(AudioFormat format, int orig_channels, int channels, AVCodecID codec, int samplerate, bool passthru, int codec_profile=-1)
Set audio output parameters.
bool HasAudioOut(void) const
Definition: audioplayer.h:52
bool HasAudioIn(void) const
Definition: audioplayer.h:51
bool CanDTSHD(void)
bool IsBufferAlmostFull(void)
A decoder for media files.
long long GetChapter(int chapter) override
uint8_t * m_audioSamples
std::chrono::milliseconds m_lastAPts
bool ProcessAudioPacket(AVCodecContext *codecContext, AVStream *stream, AVPacket *pkt, DecodeType decodetype)
MythCodecMap * CodecMap(void)
void ProcessVBIDataPacket(const AVStream *stream, const AVPacket *pkt)
Process ivtv proprietary embedded vertical blanking interval captions.
bool DecoderWillDownmix(const AVCodecContext *ctx)
QList< StreamInfo > m_streamTracks
StreamInfo for 608 and 708 Captions seen in the caption stream itself but not seen in the PMT.
int selectBestAudioTrack(int lang_key, const std::vector< int > &ftype)
void UpdateCaptionTracksFromStreams(bool check_608, bool check_708)
bool GenerateDummyVideoFrames(void)
int GetCurrentChapter(long long framesPlayed) override
AVFormatContext * m_ic
std::chrono::milliseconds m_lastVPts
void Reset(bool reset_video_data, bool seek_reset, bool reset_file) override
InteractiveTV * m_itv
MHEG/MHP decoder.
bool GetFrame(DecodeType Type, bool &Retry) override
Demux, preprocess and possibly decode a frame of video/audio.
PlayerFlags m_playerFlags
void SetIdrOnlyKeyframes(bool value) override
int GetTeletextDecoderType(void) const override
static int GetMaxReferenceFrames(AVCodecContext *Context)
void ForceSetupAudioStream(void) override
bool ProcessSubtitlePacket(AVCodecContext *codecContext, AVStream *stream, AVPacket *pkt)
QString GetTrackDesc(uint Type, uint TrackNo) override
CC608Decoder * m_ccd608
bool DoPassThrough(const AVCodecParameters *par, bool withProfile=true)
QList< TrackType > m_streamTrackTypes
TrackType (608 or 708) for Captions seen in the caption stream itself but not seen in the PMT.
QString GetCodecDecoderName(void) const override
virtual int GetCaptionLanguage(TrackType TrackType, int ServiceNum)
Return ATSC Closed Caption Language.
std::array< bool, 68 > m_ccX08InPmt
Lookup table for whether a stream was seen in the PMT entries 0-3 correspond to CEA-608 CC1 through C...
virtual int GetAudioLanguage(uint AudioIndex, uint StreamIndex)
friend int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
CC708Decoder * m_ccd708
int AutoSelectTrack(uint type) override
Select best track.
QList< TrackType > m_pmtTrackTypes
TrackType (608 or 708) for Captions seen in the PMT descriptor.
QString GetXDS(const QString &Key) const override
AVCParser * m_avcParser
MythAVFormatBuffer * m_avfRingBuffer
void RemoveAudioStreams()
remove audio streams from the context used by dvd code during title transitions to remove stale audio...
std::array< bool, 68 > m_ccX08InTracks
Lookup table for whether a stream is represented in the UI entries 0-3 correspond to CEA-608 CC1 thro...
void DecodeCCx08(const uint8_t *buf, uint buf_size)
bool do_av_seek(long long desiredFrame, bool discardFrames, int flags)
void DoFastForwardSeek(long long desiredFrame, bool &needflush) override
Seeks to the keyframe just before the desiredFrame if exact seeks is enabled, or the frame just after...
int m_seqCount
A counter used to determine if we need to force a call to HandleGopStart.
void SetupAudioStreamSubIndexes(int streamIndex)
Reacts to DUAL/STEREO changes on the fly and fix streams.
void ScanTeletextCaptions(int av_index)
bool FlagIsSet(PlayerFlags arg)
void GetChapterTimes(QList< std::chrono::seconds > &times) override
AudioInfo m_audioOut
virtual void StreamChangeCheck(void)
void InitVideoCodec(AVStream *stream, AVCodecContext *codecContext, bool selectedStream=false)
int ScanStreams(bool novideo)
void ScanRawTextCaptions(int av_stream_index)
void ScanDSMCCStreams(AVBufferRef *pmt_section)
Check to see whether there is a Network Boot Ifo sub-descriptor in the PMT which requires the MHEG ap...
int SetTrack(uint Type, int TrackNo) override
std::chrono::milliseconds m_firstVPts
bool SetAudioByComponentTag(int Tag) override
int AutoSelectAudioTrack(void)
Selects the best audio track.
void ScanATSCCaptionStreams(int av_index)
virtual void PostProcessTracks(void)
int filter_max_ch(const AVFormatContext *ic, const sinfo_vec_t &tracks, const std::vector< int > &fs, enum AVCodecID codecId=AV_CODEC_ID_NONE, int profile=-1)
QList< AVPacket * > m_storedPackets
AVProgram * get_current_AVProgram()
void SetDisablePassThrough(bool disable) override
Disables AC3/DTS pass through.
void SeekReset(long long newkey, uint skipFrames, bool doFlush, bool discardFrames) override
void HandleGopStart(AVPacket *pkt, bool can_reliably_parse_keyframes)
Update our position map, keyframe distance, and the like.
int GetNumChapters() override
void UpdateATSCCaptionTracks(void)
bool PreProcessVideoPacket(AVCodecContext *codecContext, AVStream *stream, AVPacket *pkt)
virtual AudioTrackType GetAudioTrackType(uint StreamIndex)
void MpegPreProcessPkt(AVCodecContext *codecContext, AVStream *stream, AVPacket *pkt)
Preprocess a packet, setting the video parms if necessary.
QByteArray GetSubHeader(uint TrackNo) override
bool OpenAVCodec(AVCodecContext *avctx, const AVCodec *codec)
MythCodecID m_videoCodecId
virtual int GetSubtitleLanguage(uint, uint StreamIndex)
Returns DVD Subtitle language.
void UpdateFramesPlayed(void) override
virtual bool ProcessDataPacket(AVStream *curstream, AVPacket *pkt, DecodeType decodetype)
static void av_update_stream_timings_video(AVFormatContext *ic)
AvFormatDecoder(MythPlayer *parent, const ProgramInfo &pginfo, PlayerFlags flags)
MythCodecMap m_codecMap
TeletextDecoder * m_ttd
int OpenFile(MythMediaBuffer *Buffer, bool novideo, TestBufferVec &testbuf) override
Open our file and set up or audio and video parameters.
void ProcessDSMCCPacket(const AVStream *stream, const AVPacket *pkt)
Process DSMCC object carousel packet.
int autoSelectVideoTrack(int &scanerror)
QRecursiveMutex m_avCodecLock
virtual int GetTeletextLanguage(uint Index)
Returns TeleText language.
void GetAttachmentData(uint TrackNo, QByteArray &Filename, QByteArray &Data) override
void ProcessDVBDataPacket(const AVStream *stream, const AVPacket *pkt)
Process DVB Teletext.
uint32_t m_startCodeState
struct SwsContext * m_swsCtx
int get_current_AVStream_index(TrackType type)
bool DoRewindSeek(long long desiredFrame) override
bool DoRewind(long long desiredFrame, bool discardFrames=true) override
virtual int ReadPacket(AVFormatContext *ctx, AVPacket *pkt, bool &storePacket)
int H264PreProcessPkt(AVCodecContext *codecContext, AVStream *stream, AVPacket *pkt)
bool SetupAudioStream(void)
Reinitializes audio if it needs to be reinitialized.
virtual bool IsValidStream(int)
std::chrono::milliseconds m_audioReadAhead
QString GetRawEncodingType(void) override
bool ProcessRawTextPacket(AVPacket *Packet)
~AvFormatDecoder() override
std::chrono::milliseconds NormalizeVideoTimecode(std::chrono::milliseconds timecode) override
virtual bool ProcessVideoFrame(AVCodecContext *codecContext, AVStream *Stream, AVFrame *AvFrame)
void SetEof(bool eof) override
bool SetVideoByComponentTag(int Tag) override
static bool CanHandle(TestBufferVec &testbuf, const QString &filename)
Perform an av_probe_input_format on the passed data to see if we can decode it with this class.
void remove_tracks_not_in_same_AVProgram(int stream_index)
virtual bool ProcessVideoPacket(AVCodecContext *codecContext, AVStream *stream, AVPacket *pkt, bool &Retry)
float GetVideoFrameRate(AVStream *Stream, AVCodecContext *Context, bool Sanitise=false)
bool DoFastForward(long long desiredFrame, bool discardFrames=true) override
Skips ahead or rewinds to desiredFrame.
std::chrono::microseconds m_lastCcPtsu
static void streams_changed(void *data, int avprogram_id)
bool m_seenGop
A flag to indicate that we've seen a GOP frame. Used in junction with seq_count.
QList< StreamInfo > m_pmtTracks
StreamInfo for 608 and 708 Captions seen in the PMT descriptor.
MythVideoFrame * m_decodedVideoFrame
QString GetXDS(const QString &key) const
void DecodeWSS(const unsigned char *buf)
void DecodeVPS(const unsigned char *buf)
void GetServices(std::chrono::seconds seconds, CC608Seen &seen) const
void SetIgnoreTimecode(bool val)
Definition: cc608decoder.h:103
void FormatCCField(std::chrono::milliseconds tc, size_t field, int data)
void decode_cc_data(uint cc_type, uint data1, uint data2)
void services(std::chrono::seconds seconds, cc708_seen_flags &seen) const
QString toString() const override
bool Line21Field(int i) const
bool Type(int i) const
int CanonicalLanguageKey(int i) const
int CaptionServiceNumber(int i) const
MythAVRational m_totalDuration
Definition: decoderbase.h:293
QRecursiveMutex m_positionMapLock
Definition: decoderbase.h:315
uint64_t m_frameCounter
Definition: decoderbase.h:292
virtual uint GetTrackCount(uint Type)
MarkTypes m_positionMapType
Definition: decoderbase.h:313
frm_pos_map_t m_frameToDurMap
Definition: decoderbase.h:317
virtual void DoFastForwardSeek(long long desiredFrame, bool &needflush)
Seeks to the keyframe just before the desiredFrame if exact seeks is enabled, or the frame just after...
bool m_watchingRecording
Definition: decoderbase.h:324
virtual void SetEof(bool eof)
Definition: decoderbase.h:132
bool m_dontSyncPositionMap
Definition: decoderbase.h:322
virtual QString GetTrackDesc(uint Type, uint TrackNo)
double m_fps
Definition: decoderbase.h:282
long long m_framesRead
Definition: decoderbase.h:291
virtual int SetTrack(uint Type, int TrackNo)
uint64_t GetSeekSnap(void) const
Definition: decoderbase.h:138
uint m_stereo3D
Definition: decoderbase.h:334
virtual void UpdateFramesPlayed(void)
MythMediaBuffer * m_ringBuffer
Definition: decoderbase.h:280
QRecursiveMutex m_trackLock
Definition: decoderbase.h:337
bool m_nextDecodedFrameIsKeyFrame
Definition: decoderbase.h:298
bool m_decodeAllSubtitles
Definition: decoderbase.h:338
void FileChanged(void)
bool m_exitAfterDecoded
Definition: decoderbase.h:307
std::vector< int > m_languagePreference
language preferences for auto-selection of streams
Definition: decoderbase.h:346
virtual void Reset(bool reset_video_data, bool seek_reset, bool reset_file)
Definition: decoderbase.cpp:47
long long m_readAdjust
Definition: decoderbase.h:332
MythPlayer * GetPlayer()
Definition: decoderbase.h:152
std::array< StreamInfo, kTrackTypeCount > m_wantedTrack
Definition: decoderbase.h:341
MythPlayer * m_parent
Definition: decoderbase.h:277
float m_currentAspect
Definition: decoderbase.h:288
bool m_hasFullPositionMap
Definition: decoderbase.h:310
MythVideoProfile m_videoDisplayProfile
Definition: decoderbase.h:348
bool m_trackTotalDuration
Definition: decoderbase.h:305
frm_pos_map_t m_durToFrameMap
Definition: decoderbase.h:318
int m_keyframeDist
Definition: decoderbase.h:294
bool m_waitingForChange
Definition: decoderbase.h:330
int m_fpsMultiplier
Definition: decoderbase.h:283
virtual bool DoFastForward(long long desiredFrame, bool discardFrames=true)
Skips ahead or rewinds to desiredFrame.
bool m_justAfterChange
Definition: decoderbase.h:331
virtual void SeekReset(long long newkey, uint skipFrames, bool doFlush, bool discardFrames)
Definition: decoderbase.cpp:74
std::array< sinfo_vec_t, kTrackTypeCount > m_tracks
Definition: decoderbase.h:340
virtual bool SyncPositionMap(void)
Updates the position map used for skipping frames.
virtual int AutoSelectTrack(uint Type)
Select best track.
int m_currentHeight
Definition: decoderbase.h:287
long long m_lastKey
Definition: decoderbase.h:295
MythCodecContext * m_mythCodecCtx
Definition: decoderbase.h:347
EofState m_atEof
Definition: decoderbase.h:300
AudioPlayer * m_audio
Definition: decoderbase.h:279
int m_videoRotation
Definition: decoderbase.h:333
std::array< StreamInfo, kTrackTypeCount > m_selectedForcedTrack
Definition: decoderbase.h:343
int m_currentWidth
Definition: decoderbase.h:286
long long m_framesPlayed
Definition: decoderbase.h:290
std::vector< PosMapEntry > m_positionMap
Definition: decoderbase.h:316
std::array< int, kTrackTypeCount > m_currentTrack
Definition: decoderbase.h:339
virtual bool DoRewindSeek(long long desiredFrame)
bool m_recordingHasPositionMap
Definition: decoderbase.h:311
virtual bool DoRewind(long long desiredFrame, bool discardFrames=true)
uint m_bitrate
Definition: decoderbase.h:285
ProgramInfo * m_playbackInfo
Definition: decoderbase.h:278
std::array< StreamInfo, kTrackTypeCount > m_selectedTrack
Definition: decoderbase.h:342
bool stateChanged(void) const
Definition: H2645Parser.h:59
bool onFrameStart(void) const
Definition: H2645Parser.h:61
bool onKeyFrameStart(void) const
Definition: H2645Parser.h:62
Definition: lcddevice.h:170
static LCD * Get(void)
Definition: lcddevice.cpp:69
bool IsValid(void) const
static desc_list_t ParseOnlyInclude(const unsigned char *data, uint len, int excluded_descid)
C++ wrapper for AVBufferRef.
AVIOContext * getAVIOContext()
void SetInInit(bool State)
MythAVFrame little utility class that act as a safe way to allocate an AVFrame which can then be allo...
Definition: mythavframe.h:27
C++ wrapper for FFmpeg libavutil AVRational.
long long toFixed(long long base) const
Convert the rational number to fixed point.
static VideoFrameType PixelFormatToFrameType(AVPixelFormat Fmt)
Definition: mythavutil.cpp:72
static MythCodecID FindDecoder(const QString &Decoder, AVStream *Stream, AVCodecContext **Context, const AVCodec **Codec)
virtual void SetDeinterlacing(AVCodecContext *, MythVideoProfile *, bool)
virtual void PostProcessFrame(AVCodecContext *, MythVideoFrame *)
virtual int HwDecoderInit(AVCodecContext *)
virtual bool IsDeinterlacing(bool &, bool=false)
virtual bool DecoderNeedsReset(AVCodecContext *)
virtual bool RetrieveFrame(AVCodecContext *, MythVideoFrame *, AVFrame *)
virtual void InitVideoCodec(AVCodecContext *Context, bool SelectedStream, bool &DirectRendering)
static MythCodecContext * CreateContext(DecoderBase *Parent, MythCodecID Codec)
virtual void SetDecoderOptions(AVCodecContext *, const AVCodec *)
virtual bool DecoderWillResetOnAspect(void)
virtual int FilteredReceiveFrame(AVCodecContext *Context, AVFrame *Frame)
Retrieve and process/filter AVFrame.
virtual bool DecoderWillResetOnFlush(void)
AVCodecContext * FindCodecContext(const AVStream *Stream)
Definition: mythavutil.cpp:325
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
QString GetAudioLanguage(void)
Returns two character ISO-639 language descriptor for audio language.
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
bool GetBoolSetting(const QString &key, bool defaultval=false)
int NumMenuButtons(void) const
void GetMenuSPUPkt(uint8_t *Buffer, int Size, int StreamID, uint32_t StartTime)
Get SPU pkt from dvd menu subtitle stream.
int GetAudioTrackNum(uint StreamId)
get the logical track index (into PGC_AST_CTL) of the element that maps the given physical stream id.
bool AudioStreamsChanged(void) const
bool DecodeSubtitles(AVSubtitle *Subtitle, int *GotSubtitles, const uint8_t *SpuPkt, int BufSize, uint32_t StartTime)
generate dvd subtitle bitmap or dvd menu bitmap.
float GetAspectOverride(void) const
static void Populate(class MythVideoFrame *Frame, struct AVFrame *AvFrame)
Create, update or destroy HDR metadata for the given MythVideoFrame.
long long GetRealFileSize(void) const
void UpdateRawBitrate(uint RawBitrate)
Set the raw bit rate, to allow RingBuffer adjust effective bitrate.
virtual void IgnoreWaitStates(bool)
virtual bool IsInStillFrame(void) const
bool IsDisc(void) const
void SetBufferSizeFactors(bool EstBitrate, bool Matroska)
Tells RingBuffer that the raw bitrate may be inaccurate and the underlying container is matroska,...
virtual bool IsStreamed(void)
bool IsDVD(void) const
virtual int BestBufferSize(void)
virtual bool StartFromBeginning(void)
const MythDVDBuffer * DVD(void) const
virtual bool IsInDiscMenuOrStillFrame(void) const
virtual long long GetReadPosition(void) const =0
int GetReadBufAvail(void) const
Returns number of bytes available for reading from buffer.
QString GetFilename(void) const
void SetDuration(std::chrono::seconds duration)
Definition: mythplayer.cpp:390
virtual void ReleaseNextVideoFrame(MythVideoFrame *buffer, std::chrono::milliseconds timecode, bool wrap=true)
Places frame on the queue of frames ready for display.
Definition: mythplayer.cpp:595
virtual void SetVideoParams(int w, int h, double fps, float aspect, bool ForceUpdate, int ReferenceFrames, FrameScanType=kScan_Ignore, const QString &codecName=QString())
Definition: mythplayer.cpp:321
void SetFramesPlayed(uint64_t played)
Definition: mythplayer.cpp:559
virtual InteractiveTV * GetInteractiveTV()
Definition: mythplayer.h:163
void DiscardVideoFrames(bool KeyFrame, bool Flushed)
Places frames in the available frames queue.
Definition: mythplayer.cpp:645
void SetErrored(const QString &reason)
void SetFrameRate(double fps)
Definition: mythplayer.cpp:374
void DeLimboFrame(MythVideoFrame *frame)
Definition: mythplayer.cpp:670
bool IsErrored(void) const
void EnableForcedSubtitles(bool enable)
Definition: mythplayer.cpp:676
void SetKeyframeDistance(int keyframedistance)
Definition: mythplayer.cpp:316
void SetFileLength(std::chrono::seconds total, int frames)
Definition: mythplayer.cpp:384
virtual SubtitleReader * GetSubReader(uint=0)
Definition: mythplayer.h:195
bool GetAllowForcedSubtitles(void) const
Definition: mythplayer.h:204
MythVideoFrame * GetNextVideoFrame(void)
Removes a frame from the available queue for decoding onto.
Definition: mythplayer.cpp:585
int GetFreeVideoFrames(void) const
Returns the number of frames available for decoding onto.
Definition: mythplayer.cpp:569
void DiscardVideoFrame(MythVideoFrame *buffer)
Places frame in the available frames queue.
Definition: mythplayer.cpp:626
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:14
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
@ kStartRunning
Definition: mythtimer.h:17
long long m_frameNumber
Definition: mythframe.h:128
VideoFrameType m_type
Definition: mythframe.h:118
int m_chromalocation
Definition: mythframe.h:151
bool m_colorshifted
Definition: mythframe.h:152
static uint GetNumPlanes(VideoFrameType Type)
Definition: mythframe.h:213
bool m_interlaced
Definition: mythframe.h:133
bool m_interlacedReverse
Definition: mythframe.h:135
int m_colorprimaries
Definition: mythframe.h:149
void ClearMetadata()
Definition: mythframe.cpp:149
bool m_deinterlaceInuse2x
Definition: mythframe.h:161
int m_colortransfer
Definition: mythframe.h:150
bool m_pauseFrame
Definition: mythframe.h:140
bool m_directRendering
Definition: mythframe.h:145
uint64_t m_frameCounter
Definition: mythframe.h:129
FramePitches m_pitches
Definition: mythframe.h:141
uint8_t * m_buffer
Definition: mythframe.h:119
bool m_topFieldFirst
Definition: mythframe.h:134
bool m_alreadyDeinterlaced
Definition: mythframe.h:153
float m_aspect
Definition: mythframe.h:126
MythDeintType m_deinterlaceInuse
Definition: mythframe.h:160
void ClearBufferToBlank()
Definition: mythframe.cpp:205
FrameOffsets m_offsets
Definition: mythframe.h:142
void SetInput(QSize Size, float Framerate=0, const QString &CodecName=QString(), const QStringList &DisallowedDecoders=QStringList())
uint GetMaxCPUs() const
QString GetDecoder() const
bool IsSkipLoopEnabled() const
A PSIP table is a variant of a PES packet containing an MPEG, ATSC or DVB table.
Definition: mpegtables.h:410
Holds information on recordings and videos.
Definition: programinfo.h:68
std::chrono::milliseconds QueryTotalDuration(void) const
If present this loads the total duration in milliseconds of the main video stream from recordedmarkup...
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
Definition: mpegtables.h:676
uint StreamCount(void) const
Definition: mpegtables.h:733
uint StreamType(uint i) const
Definition: mpegtables.h:721
const unsigned char * ProgramInfo(void) const
Definition: mpegtables.h:718
const unsigned char * StreamInfo(uint i) const
Definition: mpegtables.h:730
uint ProgramInfoLength(void) const
Definition: mpegtables.h:715
bool IsVideo(uint i, const QString &sistandard) const
Returns true iff the stream at index i is a video stream.
Definition: mpegtables.cpp:518
uint StreamInfoLength(uint i) const
Definition: mpegtables.h:727
float aspect(bool mpeg1) const
Returns the screen aspect ratio.
Definition: pespacket.cpp:234
@ PrivData
ISO 13818-1 PES private data & ITU H.222.0.
Definition: mpegtables.h:147
static bool IsObjectCarousel(uint type)
Returns true iff stream contains DSMCC Object Carousel.
Definition: mpegtables.h:190
uint m_language_index
Audio, Subtitle, Teletext.
Definition: decoderbase.h:107
int m_av_stream_index
Definition: decoderbase.h:103
int m_language
ISO639 canonical language key; Audio, Subtitle, CC, Teletext, RawText.
Definition: decoderbase.h:106
int m_av_substream_index
Audio only; -1 for no substream, 0 for first dual audio stream, 1 for second dual.
Definition: decoderbase.h:111
int m_stream_id
Definition: decoderbase.h:104
bool AddAVSubtitle(AVSubtitle &subtitle, bool fix_position, bool is_selected_forced_track, bool allow_forced, bool isExternal)
void AddRawTextSubtitle(const QStringList &list, std::chrono::milliseconds duration)
void Decode(const unsigned char *buf, int vbimode)
Decodes teletext data.
int GetDecoderType(void) const
static bool ReinitBuffer(MythVideoFrame *Frame, VideoFrameType Type, MythCodecID CodecID, int Width, int Height)
AudioTrackType
Definition: decoderbase.h:56
@ kAudioTypeCommentary
Definition: decoderbase.h:62
@ kAudioTypeAudioDescription
Definition: decoderbase.h:58
@ kAudioTypeSpokenSubs
Definition: decoderbase.h:61
@ kAudioTypeHearingImpaired
Definition: decoderbase.h:60
@ kAudioTypeNormal
Definition: decoderbase.h:57
@ kAudioTypeCleanEffects
Definition: decoderbase.h:59
std::vector< char > TestBufferVec
Definition: decoderbase.h:23
std::vector< StreamInfo > sinfo_vec_t
Definition: decoderbase.h:118
const int kDecoderProbeBufferSize
Definition: decoderbase.h:22
TrackType
Track types.
Definition: decoderbase.h:27
@ kTrackTypeCC608
Definition: decoderbase.h:32
@ kTrackTypeRawText
Definition: decoderbase.h:36
@ kTrackTypeSubtitle
Definition: decoderbase.h:31
@ kTrackTypeTeletextMenu
Definition: decoderbase.h:35
@ kTrackTypeCC708
Definition: decoderbase.h:33
@ kTrackTypeTeletextCaptions
Definition: decoderbase.h:34
@ kTrackTypeAudio
Definition: decoderbase.h:29
@ kTrackTypeVideo
Definition: decoderbase.h:30
@ kTrackTypeAttachment
Definition: decoderbase.h:37
DecodeType
Definition: decoderbase.h:48
@ kDecodeNothing
Definition: decoderbase.h:49
@ kDecodeVideo
Definition: decoderbase.h:50
@ kDecodeAV
Definition: decoderbase.h:52
@ kDecodeAudio
Definition: decoderbase.h:51
static const std::array< const uint64_t, 4 > samples
Definition: element.cpp:46
unsigned int uint
Definition: freesurround.h:24
static const struct wl_interface * types[]
QString iso639_key_toName(int iso639_2)
Converts a canonical key to language name in English.
Definition: iso639.cpp:109
int iso639_key_to_canonical_key(int iso639_2)
Definition: iso639.cpp:118
QString iso639_str2_to_str3(const QString &str2)
Definition: iso639.cpp:68
ISO 639-1 and ISO 639-2 support functions.
static int iso639_str3_to_key(const unsigned char *iso639_2)
Definition: iso639.h:60
static bool iso639_is_key_undefined(int code)
Returns true if the key is 0, 0xFFFFFF, or 'und'.
Definition: iso639.h:54
unsigned short uint16_t
Definition: iso6937tables.h:3
@ SPEAKER_LR
Definition: lcddevice.h:97
@ SPEAKER_71
Definition: lcddevice.h:99
@ SPEAKER_51
Definition: lcddevice.h:98
LCDAudioFormatSet
Definition: lcddevice.h:103
@ AUDIO_OGG
Definition: lcddevice.h:107
@ AUDIO_MPEG2
Definition: lcddevice.h:111
@ AUDIO_AC3
Definition: lcddevice.h:112
@ AUDIO_WAV
Definition: lcddevice.h:109
@ AUDIO_MP3
Definition: lcddevice.h:106
@ AUDIO_DTS
Definition: lcddevice.h:113
@ AUDIO_WMA
Definition: lcddevice.h:114
@ AUDIO_WMA2
Definition: lcddevice.h:108
LCDVideoFormatSet
Definition: lcddevice.h:118
@ VIDEO_XVID
Definition: lcddevice.h:122
@ VIDEO_WMV
Definition: lcddevice.h:123
@ VIDEO_MPG
Definition: lcddevice.h:120
@ VIDEO_DIVX
Definition: lcddevice.h:121
@ VARIOUS_SPDIF
Definition: lcddevice.h:151
@ VARIOUS_HDTV
Definition: lcddevice.h:150
std::vector< const unsigned char * > desc_list_t
char * av_make_error_stdstring(std::string &errbuf, int errnum)
A C++ equivalent to av_make_error_string.
Definition: mythaverror.cpp:42
MPUBLIC std::string av_make_error_stdstring_unknown(int errnum)
Definition: mythaverror.h:47
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::milliseconds > millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:91
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::seconds > secondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:80
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::microseconds > microsecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:102
QString get_decoder_name(MythCodecID codec_id)
uint mpeg_version(AVCodecID codec_id)
static bool codec_is_std(MythCodecID id)
Definition: mythcodecid.h:296
MythCodecID
Definition: mythcodecid.h:14
@ kCodec_NONE
Definition: mythcodecid.h:17
@ kCodec_MPEG1
Definition: mythcodecid.h:24
@ kCodec_MPEG2
Definition: mythcodecid.h:25
static bool CODEC_IS_H264(AVCodecID id)
Definition: mythcodecid.h:384
static bool CODEC_IS_MPEG(AVCodecID id)
Definition: mythcodecid.h:386
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
@ DEINT_NONE
Definition: mythframe.h:68
static constexpr uint8_t MYTH_WIDTH_ALIGNMENT
Definition: mythframe.h:16
VideoFrameType
Definition: mythframe.h:20
static constexpr uint8_t MYTH_HEIGHT_ALIGNMENT
Definition: mythframe.h:17
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
PlayerFlags
Definition: mythplayer.h:65
@ kDecodeLowRes
Definition: mythplayer.h:67
@ kDecodeFewBlocks
Definition: mythplayer.h:69
@ kDecodeAllowGPU
Definition: mythplayer.h:72
@ kDecodeNoDecode
Definition: mythplayer.h:71
@ kDecodeNoLoopFilter
Definition: mythplayer.h:70
@ kDecodeSingleThreaded
Definition: mythplayer.h:68
MTV_PUBLIC const uint8_t * find_start_code_truncated(const uint8_t *p, const uint8_t *end, uint32_t *start_code)
By preserving the start_code value between subsequent calls, the caller can detect start codes across...
Definition: bytereader.cpp:74
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
Definition: mythdate.cpp:242
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
std::vector< std::string_view > split_sv(const std::string_view s, const std::string_view delimiter)
Split a std::string_view into a std::vector of std::string_views.
Definition: stringutil.h:74
QString intToPaddedString(int n, int width=2)
Creates a zero padded string representation of an integer.
Definition: stringutil.h:27
dictionary info
Definition: azlyrics.py:7
string version
Definition: giantbomb.py:185
def error(message)
Definition: smolt.py:409
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
Definition: mythchrono.h:55
int64_t ptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:78
@ MARK_GOP_BYFRAME
Definition: programtypes.h:63
@ VBI_DVB_SUBTITLE
< DVB packet
Definition: vbilut.h:25
@ VBI_DVB
< IVTV packet
Definition: vbilut.h:24
@ VBI_IVTV
Definition: vbilut.h:23
@ kScan_Ignore
Definition: videoouttypes.h:96
@ kScan_Detect
Definition: videoouttypes.h:97
@ kScan_Progressive