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