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