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,0,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 if (strcmp(fmt->name, "mpegts") == 0 &&
933 gCoreContext->GetBoolSetting("FFMPEGTS", false))
934 {
935 const AVInputFormat *fmt2 = av_find_input_format("mpegts-ffmpeg");
936 if (fmt2)
937 {
938 fmt = fmt2;
939 LOG(VB_GENERAL, LOG_INFO, LOC + "Using FFmpeg MPEG-TS demuxer (forced)");
940 }
941 }
942
943 int err = 0;
944 bool scancomplete = false;
945 int remainingscans = 5;
946
947 while (!scancomplete && remainingscans--)
948 {
949 bool found = false;
950
951 // With live tv, the ringbufer may contain insufficient data for complete
952 // initialisation so we try a few times with a slight pause each time to
953 // allow extra data to become available. In the worst case scenarios, the
954 // stream may not have a keyframe for 4-5 seconds.
955 // As a last resort, we will try and fallback to the original FFmpeg MPEG-TS
956 // demuxer if it is not already used.
957 // For regular videos, this shouldn't be an issue as the complete file
958 // should be available - though we try a little harder for streamed formats
959 int retries = m_livetv || m_ringBuffer->IsStreamed() ? 50 : 10;
960
961 while (!found && --retries)
962 {
963 m_ic = avformat_alloc_context();
964 if (!m_ic)
965 {
966 LOG(VB_GENERAL, LOG_ERR, LOC + "Could not allocate format context.");
967 return -1;
968 }
969
970 delete m_avfRingBuffer;
973 LOG(VB_PLAYBACK, LOG_INFO, LOC +
974 QString("Buffer size: %1 Streamed %2 Seekable %3 Available %4")
976 .arg(m_ringBuffer->IsStreamed())
977 .arg(m_ic->pb->seekable)
980
981 err = avformat_open_input(&m_ic, filename, fmt, nullptr);
982 if (err < 0)
983 {
984 std::string error;
985 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Failed to open input ('%1')")
986 .arg(av_make_error_stdstring(error, err)));
987
988 // note - m_ic (AVFormatContext) is freed on failure
989 if (retries > 2)
990 {
991 // wait a little to buffer more data
992 // 50*0.1 = 5 seconds max
993 std::this_thread::sleep_for(100ms);
994 // resets the read position
996 continue;
997 }
998
999 if (strcmp(fmt->name, "mpegts") == 0)
1000 {
1001 fmt = av_find_input_format("mpegts-ffmpeg");
1002 if (fmt)
1003 {
1004 LOG(VB_GENERAL, LOG_ERR, LOC + "Attempting to use original FFmpeg MPEG-TS demuxer.");
1005 // resets the read position
1006 m_avfRingBuffer->SetInInit(false);
1007 continue;
1008 }
1009 break;
1010 }
1011 }
1012 found = true;
1013 }
1014
1015 if (err < 0)
1016 {
1017 LOG(VB_GENERAL, LOG_ERR, LOC + "Fatal error opening input. Aborting");
1018 m_ic = nullptr;
1019 return -1;
1020 }
1021
1022 // With certain streams, we don't get a complete stream analysis and the video
1023 // codec/frame format is not fully detected. This can have various consequences - from
1024 // failed playback to not enabling hardware decoding (as the frame formt is not valid).
1025 // Bump the duration (FFmpeg defaults to 5 seconds) to 60 seconds. This should
1026 // not impact performance as in the vast majority of cases the scan is completed
1027 // within a second or two (seconds in this case referring to stream duration - not the time
1028 // it takes to complete the scan).
1029 m_ic->max_analyze_duration = 60LL * AV_TIME_BASE;
1030
1032 m_avCodecLock.lock();
1033 err = avformat_find_stream_info(m_ic, nullptr);
1034 m_avCodecLock.unlock();
1035 if (err < 0)
1036 {
1037 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Could not find codec parameters for '%1'").arg(filename));
1038 CloseContext();
1039 return -1;
1040 }
1041 m_avfRingBuffer->SetInInit(false);
1042
1043 // final sanity check that scanned streams are valid for live tv
1044 scancomplete = true;
1045 for (uint i = 0; m_livetv && (i < m_ic->nb_streams); i++)
1046 {
1047 if (!StreamHasRequiredParameters(m_codecMap.GetCodecContext(m_ic->streams[i]), m_ic->streams[i]))
1048 {
1049 scancomplete = false;
1050 if (remainingscans)
1051 {
1052 CloseContext();
1053 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Stream scan incomplete - retrying");
1054 std::this_thread::sleep_for(250ms);
1055 }
1056 break;
1057 }
1058 }
1059 }
1060
1061 if (!scancomplete)
1062 LOG(VB_GENERAL, LOG_WARNING, LOC + "Scan incomplete - playback may not work");
1063
1064 m_ic->streams_changed = HandleStreamChange;
1065 m_ic->stream_change_data = this;
1066
1067 if (!m_livetv && !m_ringBuffer->IsDisc())
1068 {
1069 // generate timings based on the video stream to avoid bogus ffmpeg
1070 // values for duration and bitrate
1072 }
1073
1074 // FLAC, MP3 or M4A file may contains an artwork image, a single frame MJPEG,
1075 // we need to ignore it as we don't handle single frames or images in place of video
1076 // TODO: display single frame
1077 QString extension = QFileInfo(fnames).suffix();
1078 if (strcmp(fmt->name, "mp3") == 0 || strcmp(fmt->name, "flac") == 0 ||
1079 strcmp(fmt->name, "ogg") == 0 ||
1080 (extension.compare("m4a", Qt::CaseInsensitive) == 0))
1081 {
1082 novideo = true;
1083 }
1084
1085 // Scan for the initial A/V streams
1086 err = ScanStreams(novideo);
1087 if (-1 == err)
1088 {
1089 CloseContext();
1090 return err;
1091 }
1092
1093#if CONFIG_MHEG
1094 {
1095 int initialAudio = -1;
1096 int initialVideo = -1;
1097 if (m_itv == nullptr)
1099 if (m_itv != nullptr)
1100 m_itv->GetInitialStreams(initialAudio, initialVideo);
1101 if (initialAudio >= 0)
1102 SetAudioByComponentTag(initialAudio);
1103 if (initialVideo >= 0)
1104 SetVideoByComponentTag(initialVideo);
1105 }
1106#endif // CONFIG_MHEG
1107
1108 // Try to get a position map from the recorder if we don't have one yet.
1110 {
1112 {
1115 {
1116 m_hasFullPositionMap = true;
1117 m_gopSet = true;
1118 }
1119 }
1120 }
1121
1122 // If watching pre-recorded television or video use the marked duration
1123 // from the db if it exists, else ffmpeg duration
1124 std::chrono::seconds dur = 0s;
1125
1126 if (m_playbackInfo)
1127 {
1128 dur = duration_cast<std::chrono::seconds>(m_playbackInfo->QueryTotalDuration());
1129 }
1130
1131 if (dur == 0s)
1132 {
1133 dur = duration_cast<std::chrono::seconds>(av_duration(m_ic->duration));
1134 }
1135
1136 if (dur > 0s && !m_livetv && !m_watchingRecording)
1137 {
1138 m_parent->SetDuration(dur);
1139 }
1140
1141 // If we don't have a position map, set up ffmpeg for seeking
1143 {
1144 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1145 "Recording has no position -- using libavformat seeking.");
1146
1147 if (dur > 0s)
1148 {
1149 m_parent->SetFileLength(dur, (int)(dur.count() * m_fps));
1150 }
1151 else
1152 {
1153 // the pvr-250 seems to over report the bitrate by * 2
1154 float bytespersec = (float)m_bitrate / 8 / 2;
1155 float secs = m_ringBuffer->GetRealFileSize() * 1.0F / bytespersec;
1157 (int)(secs * static_cast<float>(m_fps)));
1158 }
1159
1160 // we will not see a position map from db or remote encoder,
1161 // set the gop interval to 15 frames. if we guess wrong, the
1162 // auto detection will change it.
1163 m_keyframeDist = 15;
1165
1166 if (strcmp(fmt->name, "avi") == 0)
1167 {
1168 // avi keyframes are too irregular
1169 m_keyframeDist = 1;
1170 }
1171
1172 m_dontSyncPositionMap = true;
1173 }
1174
1175 av_dump_format(m_ic, 0, filename, 0);
1176
1177 // print some useful information if playback debugging is on
1179 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Position map found");
1181 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Partial position map found");
1182 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1183 QString("Successfully opened decoder for file: \"%1\". novideo(%2)")
1184 .arg(filename).arg(novideo));
1185
1186 // Print AVChapter information
1187 for (unsigned int i=0; i < m_ic->nb_chapters; i++)
1188 {
1189 int num = m_ic->chapters[i]->time_base.num;
1190 int den = m_ic->chapters[i]->time_base.den;
1191 int64_t start = m_ic->chapters[i]->start;
1192 auto total_secs = static_cast<long double>(start) * static_cast<long double>(num) /
1193 static_cast<long double>(den);
1194 auto msec = millisecondsFromFloat(total_secs * 1000);
1195 auto framenum = static_cast<long long>(total_secs * static_cast<long double>(m_fps));
1196 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1197 QString("Chapter %1 found @ [%2]->%3")
1199 MythDate::formatTime(msec, "HH:mm:ss.zzz"),
1200 QString::number(framenum)));
1201 }
1202
1203 if (m_ringBuffer->IsDVD())
1204 {
1205 // Reset DVD playback and clear any of
1206 // our buffers so that none of the data
1207 // parsed so far to determine decoders
1208 // gets shown.
1210 return -1;
1212
1213 Reset(true, true, true);
1214
1215 // Now we're ready to process and show frames
1216 m_processFrames = true;
1217 }
1218
1219
1220 // Return true if recording has position map
1221 return static_cast<int>(m_recordingHasPositionMap);
1222}
1223
1224float AvFormatDecoder::GetVideoFrameRate(AVStream *Stream, AVCodecContext *Context, bool Sanitise)
1225{
1226 // MKV default_duration
1227 double avg_fps = (Stream->avg_frame_rate.den == 0) ? 0.0 : av_q2d(Stream->avg_frame_rate);
1228 double codec_fps = av_q2d(Context->framerate); // {0, 1} when unknown
1229 double container_fps = (Stream->time_base.num == 0) ? 0.0 : av_q2d(av_inv_q(Stream->time_base));
1230 // least common multiple of all framerates in a stream; this is a guess
1231 double estimated_fps = (Stream->r_frame_rate.den == 0) ? 0.0 : av_q2d(Stream->r_frame_rate);
1232
1233
1234 // List of known, standards based frame rates
1235 static const std::vector<double> k_standard_rates =
1236 {
1237 24000.0 / 1001.0,
1238 23.976,
1239 24.0,
1240 25.0,
1241 30000.0 / 1001.0,
1242 29.97,
1243 30.0,
1244 50.0,
1245 60000.0 / 1001.0,
1246 59.94,
1247 60.0,
1248 100.0,
1249 120000.0 / 1001.0,
1250 119.88,
1251 120.0
1252 };
1253
1254 // build a list of possible rates, best first
1255 std::vector<double> rates;
1256 rates.reserve(7);
1257
1258 // matroska demuxer sets the default_duration to avg_frame_rate
1259 // mov,mp4,m4a,3gp,3g2,mj2 demuxer sets avg_frame_rate
1260 if (QString(m_ic->iformat->name).contains("matroska") ||
1261 QString(m_ic->iformat->name).contains("mov"))
1262 {
1263 rates.emplace_back(avg_fps);
1264 }
1265
1266 // avi uses container fps for timestamps
1267 if (QString(m_ic->iformat->name).contains("avi"))
1268 {
1269 rates.emplace_back(container_fps);
1270 }
1271
1272 rates.emplace_back(codec_fps);
1273 rates.emplace_back(container_fps);
1274 rates.emplace_back(avg_fps);
1275 // certain H.264 interlaced streams are detected at 2x using estimated (i.e. wrong)
1276 rates.emplace_back(estimated_fps);
1277 // last resort, default to NTSC
1278 rates.emplace_back(30000.0 / 1001.0);
1279
1280 auto invalid_fps = [](double rate) { return rate < 3.0 || rate > 121.0; };
1281 rates.erase(std::remove_if(rates.begin(), rates.end(), invalid_fps), rates.end());
1282
1283 auto FuzzyEquals = [](double First, double Second) { return std::abs(First - Second) < 0.03; };
1284
1285 // debug
1286 if (!FuzzyEquals(rates.front(), m_fps))
1287 {
1288 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1289 QString("Selected FPS: %1 (Avg:%2 Mult:%3 Codec:%4 Container:%5 Estimated:%6)")
1290 .arg(static_cast<double>(rates.front())).arg(avg_fps)
1291 .arg(m_fpsMultiplier).arg(codec_fps).arg(container_fps).arg(estimated_fps));
1292
1293 LOG(VB_GENERAL, LOG_INFO, LOC +
1294 QString("Sanitise:%1").arg(Sanitise) +
1295 QString(" avg_fps:%1").arg(avg_fps) +
1296 QString(" codec_fps:%1").arg(codec_fps) +
1297 QString(" container_fps:%1").arg(container_fps) +
1298 QString(" estimated_fps:%1").arg(estimated_fps) +
1299 QString(" m_fps:%1").arg(m_fps));
1300
1301 QStringList rs;
1302 for (auto rate : rates)
1303 rs.append(QString::number(rate));
1304 LOG(VB_GENERAL, LOG_INFO, LOC +
1305 QString("Frame rates:%1").arg(rs.join(' ')));
1306 }
1307
1308 auto IsStandard = [&FuzzyEquals](double Rate)
1309 {
1310 if (Rate > 23.0 && Rate < 121.0)
1311 {
1312 for (auto standard_rate : k_standard_rates)
1313 if (FuzzyEquals(Rate, standard_rate))
1314 return true;
1315 }
1316 return false;
1317 // TODO do not convert AVRational to double
1318 //return k_standard_rates.find(rate) != k_standard_rates.end();
1319 };
1320
1321 auto NearestStandardFrameRate = [](double rate, double epsilon)
1322 {
1323 double result = rate;
1324 double lowest_delta = rate;
1325 for (auto standard_rate : k_standard_rates)
1326 {
1327 double delta = std::abs(rate - standard_rate);
1328 if ((delta < lowest_delta) && (delta < epsilon))
1329 {
1330 lowest_delta = delta;
1331 result = standard_rate;
1332 }
1333 }
1334 return result;
1335 };
1336
1337 // If the first choice rate is unusual, see if there is something more 'usual'
1338 double detected = rates.front();
1339
1340 // Round the detected frame rate to the nearest standard frame rate
1341 // when the detected frame rate is within 3 fps of the nearest standard frame rate.
1342 {
1343 double nearest = NearestStandardFrameRate(detected, 3.0);
1344 LOG(VB_GENERAL, LOG_INFO, LOC +
1345 QString("Frame rate %1 rounded to nearest standard rate %2")
1346 .arg(detected, 0, 'f', 2).arg(nearest, 0, 'f', 2));
1347 detected = nearest;
1348 }
1349
1350 if (Sanitise && !IsStandard(detected))
1351 {
1352 for (auto rate : rates)
1353 {
1354 if (IsStandard(rate))
1355 {
1356 LOG(VB_GENERAL, LOG_INFO, LOC + QString("%1 is non-standard - using %2 instead.")
1357 .arg(rates.front()).arg(rate));
1358
1359 // The most common problem here is mpegts files where the average
1360 // rate is slightly out and the estimated rate is the fallback.
1361 // As noted above, however, the estimated rate is sometimes twice
1362 // the actual for interlaced content. Try and detect and fix this
1363 // so that we don't throw out deinterlacing and video mode switching.
1364 // Assume anything under 30 may be interlaced - with +-10% error.
1365 if (rate > 33.0 && detected < 33.0)
1366 {
1367 double half = rate / 2.0;
1368 if (std::abs(half - detected) < (half * 0.1))
1369 {
1370 LOG(VB_GENERAL, LOG_INFO, LOC +
1371 QString("Assuming %1 is a better choice than %2")
1372 .arg(half).arg(rate));
1373 return static_cast<float>(half);
1374 }
1375 }
1376 return static_cast<float>(rate);
1377 }
1378 }
1379 }
1380
1381 return static_cast<float>(detected);
1382}
1383
1384int AvFormatDecoder::GetMaxReferenceFrames(AVCodecContext *Context)
1385{
1386 switch (Context->codec_id)
1387 {
1388 case AV_CODEC_ID_H264:
1389 {
1390 int result = 16;
1391 if (Context->extradata && (Context->extradata_size >= 7))
1392 {
1393 uint8_t offset = 0;
1394 if (Context->extradata[0] == 1)
1395 offset = 9; // avCC
1396 else if (ByteReader::readBigEndianU24(Context->extradata) == 0x01)
1397 offset = 4; // Annex B - 3 byte startcode 0x000001
1398 else if (ByteReader::readBigEndianU32(Context->extradata) == 0x01)
1399 offset= 5; // Annex B - 4 byte startcode 0x00000001
1400
1401 if (offset)
1402 {
1404 bool dummy = false;
1405 parser.parse_SPS(Context->extradata + offset,
1406 static_cast<uint>(Context->extradata_size - offset), dummy, result);
1407 }
1408 }
1409 return result;
1410 }
1411 case AV_CODEC_ID_H265: return 16;
1412 case AV_CODEC_ID_VP9: return 8;
1413 case AV_CODEC_ID_VP8: return 3;
1414 default: return 2;
1415 }
1416}
1417
1418void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *codecContext,
1419 bool selectedStream)
1420{
1421 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1422 QString("InitVideoCodec ID:%1 Type:%2 Size:%3x%4")
1423 .arg(avcodec_get_name(codecContext->codec_id),
1424 AVMediaTypeToString(codecContext->codec_type))
1425 .arg(codecContext->width).arg(codecContext->height));
1426
1428 m_directRendering = false;
1429
1430 codecContext->opaque = static_cast<void*>(this);
1431 codecContext->get_buffer2 = get_avf_buffer;
1432 codecContext->slice_flags = 0;
1433
1434 codecContext->err_recognition = AV_EF_COMPLIANT;
1435 codecContext->workaround_bugs = FF_BUG_AUTODETECT;
1436 codecContext->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
1437 codecContext->idct_algo = FF_IDCT_AUTO;
1438 codecContext->debug = 0;
1439 // codecContext->error_rate = 0;
1440
1441 const AVCodec *codec1 = codecContext->codec;
1442
1443 if (selectedStream)
1444 m_directRendering = true;
1445
1446 // retrieve rotation information
1447 const AVPacketSideData *sd = av_packet_side_data_get(stream->codecpar->coded_side_data,
1448 stream->codecpar->nb_coded_side_data, AV_PKT_DATA_DISPLAYMATRIX);
1449 if (sd)
1450 m_videoRotation = static_cast<int>(-av_display_rotation_get(reinterpret_cast<int32_t*>(sd->data)));
1451 else
1452 m_videoRotation = 0;
1453
1454 // retrieve 3D type
1455 sd = av_packet_side_data_get(stream->codecpar->coded_side_data,
1456 stream->codecpar->nb_coded_side_data, AV_PKT_DATA_STEREO3D);
1457 if (sd)
1458 {
1459 auto * avstereo = reinterpret_cast<AVStereo3D*>(sd->data);
1460 m_stereo3D = avstereo->type;
1461 }
1462
1463 delete m_mythCodecCtx;
1465 m_mythCodecCtx->InitVideoCodec(codecContext, selectedStream, m_directRendering);
1466 if (m_mythCodecCtx->HwDecoderInit(codecContext) < 0)
1467 {
1468 // force it to switch to software decoding
1470 m_streamsChanged = true;
1471 }
1472 else
1473 {
1474 // Note: This is never going to work as expected in all circumstances.
1475 // It will not account for changes in the stream and/or display. For
1476 // MediaCodec, Android will do its own thing (and judging by the Android logs,
1477 // shouldn't double rate the deinterlacing if the display cannot support it).
1478 // NVDEC will probably move to the FFmpeg YADIF CUDA deinterlacer - which
1479 // will avoid the issue (video player deinterlacing) and maybe disable
1480 // decoder VAAPI deinterlacing. If we get it wrong and the display cannot
1481 // keep up, the player should just drop frames.
1482
1483 // FIXME - need a better way to handle this
1484 bool doublerate = true;//m_parent->CanSupportDoubleRate();
1485 m_mythCodecCtx->SetDeinterlacing(codecContext, &m_videoDisplayProfile, doublerate);
1486 }
1487
1488 if (codec1 && ((AV_CODEC_ID_MPEG2VIDEO == codec1->id) ||
1489 (AV_CODEC_ID_MPEG1VIDEO == codec1->id)))
1490 {
1492 {
1493 int total_blocks = (codecContext->height + 15) / 16;
1494 codecContext->skip_top = (total_blocks + 3) / 4;
1495 codecContext->skip_bottom = (total_blocks + 3) / 4;
1496 }
1497
1499 codecContext->lowres = 2; // 1 = 1/2 size, 2 = 1/4 size
1500 }
1501 else if (codec1 && (AV_CODEC_ID_H264 == codec1->id) && FlagIsSet(kDecodeNoLoopFilter))
1502 {
1503 codecContext->flags &= ~AV_CODEC_FLAG_LOOP_FILTER;
1504 codecContext->skip_loop_filter = AVDISCARD_ALL;
1505 }
1506
1508 codecContext->skip_idct = AVDISCARD_ALL;
1509
1510 if (selectedStream)
1511 {
1512 // m_fps is now set 'correctly' in ScanStreams so this additional call
1513 // to GetVideoFrameRate may now be redundant
1514 m_fps = GetVideoFrameRate(stream, codecContext, true);
1515 QSize dim = get_video_dim(*codecContext);
1516 int width = m_currentWidth = dim.width();
1517 int height = m_currentHeight = dim.height();
1518 m_currentAspect = get_aspect(*codecContext);
1519
1520 if (!width || !height)
1521 {
1522 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1523 "InitVideoCodec invalid dimensions, resetting decoder.");
1524 width = 640;
1525 height = 480;
1526 m_fps = 29.97F;
1527 m_currentAspect = 4.0F / 3.0F;
1528 }
1529
1531 const AVCodec *codec2 = codecContext->codec;
1532 QString codecName;
1533 if (codec2)
1534 codecName = codec2->name;
1535 m_parent->SetVideoParams(width, height, m_fps,
1536 m_currentAspect, false, GetMaxReferenceFrames(codecContext),
1537 kScan_Detect, codecName);
1538 if (LCD *lcd = LCD::Get())
1539 {
1540 LCDVideoFormatSet video_format = VIDEO_MPG;
1541
1542 switch (codecContext->codec_id)
1543 {
1544 case AV_CODEC_ID_H263:
1545 case AV_CODEC_ID_MPEG4:
1546 case AV_CODEC_ID_MSMPEG4V1:
1547 case AV_CODEC_ID_MSMPEG4V2:
1548 case AV_CODEC_ID_MSMPEG4V3:
1549 case AV_CODEC_ID_H263P:
1550 case AV_CODEC_ID_H263I:
1551 video_format = VIDEO_DIVX;
1552 break;
1553 case AV_CODEC_ID_WMV1:
1554 case AV_CODEC_ID_WMV2:
1555 video_format = VIDEO_WMV;
1556 break;
1557#if 0
1558 case AV_CODEC_ID_XVID:
1559 video_format = VIDEO_XVID;
1560 break;
1561#endif
1562 default:
1563 video_format = VIDEO_MPG;
1564 break;
1565 }
1566
1567 lcd->setVideoFormatLEDs(video_format, true);
1568
1569 if(height >= 720)
1570 lcd->setVariousLEDs(VARIOUS_HDTV, true);
1571 else
1572 lcd->setVariousLEDs(VARIOUS_HDTV, false);
1573 }
1574 }
1575}
1576
1578{
1579 static constexpr std::array<uint8_t, 256> odd_parity_LUT
1580 {
1581 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1582 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1583 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1584 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1585 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1586 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1587 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1588 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1589 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1590 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1591 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1592 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1593 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1594 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1595 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1596 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1597 };
1598 bool ret = (odd_parity_LUT[data & 0xff] == 1) &&
1599 (odd_parity_LUT[(data & 0xff00) >> 8] == 1);
1600 if (!ret)
1601 {
1602 LOG(VB_VBI, LOG_ERR, LOC +
1603 QString("VBI: Bad parity in EIA-608 data (%1)") .arg(data,0,16));
1604 }
1605 return ret;
1606}
1607
1608static AVBufferRef* get_pmt_section_from_AVProgram(const AVProgram *program)
1609{
1610 if (program == nullptr)
1611 {
1612 return nullptr;
1613 }
1614 return program->pmt_section;
1615}
1616
1617static AVBufferRef* get_pmt_section_for_AVStream_index(AVFormatContext *context, int stream_index)
1618{
1619 AVProgram* program = av_find_program_from_stream(context, nullptr, stream_index);
1620 return get_pmt_section_from_AVProgram(program);
1621}
1622
1624{
1625 QMutexLocker locker(&m_trackLock);
1626
1627 m_ccX08InPmt.fill(false);
1628 m_pmtTracks.clear();
1629 m_pmtTrackTypes.clear();
1630
1631 // Figure out languages of ATSC captions
1633 if (!pmt_buffer.has_buffer())
1634 {
1635 LOG(VB_GENERAL, LOG_DEBUG, LOC +
1636 "ScanATSCCaptionStreams() called with no PMT");
1637 return;
1638 }
1639 const ProgramMapTable pmt(PSIPTable(pmt_buffer.data()));
1640
1641 bool video_found = false;
1642 uint i = 0;
1643 for (i = 0; i < pmt.StreamCount(); i++)
1644 {
1645 // MythTV remaps OpenCable Video to normal video during recording
1646 // so "dvb" is the safest choice for system info type, since this
1647 // will ignore other uses of the same stream id in DVB countries.
1648 if (pmt.IsVideo(i, "dvb"))
1649 {
1650 video_found = true;
1651 break;
1652 }
1653 }
1654 if (!video_found)
1655 return;
1656
1658 pmt.StreamInfo(i), pmt.StreamInfoLength(i),
1660
1662 pmt.ProgramInfo(), pmt.ProgramInfoLength(),
1664
1665 desc_list.insert(desc_list.end(), desc_list2.begin(), desc_list2.end());
1666
1667 for (auto & desc : desc_list)
1668 {
1669 const CaptionServiceDescriptor csd(desc);
1670 if (!csd.IsValid())
1671 continue;
1672
1673 LOG(VB_VBI, LOG_DEBUG, LOC + csd.toString());
1674
1675 for (uint k = 0; k < csd.ServicesCount(); k++)
1676 {
1677 int lang = csd.CanonicalLanguageKey(k);
1678 int type = csd.Type(k) ? 1 : 0;
1679 if (type)
1680 {
1681 StreamInfo si {av_index, csd.CaptionServiceNumber(k), lang};
1682 uint key = csd.CaptionServiceNumber(k) + 4;
1683 m_ccX08InPmt[key] = true;
1684 m_pmtTracks.push_back(si);
1686 }
1687 else
1688 {
1689 int line21 = csd.Line21Field(k) ? 3 : 1;
1690 StreamInfo si {av_index, line21, lang};
1691 m_ccX08InPmt[line21-1] = true;
1692 m_pmtTracks.push_back(si);
1694 }
1695 }
1696 }
1697}
1698
1700{
1701 QMutexLocker locker(&m_trackLock);
1702
1703 m_tracks[kTrackTypeCC608].clear();
1704 m_tracks[kTrackTypeCC708].clear();
1705 m_ccX08InTracks.fill(false);
1706
1707 uint pidx = 0;
1708 uint sidx = 0;
1709 std::array<std::map<int,uint>,2> lang_cc_cnt;
1710 while (true)
1711 {
1712 bool pofr = pidx >= (uint)m_pmtTracks.size();
1713 bool sofr = sidx >= (uint)m_streamTracks.size();
1714 if (pofr && sofr)
1715 break;
1716
1717 // choose lowest available next..
1718 // stream_id's of 608 and 708 streams alias, but this
1719 // is ok as we just want each list to be ordered.
1720 StreamInfo const *si = nullptr;
1721 int type = 0; // 0 if 608, 1 if 708
1722 bool isp = true; // if true use m_pmtTracks next, else stream_tracks
1723
1724 if (pofr && !sofr)
1725 isp = false; // NOLINT(bugprone-branch-clone)
1726 else if (!pofr && sofr)
1727 isp = true;
1728 else if (m_streamTracks[sidx] < m_pmtTracks[pidx])
1729 isp = false;
1730
1731 if (isp)
1732 {
1733 si = &m_pmtTracks[pidx];
1734 type = kTrackTypeCC708 == m_pmtTrackTypes[pidx] ? 1 : 0;
1735 pidx++;
1736 }
1737 else
1738 {
1739 si = &m_streamTracks[sidx];
1740 type = kTrackTypeCC708 == m_streamTrackTypes[sidx] ? 1 : 0;
1741 sidx++;
1742 }
1743
1744 StreamInfo nsi(*si);
1745 int lang_indx = lang_cc_cnt[type][nsi.m_language];
1746 lang_cc_cnt[type][nsi.m_language]++;
1747 nsi.m_language_index = lang_indx;
1748 m_tracks[(type) ? kTrackTypeCC708 : kTrackTypeCC608].push_back(nsi);
1749 int key = nsi.m_stream_id + ((type) ? 4 : -1);
1750 if (key < 0)
1751 {
1752 LOG(VB_GENERAL, LOG_ERR, LOC + "in_tracks key too small");
1753 }
1754 else
1755 {
1756 m_ccX08InTracks[key] = true;
1757 }
1758 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1759 QString("%1 caption service #%2 is in the %3 language.")
1760 .arg((type) ? "EIA-708" : "EIA-608")
1761 .arg(nsi.m_stream_id)
1762 .arg(iso639_key_toName(nsi.m_language)));
1763 }
1766}
1767
1769{
1770 QMutexLocker locker(&m_trackLock);
1771
1772 // ScanStreams() calls m_tracks[kTrackTypeTeletextCaptions].clear()
1774 return;
1775
1776 AVStream* st = m_ic->streams[av_index];
1777 const AVDictionaryEntry* language_dictionary_entry =
1778 av_dict_get(st->metadata, "language", nullptr, 0);
1779
1780 if (language_dictionary_entry == nullptr ||
1781 language_dictionary_entry->value == nullptr ||
1782 st->codecpar->extradata == nullptr
1783 )
1784 {
1785 return;
1786 }
1787
1788 std::vector<std::string_view> languages {StringUtil::split_sv(language_dictionary_entry->value, ","sv)};
1789
1790 if (st->codecpar->extradata_size != static_cast<int>(languages.size() * 2))
1791 {
1792 return;
1793 }
1794 for (size_t i = 0; i < languages.size(); i++)
1795 {
1796 if (languages[i].size() != 3)
1797 {
1798 continue;
1799 }
1800 //NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
1801 int language = iso639_str3_to_key(languages[i].data());
1802 uint8_t teletext_type = st->codecpar->extradata[i * 2] >> 3;
1803 uint8_t teletext_magazine_number = st->codecpar->extradata[i * 2] & 0x7;
1804 if (teletext_magazine_number == 0)
1805 teletext_magazine_number = 8;
1806 uint8_t teletext_page_number = st->codecpar->extradata[(i * 2) + 1];
1807 if (teletext_type == 2 || teletext_type == 1)
1808 {
1809 TrackType track = (teletext_type == 2) ?
1812 m_tracks[track].emplace_back(av_index, 0, language,
1813 (static_cast<unsigned>(teletext_magazine_number) << 8) | teletext_page_number);
1814 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1815 QString("Teletext stream #%1 (%2) is in the %3 language on page %4 %5.")
1816 .arg(QString::number(i),
1817 (teletext_type == 2) ? "Caption" : "Menu",
1818 iso639_key_toName(language),
1819 QString::number(teletext_magazine_number),
1820 QString::number(teletext_page_number)));
1821 }
1822 }
1823}
1824
1826{
1827 QMutexLocker locker(&m_trackLock);
1828
1829 AVDictionaryEntry *metatag =
1830 av_dict_get(m_ic->streams[av_stream_index]->metadata, "language", nullptr,
1831 0);
1832 bool forced = (m_ic->streams[av_stream_index]->disposition & AV_DISPOSITION_FORCED) != 0;
1833 int lang = metatag ? get_canonical_lang(metatag->value) :
1834 iso639_str3_to_key("und");
1835 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1836 QString("Text Subtitle track #%1 is A/V stream #%2 "
1837 "and is in the %3 language(%4), forced=%5.")
1838 .arg(m_tracks[kTrackTypeRawText].size()).arg(av_stream_index)
1839 .arg(iso639_key_toName(lang)).arg(lang).arg(forced));
1840 StreamInfo si {av_stream_index, 0, lang, 0, forced};
1841 m_tracks[kTrackTypeRawText].push_back(si);
1842}
1843
1848void AvFormatDecoder::ScanDSMCCStreams(AVBufferRef* pmt_section)
1849{
1850 if (m_itv == nullptr)
1852 if (m_itv == nullptr)
1853 return;
1854
1855 MythAVBufferRef pmt_buffer {pmt_section};
1856 if (!pmt_buffer.has_buffer())
1857 {
1858 return;
1859 }
1860 const ProgramMapTable pmt(PSIPTable(pmt_buffer.data()));
1861
1862 for (uint i = 0; i < pmt.StreamCount(); i++)
1863 {
1865 continue;
1866
1867 LOG(VB_DSMCC, LOG_NOTICE, QString("ScanDSMCCStreams Found Object Carousel in Stream %1").arg(QString::number(i)));
1868
1870 pmt.StreamInfo(i), pmt.StreamInfoLength(i),
1872
1873 for (const auto *desc : desc_list)
1874 {
1875 desc++; // Skip tag
1876 uint length = *desc++;
1877 const unsigned char *endDesc = desc+length;
1878 uint dataBroadcastId = desc[0]<<8 | desc[1];
1879 LOG(VB_DSMCC, LOG_NOTICE, QString("ScanDSMCCStreams dataBroadcastId %1").arg(QString::number(dataBroadcastId)));
1880 if (dataBroadcastId != 0x0106) // ETSI/UK Profile
1881 continue;
1882 desc += 2; // Skip data ID
1883 while (desc != endDesc)
1884 {
1885 [[maybe_unused]] uint appTypeCode = desc[0]<<8 | desc[1];
1886 desc += 3; // Skip app type code and boot priority hint
1887 uint appSpecDataLen = *desc++;
1888#if CONFIG_MHEG
1889 LOG(VB_DSMCC, LOG_NOTICE, QString("ScanDSMCCStreams AppTypeCode %1").arg(QString::number(appTypeCode)));
1890 if (appTypeCode == 0x101) // UK MHEG profile
1891 {
1892 const unsigned char *subDescEnd = desc + appSpecDataLen;
1893 while (desc < subDescEnd)
1894 {
1895 uint sub_desc_tag = *desc++;
1896 uint sub_desc_len = *desc++;
1897 // Network boot info sub-descriptor.
1898 if (sub_desc_tag == 1)
1899 m_itv->SetNetBootInfo(desc, sub_desc_len);
1900 desc += sub_desc_len;
1901 }
1902 }
1903 else
1904#endif // CONFIG_MHEG
1905 {
1906 desc += appSpecDataLen;
1907 }
1908 }
1909 }
1910 }
1911}
1912
1914{
1915 m_tracks[kTrackTypeVideo].clear();
1916 m_selectedTrack[kTrackTypeVideo].m_av_stream_index = -1;
1918 m_fps = 0;
1919
1920 const AVCodec *codec = nullptr;
1921 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Trying to select best video track");
1922
1923 /*
1924 * Find the "best" stream in the file.
1925 *
1926 * The best stream is determined according to various heuristics as
1927 * the most likely to be what the user expects. If the decoder parameter
1928 * is not nullptr, av_find_best_stream will find the default decoder
1929 * for the stream's codec; streams for which no decoder can be found
1930 * are ignored.
1931 *
1932 * If av_find_best_stream returns successfully and decoder_ret is not nullptr,
1933 * then *decoder_ret is guaranteed to be set to a valid AVCodec.
1934 */
1935 int stream_index = av_find_best_stream(m_ic, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);
1936
1937 if (stream_index < 0)
1938 {
1939 LOG(VB_PLAYBACK, LOG_INFO, LOC + "No video track found/selected.");
1940 return stream_index;
1941 }
1942
1943 AVStream *stream = m_ic->streams[stream_index];
1946 AVCodecContext *codecContext = m_codecMap.GetCodecContext(stream, codec);
1947 StreamInfo si {stream_index, 0};
1948
1949 m_tracks[kTrackTypeVideo].push_back(si);
1952
1953 QString codectype(AVMediaTypeToString(codecContext->codec_type));
1954 if (codecContext->codec_type == AVMEDIA_TYPE_VIDEO)
1955 codectype += QString("(%1x%2)").arg(codecContext->width).arg(codecContext->height);
1956 LOG(VB_PLAYBACK, LOG_INFO, LOC +
1957 QString("Selected track #%1: ID: 0x%2 Codec ID: %3 Profile: %4 Type: %5 Bitrate: %6")
1958 .arg(stream_index).arg(static_cast<uint64_t>(stream->id), 0, 16)
1959 .arg(avcodec_get_name(codecContext->codec_id),
1960 avcodec_profile_name(codecContext->codec_id, codecContext->profile),
1961 codectype,
1962 QString::number(codecContext->bit_rate)));
1963
1964 // If ScanStreams has been called on a stream change triggered by a
1965 // decoder error - because the decoder does not handle resolution
1966 // changes gracefully (NVDEC and maybe MediaCodec) - then the stream/codec
1967 // will still contain the old resolution but the AVCodecContext will
1968 // have been updated. This causes mayhem for a second or two.
1969 if ((codecContext->width != stream->codecpar->width) || (codecContext->height != stream->codecpar->height))
1970 {
1971 LOG(VB_GENERAL, LOG_INFO, LOC + QString(
1972 "Video resolution mismatch: Context: %1x%2 Stream: %3x%4 Codec: %5 Stream change: %6")
1973 .arg(codecContext->width).arg(codecContext->height)
1974 .arg(stream->codecpar->width).arg(stream->codecpar->height)
1976 }
1977
1978 m_avcParser->Reset();
1979
1980 QSize dim = get_video_dim(*codecContext);
1981 int width = std::max(dim.width(), 16);
1982 int height = std::max(dim.height(), 16);
1983 QString dec = "ffmpeg";
1984 uint thread_count = 1;
1985 QString codecName;
1986 if (codecContext->codec)
1987 codecName = codecContext->codec->name;
1988 // framerate appears to never be set - which is probably why
1989 // GetVideoFrameRate never uses it:)
1990 // So fallback to the GetVideoFrameRate call which should then ensure
1991 // the video display profile gets an accurate frame rate - instead of 0
1992 if (codecContext->framerate.den && codecContext->framerate.num)
1993 m_fps = float(codecContext->framerate.num) / float(codecContext->framerate.den);
1994 else
1995 m_fps = GetVideoFrameRate(stream, codecContext, true);
1996
1997 bool foundgpudecoder = false;
1998 QStringList unavailabledecoders;
1999 bool allowgpu = FlagIsSet(kDecodeAllowGPU);
2000
2002 {
2003 // TODO this could be improved by appending the decoder that has
2004 // failed to the unavailable list - but that could lead to circular
2005 // failures if there are 2 or more hardware decoders that fail
2006 if (FlagIsSet(kDecodeAllowGPU) && (dec != "ffmpeg"))
2007 {
2008 LOG(VB_GENERAL, LOG_WARNING, LOC + QString(
2009 "GPU/hardware decoder '%1' failed - forcing software decode")
2010 .arg(dec));
2011 }
2012 m_averrorCount = 0;
2013 allowgpu = false;
2014 }
2015
2016 while (unavailabledecoders.size() < 10)
2017 {
2018 if (!m_isDbIgnored)
2019 {
2020 if (!unavailabledecoders.isEmpty())
2021 {
2022 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Unavailable decoders: %1")
2023 .arg(unavailabledecoders.join(",")));
2024 }
2025 m_videoDisplayProfile.SetInput(QSize(width, height), m_fps, codecName, unavailabledecoders);
2027 thread_count = m_videoDisplayProfile.GetMaxCPUs();
2028 bool skip_loop_filter = m_videoDisplayProfile.IsSkipLoopEnabled();
2029 if (!skip_loop_filter)
2030 codecContext->skip_loop_filter = AVDISCARD_NONKEY;
2031 }
2032
2034 uint version = mpeg_version(codecContext->codec_id);
2035 if (version)
2036 m_videoCodecId = static_cast<MythCodecID>(kCodec_MPEG1 + version - 1);
2037
2038 if (version && allowgpu && dec != "ffmpeg")
2039 {
2040 // We need to set this so that MythyCodecContext can callback
2041 // to the player in use to check interop support.
2042 codecContext->opaque = static_cast<void*>(this);
2043 MythCodecID hwcodec = MythCodecContext::FindDecoder(dec, stream, &codecContext, &codec);
2044 if (hwcodec != kCodec_NONE)
2045 {
2046 // the context may have changed
2047 codecContext->opaque = static_cast<void*>(this);
2048 m_videoCodecId = hwcodec;
2049 foundgpudecoder = true;
2050 }
2051 else
2052 {
2053 // hardware decoder is not available - try the next best profile
2054 unavailabledecoders.append(dec);
2055 continue;
2056 }
2057 }
2058
2059 // default to mpeg2
2061 {
2062 LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown video codec - defaulting to MPEG2");
2064 }
2065
2066 break;
2067 }
2068
2070 thread_count = 1;
2071
2072 // Only use a single thread for hardware decoding. There is no
2073 // performance improvement with multithreaded hardware decode
2074 // and asynchronous callbacks create issues with decoders that
2075 // use AVHWFrameContext where we need to release video resources
2076 // before they are recreated
2077 if (!foundgpudecoder)
2078 {
2079 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Using %1 CPUs for decoding")
2080 .arg(thread_count));
2081 codecContext->thread_count = static_cast<int>(thread_count);
2082 }
2083
2084 InitVideoCodec(stream, codecContext, true);
2085
2086 ScanATSCCaptionStreams(stream_index);
2088
2089 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Using %1 for video decoding").arg(GetCodecDecoderName()));
2090 m_mythCodecCtx->SetDecoderOptions(codecContext, codec);
2091 if (!OpenAVCodec(codecContext, codec))
2092 {
2093 scanerror = -1;
2094 }
2095 return stream_index;
2096}
2097
2099{
2100 AVProgram* program = av_find_program_from_stream(m_ic, nullptr, stream_index);
2101 if (program == nullptr)
2102 {
2103 return;
2104 }
2105
2106 LOG(VB_PLAYBACK, LOG_INFO,
2107 QString("Removing streams not in Program %1 from track selection.")
2108 .arg(QString::number(program->id)));
2109
2110 const auto * const begin = program->stream_index;
2111 const auto * const end = program->stream_index + program->nb_stream_indexes;
2112
2113 for (auto & track_list : m_tracks)
2114 {
2115 LOG(VB_PLAYBACK, LOG_DEBUG,
2116 QString("Size before: %1").arg(QString::number(track_list.size())));
2117 track_list.erase(std::remove_if(track_list.begin(), track_list.end(),
2118 [&](const StreamInfo& i)
2119 {
2120 return std::find(begin, end, i.m_av_stream_index) == end;
2121 }), track_list.end());
2122 LOG(VB_PLAYBACK, LOG_DEBUG,
2123 QString("Size after: %1").arg(QString::number(track_list.size())));
2124 }
2125}
2126
2127static bool is_dual_mono(const AVChannelLayout& ch_layout)
2128{
2129 return (ch_layout.order == AV_CHANNEL_ORDER_CUSTOM) &&
2130 (ch_layout.nb_channels == 2) &&
2131 (ch_layout.u.map[0].id == AV_CHAN_FRONT_CENTER) &&
2132 (ch_layout.u.map[1].id == AV_CHAN_FRONT_CENTER);
2133}
2134
2136{
2137 QMutexLocker avlocker(&m_avCodecLock);
2138 QMutexLocker locker(&m_trackLock);
2139
2140 bool unknownbitrate = false;
2141 int scanerror = 0;
2142 m_bitrate = 0;
2143
2144 constexpr std::array<TrackType, 6> types {
2151 };
2152 for (const auto type : types)
2153 {
2154 m_tracks[type].clear();
2155 m_currentTrack[type] = -1;
2156 }
2157
2158 std::map<int,uint> lang_sub_cnt;
2159 uint subtitleStreamCount = 0;
2160 std::map<int,uint> lang_aud_cnt;
2161 uint audioStreamCount = 0;
2162
2163 if (m_ringBuffer && m_ringBuffer->IsDVD() &&
2165 {
2168 }
2169
2170 if (m_ic == nullptr)
2171 return -1;
2172
2173 for (uint strm = 0; strm < m_ic->nb_streams; strm++)
2174 {
2175 AVCodecParameters *par = m_ic->streams[strm]->codecpar;
2176
2177 QString codectype(AVMediaTypeToString(par->codec_type));
2178 if (par->codec_type == AVMEDIA_TYPE_VIDEO)
2179 codectype += QString("(%1x%2)").arg(par->width).arg(par->height);
2180 QString program_id = "null";
2181 if (av_find_program_from_stream(m_ic, nullptr, strm) != nullptr)
2182 {
2183 program_id = QString::number(av_find_program_from_stream(m_ic, nullptr, strm)->id);
2184 }
2185 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2186 QString("Stream #%1: ID: 0x%2 Program ID: %3 Codec ID: %4 Type: %5 Bitrate: %6").arg(
2187 QString::number(strm),
2188 QString::number(static_cast<uint64_t>(m_ic->streams[strm]->id), 16),
2189 program_id,
2190 avcodec_get_name(par->codec_id),
2191 codectype,
2192 QString::number(par->bit_rate))
2193 );
2194
2195 switch (par->codec_type)
2196 {
2197 case AVMEDIA_TYPE_VIDEO:
2198 {
2199 // reset any potentially errored hardware decoders
2201 {
2202 if (m_codecMap.FindCodecContext(m_ic->streams[strm]))
2203 {
2204 AVCodecContext* ctx = m_codecMap.GetCodecContext(m_ic->streams[strm]);
2205 if (ctx && (ctx->hw_frames_ctx || ctx->hw_device_ctx))
2206 m_codecMap.FreeCodecContext(m_ic->streams[strm]);
2207 }
2208 }
2209
2210 if (!par->codec_id)
2211 {
2212 LOG(VB_GENERAL, LOG_ERR, LOC +
2213 QString("Stream #%1 has an unknown video "
2214 "codec id, skipping.").arg(strm));
2215 continue;
2216 }
2217
2218 // ffmpeg does not return a bitrate for several codecs and
2219 // formats. Typically the same streams do not have a duration either
2220 // - so we cannot estimate a bitrate (which would be subject
2221 // to significant error anyway if there were multiple video streams).
2222 // So we need to guesstimate a value that avoids low bitrate optimisations
2223 // (which typically kick in around 500,000) and provides a read
2224 // chunk size large enough to avoid starving the decoder of data.
2225 // Trying to read a 20Mbs stream with a 16KB chunk size does not work:)
2226 if (par->bit_rate == 0)
2227 {
2228 static constexpr int64_t s_baseBitrate { 1000000LL };
2229 int multiplier = 1;
2230 if (par->width && par->height)
2231 {
2232 static const int s_baseSize = 1920 * 1080;
2233 multiplier = ((par->width * par->height) + s_baseSize - 1) / s_baseSize;
2234 multiplier = std::max(multiplier, 1);
2235 }
2236 par->bit_rate = s_baseBitrate * multiplier;
2237 unknownbitrate = true;
2238 }
2239 m_bitrate += par->bit_rate;
2240
2241 break;
2242 }
2243 case AVMEDIA_TYPE_AUDIO:
2244 {
2245 LOG(VB_GENERAL, LOG_INFO, LOC +
2246 QString("codec %1 has %2 channels")
2247 .arg(avcodec_get_name(par->codec_id))
2248 .arg(par->ch_layout.nb_channels));
2249
2250 m_bitrate += par->bit_rate;
2251 break;
2252 }
2253 case AVMEDIA_TYPE_SUBTITLE:
2254 {
2255 if (par->codec_id == AV_CODEC_ID_DVB_TELETEXT)
2256 ScanTeletextCaptions(static_cast<int>(strm));
2257 if (par->codec_id == AV_CODEC_ID_TEXT)
2258 ScanRawTextCaptions(static_cast<int>(strm));
2259 m_bitrate += par->bit_rate;
2260
2261 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("subtitle codec (%1)")
2262 .arg(AVMediaTypeToString(par->codec_type)));
2263 break;
2264 }
2265 case AVMEDIA_TYPE_DATA:
2266 {
2267 if (par->codec_id == AV_CODEC_ID_DVB_VBI)
2268 ScanTeletextCaptions(static_cast<int>(strm));
2269 m_bitrate += par->bit_rate;
2270 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("data codec (%1)")
2271 .arg(AVMediaTypeToString(par->codec_type)));
2272 break;
2273 }
2274 case AVMEDIA_TYPE_ATTACHMENT:
2275 {
2276 if (par->codec_id == AV_CODEC_ID_TTF)
2277 m_tracks[kTrackTypeAttachment].emplace_back(static_cast<int>(strm), m_ic->streams[strm]->id);
2278 m_bitrate += par->bit_rate;
2279 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2280 QString("Attachment codec (%1)")
2281 .arg(AVMediaTypeToString(par->codec_type)));
2282 break;
2283 }
2284 default:
2285 {
2286 m_bitrate += par->bit_rate;
2287 LOG(VB_PLAYBACK, LOG_ERR, LOC +
2288 QString("Unknown codec type (%1)")
2289 .arg(AVMediaTypeToString(par->codec_type)));
2290 break;
2291 }
2292 }
2293
2294 if (par->codec_type != AVMEDIA_TYPE_AUDIO &&
2295 par->codec_type != AVMEDIA_TYPE_SUBTITLE)
2296 continue;
2297
2298 // skip DVB teletext and text subs, there is no libavcodec decoder
2299 if (par->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2300 (par->codec_id == AV_CODEC_ID_DVB_TELETEXT ||
2301 par->codec_id == AV_CODEC_ID_TEXT))
2302 continue;
2303
2304 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Looking for decoder for %1")
2305 .arg(avcodec_get_name(par->codec_id)));
2306
2307 if (par->codec_id == AV_CODEC_ID_PROBE)
2308 {
2309 LOG(VB_GENERAL, LOG_ERR, LOC +
2310 QString("Probing of stream #%1 unsuccesful, ignoring.").arg(strm));
2311 continue;
2312 }
2313
2314 AVCodecContext* codecContext = m_codecMap.GetCodecContext(m_ic->streams[strm]);
2315
2316 if (codecContext == nullptr)
2317 {
2318 LOG(VB_GENERAL, LOG_WARNING, LOC +
2319 QString("Could not find decoder for codec (%1), ignoring.")
2320 .arg(avcodec_get_name(par->codec_id)));
2321 LOG(VB_LIBAV, LOG_INFO, "For a list of all codecs, run `mythffmpeg -codecs`.");
2322 continue;
2323 }
2324
2325 if (codecContext->codec && par->codec_id != codecContext->codec_id)
2326 {
2327 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2328 QString("Already opened codec not matching (%1 vs %2). Reopening")
2329 .arg(avcodec_get_name(codecContext->codec_id),
2330 avcodec_get_name(codecContext->codec->id)));
2331 m_codecMap.FreeCodecContext(m_ic->streams[strm]);
2332 codecContext = m_codecMap.GetCodecContext(m_ic->streams[strm]);
2333 }
2334 if (!OpenAVCodec(codecContext, codecContext->codec))
2335 continue;
2336 if (!codecContext)
2337 continue;
2338
2339 if (!IsValidStream(m_ic->streams[strm]->id))
2340 {
2341 /* Hide this stream if it's not valid in this context.
2342 * This can happen, for example, on a Blu-ray disc if there
2343 * are more physical streams than there is metadata about them.
2344 * (e.g. Despicable Me)
2345 */
2346 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2347 QString("Stream 0x%1 is not valid in this context - skipping")
2348 .arg(m_ic->streams[strm]->id, 4, 16));
2349 continue;
2350 }
2351
2352 if (par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2353 {
2354 bool forced = (m_ic->streams[strm]->disposition & AV_DISPOSITION_FORCED) != 0;
2355 int lang = GetSubtitleLanguage(subtitleStreamCount, strm);
2356 uint lang_indx = lang_sub_cnt[lang]++;
2357 subtitleStreamCount++;
2358
2359 m_tracks[kTrackTypeSubtitle].emplace_back(
2360 static_cast<int>(strm), m_ic->streams[strm]->id, lang, lang_indx, forced);
2361
2362 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2363 QString("Subtitle track #%1 is A/V stream #%2 "
2364 "and is in the %3 language(%4).")
2365 .arg(m_tracks[kTrackTypeSubtitle].size()).arg(strm)
2366 .arg(iso639_key_toName(lang)).arg(lang));
2367 }
2368
2369 if (par->codec_type == AVMEDIA_TYPE_AUDIO)
2370 {
2371 int lang = GetAudioLanguage(audioStreamCount, strm);
2373 uint lang_indx = lang_aud_cnt[lang]++;
2374 audioStreamCount++;
2375
2376 int stream_id = m_ic->streams[strm]->id;
2378 {
2379 stream_id = m_ringBuffer->DVD()->GetAudioTrackNum(stream_id);
2380 if (stream_id == -1)
2381 {
2382 // This stream isn't mapped, so skip it
2383 continue;
2384 }
2385 }
2386
2387 m_tracks[kTrackTypeAudio].emplace_back(
2388 static_cast<int>(strm), stream_id, lang, lang_indx, type);
2389
2390 if (is_dual_mono(codecContext->ch_layout))
2391 {
2392 lang_indx = lang_aud_cnt[lang]++;
2393 m_tracks[kTrackTypeAudio].emplace_back(
2394 static_cast<int>(strm), stream_id, lang, lang_indx, type);
2395 }
2396
2397 LOG(VB_AUDIO, LOG_INFO, LOC +
2398 QString("Audio Track #%1, of type (%2) is A/V stream #%3 (id=0x%4) "
2399 "and has %5 channels in the %6 language(%7).")
2400 .arg(m_tracks[kTrackTypeAudio].size()).arg(toString(type))
2401 .arg(strm).arg(m_ic->streams[strm]->id,0,16).arg(codecContext->ch_layout.nb_channels)
2402 .arg(iso639_key_toName(lang)).arg(lang));
2403 }
2404 }
2405
2406 // Now find best video track to play
2408 if (!novideo)
2409 {
2410 int stream_index = autoSelectVideoTrack(scanerror);
2412 }
2413
2414 m_bitrate = std::max(static_cast<uint>(m_ic->bit_rate), m_bitrate);
2415
2416 if (m_bitrate > 0)
2417 {
2418 m_bitrate = (m_bitrate + 999) / 1000;
2419 if (m_ringBuffer)
2421 }
2422
2423 // update RingBuffer buffer size
2424 if (m_ringBuffer)
2425 {
2426 m_ringBuffer->SetBufferSizeFactors(unknownbitrate,
2427 QString(m_ic->iformat->name).contains("matroska"));
2428 }
2429
2431
2432 for (const auto type : types)
2433 {
2435 }
2436
2437 // We have to do this here to avoid the NVP getting stuck
2438 // waiting on audio.
2439 if (m_audio->HasAudioIn() && m_tracks[kTrackTypeAudio].empty())
2440 {
2441 m_audio->SetAudioParams(FORMAT_NONE, -1, -1, AV_CODEC_ID_NONE, -1, false);
2444 m_audioIn = AudioInfo();
2445 }
2446
2447 // if we don't have a video stream we still need to make sure some
2448 // video params are set properly
2449 if (m_selectedTrack[kTrackTypeVideo].m_av_stream_index == -1)
2450 {
2451 m_fps = 23.97F; // minimum likey display refresh rate
2452 // N.B. we know longer need a 'dummy' frame to render overlays into
2453 m_parent->SetVideoParams(0, 0, 23.97, 1.0F, false, 0);
2454 }
2455
2456 if (m_parent->IsErrored())
2457 scanerror = -1;
2458
2459 if (!novideo && m_selectedTrack[kTrackTypeVideo].m_av_stream_index != -1)
2460 {
2463 }
2464 else
2465 {
2466 /* We don't yet know which AVProgram we want, so iterate through them
2467 all. This should be no more incorrect than using the last PMT when
2468 there are multiple programs. */
2469 for (unsigned i = 0; i < m_ic->nb_programs; i++)
2470 {
2471 ScanDSMCCStreams(m_ic->programs[i]->pmt_section);
2472 }
2473 }
2474
2475 return scanerror;
2476}
2477
2478bool AvFormatDecoder::OpenAVCodec(AVCodecContext *avctx, const AVCodec *codec)
2479{
2480 m_avCodecLock.lock();
2481#if CONFIG_MEDIACODEC
2482 if (QString("mediacodec") == codec->wrapper_name)
2483 av_jni_set_java_vm(QAndroidJniEnvironment::javaVM(), nullptr);
2484#endif
2485 int ret = avcodec_open2(avctx, codec, nullptr);
2486 m_avCodecLock.unlock();
2487 if (ret < 0)
2488 {
2489 std::string error;
2490 LOG(VB_GENERAL, LOG_ERR, LOC +
2491 QString("Could not open codec 0x%1, id(%2) type(%3) "
2492 "ignoring. reason %4").arg((uint64_t)avctx,0,16)
2493 .arg(avcodec_get_name(avctx->codec_id),
2494 AVMediaTypeToString(avctx->codec_type),
2496 return false;
2497 }
2498
2499 LOG(VB_GENERAL, LOG_INFO, LOC +
2500 QString("Opened codec 0x%1, id(%2) type(%3)")
2501 .arg((uint64_t)avctx,0,16)
2502 .arg(avcodec_get_name(avctx->codec_id),
2503 AVMediaTypeToString(avctx->codec_type)));
2504 return true;
2505}
2506
2508{
2510}
2511
2512bool AvFormatDecoder::DoRewindSeek(long long desiredFrame)
2513{
2514 return DecoderBase::DoRewindSeek(desiredFrame);
2515}
2516
2517void AvFormatDecoder::DoFastForwardSeek(long long desiredFrame, bool &needflush)
2518{
2519 DecoderBase::DoFastForwardSeek(desiredFrame, needflush);
2520}
2521
2524{
2525 QMutexLocker locker(&m_trackLock);
2526 for (const auto & si : m_tracks[kTrackTypeTeletextCaptions])
2527 if (si.m_language_index == Index)
2528 return si.m_language;
2529 return iso639_str3_to_key("und");
2530}
2531
2534{
2535 AVDictionaryEntry *metatag = av_dict_get(m_ic->streams[StreamIndex]->metadata, "language", nullptr, 0);
2536 return metatag ? get_canonical_lang(metatag->value) : iso639_str3_to_key("und");
2537}
2538
2541{
2542 // This doesn't strictly need write lock but it is called internally while
2543 // write lock is held. All other (external) uses are safe
2544 QMutexLocker locker(&m_trackLock);
2545
2546 int ret = -1;
2547 for (int i = 0; i < m_pmtTrackTypes.size(); i++)
2548 {
2549 if ((m_pmtTrackTypes[i] == TrackType) && (m_pmtTracks[i].m_stream_id == ServiceNum))
2550 {
2551 ret = m_pmtTracks[i].m_language;
2552 if (!iso639_is_key_undefined(ret))
2553 return ret;
2554 }
2555 }
2556
2557 for (int i = 0; i < m_streamTrackTypes.size(); i++)
2558 {
2559 if ((m_streamTrackTypes[i] == TrackType) && (m_streamTracks[i].m_stream_id == ServiceNum))
2560 {
2561 ret = m_streamTracks[i].m_language;
2562 if (!iso639_is_key_undefined(ret))
2563 return ret;
2564 }
2565 }
2566
2567 return ret;
2568}
2569
2570int AvFormatDecoder::GetAudioLanguage(uint AudioIndex, uint StreamIndex)
2571{
2572 return GetSubtitleLanguage(AudioIndex, StreamIndex);
2573}
2574
2576{
2578 AVStream *stream = m_ic->streams[StreamIndex];
2579
2580 {
2581 // We only support labelling/filtering of these two types for now
2582 if (stream->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
2584 else if (stream->disposition & AV_DISPOSITION_COMMENT)
2586 else if (stream->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
2588 else if (stream->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
2590 }
2591
2592 return type;
2593}
2594
2608{
2609 QMutexLocker locker(&m_trackLock);
2610
2611 // Find the position of the streaminfo in m_tracks[kTrackTypeAudio]
2612 auto current = m_tracks[kTrackTypeAudio].begin();
2613 for (; current != m_tracks[kTrackTypeAudio].end(); ++current)
2614 {
2615 if (current->m_av_stream_index == streamIndex)
2616 break;
2617 }
2618
2619 if (current == m_tracks[kTrackTypeAudio].end())
2620 {
2621 LOG(VB_GENERAL, LOG_WARNING, LOC +
2622 QString("Invalid stream index passed to "
2623 "SetupAudioStreamSubIndexes: %1").arg(streamIndex));
2624
2625 return;
2626 }
2627
2628 // Remove the extra substream or duplicate the current substream
2629 auto next = current + 1;
2630 if (current->m_av_substream_index == -1)
2631 {
2632 // Split stream in two (Language I + Language II)
2633 StreamInfo lang1 = *current;
2634 StreamInfo lang2 = *current;
2635 lang1.m_av_substream_index = 0;
2636 lang2.m_av_substream_index = 1;
2637 *current = lang1;
2638 m_tracks[kTrackTypeAudio].insert(next, lang2);
2639 return;
2640 }
2641
2642 if ((next == m_tracks[kTrackTypeAudio].end()) ||
2643 (next->m_av_stream_index != streamIndex))
2644 {
2645 QString msg = QString(
2646 "Expected substream 1 (Language I) of stream %1\n\t\t\t"
2647 "following substream 0, found end of list or another stream.")
2648 .arg(streamIndex);
2649
2650 LOG(VB_GENERAL, LOG_WARNING, LOC + msg);
2651
2652 return;
2653 }
2654
2655 // Remove extra stream info
2656 StreamInfo stream = *current;
2657 stream.m_av_substream_index = -1;
2658 *current = stream;
2659 m_tracks[kTrackTypeAudio].erase(next);
2660}
2661
2667{
2668 if (!m_audio->HasAudioIn())
2669 return;
2670
2671 m_avCodecLock.lock();
2672 bool do_flush = false;
2673 for (uint i = 0; i < m_ic->nb_streams; i++)
2674 {
2675 AVStream *st = m_ic->streams[i];
2676 st->index = i;
2677 AVCodecContext *avctx = m_codecMap.FindCodecContext(st);
2678 if (avctx && avctx->codec_type == AVMEDIA_TYPE_AUDIO)
2679 {
2681 LOG(VB_LIBAV, LOG_DEBUG, QString("removing audio stream (id: 0x%1, index: %2, nb_streams: %3)")
2682 .arg(QString::number(st->id, 16),
2683 QString::number(i),
2684 QString::number(m_ic->nb_streams)
2685 )
2686 );
2687 m_ic->nb_streams--;
2688 if ((m_ic->nb_streams - i) > 0) {
2689 std::memmove(reinterpret_cast<void*>(&m_ic->streams[i]),
2690 reinterpret_cast<const void*>(&m_ic->streams[i + 1]),
2691 (m_ic->nb_streams - i) * sizeof(AVFormatContext*));
2692 }
2693 else
2694 {
2695 m_ic->streams[i] = nullptr;
2696 }
2697 do_flush = true;
2698 i--;
2699 }
2700 }
2701 if (do_flush)
2702 {
2703 avformat_flush(m_ic);
2704 }
2705 m_avCodecLock.unlock();
2706}
2707
2708int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
2709{
2710 auto *decoder = static_cast<AvFormatDecoder*>(c->opaque);
2712 if (!std::any_of(decoder->m_renderFormats->cbegin(), decoder->m_renderFormats->cend(),
2713 [&type](auto Format) { return type == Format; }))
2714 {
2715 decoder->m_directRendering = false;
2716 return avcodec_default_get_buffer2(c, pic, flags);
2717 }
2718
2719 decoder->m_directRendering = true;
2720 MythVideoFrame *frame = decoder->GetPlayer()->GetNextVideoFrame();
2721 if (!frame)
2722 return -1;
2723
2724 // We pre-allocate frames to certain alignments. If the coded size differs from
2725 // those alignments then re-allocate the frame. Changes in frame type (e.g.
2726 // YV12 to NV12) are always reallocated.
2727 int width = (frame->m_width + MYTH_WIDTH_ALIGNMENT - 1) & ~(MYTH_WIDTH_ALIGNMENT - 1);
2728 int height = (frame->m_height + MYTH_HEIGHT_ALIGNMENT - 1) & ~(MYTH_HEIGHT_ALIGNMENT - 1);
2729
2730 if ((frame->m_type != type) || (pic->width > width) || (pic->height > height))
2731 {
2732 if (!VideoBuffers::ReinitBuffer(frame, type, decoder->m_videoCodecId, pic->width, pic->height))
2733 return -1;
2734 // NB the video frame may now have a new size which is currenly not an issue
2735 // as the underlying size has already been passed through to the player.
2736 // But may cause issues down the line. We should add coded_width/height to
2737 // VideoFrame as well to ensure consistentency through the rendering
2738 // pipeline.
2739 // NB remember to compare coded width/height - not 'true' values - otherwsie
2740 // we continually re-allocate the frame.
2741 //frame->width = c->width;
2742 //frame->height = c->height;
2743 }
2744
2745 frame->m_colorshifted = false;
2747 for (uint i = 0; i < 3; i++)
2748 {
2749 pic->data[i] = (i < max) ? (frame->m_buffer + frame->m_offsets[i]) : nullptr;
2750 pic->linesize[i] = frame->m_pitches[i];
2751 }
2752
2753 pic->opaque = frame;
2754
2755 // Set release method
2756 AVBufferRef *buffer = av_buffer_create(reinterpret_cast<uint8_t*>(frame), 0,
2757 [](void* Opaque, uint8_t* Data)
2758 {
2759 auto *avfd = static_cast<AvFormatDecoder*>(Opaque);
2760 auto *vf = reinterpret_cast<MythVideoFrame*>(Data);
2761 if (avfd && avfd->GetPlayer())
2762 avfd->GetPlayer()->DeLimboFrame(vf);
2763 }
2764 , decoder, 0);
2765 pic->buf[0] = buffer;
2766
2767 return 0;
2768}
2769
2770#if CONFIG_DXVA2
2771int get_avf_buffer_dxva2(struct AVCodecContext *c, AVFrame *pic, int /*flags*/)
2772{
2773 AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque);
2774 MythVideoFrame *frame = nd->GetPlayer()->GetNextVideoFrame();
2775
2776 for (int i = 0; i < 4; i++)
2777 {
2778 pic->data[i] = nullptr;
2779 pic->linesize[i] = 0;
2780 }
2781 pic->opaque = frame;
2782 frame->m_pixFmt = c->pix_fmt;
2783 pic->data[0] = (uint8_t*)frame->m_buffer;
2784 pic->data[3] = (uint8_t*)frame->m_buffer;
2785
2786 // Set release method
2787 AVBufferRef *buffer =
2788 av_buffer_create((uint8_t*)frame, 0,
2789 [](void* Opaque, uint8_t* Data)
2790 {
2791 AvFormatDecoder *avfd = static_cast<AvFormatDecoder*>(Opaque);
2792 MythVideoFrame *vf = reinterpret_cast<MythVideoFrame*>(Data);
2793 if (avfd && avfd->GetPlayer())
2794 avfd->GetPlayer()->DeLimboFrame(vf);
2795 }
2796 , nd, 0);
2797 pic->buf[0] = buffer;
2798
2799 return 0;
2800}
2801#endif
2802
2803void AvFormatDecoder::DecodeCCx08(const uint8_t *buf, uint buf_size)
2804{
2805 if (buf_size < 3)
2806 return;
2807
2808 bool had_608 = false;
2809 bool had_708 = false;
2810 for (uint cur = 0; cur + 2 < buf_size; cur += 3)
2811 {
2812 uint cc_code = buf[cur];
2813 bool cc_valid = (cc_code & 0x04) != 0U;
2814
2815 uint data1 = buf[cur+1];
2816 uint data2 = buf[cur+2];
2817 uint data = (data2 << 8) | data1;
2818 uint cc_type = cc_code & 0x03;
2819
2820 if (!cc_valid)
2821 {
2822 continue;
2823 }
2824
2825 if (cc_type <= 0x1) // EIA-608 field-1/2
2826 {
2827 if (cc608_good_parity(data))
2828 {
2829 had_608 = true;
2830 m_ccd608->FormatCCField(duration_cast<std::chrono::milliseconds>(m_lastCcPtsu), cc_type, data);
2831 }
2832 }
2833 else
2834 {
2835 had_708 = true;
2836 m_ccd708->decode_cc_data(cc_type, data1, data2);
2837 }
2838 }
2839 UpdateCaptionTracksFromStreams(had_608, had_708);
2840}
2841
2843 bool check_608, bool check_708)
2844{
2845 bool need_change_608 = false;
2846 CC608Seen seen_608;
2847 if (check_608)
2848 {
2849 m_ccd608->GetServices(15s, seen_608);
2850 for (uint i = 0; i < 4; i++)
2851 {
2852 need_change_608 |= (seen_608[i] && !m_ccX08InTracks[i]) ||
2853 (!seen_608[i] && m_ccX08InTracks[i] && !m_ccX08InPmt[i]);
2854 }
2855 }
2856
2857 bool need_change_708 = false;
2858 cc708_seen_flags seen_708;
2859 if (check_708 || need_change_608)
2860 {
2861 m_ccd708->services(15s, seen_708);
2862 for (uint i = 1; i < 64 && !need_change_608 && !need_change_708; i++)
2863 {
2864 need_change_708 |= (seen_708[i] && !m_ccX08InTracks[i+4]) ||
2865 (!seen_708[i] && m_ccX08InTracks[i+4] && !m_ccX08InPmt[i+4]);
2866 }
2867 if (need_change_708 && !check_608)
2868 m_ccd608->GetServices(15s, seen_608);
2869 }
2870
2871 if (!need_change_608 && !need_change_708)
2872 return;
2873
2874 m_trackLock.lock();
2875
2877
2878 m_streamTracks.clear();
2879 m_streamTrackTypes.clear();
2880 int av_index = m_selectedTrack[kTrackTypeVideo].m_av_stream_index;
2881 int lang = iso639_str3_to_key("und");
2882 for (int i = 1; i < 64; i++)
2883 {
2884 if (seen_708[i] && !m_ccX08InPmt[i+4])
2885 {
2886 StreamInfo si {av_index, i, lang};
2887 m_streamTracks.push_back(si);
2889 }
2890 }
2891 for (int i = 0; i < 4; i++)
2892 {
2893 if (seen_608[i] && !m_ccX08InPmt[i])
2894 {
2895 if (0==i)
2897 else if (2==i)
2899 else
2900 lang = iso639_str3_to_key("und");
2901
2902 StreamInfo si {av_index, i+1, lang};
2903 m_streamTracks.push_back(si);
2905 }
2906 }
2907 m_trackLock.unlock();
2909}
2910
2912 AVPacket *pkt, bool can_reliably_parse_keyframes)
2913{
2914 if (m_prevGopPos != 0 && m_keyframeDist != 1)
2915 {
2916 int tempKeyFrameDist = m_framesRead - 1 - m_prevGopPos;
2917 bool reset_kfd = false;
2918
2919 if (!m_gopSet || m_livetv) // gopset: we've seen 2 keyframes
2920 {
2921 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2922 "gopset not set, syncing positionMap");
2924 if (tempKeyFrameDist > 0 && !m_livetv)
2925 {
2926 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2927 QString("Initial key frame distance: %1.")
2928 .arg(m_keyframeDist));
2929 m_gopSet = true;
2930 reset_kfd = true;
2931 }
2932 }
2933 else if (m_keyframeDist != tempKeyFrameDist && tempKeyFrameDist > 0)
2934 {
2935 LOG(VB_PLAYBACK, LOG_INFO, LOC +
2936 QString("Key frame distance changed from %1 to %2.")
2937 .arg(m_keyframeDist).arg(tempKeyFrameDist));
2938 reset_kfd = true;
2939 }
2940
2941 if (reset_kfd)
2942 {
2943 m_keyframeDist = tempKeyFrameDist;
2945
2947
2948#if 0
2949 // also reset length
2950 QMutexLocker locker(&m_positionMapLock);
2951 if (!m_positionMap.empty())
2952 {
2953 long long index = m_positionMap.back().index;
2954 long long totframes = index * m_keyframeDist;
2955 uint length = (uint)((totframes * 1.0F) / m_fps);
2956 m_parent->SetFileLength(length, totframes);
2957 }
2958#endif
2959 }
2960 }
2961
2963
2964 if (can_reliably_parse_keyframes &&
2966 {
2967 long long last_frame = 0;
2968 {
2969 QMutexLocker locker(&m_positionMapLock);
2970 if (!m_positionMap.empty())
2971 last_frame = m_positionMap.back().index;
2972 }
2973
2974#if 0
2975 LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
2976 QString("framesRead: %1 last_frame: %2 keyframedist: %3")
2977 .arg(m_framesRead) .arg(last_frame) .arg(m_keyframeDist));
2978#endif
2979
2980 // if we don't have an entry, fill it in with what we've just parsed
2981 if (m_framesRead > last_frame && m_keyframeDist > 0)
2982 {
2983 long long startpos = pkt->pos;
2984
2985 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
2986 QString("positionMap[ %1 ] == %2.")
2987 .arg(m_framesRead).arg(startpos));
2988
2989 PosMapEntry entry = {m_framesRead, m_framesRead, startpos};
2990
2991 QMutexLocker locker(&m_positionMapLock);
2992 // Create a dummy positionmap entry for frame 0 so that
2993 // seeking will work properly. (See
2994 // DecoderBase::FindPosition() which subtracts
2995 // DecoderBase::indexOffset from each frame number.)
2996 if (m_positionMap.empty())
2997 {
2998 PosMapEntry dur = {0, 0, 0};
2999 m_positionMap.push_back(dur);
3000 }
3001 m_positionMap.push_back(entry);
3003 {
3004 long long duration = m_totalDuration.toFixed(1000LL);
3005 m_frameToDurMap[m_framesRead] = duration;
3006 m_durToFrameMap[duration] = m_framesRead;
3007 }
3008 }
3009
3010#if 0
3011 // If we are > 150 frames in and saw no positionmap at all, reset
3012 // length based on the actual bitrate seen so far
3014 {
3015 m_bitrate = (int)((pkt->pos * 8 * m_fps) / (m_framesRead - 1));
3016 float bytespersec = (float)m_bitrate / 8;
3017 float secs = m_ringBuffer->GetRealFileSize() * 1.0F / bytespersec;
3018 m_parent->SetFileLength((int)(secs), (int)(secs * m_fps));
3019 }
3020#endif
3021 }
3022}
3023
3024static constexpr uint32_t SEQ_START { 0x000001b3 };
3025static constexpr uint32_t GOP_START { 0x000001b8 };
3026//static constexpr uint32_t PICTURE_START { 0x00000100 };
3027static constexpr uint32_t SLICE_MIN { 0x00000101 };
3028static constexpr uint32_t SLICE_MAX { 0x000001af };
3029//static constexpr uint32_t SEQ_END_CODE { 0x000001b7 };
3030
3031void AvFormatDecoder::MpegPreProcessPkt(AVCodecContext* context, AVStream *stream, AVPacket *pkt)
3032{
3033 const uint8_t *bufptr = pkt->data;
3034 const uint8_t *bufend = pkt->data + pkt->size;
3035
3036 while (bufptr < bufend)
3037 {
3039
3040 float aspect_override = -1.0F;
3041 if (m_ringBuffer->IsDVD())
3042 aspect_override = m_ringBuffer->DVD()->GetAspectOverride();
3043
3045 continue;
3046
3048 {
3049 if (bufptr + 11 >= pkt->data + pkt->size)
3050 continue; // not enough valid data...
3051 const auto *seq = reinterpret_cast<const SequenceHeader*>(bufptr);
3052
3053 int width = static_cast<int>(seq->width()) >> context->lowres;
3054 int height = static_cast<int>(seq->height()) >> context->lowres;
3055 float aspect = seq->aspect(context->codec_id == AV_CODEC_ID_MPEG1VIDEO);
3056 if (stream->sample_aspect_ratio.num)
3057 aspect = static_cast<float>(av_q2d(stream->sample_aspect_ratio) * width / height);
3058 if (aspect_override > 0.0F)
3059 aspect = aspect_override;
3060 float seqFPS = seq->fps();
3061
3062 bool changed = (width != m_currentWidth );
3063 changed |= (height != m_currentHeight);
3064 changed |= (seqFPS > static_cast<float>(m_fps)+0.01F) ||
3065 (seqFPS < static_cast<float>(m_fps)-0.01F);
3066
3067 // some hardware decoders (e.g. VAAPI MPEG2) will reset when the aspect
3068 // ratio changes
3069 bool forceaspectchange = !qFuzzyCompare(m_currentAspect + 10.0F, aspect + 10.0F) &&
3071 m_currentAspect = aspect;
3072
3073 if (changed || forceaspectchange)
3074 {
3075 // N.B. We now set the default scan to kScan_Ignore as interlaced detection based on frame
3076 // size and rate is extremely error prone and FFmpeg gets it right far more often.
3077 // As for H.264, if a decoder deinterlacer is in operation - the stream must be progressive
3078 bool doublerate = false;
3079 bool decoderdeint = m_mythCodecCtx && m_mythCodecCtx->IsDeinterlacing(doublerate, true);
3080 m_parent->SetVideoParams(width, height, static_cast<double>(seqFPS), m_currentAspect,
3081 forceaspectchange, 2,
3082 decoderdeint ? kScan_Progressive : kScan_Ignore);
3083
3084 if (context->hw_frames_ctx)
3085 if (context->internal)
3086 avcodec_flush_buffers(context);
3087
3088 m_currentWidth = width;
3089 m_currentHeight = height;
3090 m_fps = seqFPS;
3091
3092 m_gopSet = false;
3093 m_prevGopPos = 0;
3095 m_lastCcPtsu = 0us;
3096 m_firstVPtsInuse = true;
3097
3098 // fps debugging info
3099 float avFPS = GetVideoFrameRate(stream, context);
3100 if ((seqFPS > avFPS+0.01F) || (seqFPS < avFPS-0.01F))
3101 {
3102 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("avFPS(%1) != seqFPS(%2)")
3103 .arg(static_cast<double>(avFPS)).arg(static_cast<double>(seqFPS)));
3104 }
3105 }
3106
3107 m_seqCount++;
3108
3109 if (!m_seenGop && m_seqCount > 1)
3110 {
3111 HandleGopStart(pkt, true);
3112 pkt->flags |= AV_PKT_FLAG_KEY;
3113 }
3114 }
3115 else if (GOP_START == m_startCodeState)
3116 {
3117 HandleGopStart(pkt, true);
3118 m_seenGop = true;
3119 pkt->flags |= AV_PKT_FLAG_KEY;
3120 }
3121 }
3122}
3123
3124// Returns the number of frame starts identified in the packet.
3125int AvFormatDecoder::H264PreProcessPkt(AVCodecContext* context, AVStream *stream, AVPacket *pkt)
3126{
3127 const uint8_t *buf = pkt->data;
3128 const uint8_t *buf_end = pkt->data + pkt->size;
3129 int num_frames = 0;
3130
3131 // The parser only understands Annex B/bytestream format - so check for avCC
3132 // format (starts with 0x01) and rely on FFmpeg keyframe detection
3133 if (context->extradata && (context->extradata_size >= 7) && (context->extradata[0] == 0x01))
3134 {
3135 if (pkt->flags & AV_PKT_FLAG_KEY)
3136 HandleGopStart(pkt, false);
3137 return 1;
3138 }
3139
3140 while (buf < buf_end)
3141 {
3142 buf += m_avcParser->addBytes(buf, static_cast<unsigned int>(buf_end - buf), 0);
3143
3145 {
3147 {
3149 ++num_frames;
3150
3152 continue;
3153 }
3154 else
3155 {
3156 continue;
3157 }
3158 }
3159 else
3160 {
3161 continue;
3162 }
3163
3165 float aspect = get_aspect(*m_avcParser);
3166 int width = static_cast<int>(m_avcParser->pictureWidthCropped());
3167 int height = static_cast<int>(m_avcParser->pictureHeightCropped());
3168 double seqFPS = m_avcParser->frameRate();
3169
3170 bool res_changed = ((width != m_currentWidth) || (height != m_currentHeight));
3171 bool fps_changed = (seqFPS > 0.0) && ((seqFPS > m_fps + 0.01) ||
3172 (seqFPS < m_fps - 0.01));
3173 bool forcechange = !qFuzzyCompare(aspect + 10.0F, m_currentAspect) &&
3175 m_currentAspect = aspect;
3176
3177 if (fps_changed || res_changed || forcechange)
3178 {
3179 // N.B. we now set the default scan to kScan_Ignore as interlaced detection based on frame
3180 // size and rate is extremely error prone and FFmpeg gets it right far more often.
3181 // N.B. if a decoder deinterlacer is in use - the stream must be progressive
3182 bool doublerate = false;
3183 bool decoderdeint = m_mythCodecCtx ? m_mythCodecCtx->IsDeinterlacing(doublerate, true) : false;
3184 m_parent->SetVideoParams(width, height, seqFPS, m_currentAspect, forcechange,
3185 static_cast<int>(m_avcParser->getRefFrames()),
3186 decoderdeint ? kScan_Progressive : kScan_Ignore);
3187
3188 // the SetVideoParams call above will have released all held frames
3189 // when using a hardware frames context - but for H264 (as opposed to mpeg2)
3190 // the codec will still hold references for reference frames (decoded picture buffer).
3191 // Flushing the context will release these references and the old
3192 // hardware context is released correctly before a new one is created.
3193 // TODO check what is needed here when a device context is used
3194 // TODO check whether any codecs need to be flushed for a frame rate change (e.g. mediacodec?)
3195 if (context->hw_frames_ctx && (forcechange || res_changed))
3196 if (context->internal)
3197 avcodec_flush_buffers(context);
3198
3199 m_currentWidth = width;
3200 m_currentHeight = height;
3201
3202 if (seqFPS > 0.0)
3203 m_fps = static_cast<float>(seqFPS);
3204
3205 m_gopSet = false;
3206 m_prevGopPos = 0;
3208 m_lastCcPtsu = 0us;
3209 m_firstVPtsInuse = true;
3210
3211 // fps debugging info
3212 auto avFPS = static_cast<double>(GetVideoFrameRate(stream, context));
3213 if ((seqFPS > avFPS + 0.01) || (seqFPS < avFPS - 0.01))
3214 {
3215 LOG(VB_PLAYBACK, LOG_INFO, LOC +
3216 QString("avFPS(%1) != seqFPS(%2)").arg(avFPS).arg(seqFPS));
3217 }
3218 }
3219
3220 HandleGopStart(pkt, true);
3221 pkt->flags |= AV_PKT_FLAG_KEY;
3222 }
3223
3224 return num_frames;
3225}
3226
3227bool AvFormatDecoder::PreProcessVideoPacket(AVCodecContext* context, AVStream *curstream, AVPacket *pkt)
3228{
3229 int num_frames = 1;
3230
3231 if (CODEC_IS_MPEG(context->codec_id))
3232 {
3233 MpegPreProcessPkt(context, curstream, pkt);
3234 }
3235 else if (CODEC_IS_H264(context->codec_id))
3236 {
3237 num_frames = H264PreProcessPkt(context, curstream, pkt);
3238 }
3239 else
3240 {
3241 if (pkt->flags & AV_PKT_FLAG_KEY)
3242 {
3243 HandleGopStart(pkt, false);
3244 m_seenGop = true;
3245 }
3246 else
3247 {
3248 m_seqCount++;
3249 if (!m_seenGop && m_seqCount > 1)
3250 {
3251 HandleGopStart(pkt, false);
3252 }
3253 }
3254 }
3255
3256 if (m_framesRead == 0 && !m_justAfterChange &&
3257 !(pkt->flags & AV_PKT_FLAG_KEY))
3258 {
3259 av_packet_unref(pkt);
3260 return false;
3261 }
3262
3263 m_framesRead += num_frames;
3264
3266 {
3267 // The ffmpeg libraries represent a frame interval of a
3268 // 59.94fps video as 1501/90000 seconds, when it should
3269 // actually be 1501.5/90000 seconds.
3270 MythAVRational pkt_dur {static_cast<int>(pkt->duration)};
3271 pkt_dur *= MythAVRational(curstream->time_base);
3272 if (pkt_dur == MythAVRational(1501, 90000))
3273 pkt_dur = MythAVRational(1001, 60000); // 1501.5/90000
3274 m_totalDuration += pkt_dur;
3275 }
3276
3277 m_justAfterChange = false;
3278
3280 m_gotVideoFrame = true;
3281
3282 return true;
3283}
3284
3285bool AvFormatDecoder::ProcessVideoPacket(AVCodecContext* context, AVStream *curstream, AVPacket *pkt, bool &Retry)
3286{
3287 int ret = 0;
3288 int gotpicture = 0;
3289 MythAVFrame mpa_pic;
3290 if (!mpa_pic)
3291 return false;
3292
3293 bool sentPacket = false;
3294 int ret2 = 0;
3295
3296 m_avCodecLock.lock();
3297
3298 // SUGGESTION
3299 // Now that avcodec_decode_video2 is deprecated and replaced
3300 // by 2 calls (receive frame and send packet), this could be optimized
3301 // into separate routines or separate threads.
3302 // Also now that it always consumes a whole buffer some code
3303 // in the caller may be able to be optimized.
3304
3305 // FilteredReceiveFrame will call avcodec_receive_frame and
3306 // apply any codec-dependent filtering
3307 ret = m_mythCodecCtx->FilteredReceiveFrame(context, mpa_pic);
3308
3309 if (ret == 0)
3310 gotpicture = 1;
3311 else
3312 gotpicture = 0;
3313 if (ret == AVERROR(EAGAIN))
3314 ret = 0;
3315 // If we got a picture do not send the packet until we have
3316 // all available pictures
3317 if (ret==0 && !gotpicture)
3318 {
3319 ret2 = avcodec_send_packet(context, pkt);
3320 if (ret2 == AVERROR(EAGAIN))
3321 {
3322 Retry = true;
3323 ret2 = 0;
3324 }
3325 else
3326 {
3327 sentPacket = true;
3328 }
3329 }
3330 m_avCodecLock.unlock();
3331
3332 if (ret < 0 || ret2 < 0)
3333 {
3334 std::string error;
3335 if (ret < 0)
3336 {
3337 LOG(VB_GENERAL, LOG_ERR, LOC +
3338 QString("video avcodec_receive_frame error: %1 (%2) gotpicture:%3")
3339 .arg(av_make_error_stdstring(error, ret))
3340 .arg(ret).arg(gotpicture));
3341 }
3342
3343 if (ret2 < 0)
3344 {
3345 LOG(VB_GENERAL, LOG_ERR, LOC +
3346 QString("video avcodec_send_packet error: %1 (%2) gotpicture:%3")
3347 .arg(av_make_error_stdstring(error, ret2))
3348 .arg(ret2).arg(gotpicture));
3349 }
3350
3352 {
3353 // If erroring on GPU assist, try switching to software decode
3355 m_parent->SetErrored(QObject::tr("Video Decode Error"));
3356 else
3357 m_streamsChanged = true;
3358 }
3359
3360 if (m_mythCodecCtx->DecoderNeedsReset(context))
3361 {
3362 LOG(VB_GENERAL, LOG_INFO, LOC + "Decoder needs reset");
3364 }
3365
3366 if (ret == AVERROR_EXTERNAL || ret2 == AVERROR_EXTERNAL)
3367 {
3368 LOG(VB_PLAYBACK, LOG_INFO, LOC + "FFmpeg external library error - assuming streams changed");
3369 m_streamsChanged = true;
3370 }
3371
3372 return false;
3373 }
3374
3375 // averror_count counts sequential errors, so if you have a successful
3376 // packet then reset it
3377 m_averrorCount = 0;
3378 if (gotpicture)
3379 {
3380 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
3381 QString("video timecodes packet-pts:%1 frame-pts:%2 packet-dts: %3 frame-dts:%4")
3382 .arg(pkt->pts).arg(mpa_pic->pts).arg(pkt->dts)
3383 .arg(mpa_pic->pkt_dts));
3384
3385 ProcessVideoFrame(context, curstream, mpa_pic);
3386 }
3387
3388 if (!sentPacket)
3389 {
3390 // MythTV logic expects that only one frame is processed
3391 // Save the packet for later and return.
3392 auto *newPkt = av_packet_clone(pkt);
3393 if (newPkt)
3394 m_storedPackets.prepend(newPkt);
3395 }
3396 return true;
3397}
3398
3399bool AvFormatDecoder::ProcessVideoFrame(AVCodecContext* context, AVStream *Stream, AVFrame *AvFrame)
3400{
3401 // look for A53 captions
3402 auto * side_data = av_frame_get_side_data(AvFrame, AV_FRAME_DATA_A53_CC);
3403 if (side_data && (side_data->size > 0))
3404 DecodeCCx08(side_data->data, static_cast<uint>(side_data->size));
3405
3406 auto * frame = static_cast<MythVideoFrame*>(AvFrame->opaque);
3407 if (frame)
3409
3411 {
3412 // Do nothing, we just want the pts, captions, subtites, etc.
3413 // So we can release the unconverted blank video frame to the
3414 // display queue.
3415 if (frame)
3416 frame->m_directRendering = false;
3417 }
3418 else if (!m_directRendering)
3419 {
3420 MythVideoFrame *oldframe = frame;
3421 frame = m_parent->GetNextVideoFrame();
3422 frame->m_directRendering = false;
3423
3424 if (!m_mythCodecCtx->RetrieveFrame(context, frame, AvFrame))
3425 {
3426 AVFrame tmppicture;
3427 av_image_fill_arrays(tmppicture.data, tmppicture.linesize,
3428 frame->m_buffer, AV_PIX_FMT_YUV420P, AvFrame->width,
3429 AvFrame->height, IMAGE_ALIGN);
3430 tmppicture.data[0] = frame->m_buffer + frame->m_offsets[0];
3431 tmppicture.data[1] = frame->m_buffer + frame->m_offsets[1];
3432 tmppicture.data[2] = frame->m_buffer + frame->m_offsets[2];
3433 tmppicture.linesize[0] = frame->m_pitches[0];
3434 tmppicture.linesize[1] = frame->m_pitches[1];
3435 tmppicture.linesize[2] = frame->m_pitches[2];
3436
3437 QSize dim = get_video_dim(*context);
3438 m_swsCtx = sws_getCachedContext(m_swsCtx, AvFrame->width,
3439 AvFrame->height, static_cast<AVPixelFormat>(AvFrame->format),
3440 AvFrame->width, AvFrame->height,
3441 AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
3442 nullptr, nullptr, nullptr);
3443 if (!m_swsCtx)
3444 {
3445 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate sws context");
3446 return false;
3447 }
3448 sws_scale(m_swsCtx, AvFrame->data, AvFrame->linesize, 0, dim.height(),
3449 tmppicture.data, tmppicture.linesize);
3450 }
3451
3452 // Discard any old VideoFrames
3453 if (oldframe)
3454 {
3455 // Set the frame flags, but then discard it
3456 // since we are not using it for display.
3457 oldframe->m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3458 oldframe->m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3459 oldframe->m_colorspace = AvFrame->colorspace;
3460 oldframe->m_colorrange = AvFrame->color_range;
3461 oldframe->m_colorprimaries = AvFrame->color_primaries;
3462 oldframe->m_colortransfer = AvFrame->color_trc;
3463 oldframe->m_chromalocation = AvFrame->chroma_location;
3464 oldframe->m_frameNumber = m_framesPlayed;
3465 oldframe->m_frameCounter = m_frameCounter++;
3466 oldframe->m_aspect = m_currentAspect;
3467 oldframe->m_rotation = m_videoRotation;
3468 oldframe->m_stereo3D = m_stereo3D;
3469
3470 oldframe->m_dummy = false;
3471 oldframe->m_pauseFrame = false;
3472 oldframe->m_interlacedReverse = false;
3473 oldframe->m_newGOP = false;
3474 oldframe->m_deinterlaceInuse = DEINT_NONE;
3475 oldframe->m_deinterlaceInuse2x = false;
3476 oldframe->m_alreadyDeinterlaced = false;
3477
3478 m_parent->DiscardVideoFrame(oldframe);
3479 }
3480 }
3481
3482 if (!frame)
3483 {
3484 LOG(VB_GENERAL, LOG_ERR, LOC + "NULL videoframe - direct rendering not "
3485 "correctly initialized.");
3486 return false;
3487 }
3488
3489
3490 if (AvFrame->best_effort_timestamp == AV_NOPTS_VALUE)
3491 {
3492 LOG(VB_GENERAL, LOG_ERR, LOC + "No PTS found - unable to process video.");
3493 return false;
3494 }
3495 std::chrono::milliseconds pts = millisecondsFromFloat(av_q2d(Stream->time_base) *
3496 AvFrame->best_effort_timestamp * 1000);
3497 std::chrono::milliseconds temppts = pts;
3498 // Validate the video pts against the last pts. If it's
3499 // a little bit smaller, equal or missing, compute
3500 // it from the last. Otherwise assume a wraparound.
3501 if (!m_ringBuffer->IsDVD() &&
3502 temppts <= m_lastVPts &&
3503 (temppts + millisecondsFromFloat(1000 / m_fps) > m_lastVPts ||
3504 temppts <= 0ms))
3505 {
3506 temppts = m_lastVPts;
3507 temppts += millisecondsFromFloat(1000 / m_fps);
3508 // MPEG2/H264 frames can be repeated, update pts accordingly
3509 temppts += millisecondsFromFloat(AvFrame->repeat_pict * 500 / m_fps);
3510 }
3511
3512 // Calculate actual fps from the pts values.
3513 std::chrono::milliseconds ptsdiff = temppts - m_lastVPts;
3514 double calcfps = 1000.0 / ptsdiff.count();
3515 if (calcfps < 121.0 && calcfps > 3.0)
3516 {
3517 // If fps has doubled due to frame-doubling deinterlace
3518 // Set fps to double value.
3519 double fpschange = calcfps / m_fps;
3520 int prior = m_fpsMultiplier;
3521 if (fpschange > 1.9 && fpschange < 2.1)
3522 m_fpsMultiplier = 2;
3523 if (fpschange > 0.9 && fpschange < 1.1)
3524 m_fpsMultiplier = 1;
3525 if (m_fpsMultiplier != prior)
3527 }
3528
3529 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
3530 QString("video timecode %1 %2 %3 %4%5")
3531 .arg(AvFrame->best_effort_timestamp)
3532 .arg(pts.count()).arg(temppts.count()).arg(m_lastVPts.count())
3533 .arg((pts != temppts) ? " fixup" : ""));
3534
3535 frame->m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3536 frame->m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3537 frame->m_newGOP = m_nextDecodedFrameIsKeyFrame;
3538 frame->m_repeatPic = AvFrame->repeat_pict != 0;
3539 frame->m_displayTimecode = NormalizeVideoTimecode(Stream, std::chrono::milliseconds(temppts));
3540 frame->m_frameNumber = m_framesPlayed;
3541 frame->m_frameCounter = m_frameCounter++;
3542 frame->m_aspect = m_currentAspect;
3543 frame->m_colorspace = AvFrame->colorspace;
3544 frame->m_colorrange = AvFrame->color_range;
3545 frame->m_colorprimaries = AvFrame->color_primaries;
3546 frame->m_colortransfer = AvFrame->color_trc;
3547 frame->m_chromalocation = AvFrame->chroma_location;
3548 frame->m_pixFmt = AvFrame->format;
3549 frame->m_deinterlaceInuse = DEINT_NONE;
3550 frame->m_rotation = m_videoRotation;
3551 frame->m_stereo3D = m_stereo3D;
3552
3553 frame->m_dummy = false;
3554 frame->m_pauseFrame = false;
3555 frame->m_deinterlaceInuse2x = false;
3556 frame->m_alreadyDeinterlaced = false;
3557 frame->m_interlacedReverse = false;
3558
3559 // Retrieve HDR metadata
3560 MythHDRVideoMetadata::Populate(frame, AvFrame);
3561
3562 m_parent->ReleaseNextVideoFrame(frame, std::chrono::milliseconds(temppts));
3563 m_mythCodecCtx->PostProcessFrame(context, frame);
3564
3566 m_decodedVideoFrame = frame;
3567 m_gotVideoFrame = true;
3568 if (++m_fpsSkip >= m_fpsMultiplier)
3569 {
3571 m_fpsSkip = 0;
3572 }
3573
3574 m_lastVPts = temppts;
3575 if ((m_firstVPts == 0ms) && m_firstVPtsInuse)
3576 m_firstVPts = temppts;
3577
3578 return true;
3579}
3580
3587 [[maybe_unused]] const AVStream *stream, const AVPacket *pkt)
3588{
3589 const uint8_t *buf = pkt->data;
3590 uint64_t linemask = 0;
3591 std::chrono::microseconds utc = m_lastCcPtsu;
3592
3593 // [i]tv0 means there is a linemask
3594 // [I]TV0 means there is no linemask and all lines are present
3595 if ((buf[0]=='t') && (buf[1]=='v') && (buf[2] == '0'))
3596 {
3598 memcpy(&linemask, buf + 3, 8);
3599 buf += 11;
3600 }
3601 else if ((buf[0]=='T') && (buf[1]=='V') && (buf[2] == '0'))
3602 {
3603 linemask = 0xffffffffffffffffLL;
3604 buf += 3;
3605 }
3606 else
3607 {
3608 LOG(VB_VBI, LOG_ERR, LOC + QString("Unknown VBI data stream '%1%2%3'")
3609 .arg(QChar(buf[0])).arg(QChar(buf[1])).arg(QChar(buf[2])));
3610 return;
3611 }
3612
3613 static constexpr uint kMinBlank = 6;
3614 for (uint i = 0; i < 36; i++)
3615 {
3616 if (!((linemask >> i) & 0x1))
3617 continue;
3618
3619 const uint line = ((i < 18) ? i : i-18) + kMinBlank;
3620 const uint field = (i<18) ? 0 : 1;
3621 const uint id2 = *buf & 0xf;
3622 switch (id2)
3623 {
3625 // SECAM lines 6-23
3626 // PAL lines 6-22
3627 // NTSC lines 10-21 (rare)
3628 m_trackLock.lock();
3629 if (m_tracks[kTrackTypeTeletextMenu].empty())
3630 {
3631 StreamInfo si {pkt->stream_index, 0};
3632 m_trackLock.lock();
3633 m_tracks[kTrackTypeTeletextMenu].push_back(si);
3634 m_trackLock.unlock();
3636 }
3637 m_trackLock.unlock();
3638 m_ttd->Decode(buf+1, VBI_IVTV);
3639 break;
3641 // PAL line 22 (rare)
3642 // NTSC line 21
3643 if (21 == line)
3644 {
3645 int data = (buf[2] << 8) | buf[1];
3646 if (cc608_good_parity(data))
3647 m_ccd608->FormatCCField(duration_cast<std::chrono::milliseconds>(utc), field, data);
3648 utc += 33367us;
3649 }
3650 break;
3651 case V4L2_MPEG_VBI_IVTV_VPS: // Video Programming System
3652 // PAL line 16
3653 m_ccd608->DecodeVPS(buf+1); // a.k.a. PDC
3654 break;
3655 case V4L2_MPEG_VBI_IVTV_WSS_625: // Wide Screen Signal
3656 // PAL line 23
3657 // NTSC line 20
3658 m_ccd608->DecodeWSS(buf+1);
3659 break;
3660 }
3661 buf += 43;
3662 }
3663 m_lastCcPtsu = utc;
3664 UpdateCaptionTracksFromStreams(true, false);
3665}
3666
3672 const AVStream* /*stream*/, const AVPacket *pkt)
3673{
3674 // ETSI EN 301 775 V1.2.1 (2003-05)
3675 // Check data_identifier value
3676 // Defined in 4.4.2 Semantics for PES data field, Table 2
3677 // Support only the "low range" 0x10-0x1F because they have
3678 // the fixed data_unit_length of 0x2C (44) that the teletext
3679 // decoder expects.
3680 //
3681 const uint8_t *buf = pkt->data;
3682 const uint8_t *buf_end = pkt->data + pkt->size;
3683
3684 if (*buf >= 0x10 && *buf <= 0x1F)
3685 {
3686 buf++;
3687 }
3688 else
3689 {
3690 LOG(VB_VBI, LOG_WARNING, LOC +
3691 QString("VBI: Unknown data_identier: %1 discarded").arg(*buf));
3692 return;
3693 }
3694
3695 // Process data packets in the PES packet payload
3696 while (buf < buf_end)
3697 {
3698 if (*buf == 0x02) // data_unit_id 0x02 EBU Teletext non-subtitle data
3699 {
3700 buf += 4; // Skip data_unit_id, data_unit_length (0x2C, 44) and first two data bytes
3701 if ((buf_end - buf) >= 42)
3702 m_ttd->Decode(buf, VBI_DVB);
3703 buf += 42;
3704 }
3705 else if (*buf == 0x03) // data_unit_id 0x03 EBU Teletext subtitle data
3706 {
3707 buf += 4;
3708 if ((buf_end - buf) >= 42)
3710 buf += 42;
3711 }
3712 else if (*buf == 0xff) // data_unit_id 0xff stuffing
3713 {
3714 buf += 46; // data_unit_id, data_unit_length and 44 data bytes
3715 }
3716 else
3717 {
3718 LOG(VB_VBI, LOG_WARNING, LOC +
3719 QString("VBI: Unsupported data_unit_id: %1 discarded").arg(*buf));
3720 buf += 46;
3721 }
3722 }
3723}
3724
3728void AvFormatDecoder::ProcessDSMCCPacket([[maybe_unused]] const AVStream *str,
3729 [[maybe_unused]] const AVPacket *pkt)
3730{
3731#if CONFIG_MHEG
3732 if (m_itv == nullptr)
3734 if (m_itv == nullptr)
3735 return;
3736
3737 // The packet may contain several tables.
3738 uint8_t *data = pkt->data;
3739 int length = pkt->size;
3740 int componentTag = 0;
3741 int dataBroadcastId = 0;
3742 unsigned carouselId = 0;
3743 {
3744 m_avCodecLock.lock();
3745 componentTag = str->component_tag;
3746 dataBroadcastId = str->data_id;
3747 carouselId = (unsigned) str->carousel_id;
3748 m_avCodecLock.unlock();
3749 }
3750 while (length > 3)
3751 {
3752 uint16_t sectionLen = (((data[1] & 0xF) << 8) | data[2]) + 3;
3753
3754 if (sectionLen > length) // This may well be filler
3755 return;
3756
3757 m_itv->ProcessDSMCCSection(data, sectionLen,
3758 componentTag, carouselId,
3759 dataBroadcastId);
3760 length -= sectionLen;
3761 data += sectionLen;
3762 }
3763#endif // CONFIG_MHEG
3764}
3765
3766bool AvFormatDecoder::ProcessSubtitlePacket(AVCodecContext* codecContext, AVStream *curstream, AVPacket *pkt)
3767{
3768 if (!m_parent->GetSubReader(pkt->stream_index))
3769 return true;
3770
3771 long long pts = pkt->pts;
3772 if (pts == AV_NOPTS_VALUE)
3773 pts = pkt->dts;
3774 if (pts == AV_NOPTS_VALUE)
3775 {
3776 LOG(VB_GENERAL, LOG_ERR, LOC + "No PTS found - unable to process subtitle.");
3777 return false;
3778 }
3779 pts = static_cast<long long>(av_q2d(curstream->time_base) * pts * 1000);
3780
3781 m_trackLock.lock();
3782 int subIdx = m_selectedTrack[kTrackTypeSubtitle].m_av_stream_index;
3783 int forcedSubIdx = m_selectedForcedTrack[kTrackTypeSubtitle].m_av_stream_index;
3784 bool mainTrackIsForced = m_selectedTrack[kTrackTypeSubtitle].m_forced;
3785 bool isForcedTrack = false;
3786 m_trackLock.unlock();
3787
3788 int gotSubtitles = 0;
3789 AVSubtitle subtitle;
3790 memset(&subtitle, 0, sizeof(AVSubtitle));
3791
3792 if (m_ringBuffer->IsDVD())
3793 {
3794 if (m_ringBuffer->DVD()->NumMenuButtons() > 0)
3795 {
3796 m_ringBuffer->DVD()->GetMenuSPUPkt(pkt->data, pkt->size,
3797 curstream->id, pts);
3798 }
3799 else
3800 {
3801 if (pkt->stream_index == subIdx)
3802 {
3803 m_avCodecLock.lock();
3804 m_ringBuffer->DVD()->DecodeSubtitles(&subtitle, &gotSubtitles,
3805 pkt->data, pkt->size, pts);
3806 m_avCodecLock.unlock();
3807 }
3808 }
3809 }
3810 else if (m_decodeAllSubtitles || pkt->stream_index == subIdx
3811 || pkt->stream_index == forcedSubIdx)
3812 {
3813 m_avCodecLock.lock();
3814 avcodec_decode_subtitle2(codecContext, &subtitle, &gotSubtitles, pkt);
3815 m_avCodecLock.unlock();
3816
3817 subtitle.start_display_time += pts;
3818 subtitle.end_display_time += pts;
3819
3820 if (pkt->stream_index != subIdx)
3821 isForcedTrack = true;
3822 }
3823
3824 if (gotSubtitles)
3825 {
3826 if (isForcedTrack)
3827 {
3828 for (unsigned i = 0; i < subtitle.num_rects; i++)
3829 {
3830 subtitle.rects[i]->flags |= AV_SUBTITLE_FLAG_FORCED;
3831 }
3832 }
3833 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
3834 QString("subtl timecode %1 %2 %3 %4")
3835 .arg(pkt->pts).arg(pkt->dts)
3836 .arg(subtitle.start_display_time)
3837 .arg(subtitle.end_display_time));
3838
3839 bool forcedon = m_parent->GetSubReader(pkt->stream_index)->AddAVSubtitle(
3840 subtitle, curstream->codecpar->codec_id == AV_CODEC_ID_XSUB,
3841 isForcedTrack,
3842 (m_parent->GetAllowForcedSubtitles() && !mainTrackIsForced), false);
3843 m_parent->EnableForcedSubtitles(forcedon || isForcedTrack);
3844 }
3845
3846 return true;
3847}
3848
3850{
3851 if (!m_decodeAllSubtitles && m_selectedTrack[kTrackTypeRawText].m_av_stream_index != Packet->stream_index)
3852 return false;
3853
3854 auto id = static_cast<uint>(Packet->stream_index + 0x2000);
3855 if (!m_parent->GetSubReader(id))
3856 return false;
3857
3858#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
3859 const auto * codec = QTextCodec::codecForName("utf-8");
3860 auto text = codec->toUnicode(reinterpret_cast<const char *>(Packet->data), Packet->size - 1);
3861#else
3862 auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);
3863 QString text = toUtf16.decode(Packet->data);
3864#endif
3865 auto list = text.split('\n', Qt::SkipEmptyParts);
3866 m_parent->GetSubReader(id)->AddRawTextSubtitle(list, std::chrono::milliseconds(Packet->duration));
3867 return true;
3868}
3869
3870bool AvFormatDecoder::ProcessDataPacket(AVStream *curstream, AVPacket *pkt,
3871 [[maybe_unused]] DecodeType decodetype)
3872{
3873 enum AVCodecID codec_id = curstream->codecpar->codec_id;
3874
3875 switch (codec_id)
3876 {
3877 case AV_CODEC_ID_DVB_VBI:
3878 ProcessDVBDataPacket(curstream, pkt);
3879 break;
3880 case AV_CODEC_ID_DSMCC_B:
3881 {
3882 ProcessDSMCCPacket(curstream, pkt);
3884 // Have to return regularly to ensure that the OSD is updated.
3885 // This applies both to MHEG and also channel browsing.
3886#if CONFIG_MHEG
3887 if (!(decodetype & kDecodeVideo))
3888 m_allowedQuit |= (m_itv && m_itv->ImageHasChanged());
3889#endif // CONFIG_MHEG:
3890 break;
3891 }
3892 default:
3893 break;
3894 }
3895 return true;
3896}
3897
3898int AvFormatDecoder::SetTrack(uint Type, int TrackNo)
3899{
3900 QMutexLocker locker(&m_trackLock);
3901 int ret = DecoderBase::SetTrack(Type, TrackNo);
3902 if (kTrackTypeAudio == Type)
3903 {
3904 QString msg = SetupAudioStream() ? "" : "not ";
3905 LOG(VB_AUDIO, LOG_INFO, LOC + "Audio stream type " + msg + "changed.");
3906 }
3907 return ret;
3908}
3909
3911{
3912 QMutexLocker locker(&m_trackLock);
3913
3914 if (!m_ic || TrackNo >= m_tracks[type].size())
3915 return "";
3916
3917 bool forced = m_tracks[type][TrackNo].m_forced;
3918 int lang_key = m_tracks[type][TrackNo].m_language;
3919 QString forcedString = forced ? QObject::tr(" (forced)") : "";
3920
3921 int av_index = m_tracks[type][TrackNo].m_av_stream_index;
3922 AVStream *stream { nullptr };
3923 if (av_index >= 0 && av_index < (int)m_ic->nb_streams)
3924 stream = m_ic->streams[av_index];
3925 AVDictionaryEntry *entry =
3926 stream ? av_dict_get(stream->metadata, "title", nullptr, 0) : nullptr;
3927 QString user_title = entry ? QString(R"( "%1")").arg(entry->value) : "";
3928
3929 if (kTrackTypeAudio == type)
3930 {
3931 QString msg = iso639_key_toName(lang_key);
3932
3933 switch (m_tracks[type][TrackNo].m_audio_type)
3934 {
3935 case kAudioTypeNormal :
3936 {
3937 if (stream)
3938 {
3939 AVCodecParameters *par = stream->codecpar;
3940 AVCodecContext *ctx = m_codecMap.GetCodecContext(stream);
3941 if (par->codec_id == AV_CODEC_ID_MP3)
3942 msg += QString(" MP3");
3943 else if (ctx && ctx->codec)
3944 msg += QString(" %1").arg(ctx->codec->name).toUpper();
3945 if (!user_title.isEmpty())
3946 msg += user_title;
3947
3948 int channels = par->ch_layout.nb_channels;
3949
3950 if (channels == 0)
3951 msg += QString(" ?ch");
3952 else if((channels > 4) && !(channels & 1))
3953 msg += QString(" %1.1ch").arg(channels - 1);
3954 else
3955 msg += QString(" %1ch").arg(channels);
3956 }
3957 break;
3958 }
3964 default :
3965 if (!user_title.isEmpty())
3966 msg += user_title;
3967 else
3968 msg += QString(" (%1)")
3969 .arg(toString(m_tracks[type][TrackNo].m_audio_type));
3970 break;
3971 }
3972 return QString("%1: %2").arg(TrackNo + 1).arg(msg);
3973 }
3974 if (kTrackTypeSubtitle == type)
3975 {
3976 return QObject::tr("Subtitle") + QString(" %1: %2%3%4")
3977 .arg(QString::number(TrackNo + 1),
3978 iso639_key_toName(lang_key),
3979 user_title,
3980 forcedString);
3981 }
3982 if (forced && kTrackTypeRawText == type)
3983 return DecoderBase::GetTrackDesc(type, TrackNo) + forcedString;
3984 return DecoderBase::GetTrackDesc(type, TrackNo);
3985}
3986
3988{
3989 return m_ttd->GetDecoderType();
3990}
3991
3992QString AvFormatDecoder::GetXDS(const QString &Key) const
3993{
3994 return m_ccd608->GetXDS(Key);
3995}
3996
3998{
3999 QMutexLocker locker(&m_trackLock);
4000 if (TrackNo >= m_tracks[kTrackTypeSubtitle].size())
4001 return {};
4002
4003 int index = m_tracks[kTrackTypeSubtitle][TrackNo].m_av_stream_index;
4004 AVCodecContext *ctx = m_codecMap.GetCodecContext(m_ic->streams[index]);
4005 return ctx ? QByteArray(reinterpret_cast<char*>(ctx->subtitle_header), ctx->subtitle_header_size) :
4006 QByteArray();
4007}
4008
4009void AvFormatDecoder::GetAttachmentData(uint TrackNo, QByteArray &Filename, QByteArray &Data)
4010{
4011 QMutexLocker locker(&m_trackLock);
4012 if (TrackNo >= m_tracks[kTrackTypeAttachment].size())
4013 return;
4014
4015 int index = m_tracks[kTrackTypeAttachment][TrackNo].m_av_stream_index;
4016 AVDictionaryEntry *tag = av_dict_get(m_ic->streams[index]->metadata, "filename", nullptr, 0);
4017 if (tag)
4018 Filename = QByteArray(tag->value);
4019 AVCodecParameters *par = m_ic->streams[index]->codecpar;
4020 Data = QByteArray(reinterpret_cast<char*>(par->extradata), par->extradata_size);
4021}
4022
4024{
4025 QMutexLocker locker(&m_trackLock);
4026 for (size_t i = 0; i < m_tracks[kTrackTypeAudio].size(); i++)
4027 {
4028 AVStream *stream = m_ic->streams[m_tracks[kTrackTypeAudio][i].m_av_stream_index];
4029 if (stream)
4030 if ((stream->component_tag == Tag) || ((Tag <= 0) && stream->component_tag <= 0))
4031 return SetTrack(kTrackTypeAudio, static_cast<int>(i)) != -1;
4032 }
4033 return false;
4034}
4035
4037{
4038 QMutexLocker locker(&m_trackLock);
4039 for (uint i = 0; i < m_ic->nb_streams; i++)
4040 {
4041 AVStream *stream = m_ic->streams[i];
4042 if (stream)
4043 {
4044 if (stream->component_tag == Tag)
4045 {
4046 StreamInfo si {static_cast<int>(i), 0};
4048 return true;
4049 }
4050 }
4051 }
4052 return false;
4053}
4054
4055// documented in decoderbase.cpp
4057{
4058 if (kTrackTypeAudio == type)
4059 return AutoSelectAudioTrack();
4060
4062 return -1;
4063
4065}
4066
4067static std::vector<int> filter_lang(const sinfo_vec_t &tracks, int lang_key,
4068 const std::vector<int> &ftype)
4069{
4070 std::vector<int> ret;
4071
4072 for (int index : ftype)
4073 {
4074 if ((lang_key < 0) || tracks[index].m_language == lang_key)
4075 ret.push_back(index);
4076 }
4077
4078 return ret;
4079}
4080
4081static std::vector<int> filter_type(const sinfo_vec_t &tracks, AudioTrackType type)
4082{
4083 std::vector<int> ret;
4084
4085 for (size_t i = 0; i < tracks.size(); i++)
4086 {
4087 if (tracks[i].m_audio_type == type)
4088 ret.push_back(i);
4089 }
4090
4091 return ret;
4092}
4093
4094int AvFormatDecoder::filter_max_ch(const AVFormatContext *ic,
4095 const sinfo_vec_t &tracks,
4096 const std::vector<int>&fs,
4097 enum AVCodecID codecId,
4098 int profile)
4099{
4100 int selectedTrack = -1;
4101 int max_seen = -1;
4102
4103 for (int f : fs)
4104 {
4105 const int stream_index = tracks[f].m_av_stream_index;
4106 AVCodecParameters *par = ic->streams[stream_index]->codecpar;
4107 if ((codecId == AV_CODEC_ID_NONE || codecId == par->codec_id) &&
4108 (max_seen < par->ch_layout.nb_channels))
4109 {
4110 if (codecId == AV_CODEC_ID_DTS && profile > 0)
4111 {
4112 // we cannot decode dts-hd, so only select it if passthrough
4113 if (!DoPassThrough(par, true) || par->profile != profile)
4114 continue;
4115 }
4116 selectedTrack = f;
4117 max_seen = par->ch_layout.nb_channels;
4118 }
4119 }
4120
4121 return selectedTrack;
4122}
4123
4124int AvFormatDecoder::selectBestAudioTrack(int lang_key, const std::vector<int> &ftype)
4125{
4126 const sinfo_vec_t &atracks = m_tracks[kTrackTypeAudio];
4127 int selTrack = -1;
4128
4129 std::vector<int> flang = filter_lang(atracks, lang_key, ftype);
4130
4131 if (m_audio->CanDTSHD())
4132 {
4133 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_DTS,
4134 AV_PROFILE_DTS_HD_MA);
4135 if (selTrack >= 0)
4136 return selTrack;
4137 }
4138 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_TRUEHD);
4139 if (selTrack >= 0)
4140 return selTrack;
4141
4142 if (m_audio->CanDTSHD())
4143 {
4144 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_DTS,
4145 AV_PROFILE_DTS_HD_HRA);
4146 if (selTrack >= 0)
4147 return selTrack;
4148 }
4149 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_EAC3);
4150 if (selTrack >= 0)
4151 return selTrack;
4152
4153 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_DTS);
4154 if (selTrack >= 0)
4155 return selTrack;
4156
4157 selTrack = filter_max_ch(m_ic, atracks, flang, AV_CODEC_ID_AC3);
4158 if (selTrack >= 0)
4159 return selTrack;
4160
4161 selTrack = filter_max_ch(m_ic, atracks, flang);
4162
4163 return selTrack;
4164}
4165
4213{
4214 QMutexLocker locker(&m_trackLock);
4215
4216 const sinfo_vec_t &atracks = m_tracks[kTrackTypeAudio];
4219 int &ctrack = m_currentTrack[kTrackTypeAudio];
4220
4221 uint numStreams = atracks.size();
4222 int selTrack = -1;
4223 if (numStreams > 0)
4224 {
4225 if ((ctrack >= 0) && (ctrack < (int)numStreams))
4226 return ctrack; // audio already selected
4227
4228 LOG(VB_AUDIO, LOG_DEBUG, QString("%1 available audio streams").arg(numStreams));
4229 for (const auto & track : atracks)
4230 {
4231 AVCodecParameters *codecpar = m_ic->streams[track.m_av_stream_index]->codecpar;
4232 LOG(VB_AUDIO, LOG_DEBUG, QString("%1: %2 bps, %3 Hz, %4 channels, passthrough(%5)")
4233 .arg(avcodec_get_name(codecpar->codec_id), QString::number(codecpar->bit_rate),
4234 QString::number(codecpar->sample_rate), QString::number(codecpar->ch_layout.nb_channels),
4235 (DoPassThrough(codecpar, true)) ? "true" : "false")
4236 );
4237 }
4238
4239 if (1 == numStreams)
4240 {
4241 selTrack = 0;
4242 }
4243 else
4244 {
4245 int wlang = wtrack.m_language;
4246
4247 if ((selTrack < 0) && (wtrack.m_av_substream_index >= 0))
4248 {
4249 LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to reselect audio sub-stream");
4250 // Dual stream without language information: choose
4251 // the previous substream that was kept in wtrack,
4252 // ignoring the stream index (which might have changed).
4253 int substream_index = wtrack.m_av_substream_index;
4254
4255 for (uint i = 0; i < numStreams; i++)
4256 {
4257 if (atracks[i].m_av_substream_index == substream_index)
4258 {
4259 selTrack = i;
4260 break;
4261 }
4262 }
4263 }
4264
4265 if ((selTrack < 0) && wlang >= -1)
4266 {
4267 LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to reselect audio track");
4268 // Try to reselect user selected audio stream.
4269 // This should find the stream after a commercial
4270 // break and in some cases after a channel change.
4271 uint windx = wtrack.m_language_index;
4272 for (uint i = 0; i < numStreams; i++)
4273 {
4274 if (wlang == atracks[i].m_language)
4275 {
4276 selTrack = i;
4277
4278 if (windx == atracks[i].m_language_index)
4279 break;
4280 }
4281 }
4282 }
4283
4284 if (selTrack < 0)
4285 {
4286 LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to select audio track (w/lang)");
4287
4288 // Filter out commentary and audio description tracks
4289 std::vector<int> ftype = filter_type(atracks, kAudioTypeNormal);
4290
4291 if (ftype.empty())
4292 {
4293 LOG(VB_AUDIO, LOG_WARNING, "No audio tracks matched the type filter, "
4294 "so trying all tracks.");
4295 for (int i = 0; i < static_cast<int>(atracks.size()); i++)
4296 ftype.push_back(i);
4297 }
4298
4299 // Try to get the language track for the preferred language for audio
4300 QString language_key_convert = iso639_str2_to_str3(gCoreContext->GetAudioLanguage());
4301 uint language_key = iso639_str3_to_key(language_key_convert);
4302 uint canonical_key = iso639_key_to_canonical_key(language_key);
4303
4304 selTrack = selectBestAudioTrack(canonical_key, ftype);
4305
4306 // Try to get best track for most preferred language for audio.
4307 // Set by the "Guide Data" "Audio Language" preference in Appearance.
4308 if (selTrack < 0)
4309 {
4310 auto it = m_languagePreference.begin();
4311 for (; it != m_languagePreference.end() && selTrack < 0; ++it)
4312 {
4313 selTrack = selectBestAudioTrack(*it, ftype);
4314 }
4315 }
4316
4317 // Could not select track based on user preferences (audio language)
4318 // Try to select the default track
4319 if (selTrack < 0)
4320 {
4321 LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to select default track");
4322 for (size_t i = 0; i < atracks.size(); i++) {
4323 int idx = atracks[i].m_av_stream_index;
4324 if (m_ic->streams[idx]->disposition & AV_DISPOSITION_DEFAULT)
4325 {
4326 selTrack = i;
4327 break;
4328 }
4329 }
4330 }
4331
4332 // Try to get best track for any language
4333 if (selTrack < 0)
4334 {
4335 LOG(VB_AUDIO, LOG_INFO, LOC +
4336 "Trying to select audio track (wo/lang)");
4337 selTrack = selectBestAudioTrack(-1, ftype);
4338 }
4339 }
4340 }
4341 }
4342
4343 if (selTrack < 0)
4344 {
4345 strack.m_av_stream_index = -1;
4346 if (ctrack != selTrack)
4347 {
4348 LOG(VB_AUDIO, LOG_INFO, LOC + "No suitable audio track exists.");
4349 ctrack = selTrack;
4350 }
4351 }
4352 else
4353 {
4354 ctrack = selTrack;
4355 strack = atracks[selTrack];
4356
4357 if (wtrack.m_av_stream_index < 0)
4358 wtrack = strack;
4359
4360 LOG(VB_AUDIO, LOG_INFO, LOC + QString("Selected track %1 (A/V Stream #%2)")
4361 .arg(static_cast<uint>(ctrack)).arg(strack.m_av_stream_index));
4362 }
4363
4365 return selTrack;
4366}
4367
4368static void extract_mono_channel(uint channel, AudioInfo *audioInfo,
4369 char *buffer, int bufsize)
4370{
4371 // Only stereo -> mono (left or right) is supported
4372 if (audioInfo->m_channels != 2)
4373 return;
4374
4375 if (channel >= (uint)audioInfo->m_channels)
4376 return;
4377
4378 const uint samplesize = audioInfo->m_sampleSize;
4379 const uint samples = bufsize / samplesize;
4380 const uint halfsample = samplesize >> 1;
4381
4382 const char *from = (channel == 1) ? buffer + halfsample : buffer;
4383 char *to = (channel == 0) ? buffer + halfsample : buffer;
4384
4385 for (uint sample = 0; sample < samples;
4386 (sample++), (from += samplesize), (to += samplesize))
4387 {
4388 memmove(to, from, halfsample);
4389 }
4390}
4391
4392bool AvFormatDecoder::ProcessAudioPacket(AVCodecContext* context, AVStream *curstream, AVPacket *pkt,
4393 DecodeType decodetype)
4394{
4395 int ret = 0;
4396 int data_size = 0;
4397 bool firstloop = true;
4398 int decoded_size = -1;
4399
4400 m_trackLock.lock();
4401 int audIdx = m_selectedTrack[kTrackTypeAudio].m_av_stream_index;
4402 int audSubIdx = m_selectedTrack[kTrackTypeAudio].m_av_substream_index;
4403 m_trackLock.unlock();
4404
4405 AVPacket *tmp_pkt = av_packet_alloc();
4406 tmp_pkt->data = pkt->data;
4407 tmp_pkt->size = pkt->size;
4408 while (tmp_pkt->size > 0)
4409 {
4410 bool reselectAudioTrack = false;
4411
4413 if (!m_audio->HasAudioIn())
4414 {
4415 LOG(VB_AUDIO, LOG_INFO, LOC +
4416 "Audio is disabled - trying to restart it");
4417 reselectAudioTrack = true;
4418 }
4420
4421 // detect switches between stereo and dual languages
4422 bool wasDual = audSubIdx != -1;
4423 bool isDual = is_dual_mono(context->ch_layout);
4424 if ((wasDual && !isDual) || (!wasDual && isDual))
4425 {
4427 reselectAudioTrack = true;
4428 }
4429
4430 // detect channels on streams that need
4431 // to be decoded before we can know this
4432 bool already_decoded = false;
4433 if (!context->ch_layout.nb_channels)
4434 {
4435 m_avCodecLock.lock();
4436 if (DoPassThrough(curstream->codecpar, false) || !DecoderWillDownmix(context))
4437 {
4438 // for passthru or codecs for which the decoder won't downmix
4439 // let the decoder set the number of channels. For other codecs
4440 // we downmix if necessary in audiooutputbase
4441 ;
4442 }
4443 else // No passthru, the decoder will downmix
4444 {
4445 AVChannelLayout channel_layout;
4446 av_channel_layout_default(&channel_layout, m_audio->GetMaxChannels());
4447 av_opt_set_chlayout(context->priv_data, "downmix", &channel_layout, 0);
4448
4449 if (context->codec_id == AV_CODEC_ID_AC3)
4450 context->ch_layout.nb_channels = m_audio->GetMaxChannels();
4451 }
4452
4453 ret = m_audio->DecodeAudio(context, m_audioSamples, data_size, tmp_pkt);
4454 decoded_size = data_size;
4455 already_decoded = true;
4456 reselectAudioTrack |= context->ch_layout.nb_channels;
4457 m_avCodecLock.unlock();
4458 }
4459
4460 if (reselectAudioTrack)
4461 {
4462 QMutexLocker locker(&m_trackLock);
4464 m_selectedTrack[kTrackTypeAudio].m_av_stream_index = -1;
4466 audIdx = m_selectedTrack[kTrackTypeAudio].m_av_stream_index;
4467 audSubIdx = m_selectedTrack[kTrackTypeAudio].m_av_substream_index;
4468 }
4469
4470 if (!(decodetype & kDecodeAudio) || (pkt->stream_index != audIdx)
4471 || !m_audio->HasAudioOut())
4472 break;
4473
4474 if (firstloop && pkt->pts != AV_NOPTS_VALUE)
4475 m_lastAPts = millisecondsFromFloat(av_q2d(curstream->time_base) * pkt->pts * 1000);
4476
4477 m_firstVPtsInuse = false;
4478 m_avCodecLock.lock();
4479 data_size = 0;
4480
4481 // Check if the number of channels or sampling rate have changed
4482 if (context->sample_rate != m_audioOut.m_sampleRate ||
4483 context->ch_layout.nb_channels != m_audioOut.m_channels ||
4485 context->bits_per_raw_sample) != m_audioOut.format)
4486 {
4487 LOG(VB_GENERAL, LOG_INFO, LOC + "Audio stream changed");
4488 if (context->ch_layout.nb_channels != m_audioOut.m_channels)
4489 {
4490 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Number of audio channels changed from %1 to %2")
4491 .arg(m_audioOut.m_channels).arg(context->ch_layout.nb_channels));
4492 }
4493 QMutexLocker locker(&m_trackLock);
4495 m_selectedTrack[kTrackTypeAudio].m_av_stream_index = -1;
4496 audIdx = -1;
4498 }
4499
4501 {
4502 if (!already_decoded)
4503 {
4505 {
4506 ret = m_audio->DecodeAudio(context, m_audioSamples, data_size, tmp_pkt);
4507 decoded_size = data_size;
4508 }
4509 else
4510 {
4511 decoded_size = -1;
4512 }
4513 }
4514 memcpy(m_audioSamples, tmp_pkt->data, tmp_pkt->size);
4515 data_size = tmp_pkt->size;
4516 // We have processed all the data, there can't be any left
4517 tmp_pkt->size = 0;
4518 }
4519 else
4520 {
4521 if (!already_decoded)
4522 {
4523 if (DecoderWillDownmix(context))
4524 {
4525 AVChannelLayout channel_layout;
4526 av_channel_layout_default(&channel_layout, m_audio->GetMaxChannels());
4527 av_opt_set_chlayout(context->priv_data, "downmix", &channel_layout, 0);
4528 }
4529
4530 ret = m_audio->DecodeAudio(context, m_audioSamples, data_size, tmp_pkt);
4531 decoded_size = data_size;
4532 }
4533 }
4534 m_avCodecLock.unlock();
4535
4536 if (ret < 0)
4537 {
4538 LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown audio decoding error");
4539 av_packet_free(&tmp_pkt);
4540 return false;
4541 }
4542
4543 if (data_size <= 0)
4544 {
4545 tmp_pkt->data += ret;
4546 tmp_pkt->size -= ret;
4547 continue;
4548 }
4549
4550 std::chrono::milliseconds temppts = m_lastAPts;
4551
4552 if (audSubIdx != -1 && !m_audioOut.m_doPassthru)
4553 extract_mono_channel(audSubIdx, &m_audioOut,
4554 (char *)m_audioSamples, data_size);
4555
4557 int frames = (context->ch_layout.nb_channels <= 0 || decoded_size < 0 || !samplesize) ? -1 :
4558 decoded_size / (context->ch_layout.nb_channels * samplesize);
4559 m_audio->AddAudioData((char *)m_audioSamples, data_size, temppts, frames);
4561 {
4563 }
4564 else
4565 {
4567 ((double)(frames * 1000) / context->sample_rate);
4568 }
4569
4570 LOG(VB_TIMESTAMP, LOG_INFO, LOC + QString("audio timecode %1 %2 %3 %4")
4571 .arg(pkt->pts).arg(pkt->dts).arg(temppts.count()).arg(m_lastAPts.count()));
4572
4575
4576 tmp_pkt->data += ret;
4577 tmp_pkt->size -= ret;
4578 firstloop = false;
4579 }
4580
4581 av_packet_free(&tmp_pkt);
4582 return true;
4583}
4584
4585// documented in decoderbase.h
4586bool AvFormatDecoder::GetFrame(DecodeType decodetype, bool &Retry)
4587{
4588 AVPacket *pkt = nullptr;
4589 bool have_err = false;
4590
4591 const DecodeType origDecodetype = decodetype;
4592
4593 m_gotVideoFrame = false;
4594
4595 m_frameDecoded = 0;
4596 m_decodedVideoFrame = nullptr;
4597
4598 m_allowedQuit = false;
4599 bool storevideoframes = false;
4600
4601 m_skipAudio = (m_lastVPts == 0ms);
4602
4603 if( !m_processFrames )
4604 {
4605 return false;
4606 }
4607
4608 m_hasVideo = HasVideo();
4609 m_needDummyVideoFrames = false;
4610
4611 if (!m_hasVideo && (decodetype & kDecodeVideo))
4612 {
4613 // NB This could be an issue if the video stream is not
4614 // detected initially as the video buffers will be filled.
4616 decodetype = (DecodeType)((int)decodetype & ~kDecodeVideo);
4617 m_skipAudio = false;
4618 }
4619
4621
4622 while (!m_allowedQuit)
4623 {
4624 if (decodetype & kDecodeAudio)
4625 {
4626 if (((m_currentTrack[kTrackTypeAudio] < 0) ||
4627 (m_selectedTrack[kTrackTypeAudio].m_av_stream_index < 0)))
4628 {
4629 // disable audio request if there are no audio streams anymore
4630 // and we have video, otherwise allow decoding to stop
4631 if (m_hasVideo)
4632 decodetype = (DecodeType)((int)decodetype & ~kDecodeAudio);
4633 else
4634 m_allowedQuit = true;
4635 }
4636 }
4637 else if ((origDecodetype & kDecodeAudio) &&
4639 (m_selectedTrack[kTrackTypeAudio].m_av_stream_index >= 0))
4640 {
4641 // Turn on audio decoding again if it was on originally
4642 // and an audio stream has now appeared. This can happen
4643 // in still DVD menus with audio
4644 decodetype = (DecodeType)((int)decodetype | kDecodeAudio);
4645 }
4646
4648
4649 if (m_gotVideoFrame)
4650 {
4651 if (decodetype == kDecodeNothing)
4652 {
4653 // no need to buffer audio or video if we
4654 // only care about building a keyframe map.
4655 // NB but allow for data only (MHEG) streams
4656 m_allowedQuit = true;
4657 }
4658 else if ((decodetype & kDecodeAV) == kDecodeAV &&
4659 (m_storedPackets.count() < kMaxVideoQueueSize) &&
4660 // buffer audio to prevent audio buffer
4661 // underruns in case you are setting negative values
4662 // in Adjust Audio Sync.
4665 {
4666 storevideoframes = true;
4667 }
4668 else if (decodetype & kDecodeVideo)
4669 {
4670 if (m_storedPackets.count() >= kMaxVideoQueueSize)
4671 {
4672 LOG(VB_GENERAL, LOG_WARNING, LOC +
4673 QString("Audio %1 ms behind video but already %2 "
4674 "video frames queued. AV-Sync might be broken.")
4675 .arg((m_lastVPts-m_lastAPts).count()).arg(m_storedPackets.count()));
4676 }
4677 m_allowedQuit = true;
4678 continue;
4679 }
4680 }
4681
4682 if (!storevideoframes && m_storedPackets.count() > 0)
4683 {
4684 if (pkt)
4685 av_packet_free(&pkt);
4686 pkt = m_storedPackets.takeFirst();
4687 }
4688 else
4689 {
4690 if (!pkt)
4691 pkt = av_packet_alloc();
4692
4693 int retval = 0;
4694 if (m_ic != nullptr)
4695 retval = ReadPacket(m_ic, pkt, storevideoframes);
4696 if ((m_ic == nullptr) || (retval < 0))
4697 {
4698 if (retval == -EAGAIN)
4699 continue;
4700
4701 SetEof(true);
4702 av_packet_free(&pkt);
4703
4704 if (retval == AVERROR_EOF)
4705 {
4706 // Reaching the end of file isn't an error
4707 LOG(VB_GENERAL, LOG_INFO, QString("decoding reached end of file"));
4708 }
4709 else
4710 {
4711 LOG(VB_GENERAL, LOG_ERR, QString("decoding error %1 (%2)")
4712 .arg(QString::fromStdString(av_make_error_stdstring_unknown(retval)),
4713 QString::number(retval)));
4714 }
4715 return false;
4716 }
4717
4718 if (m_waitingForChange && pkt->pos >= m_readAdjust)
4719 FileChanged();
4720
4721 if (pkt->pos > m_readAdjust)
4722 pkt->pos -= m_readAdjust;
4723 }
4724
4725 if (!m_ic)
4726 {
4727 LOG(VB_GENERAL, LOG_ERR, LOC + "No context");
4728 av_packet_unref(pkt);
4729 continue;
4730 }
4731
4732 if (pkt->stream_index >= (int)m_ic->nb_streams)
4733 {
4734 LOG(VB_GENERAL, LOG_ERR, LOC + "Bad stream");
4735 av_packet_unref(pkt);
4736 continue;
4737 }
4738
4739 AVStream *curstream = m_ic->streams[pkt->stream_index];
4740
4741 if (!curstream)
4742 {
4743 LOG(VB_GENERAL, LOG_ERR, LOC + "Bad stream (NULL)");
4744 av_packet_unref(pkt);
4745 continue;
4746 }
4747
4748 enum AVMediaType codec_type = curstream->codecpar->codec_type;
4749 const AVCodecID codec_id = curstream->codecpar->codec_id;
4750
4751 // Handle AVCodecID values that don't have an AVCodec decoder and
4752 // store video packets
4753 switch (codec_type)
4754 {
4755 case AVMEDIA_TYPE_VIDEO:
4756 if (storevideoframes)
4757 {
4758 m_storedPackets.append(pkt);
4759 pkt = nullptr;
4760 continue;
4761 }
4762 break;
4763 case AVMEDIA_TYPE_AUDIO:
4764 // FFmpeg does not currently have an AC-4 decoder
4765 if (codec_id == AV_CODEC_ID_AC4)
4766 {
4767 av_packet_unref(pkt);
4768 continue;
4769 }
4770 break;
4771 case AVMEDIA_TYPE_SUBTITLE:
4772 switch (codec_id)
4773 {
4774 case AV_CODEC_ID_TEXT:
4776 av_packet_unref(pkt);
4777 continue;
4778 case AV_CODEC_ID_DVB_TELETEXT:
4779 ProcessDVBDataPacket(curstream, pkt);
4780 av_packet_unref(pkt);
4781 continue;
4782 case AV_CODEC_ID_IVTV_VBI:
4783 ProcessVBIDataPacket(curstream, pkt);
4784 av_packet_unref(pkt);
4785 continue;
4786 default:
4787 break;
4788 }
4789 break;
4790 case AVMEDIA_TYPE_DATA:
4791 ProcessDataPacket(curstream, pkt, decodetype);
4792 av_packet_unref(pkt);
4793 continue;
4794 default:
4795 break;
4796 }
4797
4798 // ensure there is an AVCodecContext for this stream
4799 AVCodecContext *context = m_codecMap.GetCodecContext(curstream);
4800 if (context == nullptr)
4801 {
4802 if (codec_type != AVMEDIA_TYPE_VIDEO)
4803 {
4804 LOG(VB_PLAYBACK, LOG_ERR, LOC +
4805 QString("No codec for stream index %1, type(%2) id(%3:%4)")
4806 .arg(QString::number(pkt->stream_index),
4807 AVMediaTypeToString(codec_type),
4808 avcodec_get_name(codec_id),
4809 QString::number(codec_id)
4810 )
4811 );
4812 // Process Stream Change in case we have no audio
4813 if (codec_type == AVMEDIA_TYPE_AUDIO && !m_audio->HasAudioIn())
4814 m_streamsChanged = true;
4815 }
4816 av_packet_unref(pkt);
4817 continue;
4818 }
4819
4820 have_err = false;
4821
4822 switch (codec_type)
4823 {
4824 case AVMEDIA_TYPE_AUDIO:
4825 {
4826 if (!ProcessAudioPacket(context, curstream, pkt, decodetype))
4827 have_err = true;
4828 else
4830 break;
4831 }
4832
4833 case AVMEDIA_TYPE_VIDEO:
4834 {
4835 if (pkt->stream_index != m_selectedTrack[kTrackTypeVideo].m_av_stream_index)
4836 {
4837 break;
4838 }
4839
4840 if (!PreProcessVideoPacket(context, curstream, pkt))
4841 continue;
4842
4843 // If the resolution changed in XXXPreProcessPkt, we may
4844 // have a fatal error, so check for this before continuing.
4845 if (m_parent->IsErrored())
4846 {
4847 av_packet_free(&pkt);
4848 return false;
4849 }
4850
4851 if (pkt->pts != AV_NOPTS_VALUE)
4852 {
4854 (av_q2d(curstream->time_base)*pkt->pts*1000000);
4855 }
4856
4857 if (!(decodetype & kDecodeVideo))
4858 {
4860 m_gotVideoFrame = true;
4861 break;
4862 }
4863
4864 if (!ProcessVideoPacket(context, curstream, pkt, Retry))
4865 have_err = true;
4866 break;
4867 }
4868
4869 case AVMEDIA_TYPE_SUBTITLE:
4870 {
4871 if (!ProcessSubtitlePacket(context, curstream, pkt))
4872 have_err = true;
4873 break;
4874 }
4875
4876 default:
4877 {
4878 LOG(VB_GENERAL, LOG_ERR, LOC +
4879 QString("Decoding - id(%1) type(%2)")
4880 .arg(avcodec_get_name(codec_id),
4881 AVMediaTypeToString(codec_type)));
4882 have_err = true;
4883 break;
4884 }
4885 }
4886
4887 if (!have_err && !Retry)
4888 m_frameDecoded = 1;
4889 av_packet_unref(pkt);
4890 if (Retry)
4891 break;
4892 }
4893
4894 av_packet_free(&pkt);
4895 return true;
4896}
4897
4899{
4900 if (m_streamsChanged)
4901 {
4902 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("StreamChangeCheck skip SeekReset"));
4903 // SeekReset(0, 0, true, true);
4904 ScanStreams(false);
4905 m_streamsChanged = false;
4906 }
4907}
4908
4909int AvFormatDecoder::ReadPacket(AVFormatContext *ctx, AVPacket *pkt, bool &/*storePacket*/)
4910{
4911 m_avCodecLock.lock();
4912 int result = av_read_frame(ctx, pkt);
4913 m_avCodecLock.unlock();
4914 return result;
4915}
4916
4918{
4920 if (pmt_buffer.has_buffer())
4921 {
4922 const ProgramMapTable pmt(PSIPTable(pmt_buffer.data()));
4923
4924 for (uint i = 0; i < pmt.StreamCount(); i++)
4925 {
4926 // MythTV remaps OpenCable Video to normal video during recording
4927 // so "dvb" is the safest choice for system info type, since this
4928 // will ignore other uses of the same stream id in DVB countries.
4929 if (pmt.IsVideo(i, "dvb"))
4930 return true;
4931
4932 // MHEG may explicitly select a private stream as video
4933 if ((i == (uint)m_selectedTrack[kTrackTypeVideo].m_av_stream_index) &&
4934 (pmt.StreamType(i) == StreamID::PrivData))
4935 {
4936 return true;
4937 }
4938 }
4939 }
4940
4941 return GetTrackCount(kTrackTypeVideo) != 0U;
4942}
4943
4945{
4947 {
4949 if (!frame)
4950 return false;
4951
4952 frame->ClearMetadata();
4953 frame->ClearBufferToBlank();
4954
4955 frame->m_dummy = true;
4957 frame->m_frameCounter = m_frameCounter++;
4958
4960 m_parent->DeLimboFrame(frame);
4961
4962 m_decodedVideoFrame = frame;
4964 m_gotVideoFrame = true;
4965 }
4966 return true;
4967}
4968
4970{
4972}
4973
4975{
4976 int stream = m_selectedTrack[kTrackTypeVideo].m_av_stream_index;
4977 if (stream < 0 || !m_ic)
4978 return {};
4979 return avcodec_get_name(m_ic->streams[stream]->codecpar->codec_id);
4980}
4981
4983{
4984 if (m_selectedTrack[kTrackTypeAudio].m_av_stream_index < 0)
4985 {
4986 m_disablePassthru = disable;
4987 return;
4988 }
4989
4990 if (disable != m_disablePassthru)
4991 {
4992 m_disablePassthru = disable;
4993 QString msg = (disable) ? "Disabling" : "Allowing";
4994 LOG(VB_AUDIO, LOG_INFO, LOC + msg + " pass through");
4995
4996 // Force pass through state to be reanalyzed
4998 }
4999}
5000
5002{
5003 QMutexLocker locker(&m_trackLock);
5005}
5006
5007inline bool AvFormatDecoder::DecoderWillDownmix(const AVCodecContext *ctx)
5008{
5009 // Until ffmpeg properly implements dialnorm
5010 // use Myth internal downmixer if machine has SSE2
5012 return false;
5013 // use ffmpeg only for dolby codecs if we have to
5014 //return av_opt_find(ctx->priv_data, "downmix", nullptr, 0, 0);
5015 // av_opt_find was causing segmentation faults, so explicitly list the
5016 // compatible decoders
5017 switch (ctx->codec_id)
5018 {
5019 case AV_CODEC_ID_AC3:
5020 case AV_CODEC_ID_TRUEHD:
5021 case AV_CODEC_ID_EAC3:
5022 case AV_CODEC_ID_MLP:
5023 case AV_CODEC_ID_DTS:
5024 return true;
5025 default:
5026 return false;
5027 }
5028}
5029
5030bool AvFormatDecoder::DoPassThrough(const AVCodecParameters *par, bool withProfile)
5031{
5032 bool passthru = false;
5033
5034 // if withProfile == false, we will accept any DTS stream regardless
5035 // of its profile. We do so, so we can bitstream DTS-HD as DTS core
5036 if (!withProfile && par->codec_id == AV_CODEC_ID_DTS && !m_audio->CanDTSHD())
5037 {
5038 passthru = m_audio->CanPassthrough(par->sample_rate, par->ch_layout.nb_channels,
5039 par->codec_id, AV_PROFILE_DTS);
5040 }
5041 else
5042 {
5043 passthru = m_audio->CanPassthrough(par->sample_rate, par->ch_layout.nb_channels,
5044 par->codec_id, par->profile);
5045 }
5046
5047 passthru &= !m_disablePassthru;
5048
5049 return passthru;
5050}
5051
5058{
5059 AudioInfo info; // no_audio
5060 AVStream *curstream = nullptr;
5061 AVCodecContext *ctx = nullptr;
5062 AudioInfo old_in = m_audioIn;
5063 int requested_channels = 0;
5064
5065 if ((m_currentTrack[kTrackTypeAudio] >= 0) && m_ic &&
5066 (m_selectedTrack[kTrackTypeAudio].m_av_stream_index <=
5067 (int) m_ic->nb_streams))
5068 {
5069 curstream = m_ic->streams[m_selectedTrack[kTrackTypeAudio]
5070 .m_av_stream_index];
5071 if (curstream != nullptr)
5072 ctx = m_codecMap.GetCodecContext(curstream);
5073 }
5074
5075 if (ctx == nullptr)
5076 {
5077 if (!m_tracks[kTrackTypeAudio].empty())
5078 LOG(VB_PLAYBACK, LOG_INFO, LOC + "No codec context. Returning false");
5079 return false;
5080 }
5081
5082 AudioFormat fmt =
5084 ctx->bits_per_raw_sample);
5085
5086 if (av_sample_fmt_is_planar(ctx->sample_fmt))
5087 {
5088 LOG(VB_AUDIO, LOG_INFO, LOC + QString("Audio data is planar"));
5089 }
5090
5091 if (fmt == FORMAT_NONE)
5092 {
5093 int bps = av_get_bytes_per_sample(ctx->sample_fmt) << 3;
5094 if (ctx->sample_fmt == AV_SAMPLE_FMT_S32 &&
5095 ctx->bits_per_raw_sample)
5096 bps = ctx->bits_per_raw_sample;
5097 LOG(VB_GENERAL, LOG_ERR, LOC +
5098 QString("Unsupported sample format with %1 bits").arg(bps));
5099 return false;
5100 }
5101
5102 bool using_passthru = DoPassThrough(curstream->codecpar, false);
5103
5104 requested_channels = ctx->ch_layout.nb_channels;
5105
5106 if (!using_passthru &&
5107 ctx->ch_layout.nb_channels > (int)m_audio->GetMaxChannels() &&
5108 DecoderWillDownmix(ctx))
5109 {
5110 requested_channels = m_audio->GetMaxChannels();
5111
5112 AVChannelLayout channel_layout;
5113 av_channel_layout_default(&channel_layout, requested_channels);
5114 av_opt_set_chlayout(ctx->priv_data, "downmix", &channel_layout, 0);
5115 }
5116
5117 info = AudioInfo(ctx->codec_id, fmt, ctx->sample_rate,
5118 requested_channels, using_passthru, ctx->ch_layout.nb_channels,
5119 ctx->codec_id == AV_CODEC_ID_DTS ? ctx->profile : 0);
5120 if (info == m_audioIn)
5121 return false;
5122
5123 LOG(VB_AUDIO, LOG_INFO, LOC + "Initializing audio parms from " +
5124 QString("audio track #%1").arg(m_currentTrack[kTrackTypeAudio]+1));
5125
5127
5128 LOG(VB_AUDIO, LOG_INFO, LOC + "Audio format changed " +
5129 QString("\n\t\t\tfrom %1 to %2")
5130 .arg(old_in.toString(), m_audioOut.toString()));
5131
5132 m_audio->SetAudioParams(m_audioOut.format, ctx->ch_layout.nb_channels,
5133 requested_channels,
5137 AudioOutput *audioOutput = m_audio->GetAudioOutput();
5138 if (audioOutput)
5139 audioOutput->SetSourceBitrate(ctx->bit_rate);
5140
5141 if (LCD *lcd = LCD::Get())
5142 {
5143 LCDAudioFormatSet audio_format = AUDIO_MP3;
5144
5145 switch (ctx->codec_id)
5146 {
5147 case AV_CODEC_ID_MP2:
5148 audio_format = AUDIO_MPEG2;
5149 break;
5150 case AV_CODEC_ID_MP3:
5151 audio_format = AUDIO_MP3;
5152 break;
5153 case AV_CODEC_ID_AC3:
5154 audio_format = AUDIO_AC3;
5155 break;
5156 case AV_CODEC_ID_DTS:
5157 audio_format = AUDIO_DTS;
5158 break;
5159 case AV_CODEC_ID_VORBIS:
5160 audio_format = AUDIO_OGG;
5161 break;
5162 case AV_CODEC_ID_WMAV1:
5163 audio_format = AUDIO_WMA;
5164 break;
5165 case AV_CODEC_ID_WMAV2:
5166 audio_format = AUDIO_WMA2;
5167 break;
5168 default:
5169 audio_format = AUDIO_WAV;
5170 break;
5171 }
5172
5173 lcd->setAudioFormatLEDs(audio_format, true);
5174
5176 lcd->setVariousLEDs(VARIOUS_SPDIF, true);
5177 else
5178 lcd->setVariousLEDs(VARIOUS_SPDIF, false);
5179
5180 switch (m_audioIn.m_channels)
5181 {
5182 case 0:
5183 /* nb: aac and mp3 seem to be coming up 0 here, may point to an
5184 * avformatdecoder audio channel handling bug, per janneg */
5185 case 1:
5186 case 2:
5187 /* all audio codecs have at *least* one channel, but
5188 * LR is the fewest LED we can light up */
5189 lcd->setSpeakerLEDs(SPEAKER_LR, true);
5190 break;
5191 case 3:
5192 case 4:
5193 case 5:
5194 case 6:
5195 lcd->setSpeakerLEDs(SPEAKER_51, true);
5196 break;
5197 default:
5198 lcd->setSpeakerLEDs(SPEAKER_71, true);
5199 break;
5200 }
5201
5202 }
5203 return true;
5204}
5205
5207{
5208 int64_t start_time = INT64_MAX;
5209 int64_t end_time = INT64_MIN;
5210 AVStream *st = nullptr;
5211
5212 for (uint i = 0; i < ic->nb_streams; i++)
5213 {
5214 AVStream *st1 = ic->streams[i];
5215 if (st1 && st1->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5216 {
5217 st = st1;
5218 break;
5219 }
5220 }
5221 if (!st)
5222 return;
5223
5224 int64_t duration = INT64_MIN;
5225 if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {
5226 int64_t start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
5227 start_time = std::min(start_time1, start_time);
5228 if (st->duration != AV_NOPTS_VALUE) {
5229 int64_t end_time1 = start_time1 +
5230 av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
5231 end_time = std::max(end_time1, end_time);
5232 }
5233 }
5234 if (st->duration != AV_NOPTS_VALUE) {
5235 int64_t duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
5236 duration = std::max(duration1, duration);
5237 }
5238 if (start_time != INT64_MAX) {
5239 ic->start_time = start_time;
5240 if (end_time != INT64_MIN) {
5241 duration = std::max(end_time - start_time, duration);
5242 }
5243 }
5244 if (duration != INT64_MIN) {
5245 ic->duration = duration;
5246 if (!ic->pb)
5247 return;
5248 int64_t filesize = avio_size(ic->pb);
5249 if (filesize > 0) {
5250 /* compute the bitrate */
5251 ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE /
5252 (double)ic->duration;
5253 }
5254 }
5255}
5256
5258{
5259 if (m_currentTrack[type] < 0 || static_cast<size_t>(m_currentTrack[type]) >= m_tracks[type].size())
5260 {
5261 return -1;
5262 }
5263 return m_tracks[type][m_currentTrack[type]].m_av_stream_index;
5264}
5265
5267{
5268 if (m_ic == nullptr)
5269 {
5270 return nullptr;
5271 }
5272 AVProgram* program = av_find_program_from_stream(m_ic, nullptr, get_current_AVStream_index(kTrackTypeAudio));
5273 if (program == nullptr)
5274 {
5275 program = av_find_program_from_stream(m_ic, nullptr, get_current_AVStream_index(kTrackTypeVideo));
5276 }
5277 return program;
5278}
5279
5280/* 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.
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
bool GetBoolSetting(const QString &key, bool defaultval=false)
int NumMenuButtons(void) const
void GetMenuSPUPkt(uint8_t *Buffer, int Size, int StreamID, uint32_t StartTime)
Get SPU pkt from dvd menu subtitle stream.
int GetAudioTrackNum(uint StreamId)
get the logical track index (into PGC_AST_CTL) of the element that maps the given physical stream id.
bool AudioStreamsChanged(void) const
bool DecodeSubtitles(AVSubtitle *Subtitle, int *GotSubtitles, const uint8_t *SpuPkt, int BufSize, uint32_t StartTime)
generate dvd subtitle bitmap or dvd menu bitmap.
float GetAspectOverride(void) const
static void Populate(class MythVideoFrame *Frame, struct AVFrame *AvFrame)
Create, update or destroy HDR metadata for the given MythVideoFrame.
long long GetRealFileSize(void) const
void UpdateRawBitrate(uint RawBitrate)
Set the raw bit rate, to allow RingBuffer adjust effective bitrate.
virtual void IgnoreWaitStates(bool)
virtual bool IsInStillFrame(void) const
bool IsDisc(void) const
void SetBufferSizeFactors(bool EstBitrate, bool Matroska)
Tells RingBuffer that the raw bitrate may be inaccurate and the underlying container is matroska,...
virtual bool IsStreamed(void)
bool IsDVD(void) const
virtual int BestBufferSize(void)
virtual bool StartFromBeginning(void)
const MythDVDBuffer * DVD(void) const
virtual bool IsInDiscMenuOrStillFrame(void) const
virtual long long GetReadPosition(void) const =0
int GetReadBufAvail(void) const
Returns number of bytes available for reading from buffer.
QString GetFilename(void) const
void SetDuration(std::chrono::seconds duration)
Definition: mythplayer.cpp: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:149
bool m_deinterlaceInuse2x
Definition: mythframe.h:161
int m_colortransfer
Definition: mythframe.h:150
bool m_pauseFrame
Definition: mythframe.h:140
bool m_directRendering
Definition: mythframe.h:145
uint64_t m_frameCounter
Definition: mythframe.h:129
FramePitches m_pitches
Definition: mythframe.h:141
uint8_t * m_buffer
Definition: mythframe.h:119
bool m_topFieldFirst
Definition: mythframe.h:134
bool m_alreadyDeinterlaced
Definition: mythframe.h:153
float m_aspect
Definition: mythframe.h:126
MythDeintType m_deinterlaceInuse
Definition: mythframe.h:160
void ClearBufferToBlank()
Definition: mythframe.cpp:205
FrameOffsets m_offsets
Definition: mythframe.h:142
void SetInput(QSize Size, float Framerate=0, const QString &CodecName=QString(), const QStringList &DisallowedDecoders=QStringList())
uint GetMaxCPUs() const
QString GetDecoder() const
bool IsSkipLoopEnabled() const
A PSIP table is a variant of a PES packet containing an MPEG, ATSC or DVB table.
Definition: mpegtables.h:410
Holds information on recordings and videos.
Definition: programinfo.h: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:518
uint StreamInfoLength(uint i) const
Definition: mpegtables.h:727
float aspect(bool mpeg1) const
Returns the screen aspect ratio.
Definition: pespacket.cpp:234
@ PrivData
ISO 13818-1 PES private data & ITU H.222.0.
Definition: mpegtables.h:147
static bool IsObjectCarousel(uint type)
Returns true iff stream contains DSMCC Object Carousel.
Definition: mpegtables.h:190
uint m_language_index
Audio, Subtitle, Teletext.
Definition: decoderbase.h:107
int m_av_stream_index
Definition: decoderbase.h:103
int m_language
ISO639 canonical language key; Audio, Subtitle, CC, Teletext, RawText.
Definition: decoderbase.h:106
int m_av_substream_index
Audio only; -1 for no substream, 0 for first dual audio stream, 1 for second dual.
Definition: decoderbase.h:111
int m_stream_id
Definition: decoderbase.h:104
bool AddAVSubtitle(AVSubtitle &subtitle, bool fix_position, bool is_selected_forced_track, bool allow_forced, bool isExternal)
void AddRawTextSubtitle(const QStringList &list, std::chrono::milliseconds duration)
void Decode(const unsigned char *buf, int vbimode)
Decodes teletext data.
int GetDecoderType(void) const
static bool ReinitBuffer(MythVideoFrame *Frame, VideoFrameType Type, MythCodecID CodecID, int Width, int Height)
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 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:109
int iso639_key_to_canonical_key(int iso639_2)
Definition: iso639.cpp:118
QString iso639_str2_to_str3(const QString &str2)
Definition: iso639.cpp:68
ISO 639-1 and ISO 639-2 support functions.
static int iso639_str3_to_key(const unsigned char *iso639_2)
Definition: iso639.h:60
static bool iso639_is_key_undefined(int code)
Returns true if the key is 0, 0xFFFFFF, or 'und'.
Definition: iso639.h:54
unsigned short uint16_t
Definition: iso6937tables.h:3
@ SPEAKER_LR
Definition: lcddevice.h:97
@ SPEAKER_71
Definition: lcddevice.h:99
@ SPEAKER_51
Definition: lcddevice.h:98
LCDAudioFormatSet
Definition: lcddevice.h:103
@ AUDIO_OGG
Definition: lcddevice.h:107
@ AUDIO_MPEG2
Definition: lcddevice.h:111
@ AUDIO_AC3
Definition: lcddevice.h:112
@ AUDIO_WAV
Definition: lcddevice.h:109
@ AUDIO_MP3
Definition: lcddevice.h:106
@ AUDIO_DTS
Definition: lcddevice.h:113
@ AUDIO_WMA
Definition: lcddevice.h:114
@ AUDIO_WMA2
Definition: lcddevice.h:108
LCDVideoFormatSet
Definition: lcddevice.h:118
@ VIDEO_XVID
Definition: lcddevice.h:122
@ VIDEO_WMV
Definition: lcddevice.h:123
@ VIDEO_MPG
Definition: lcddevice.h:120
@ VIDEO_DIVX
Definition: lcddevice.h:121
@ VARIOUS_SPDIF
Definition: lcddevice.h:151
@ VARIOUS_HDTV
Definition: lcddevice.h:150
std::vector< const unsigned char * > desc_list_t
char * av_make_error_stdstring(std::string &errbuf, int errnum)
A C++ equivalent to av_make_error_string.
Definition: mythaverror.cpp:42
MTV_PUBLIC std::string av_make_error_stdstring_unknown(int errnum)
Definition: mythaverror.h:47
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::milliseconds > millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:91
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::seconds > secondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:80
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::microseconds > microsecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:102
QString get_decoder_name(MythCodecID codec_id)
uint mpeg_version(AVCodecID codec_id)
static bool codec_is_std(MythCodecID id)
Definition: mythcodecid.h:296
MythCodecID
Definition: mythcodecid.h:14
@ kCodec_NONE
Definition: mythcodecid.h:17
@ kCodec_MPEG1
Definition: mythcodecid.h:24
@ kCodec_MPEG2
Definition: mythcodecid.h:25
static bool CODEC_IS_H264(AVCodecID id)
Definition: mythcodecid.h:384
static bool CODEC_IS_MPEG(AVCodecID id)
Definition: mythcodecid.h:386
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
@ DEINT_NONE
Definition: mythframe.h:68
static constexpr uint8_t MYTH_WIDTH_ALIGNMENT
Definition: mythframe.h:16
VideoFrameType
Definition: mythframe.h:20
static constexpr uint8_t MYTH_HEIGHT_ALIGNMENT
Definition: mythframe.h:17
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
static bool VERBOSE_LEVEL_NONE()
Definition: mythlogging.h:28
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
PlayerFlags
Definition: mythplayer.h: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:74
QString intToPaddedString(int n, int width=2)
Creates a zero padded string representation of an integer.
Definition: stringutil.h:27
dictionary info
Definition: azlyrics.py:7
string version
Definition: giantbomb.py:185
def error(message)
Definition: smolt.py:409
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
Definition: mythchrono.h:55
int64_t ptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:78
@ MARK_GOP_BYFRAME
Definition: programtypes.h:63
@ VBI_DVB_SUBTITLE
< DVB packet
Definition: vbilut.h: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