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