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