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"
29#include "libmythbase/mythconfig.h"
31#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
32#include <QtSystemDetection>
33#include <QtVersionChecks>
38#include "libavcodec/jni.h"
40#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
41#include <QtAndroidExtras>
43#include <QJniEnvironment>
44#define QAndroidJniEnvironment QJniEnvironment
72#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
75#include <QStringDecoder>
119using namespace std::string_view_literals;
121#define LOC QString("AFD: ")
131#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
139 return {ctx.width >> ctx.lowres, ctx.height >> ctx.lowres};
143 float aspect_ratio = 0.0F;
145 if (ctx.sample_aspect_ratio.num && ctx.height)
147 aspect_ratio = av_q2d(ctx.sample_aspect_ratio) *
148 static_cast<double>(ctx.width);
149 aspect_ratio /= (float) ctx.height;
152 if (aspect_ratio <= 0.0F || aspect_ratio > 6.0F)
155 aspect_ratio = (float)ctx.width / (
float)ctx.height;
157 aspect_ratio = 4.0F / 3.0F;
164 static constexpr float kDefaultAspect = 4.0F / 3.0F;
165 int asp =
p.aspectRatio();
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;
175 float aspect_ratio = asp * 0.000001F;
176 if (aspect_ratio <= 0.0F || aspect_ratio > 6.0F)
178 if (
p.pictureHeight() &&
p.pictureWidth())
181 (float)
p.pictureWidth() /(float)
p.pictureHeight();
185 aspect_ratio = kDefaultAspect;
206#define FAIL(errmsg) do { \
207 LOG(VB_PLAYBACK, LOG_INFO, LOC + (errmsg)); \
218 switch (Stream->codecpar->codec_type)
222 case AVMEDIA_TYPE_VIDEO:
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");
235 case AVMEDIA_TYPE_AUDIO:
237 FAIL(
"No codec for audio stream");
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");
259 case AVMEDIA_TYPE_DATA:
260 if (Stream->codecpar->codec_id == AV_CODEC_ID_NONE)
267 if (Stream->codecpar->codec_id == AV_CODEC_ID_NONE)
268 FAIL(
"Unknown codec");
272static void myth_av_log(
void *ptr,
int level,
const char* fmt, va_list vl)
277 static QString s_fullLine(
"");
278 static QMutex s_stringLock;
279 uint64_t verbose_mask = VB_LIBAV;
280 LogLevel_t verbose_level = LOG_EMERG;
286 verbose_level = LOG_EMERG;
287 verbose_mask |= VB_GENERAL;
290 verbose_level = LOG_CRIT;
291 verbose_mask |= VB_GENERAL;
294 verbose_level = LOG_ERR;
297 verbose_level = LOG_WARNING;
300 verbose_level = LOG_INFO;
304 verbose_level = LOG_DEBUG;
307 verbose_level = LOG_TRACE;
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'));
324 s_fullLine += QString::vasprintf(fmt, vl);
325 if (s_fullLine.endsWith(
"\n"))
327 LOG(verbose_mask, verbose_level, s_fullLine.trimmed());
328 s_fullLine.truncate(0);
330 s_stringLock.unlock();
335 if (lang_cstr[0] ==
'\0' || lang_cstr[1] ==
'\0')
339 if (lang_cstr[2] ==
'\0')
341 QString tmp2 = lang_cstr;
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";
375 m_playerFlags(flags),
380 m_itv(parent->GetInteractiveTV()),
381 m_audioSamples((uint8_t *)av_mallocz(
AudioOutput::kMaxSizeBuffer))
395 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"PlayerFlags: 0x%1, AudioReadAhead: %2 msec")
404 av_packet_free(&pkt);
422 lcd->setAudioFormatLEDs(
AUDIO_AC3,
false);
423 lcd->setVideoFormatLEDs(
VIDEO_MPG,
false);
440 for (
uint i = 0; i <
m_ic->nb_streams; i++)
442 AVStream *st =
m_ic->streams[i];
458 avformat_close_input(&
m_ic);
464static int64_t
lsb3full(int64_t lsb, int64_t base_ts,
int lsb_bits)
466 int64_t mask = (lsb_bits < 64) ? (1LL<<lsb_bits)-1 : -1LL;
467 return ((lsb - base_ts)&mask);
472 int64_t start_pts = 0;
474 AVStream *st =
nullptr;
475 for (
uint i = 0; i <
m_ic->nb_streams; i++)
477 AVStream *st1 =
m_ic->streams[i];
478 if (st1 && st1->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
487 if (
m_ic->start_time != AV_NOPTS_VALUE)
489 start_pts = av_rescale(
m_ic->start_time,
491 AV_TIME_BASE * (int64_t)st->time_base.num);
494 int64_t
pts = av_rescale(timecode.count() / 1000.0,
505 std::chrono::milliseconds timecode)
507 int64_t start_pts = 0;
509 if (
m_ic->start_time != AV_NOPTS_VALUE)
511 start_pts = av_rescale(
m_ic->start_time,
513 AV_TIME_BASE * (int64_t)st->time_base.num);
516 int64_t
pts = av_rescale(timecode.count() / 1000.0,
529 return m_ic->nb_chapters;
539 for (
int i = 0; i < total; i++)
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 /
546 times.push_back(std::chrono::seconds((
long long)total_secs));
555 for (
int i = (
m_ic->nb_chapters - 1); i > -1 ; i--)
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 /
562 auto framenum = (
long long)(total_secs *
m_fps);
563 if (framesPlayed >= framenum)
565 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
566 QString(
"GetCurrentChapter(selected chapter %1 framenum %2)")
567 .arg(i + 1).arg(framenum));
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 /
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));
592 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DoRewind(%1, %2 discard frames)")
593 .arg(desiredFrame).arg( discardFrames ?
"do" :
"don't" ));
599 return do_av_seek(desiredFrame, discardFrames, AVSEEK_FLAG_BACKWARD);
604 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
605 QString(
"DoFastForward(%1 (%2), %3 discard frames)")
607 .arg((discardFrames) ?
"do" :
"don't"));
615 if (seekDelta >= 0 && seekDelta < 2 && m_parent->GetPlaySpeed() == 0.0F)
621 return do_av_seek(desiredFrame, discardFrames, 0);
627 if (
m_ic->start_time != AV_NOPTS_VALUE)
628 ts =
m_ic->start_time;
631 long double seekts = desiredFrame * AV_TIME_BASE /
m_fps;
632 ts += (
long long)seekts;
639 flags |= AVSEEK_FLAG_BACKWARD;
642 int ret = av_seek_frame(
m_ic, -1, ts, flags);
645 LOG(VB_GENERAL, LOG_ERR,
LOC +
646 QString(
"av_seek_frame(m_ic, -1, %1, 0b%2) error: %3").arg(
648 QString::number(flags, 2),
655 reader->SeekFrame(ts, flags);
657 int normalframes = 0;
675 bool doflush,
bool discardFrames)
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"));
704 avformat_flush(
m_ic);
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;
717 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"SeekReset() flushing");
718 for (
uint i = 0; i <
m_ic->nb_streams; i++)
724 if (codecContext && codecContext->internal)
725 avcodec_flush_buffers(codecContext);
732 av_packet_free(&pkt);
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)
763 QElapsedTimer getframetimer;
764 getframetimer.start();
766 while (retry && !getframetimer.hasExpired(100))
771 std::this_thread::sleep_for(1ms);
779 if (!exactSeeks && profileFrames >= 5 && profileFrames < 10)
781 const int giveUpPredictionMs = 400;
782 int remainingTimeMs =
783 skipFrames * (float)begin.
elapsed().count() / profileFrames;
784 if (remainingTimeMs > giveUpPredictionMs)
786 LOG(VB_PLAYBACK, LOG_DEBUG,
787 QString(
"Frame-by-frame seeking would take "
788 "%1 ms to finish, skipping.").arg(remainingTimeMs));
805 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
806 QString(
"Resetting byte context eof (livetv %1 was eof %2)")
808 m_ic->pb->eof_reached = 0;
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));
825 if (reset_video_data)
835 memset(&probe, 0,
sizeof(AVProbeData));
837 QByteArray fname =
filename.toLatin1();
838 probe.filename = fname.constData();
839 probe.buf = (
unsigned char *)testbuf.data();
840 probe.buf_size = testbuf.size();
842 int score = AVPROBE_SCORE_MAX/4;
854 memset(probe.buf + probe.buf_size, 0, AVPROBE_PADDING_SIZE);
856 return av_probe_input_format2(&probe,
static_cast<int>(
true), &score) !=
nullptr;
863 int cnt = decoder->
m_ic->nb_streams;
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)));
869 auto* program = decoder->get_current_AVProgram();
870 if (program !=
nullptr && program->id != avprogram_id)
874 decoder->m_streamsChanged =
true;
911 const AVInputFormat *fmt =
nullptr;
913 QByteArray fnamea = fnames.toLatin1();
914 const char *
filename = fnamea.constData();
917 memset(&probe, 0,
sizeof(AVProbeData));
919 probe.buf =
reinterpret_cast<unsigned char *
>(testbuf.data());
921 probe.buf_size = testbuf.size();
924 memset(probe.buf + probe.buf_size, 0, AVPROBE_PADDING_SIZE);
926 fmt = av_probe_input_format(&probe,
static_cast<int>(
true));
929 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Probe failed for '%1'").arg(
filename));
933 if (strcmp(fmt->name,
"mpegts") == 0 &&
936 const AVInputFormat *fmt2 = av_find_input_format(
"mpegts-ffmpeg");
940 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Using FFmpeg MPEG-TS demuxer (forced)");
945 bool scancomplete =
false;
946 int remainingscans = 5;
948 while (!scancomplete && remainingscans--)
962 while (!found && --retries)
964 m_ic = avformat_alloc_context();
967 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Could not allocate format context.");
974 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
975 QString(
"Buffer size: %1 Streamed %2 Seekable %3 Available %4")
978 .arg(
m_ic->pb->seekable)
982 err = avformat_open_input(&
m_ic,
filename, fmt,
nullptr);
986 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Failed to open input ('%1')")
994 QThread::usleep(100000);
1000 if (strcmp(fmt->name,
"mpegts") == 0)
1002 fmt = av_find_input_format(
"mpegts-ffmpeg");
1005 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Attempting to use original FFmpeg MPEG-TS demuxer.");
1018 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Fatal error opening input. Aborting");
1030 m_ic->max_analyze_duration = 60LL * AV_TIME_BASE;
1034 err = avformat_find_stream_info(
m_ic,
nullptr);
1038 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Could not find codec parameters for '%1'").arg(
filename));
1045 scancomplete =
true;
1050 scancomplete =
false;
1054 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Stream scan incomplete - retrying");
1055 QThread::usleep(250000);
1063 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Scan incomplete - playback may not work");
1066 m_ic->stream_change_data =
this;
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))
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)
1104 if (initialVideo >= 0)
1125 std::chrono::seconds dur = 0s;
1134 dur = duration_cast<std::chrono::seconds>(av_duration(
m_ic->duration));
1145 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1146 "Recording has no position -- using libavformat seeking.");
1155 float bytespersec = (float)
m_bitrate / 8 / 2;
1158 (int)(secs *
static_cast<float>(
m_fps)));
1167 if (strcmp(fmt->name,
"avi") == 0)
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)")
1188 for (
unsigned int i=0; i <
m_ic->nb_chapters; i++)
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);
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")
1201 QString::number(framenum)));
1214 Reset(
true,
true,
true);
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);
1230 double container_fps = (Stream->time_base.num == 0) ? 0.0 : av_q2d(av_inv_q(Stream->time_base));
1232 double estimated_fps = (Stream->r_frame_rate.den == 0) ? 0.0 : av_q2d(Stream->r_frame_rate);
1236 static const std::vector<double> k_standard_rates =
1256 std::vector<double> rates;
1261 if (QString(
m_ic->iformat->name).contains(
"matroska") ||
1262 QString(
m_ic->iformat->name).contains(
"mov"))
1264 rates.emplace_back(avg_fps);
1268 if (QString(
m_ic->iformat->name).contains(
"avi"))
1270 rates.emplace_back(container_fps);
1273 rates.emplace_back(codec_fps);
1274 rates.emplace_back(container_fps);
1275 rates.emplace_back(avg_fps);
1277 rates.emplace_back(estimated_fps);
1279 rates.emplace_back(30000.0 / 1001.0);
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());
1284 auto FuzzyEquals = [](
double First,
double Second) {
return std::abs(First - Second) < 0.03; };
1287 if (!FuzzyEquals(rates.front(),
m_fps))
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));
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));
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(
' ')));
1309 auto IsStandard = [&FuzzyEquals](
double Rate)
1311 if (Rate > 23.0 && Rate < 121.0)
1313 for (
auto standard_rate : k_standard_rates)
1314 if (FuzzyEquals(Rate, standard_rate))
1322 auto NearestStandardFrameRate = [](
double rate,
double epsilon)
1324 double result = rate;
1325 double lowest_delta = rate;
1326 for (
auto standard_rate : k_standard_rates)
1328 double delta = std::abs(rate - standard_rate);
1329 if ((delta < lowest_delta) && (delta <
epsilon))
1331 lowest_delta = delta;
1332 result = standard_rate;
1339 double detected = rates.front();
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));
1351 if (Sanitise && !IsStandard(detected))
1353 for (
auto rate : rates)
1355 if (IsStandard(rate))
1357 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"%1 is non-standard - using %2 instead.")
1358 .arg(rates.front()).arg(rate));
1366 if (rate > 33.0 && detected < 33.0)
1368 double half = rate / 2.0;
1369 if (std::abs(half - detected) < (half * 0.1))
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);
1377 return static_cast<float>(rate);
1382 return static_cast<float>(detected);
1387 switch (Context->codec_id)
1389 case AV_CODEC_ID_H264:
1392 if (Context->extradata && (Context->extradata_size >= 7))
1395 if (Context->extradata[0] == 1)
1406 parser.parse_SPS(Context->extradata + offset,
1407 static_cast<uint>(Context->extradata_size - offset), dummy, result);
1412 case AV_CODEC_ID_H265:
return 16;
1413 case AV_CODEC_ID_VP9:
return 8;
1414 case AV_CODEC_ID_VP8:
return 3;
1420 bool selectedStream)
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),
1426 .arg(codecContext->width).arg(codecContext->height));
1431 codecContext->opaque =
static_cast<void*
>(
this);
1433 codecContext->slice_flags = 0;
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;
1442 const AVCodec *codec1 = codecContext->codec;
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);
1451 m_videoRotation =
static_cast<int>(-av_display_rotation_get(
reinterpret_cast<int32_t*
>(sd->data)));
1456 sd = av_packet_side_data_get(stream->codecpar->coded_side_data,
1457 stream->codecpar->nb_coded_side_data, AV_PKT_DATA_STEREO3D);
1460 auto * avstereo =
reinterpret_cast<AVStereo3D*
>(sd->data);
1485 bool doublerate =
true;
1489 if (codec1 && ((AV_CODEC_ID_MPEG2VIDEO == codec1->id) ||
1490 (AV_CODEC_ID_MPEG1VIDEO == codec1->id)))
1494 int total_blocks = (codecContext->height + 15) / 16;
1495 codecContext->skip_top = (total_blocks + 3) / 4;
1496 codecContext->skip_bottom = (total_blocks + 3) / 4;
1500 codecContext->lowres = 2;
1504 codecContext->flags &= ~AV_CODEC_FLAG_LOOP_FILTER;
1505 codecContext->skip_loop_filter = AVDISCARD_ALL;
1509 codecContext->skip_idct = AVDISCARD_ALL;
1521 if (!width || !height)
1523 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1524 "InitVideoCodec invalid dimensions, resetting decoder.");
1532 const AVCodec *codec2 = codecContext->codec;
1535 codecName = codec2->name;
1543 switch (codecContext->codec_id)
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:
1554 case AV_CODEC_ID_WMV1:
1555 case AV_CODEC_ID_WMV2:
1559 case AV_CODEC_ID_XVID:
1568 lcd->setVideoFormatLEDs(video_format,
true);
1580 static constexpr std::array<uint8_t, 256> odd_parity_LUT
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,
1599 bool ret = (odd_parity_LUT[data & 0xff] == 1) &&
1600 (odd_parity_LUT[(data & 0xff00) >> 8] == 1);
1603 LOG(VB_VBI, LOG_ERR,
LOC +
1604 QString(
"VBI: Bad parity in EIA-608 data (%1)") .arg(data,0,16));
1611 if (program ==
nullptr)
1615 return program->pmt_section;
1620 AVProgram* program = av_find_program_from_stream(context,
nullptr, stream_index);
1634 if (!pmt_buffer.has_buffer())
1636 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1637 "ScanATSCCaptionStreams() called with no PMT");
1642 bool video_found =
false;
1666 desc_list.insert(desc_list.end(), desc_list2.begin(), desc_list2.end());
1668 for (
auto & desc : desc_list)
1710 std::array<std::map<int,uint>,2> lang_cc_cnt;
1727 else if (!pofr && sofr)
1753 LOG(VB_GENERAL, LOG_ERR,
LOC +
"in_tracks key too small");
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")
1777 AVStream* st =
m_ic->streams[av_index];
1778 const AVDictionaryEntry* language_dictionary_entry =
1779 av_dict_get(st->metadata,
"language",
nullptr, 0);
1781 if (language_dictionary_entry ==
nullptr ||
1782 language_dictionary_entry->value ==
nullptr ||
1783 st->codecpar->extradata ==
nullptr
1789 std::vector<std::string_view> languages {
StringUtil::split_sv(language_dictionary_entry->value,
","sv)};
1791 if (st->codecpar->extradata_size !=
static_cast<int>(languages.size() * 2))
1795 for (
size_t i = 0; i < languages.size(); i++)
1797 if (languages[i].size() != 3)
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)
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",
1820 QString::number(teletext_magazine_number),
1821 QString::number(teletext_page_number)));
1830 AVDictionaryEntry *metatag =
1831 av_dict_get(
m_ic->streams[av_stream_index]->metadata,
"language",
nullptr,
1833 bool forced = (
m_ic->streams[av_stream_index]->disposition & AV_DISPOSITION_FORCED) != 0;
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.")
1841 StreamInfo si {av_stream_index, 0, lang, 0, forced};
1851 if (
m_itv ==
nullptr)
1853 if (
m_itv ==
nullptr)
1857 if (!pmt_buffer.has_buffer())
1868 LOG(VB_DSMCC, LOG_NOTICE, QString(
"ScanDSMCCStreams Found Object Carousel in Stream %1").arg(QString::number(i)));
1874 for (
const auto *desc : desc_list)
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)
1884 while (desc != endDesc)
1886 [[maybe_unused]]
uint appTypeCode = desc[0]<<8 | desc[1];
1888 uint appSpecDataLen = *desc++;
1890 LOG(VB_DSMCC, LOG_NOTICE, QString(
"ScanDSMCCStreams AppTypeCode %1").arg(QString::number(appTypeCode)));
1891 if (appTypeCode == 0x101)
1893 const unsigned char *subDescEnd = desc + appSpecDataLen;
1894 while (desc < subDescEnd)
1896 uint sub_desc_tag = *desc++;
1897 uint sub_desc_len = *desc++;
1899 if (sub_desc_tag == 1)
1900 m_itv->SetNetBootInfo(desc, sub_desc_len);
1901 desc += sub_desc_len;
1907 desc += appSpecDataLen;
1921 const AVCodec *codec =
nullptr;
1922 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Trying to select best video track");
1936 int stream_index = av_find_best_stream(
m_ic, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);
1938 if (stream_index < 0)
1940 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"No video track found/selected.");
1941 return stream_index;
1944 AVStream *stream =
m_ic->streams[stream_index];
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),
1963 QString::number(codecContext->bit_rate)));
1970 if ((codecContext->width != stream->codecpar->width) || (codecContext->height != stream->codecpar->height))
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)
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;
1987 if (codecContext->codec)
1988 codecName = codecContext->codec->name;
1993 if (codecContext->framerate.den && codecContext->framerate.num)
1994 m_fps = float(codecContext->framerate.num) / float(codecContext->framerate.den);
1998 bool foundgpudecoder =
false;
1999 QStringList unavailabledecoders;
2009 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
2010 "GPU/hardware decoder '%1' failed - forcing software decode")
2017 while (unavailabledecoders.size() < 10)
2021 if (!unavailabledecoders.isEmpty())
2023 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Unavailable decoders: %1")
2024 .arg(unavailabledecoders.join(
",")));
2030 if (!skip_loop_filter)
2031 codecContext->skip_loop_filter = AVDISCARD_NONKEY;
2039 if (
version && allowgpu && dec !=
"ffmpeg")
2043 codecContext->opaque =
static_cast<void*
>(
this);
2048 codecContext->opaque =
static_cast<void*
>(
this);
2050 foundgpudecoder =
true;
2055 unavailabledecoders.append(dec);
2063 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unknown video codec - defaulting to MPEG2");
2078 if (!foundgpudecoder)
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);
2096 return stream_index;
2101 AVProgram* program = av_find_program_from_stream(
m_ic,
nullptr, stream_index);
2102 if (program ==
nullptr)
2107 LOG(VB_PLAYBACK, LOG_INFO,
2108 QString(
"Removing streams not in Program %1 from track selection.")
2109 .arg(QString::number(program->id)));
2111 const auto *
const begin = program->stream_index;
2112 const auto *
const end = program->stream_index + program->nb_stream_indexes;
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(),
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())));
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);
2141 bool unknownbitrate =
false;
2145 constexpr std::array<TrackType, 6>
types {
2159 std::map<int,uint> lang_sub_cnt;
2160 uint subtitleStreamCount = 0;
2161 std::map<int,uint> lang_aud_cnt;
2162 uint audioStreamCount = 0;
2171 if (
m_ic ==
nullptr)
2174 for (
uint strm = 0; strm <
m_ic->nb_streams; strm++)
2176 AVCodecParameters *par =
m_ic->streams[strm]->codecpar;
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)
2184 program_id = QString::number(av_find_program_from_stream(
m_ic,
nullptr, strm)->
id);
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),
2191 avcodec_get_name(par->codec_id),
2193 QString::number(par->bit_rate))
2196 switch (par->codec_type)
2198 case AVMEDIA_TYPE_VIDEO:
2206 if (ctx && (ctx->hw_frames_ctx || ctx->hw_device_ctx))
2213 LOG(VB_GENERAL, LOG_ERR,
LOC +
2214 QString(
"Stream #%1 has an unknown video "
2215 "codec id, skipping.").arg(strm));
2227 if (par->bit_rate == 0)
2229 static constexpr int64_t s_baseBitrate { 1000000LL };
2231 if (par->width && par->height)
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);
2237 par->bit_rate = s_baseBitrate * multiplier;
2238 unknownbitrate =
true;
2244 case AVMEDIA_TYPE_AUDIO:
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));
2254 case AVMEDIA_TYPE_SUBTITLE:
2256 if (par->codec_id == AV_CODEC_ID_DVB_TELETEXT)
2258 if (par->codec_id == AV_CODEC_ID_TEXT)
2262 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"subtitle codec (%1)")
2266 case AVMEDIA_TYPE_DATA:
2268 if (par->codec_id == AV_CODEC_ID_DVB_VBI)
2271 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"data codec (%1)")
2275 case AVMEDIA_TYPE_ATTACHMENT:
2277 if (par->codec_id == AV_CODEC_ID_TTF)
2280 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2281 QString(
"Attachment codec (%1)")
2288 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
2289 QString(
"Unknown codec type (%1)")
2295 if (par->codec_type != AVMEDIA_TYPE_AUDIO &&
2296 par->codec_type != AVMEDIA_TYPE_SUBTITLE)
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))
2305 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Looking for decoder for %1")
2306 .arg(avcodec_get_name(par->codec_id)));
2308 if (par->codec_id == AV_CODEC_ID_PROBE)
2310 LOG(VB_GENERAL, LOG_ERR,
LOC +
2311 QString(
"Probing of stream #%1 unsuccesful, ignoring.").arg(strm));
2317 if (codecContext ==
nullptr)
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`.");
2326 if (codecContext->codec && par->codec_id != codecContext->codec_id)
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)));
2335 if (!
OpenAVCodec(codecContext, codecContext->codec))
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));
2353 if (par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2355 bool forced = (
m_ic->streams[strm]->disposition & AV_DISPOSITION_FORCED) != 0;
2357 uint lang_indx = lang_sub_cnt[lang]++;
2358 subtitleStreamCount++;
2361 static_cast<int>(strm),
m_ic->streams[strm]->id, lang, lang_indx, forced);
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).")
2370 if (par->codec_type == AVMEDIA_TYPE_AUDIO)
2374 uint lang_indx = lang_aud_cnt[lang]++;
2377 int stream_id =
m_ic->streams[strm]->id;
2381 if (stream_id == -1)
2389 static_cast<int>(strm), stream_id, lang, lang_indx,
type);
2393 lang_indx = lang_aud_cnt[lang]++;
2395 static_cast<int>(strm), stream_id, lang, lang_indx,
type);
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).")
2402 .arg(strm).arg(
m_ic->streams[strm]->id,0,16).arg(codecContext->ch_layout.nb_channels)
2428 QString(
m_ic->iformat->name).contains(
"matroska"));
2470 for (
unsigned i = 0; i <
m_ic->nb_programs; i++)
2482#if CONFIG_MEDIACODEC
2483 if (QString(
"mediacodec") == codec->wrapper_name)
2484 av_jni_set_java_vm(QAndroidJniEnvironment::javaVM(),
nullptr);
2486 int ret = avcodec_open2(avctx, codec,
nullptr);
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),
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),
2528 if (si.m_language_index == Index)
2529 return si.m_language;
2536 AVDictionaryEntry *metatag = av_dict_get(
m_ic->streams[StreamIndex]->metadata,
"language",
nullptr, 0);
2579 AVStream *stream =
m_ic->streams[StreamIndex];
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)
2616 if (
current->m_av_stream_index == streamIndex)
2622 LOG(VB_GENERAL, LOG_WARNING,
LOC +
2623 QString(
"Invalid stream index passed to "
2624 "SetupAudioStreamSubIndexes: %1").arg(streamIndex));
2631 if (
current->m_av_substream_index == -1)
2644 (next->m_av_stream_index != streamIndex))
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.")
2651 LOG(VB_GENERAL, LOG_WARNING,
LOC + msg);
2673 bool do_flush =
false;
2674 for (
uint i = 0; i <
m_ic->nb_streams; i++)
2676 AVStream *st =
m_ic->streams[i];
2679 if (avctx && avctx->codec_type == AVMEDIA_TYPE_AUDIO)
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),
2685 QString::number(
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*));
2696 m_ic->streams[i] =
nullptr;
2704 avformat_flush(
m_ic);
2713 if (!std::any_of(decoder->m_renderFormats->cbegin(), decoder->m_renderFormats->cend(),
2714 [&
type](
auto Format) { return type == Format; }))
2716 decoder->m_directRendering =
false;
2717 return avcodec_default_get_buffer2(c, pic, flags);
2720 decoder->m_directRendering =
true;
2721 MythVideoFrame *frame = decoder->GetPlayer()->GetNextVideoFrame();
2731 if ((frame->
m_type !=
type) || (pic->width > width) || (pic->height > height))
2748 for (
uint i = 0; i < 3; i++)
2754 pic->opaque = frame;
2757 AVBufferRef *buffer = av_buffer_create(
reinterpret_cast<uint8_t*
>(frame), 0,
2758 [](
void* Opaque, uint8_t* Data)
2762 if (avfd && avfd->GetPlayer())
2763 avfd->GetPlayer()->DeLimboFrame(vf);
2766 pic->buf[0] = buffer;
2772int get_avf_buffer_dxva2(
struct AVCodecContext *c,
AVFrame *pic,
int )
2777 for (
int i = 0; i < 4; i++)
2779 pic->data[i] =
nullptr;
2780 pic->linesize[i] = 0;
2782 pic->opaque = frame;
2784 pic->data[0] = (uint8_t*)frame->
m_buffer;
2785 pic->data[3] = (uint8_t*)frame->
m_buffer;
2788 AVBufferRef *buffer =
2789 av_buffer_create((uint8_t*)frame, 0,
2790 [](
void* Opaque, uint8_t* Data)
2798 pic->buf[0] = buffer;
2809 bool had_608 =
false;
2810 bool had_708 =
false;
2811 for (
uint cur = 0; cur + 2 < buf_size; cur += 3)
2813 uint cc_code = buf[cur];
2814 bool cc_valid = (cc_code & 0x04) != 0U;
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;
2844 bool check_608,
bool check_708)
2846 bool need_change_608 =
false;
2851 for (
uint i = 0; i < 4; i++)
2858 bool need_change_708 =
false;
2860 if (check_708 || need_change_608)
2863 for (
uint i = 1; i < 64 && !need_change_608 && !need_change_708; i++)
2868 if (need_change_708 && !check_608)
2872 if (!need_change_608 && !need_change_708)
2883 for (
int i = 1; i < 64; i++)
2892 for (
int i = 0; i < 4; i++)
2913 AVPacket *pkt,
bool can_reliably_parse_keyframes)
2918 bool reset_kfd =
false;
2922 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2923 "gopset not set, syncing positionMap");
2925 if (tempKeyFrameDist > 0 && !
m_livetv)
2927 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2928 QString(
"Initial key frame distance: %1.")
2934 else if (
m_keyframeDist != tempKeyFrameDist && tempKeyFrameDist > 0)
2936 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2937 QString(
"Key frame distance changed from %1 to %2.")
2965 if (can_reliably_parse_keyframes &&
2968 long long last_frame = 0;
2976 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
2977 QString(
"framesRead: %1 last_frame: %2 keyframedist: %3")
2984 long long startpos = pkt->pos;
2986 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
2987 QString(
"positionMap[ %1 ] == %2.")
3017 float bytespersec = (float)
m_bitrate / 8;
3034 const uint8_t *bufptr = pkt->data;
3035 const uint8_t *bufend = pkt->data + pkt->size;
3037 while (bufptr < bufend)
3041 float aspect_override = -1.0F;
3050 if (bufptr + 11 >= pkt->data + pkt->size)
3052 const auto *seq =
reinterpret_cast<const SequenceHeader*
>(bufptr);
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();
3065 changed |= (seqFPS >
static_cast<float>(
m_fps)+0.01F) ||
3066 (seqFPS < static_cast<float>(
m_fps)-0.01F);
3070 bool forceaspectchange = !qFuzzyCompare(
m_currentAspect + 10.0F, aspect + 10.0F) &&
3074 if (changed || forceaspectchange)
3079 bool doublerate =
false;
3082 forceaspectchange, 2,
3085 if (context->hw_frames_ctx)
3086 if (context->internal)
3087 avcodec_flush_buffers(context);
3101 if ((seqFPS > avFPS+0.01F) || (seqFPS < avFPS-0.01F))
3103 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"avFPS(%1) != seqFPS(%2)")
3104 .arg(
static_cast<double>(avFPS)).arg(
static_cast<double>(seqFPS)));
3113 pkt->flags |= AV_PKT_FLAG_KEY;
3120 pkt->flags |= AV_PKT_FLAG_KEY;
3128 const uint8_t *buf = pkt->data;
3129 const uint8_t *buf_end = pkt->data + pkt->size;
3134 if (context->extradata && (context->extradata_size >= 7) && (context->extradata[0] == 0x01))
3136 if (pkt->flags & AV_PKT_FLAG_KEY)
3141 while (buf < buf_end)
3172 bool fps_changed = (seqFPS > 0.0) && ((seqFPS >
m_fps + 0.01) ||
3173 (seqFPS <
m_fps - 0.01));
3178 if (fps_changed || res_changed || forcechange)
3183 bool doublerate =
false;
3196 if (context->hw_frames_ctx && (forcechange || res_changed))
3197 if (context->internal)
3198 avcodec_flush_buffers(context);
3204 m_fps =
static_cast<float>(seqFPS);
3214 if ((seqFPS > avFPS + 0.01) || (seqFPS < avFPS - 0.01))
3216 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
3217 QString(
"avFPS(%1) != seqFPS(%2)").arg(avFPS).arg(seqFPS));
3222 pkt->flags |= AV_PKT_FLAG_KEY;
3242 if (pkt->flags & AV_PKT_FLAG_KEY)
3258 !(pkt->flags & AV_PKT_FLAG_KEY))
3260 av_packet_unref(pkt);
3294 bool sentPacket =
false;
3314 if (ret == AVERROR(EAGAIN))
3318 if (ret==0 && !gotpicture)
3320 ret2 = avcodec_send_packet(context, pkt);
3321 if (ret2 == AVERROR(EAGAIN))
3333 if (ret < 0 || ret2 < 0)
3338 LOG(VB_GENERAL, LOG_ERR,
LOC +
3339 QString(
"video avcodec_receive_frame error: %1 (%2) gotpicture:%3")
3341 .arg(ret).arg(gotpicture));
3346 LOG(VB_GENERAL, LOG_ERR,
LOC +
3347 QString(
"video avcodec_send_packet error: %1 (%2) gotpicture:%3")
3349 .arg(ret2).arg(gotpicture));
3363 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Decoder needs reset");
3367 if (ret == AVERROR_EXTERNAL || ret2 == AVERROR_EXTERNAL)
3369 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"FFmpeg external library error - assuming streams changed");
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));
3393 auto *newPkt = av_packet_clone(pkt);
3403 auto * side_data = av_frame_get_side_data(AvFrame, AV_FRAME_DATA_A53_CC);
3404 if (side_data && (side_data->size > 0))
3417 frame->m_directRendering =
false;
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];
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);
3446 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to allocate sws context");
3449 sws_scale(
m_swsCtx, AvFrame->data, AvFrame->linesize, 0, dim.height(),
3450 tmppicture.data, tmppicture.linesize);
3458 oldframe->
m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3459 oldframe->
m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3485 LOG(VB_GENERAL, LOG_ERR,
LOC +
"NULL videoframe - direct rendering not "
3486 "correctly initialized.");
3491 if (AvFrame->best_effort_timestamp == AV_NOPTS_VALUE)
3493 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No PTS found - unable to process video.");
3497 AvFrame->best_effort_timestamp * 1000);
3498 std::chrono::milliseconds temppts =
pts;
3515 double calcfps = 1000.0 /
ptsdiff.count();
3516 if (calcfps < 121.0 && calcfps > 3.0)
3520 double fpschange = calcfps /
m_fps;
3522 if (fpschange > 1.9 && fpschange < 2.1)
3524 if (fpschange > 0.9 && fpschange < 1.1)
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" :
""));
3536 frame->m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3537 frame->m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3539 frame->m_repeatPic = AvFrame->repeat_pict != 0;
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;
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;
3588 [[maybe_unused]]
const AVStream *stream,
const AVPacket *pkt)
3590 const uint8_t *buf = pkt->data;
3591 uint64_t linemask = 0;
3596 if ((buf[0]==
't') && (buf[1]==
'v') && (buf[2] ==
'0'))
3599 memcpy(&linemask, buf + 3, 8);
3602 else if ((buf[0]==
'T') && (buf[1]==
'V') && (buf[2] ==
'0'))
3604 linemask = 0xffffffffffffffffLL;
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])));
3614 static constexpr uint kMinBlank = 6;
3615 for (
uint i = 0; i < 36; i++)
3617 if (!((linemask >> i) & 0x1))
3620 const uint line = ((i < 18) ? i : i-18) + kMinBlank;
3621 const uint field = (i<18) ? 0 : 1;
3622 const uint id2 = *buf & 0xf;
3646 int data = (buf[2] << 8) | buf[1];
3673 const AVStream* ,
const AVPacket *pkt)
3682 const uint8_t *buf = pkt->data;
3683 const uint8_t *buf_end = pkt->data + pkt->size;
3685 if (*buf >= 0x10 && *buf <= 0x1F)
3691 LOG(VB_VBI, LOG_WARNING,
LOC +
3692 QString(
"VBI: Unknown data_identier: %1 discarded").arg(*buf));
3697 while (buf < buf_end)
3702 if ((buf_end - buf) >= 42)
3706 else if (*buf == 0x03)
3709 if ((buf_end - buf) >= 42)
3713 else if (*buf == 0xff)
3719 LOG(VB_VBI, LOG_WARNING,
LOC +
3720 QString(
"VBI: Unsupported data_unit_id: %1 discarded").arg(*buf));
3730 [[maybe_unused]]
const AVPacket *pkt)
3733 if (
m_itv ==
nullptr)
3735 if (
m_itv ==
nullptr)
3739 uint8_t *data = pkt->data;
3740 int length = pkt->size;
3741 int componentTag = 0;
3742 int dataBroadcastId = 0;
3743 unsigned carouselId = 0;
3746 componentTag = str->component_tag;
3747 dataBroadcastId = str->data_id;
3748 carouselId = (unsigned) str->carousel_id;
3753 uint16_t sectionLen = (((data[1] & 0xF) << 8) | data[2]) + 3;
3755 if (sectionLen > length)
3758 m_itv->ProcessDSMCCSection(data, sectionLen,
3759 componentTag, carouselId,
3761 length -= sectionLen;
3772 long long pts = pkt->pts;
3773 if (
pts == AV_NOPTS_VALUE)
3775 if (
pts == AV_NOPTS_VALUE)
3777 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No PTS found - unable to process subtitle.");
3780 pts =
static_cast<long long>(av_q2d(curstream->time_base) *
pts * 1000);
3786 bool isForcedTrack =
false;
3789 int gotSubtitles = 0;
3790 AVSubtitle subtitle;
3791 memset(&subtitle, 0,
sizeof(AVSubtitle));
3798 curstream->id,
pts);
3802 if (pkt->stream_index == subIdx)
3806 pkt->data, pkt->size,
pts);
3812 || pkt->stream_index == forcedSubIdx)
3815 avcodec_decode_subtitle2(codecContext, &subtitle, &gotSubtitles, pkt);
3818 subtitle.start_display_time +=
pts;
3819 subtitle.end_display_time +=
pts;
3821 if (pkt->stream_index != subIdx)
3822 isForcedTrack =
true;
3829 for (
unsigned i = 0; i < subtitle.num_rects; i++)
3831 subtitle.rects[i]->flags |= AV_SUBTITLE_FLAG_FORCED;
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));
3841 subtitle, curstream->codecpar->codec_id == AV_CODEC_ID_XSUB,
3855 auto id =
static_cast<uint>(Packet->stream_index + 0x2000);
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);
3863 auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);
3864 QString text = toUtf16.decode(Packet->data);
3866 auto list = text.split(
'\n', Qt::SkipEmptyParts);
3874 enum AVCodecID codec_id = curstream->codecpar->codec_id;
3878 case AV_CODEC_ID_DVB_VBI:
3881 case AV_CODEC_ID_DSMCC_B:
3906 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio stream type " + msg +
"changed.");
3920 QString forcedString = forced ? QObject::tr(
" (forced)") :
"";
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) : "";
3940 AVCodecParameters *par = stream->codecpar;
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())
3949 int channels = par->ch_layout.nb_channels;
3952 msg += QString(
" ?ch");
3953 else if((channels > 4) && !(channels & 1))
3954 msg += QString(
" %1.1ch").arg(channels - 1);
3956 msg += QString(
" %1ch").arg(channels);
3966 if (!user_title.isEmpty())
3969 msg += QString(
" (%1)")
3973 return QString(
"%1: %2").arg(TrackNo + 1).arg(msg);
3977 return QObject::tr(
"Subtitle") + QString(
" %1: %2%3%4")
3978 .arg(QString::number(TrackNo + 1),
4006 return ctx ? QByteArray(
reinterpret_cast<char*
>(ctx->subtitle_header), ctx->subtitle_header_size) :
4017 AVDictionaryEntry *tag = av_dict_get(
m_ic->streams[index]->metadata,
"filename",
nullptr, 0);
4019 Filename = QByteArray(tag->value);
4020 AVCodecParameters *par =
m_ic->streams[index]->codecpar;
4021 Data = QByteArray(
reinterpret_cast<char*
>(par->extradata), par->extradata_size);
4031 if ((stream->component_tag == Tag) || ((Tag <= 0) && stream->component_tag <= 0))
4040 for (
uint i = 0; i <
m_ic->nb_streams; i++)
4042 AVStream *stream =
m_ic->streams[i];
4045 if (stream->component_tag == Tag)
4069 const std::vector<int> &ftype)
4071 std::vector<int> ret;
4073 for (
int index : ftype)
4075 if ((lang_key < 0) || tracks[index].m_language == lang_key)
4076 ret.push_back(index);
4084 std::vector<int> ret;
4086 for (
size_t i = 0; i < tracks.size(); i++)
4088 if (tracks[i].m_audio_type ==
type)
4097 const std::vector<int>&fs,
4098 enum AVCodecID codecId,
4101 int selectedTrack = -1;
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))
4111 if (codecId == AV_CODEC_ID_DTS &&
profile > 0)
4118 max_seen = par->ch_layout.nb_channels;
4122 return selectedTrack;
4130 std::vector<int> flang =
filter_lang(atracks, lang_key, ftype);
4135 AV_PROFILE_DTS_HD_MA);
4146 AV_PROFILE_DTS_HD_HRA);
4222 uint numStreams = atracks.size();
4226 if ((ctrack >= 0) && (ctrack < (
int)numStreams))
4229 LOG(VB_AUDIO, LOG_DEBUG, QString(
"%1 available audio streams").arg(numStreams));
4230 for (
const auto & track : atracks)
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),
4240 if (1 == numStreams)
4250 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Trying to reselect audio sub-stream");
4256 for (
uint i = 0; i < numStreams; i++)
4258 if (atracks[i].m_av_substream_index == substream_index)
4266 if ((selTrack < 0) && wlang >= -1)
4268 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Trying to reselect audio track");
4273 for (
uint i = 0; i < numStreams; i++)
4275 if (wlang == atracks[i].m_language)
4279 if (windx == atracks[i].m_language_index)
4287 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Trying to select audio track (w/lang)");
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++)
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)
4336 LOG(VB_AUDIO, LOG_INFO,
LOC +
4337 "Trying to select audio track (wo/lang)");
4347 if (ctrack != selTrack)
4349 LOG(VB_AUDIO, LOG_INFO,
LOC +
"No suitable audio track exists.");
4356 strack = atracks[selTrack];
4361 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Selected track %1 (A/V Stream #%2)")
4370 char *buffer,
int bufsize)
4381 const uint halfsample = samplesize >> 1;
4383 const char *from = (channel == 1) ? buffer + halfsample : buffer;
4384 char *to = (channel == 0) ? buffer + halfsample : buffer;
4387 (sample++), (from += samplesize), (to += samplesize))
4389 memmove(to, from, halfsample);
4398 bool firstloop =
true;
4399 int decoded_size = -1;
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)
4411 bool reselectAudioTrack =
false;
4416 LOG(VB_AUDIO, LOG_INFO,
LOC +
4417 "Audio is disabled - trying to restart it");
4418 reselectAudioTrack =
true;
4423 bool wasDual = audSubIdx != -1;
4425 if ((wasDual && !isDual) || (!wasDual && isDual))
4428 reselectAudioTrack =
true;
4433 bool already_decoded =
false;
4434 if (!context->ch_layout.nb_channels)
4446 AVChannelLayout channel_layout;
4448 av_opt_set_chlayout(context->priv_data,
"downmix", &channel_layout, 0);
4450 if (context->codec_id == AV_CODEC_ID_AC3)
4455 decoded_size = data_size;
4456 already_decoded =
true;
4457 reselectAudioTrack |= context->ch_layout.nb_channels;
4461 if (reselectAudioTrack)
4471 if (!(decodetype &
kDecodeAudio) || (pkt->stream_index != audIdx)
4475 if (firstloop && pkt->pts != AV_NOPTS_VALUE)
4488 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Audio stream changed");
4491 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Number of audio channels changed from %1 to %2")
4503 if (!already_decoded)
4508 decoded_size = data_size;
4516 data_size = tmp_pkt->size;
4522 if (!already_decoded)
4526 AVChannelLayout channel_layout;
4528 av_opt_set_chlayout(context->priv_data,
"downmix", &channel_layout, 0);
4532 decoded_size = data_size;
4539 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unknown audio decoding error");
4540 av_packet_free(&tmp_pkt);
4546 tmp_pkt->data += ret;
4547 tmp_pkt->size -= ret;
4551 std::chrono::milliseconds temppts =
m_lastAPts;
4558 int frames = (context->ch_layout.nb_channels <= 0 || decoded_size < 0 || !samplesize) ? -1 :
4559 decoded_size / (context->ch_layout.nb_channels * samplesize);
4568 ((
double)(frames * 1000) / context->sample_rate);
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()));
4577 tmp_pkt->data += ret;
4578 tmp_pkt->size -= ret;
4582 av_packet_free(&tmp_pkt);
4589 AVPacket *pkt =
nullptr;
4590 bool have_err =
false;
4592 const DecodeType origDecodetype = decodetype;
4600 bool storevideoframes =
false;
4617 decodetype = (
DecodeType)((
int)decodetype & ~kDecodeVideo);
4633 decodetype = (
DecodeType)((
int)decodetype & ~kDecodeAudio);
4667 storevideoframes =
true;
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.")
4686 av_packet_free(&pkt);
4692 pkt = av_packet_alloc();
4695 if (
m_ic !=
nullptr)
4697 if ((
m_ic ==
nullptr) || (retval < 0))
4699 if (retval == -EAGAIN)
4703 av_packet_free(&pkt);
4705 LOG(VB_GENERAL, LOG_ERR, QString(
"decoding error %1 (%2)")
4707 QString::number(retval)));
4720 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No context");
4721 av_packet_unref(pkt);
4725 if (pkt->stream_index >= (
int)
m_ic->nb_streams)
4727 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bad stream");
4728 av_packet_unref(pkt);
4732 AVStream *curstream =
m_ic->streams[pkt->stream_index];
4736 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bad stream (NULL)");
4737 av_packet_unref(pkt);
4741 enum AVMediaType codec_type = curstream->codecpar->codec_type;
4742 const AVCodecID codec_id = curstream->codecpar->codec_id;
4748 case AVMEDIA_TYPE_VIDEO:
4749 if (storevideoframes)
4756 case AVMEDIA_TYPE_AUDIO:
4758 if (codec_id == AV_CODEC_ID_AC4)
4760 av_packet_unref(pkt);
4764 case AVMEDIA_TYPE_SUBTITLE:
4767 case AV_CODEC_ID_TEXT:
4769 av_packet_unref(pkt);
4771 case AV_CODEC_ID_DVB_TELETEXT:
4773 av_packet_unref(pkt);
4775 case AV_CODEC_ID_IVTV_VBI:
4777 av_packet_unref(pkt);
4783 case AVMEDIA_TYPE_DATA:
4785 av_packet_unref(pkt);
4793 if (context ==
nullptr)
4795 if (codec_type != AVMEDIA_TYPE_VIDEO)
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),
4801 avcodec_get_name(codec_id),
4802 QString::number(codec_id)
4809 av_packet_unref(pkt);
4817 case AVMEDIA_TYPE_AUDIO:
4826 case AVMEDIA_TYPE_VIDEO:
4840 av_packet_free(&pkt);
4844 if (pkt->pts != AV_NOPTS_VALUE)
4847 (av_q2d(curstream->time_base)*pkt->pts*1000000);
4862 case AVMEDIA_TYPE_SUBTITLE:
4871 LOG(VB_GENERAL, LOG_ERR,
LOC +
4872 QString(
"Decoding - id(%1) type(%2)")
4873 .arg(avcodec_get_name(codec_id),
4880 if (!have_err && !Retry)
4882 av_packet_unref(pkt);
4887 av_packet_free(&pkt);
4895 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"StreamChangeCheck skip SeekReset"));
4905 int result = av_read_frame(ctx, pkt);
4913 if (pmt_buffer.has_buffer())
4970 if (stream < 0 || !
m_ic)
4972 return avcodec_get_name(
m_ic->streams[stream]->codecpar->codec_id);
4986 QString msg = (disable) ?
"Disabling" :
"Allowing";
4987 LOG(VB_AUDIO, LOG_INFO,
LOC + msg +
" pass through");
5010 switch (ctx->codec_id)
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:
5025 bool passthru =
false;
5029 if (!withProfile && par->codec_id == AV_CODEC_ID_DTS && !
m_audio->
CanDTSHD())
5032 par->codec_id, AV_PROFILE_DTS);
5037 par->codec_id, par->profile);
5053 AVStream *curstream =
nullptr;
5054 AVCodecContext *ctx =
nullptr;
5056 int requested_channels = 0;
5060 (
int)
m_ic->nb_streams))
5063 .m_av_stream_index];
5064 if (curstream !=
nullptr)
5071 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"No codec context. Returning false");
5077 ctx->bits_per_raw_sample);
5079 if (av_sample_fmt_is_planar(ctx->sample_fmt))
5081 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Audio data is planar"));
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));
5095 bool using_passthru =
DoPassThrough(curstream->codecpar,
false);
5097 requested_channels = ctx->ch_layout.nb_channels;
5099 if (!using_passthru &&
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);
5111 requested_channels, using_passthru, ctx->ch_layout.nb_channels,
5112 ctx->codec_id == AV_CODEC_ID_DTS ? ctx->profile : 0);
5116 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Initializing audio parms from " +
5121 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio format changed " +
5122 QString(
"\n\t\t\tfrom %1 to %2")
5138 switch (ctx->codec_id)
5140 case AV_CODEC_ID_MP2:
5143 case AV_CODEC_ID_MP3:
5146 case AV_CODEC_ID_AC3:
5149 case AV_CODEC_ID_DTS:
5152 case AV_CODEC_ID_VORBIS:
5155 case AV_CODEC_ID_WMAV1:
5158 case AV_CODEC_ID_WMAV2:
5166 lcd->setAudioFormatLEDs(audio_format,
true);
5201 int64_t start_time = INT64_MAX;
5202 int64_t end_time = INT64_MIN;
5203 AVStream *st =
nullptr;
5205 for (
uint i = 0; i < ic->nb_streams; i++)
5207 AVStream *st1 = ic->streams[i];
5208 if (st1 && st1->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
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);
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);
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);
5237 if (duration != INT64_MIN) {
5238 ic->duration = duration;
5241 int64_t filesize = avio_size(ic->pb);
5244 ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE /
5245 (
double)ic->duration;
5261 if (
m_ic ==
nullptr)
5266 if (program ==
nullptr)
This is in libmythtv because that is where the parsers, which are its main users, are.
std::array< bool, 4 > CC608Seen
std::array< bool, 64 > cc708_seen_flags
uint pictureWidthCropped(void) const override
uint32_t addBytes(const uint8_t *bytes, uint32_t byte_count, uint64_t stream_offset) override
uint pictureHeightCropped(void) const override
field_type getFieldType(void) const override
double frameRate(void) const
void Reset(void) override
uint getRefFrames(void) const
static int SampleSize(AudioFormat format)
static AudioFormat AVSampleFormatToFormat(AVSampleFormat format, int bits=0)
Return AVSampleFormat closest equivalent to AudioFormat.
virtual bool has_optimized_SIMD()
virtual void SetSourceBitrate(int)
AudioOutput * GetAudioOutput(void) const
Return internal AudioOutput object.
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)
AudioFormat GetFormat(void) const
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
bool HasAudioIn(void) const
bool IsBufferAlmostFull(void)
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)
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
int CanonicalLanguageKey(int i) const
uint ServicesCount() const
int CaptionServiceNumber(int i) const
MythAVRational m_totalDuration
QRecursiveMutex m_positionMapLock
virtual uint GetTrackCount(uint Type)
MarkTypes m_positionMapType
frm_pos_map_t m_frameToDurMap
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...
virtual void SetEof(bool eof)
bool m_dontSyncPositionMap
virtual QString GetTrackDesc(uint Type, uint TrackNo)
virtual int SetTrack(uint Type, int TrackNo)
uint64_t GetSeekSnap(void) const
virtual void UpdateFramesPlayed(void)
MythMediaBuffer * m_ringBuffer
QRecursiveMutex m_trackLock
bool m_nextDecodedFrameIsKeyFrame
bool m_decodeAllSubtitles
std::vector< int > m_languagePreference
language preferences for auto-selection of streams
virtual void Reset(bool reset_video_data, bool seek_reset, bool reset_file)
std::array< StreamInfo, kTrackTypeCount > m_wantedTrack
bool m_hasFullPositionMap
MythVideoProfile m_videoDisplayProfile
bool m_trackTotalDuration
frm_pos_map_t m_durToFrameMap
virtual bool DoFastForward(long long desiredFrame, bool discardFrames=true)
Skips ahead or rewinds to desiredFrame.
virtual void SeekReset(long long newkey, uint skipFrames, bool doFlush, bool discardFrames)
std::array< sinfo_vec_t, kTrackTypeCount > m_tracks
virtual bool SyncPositionMap(void)
Updates the position map used for skipping frames.
virtual int AutoSelectTrack(uint Type)
Select best track.
MythCodecContext * m_mythCodecCtx
std::array< StreamInfo, kTrackTypeCount > m_selectedForcedTrack
std::vector< PosMapEntry > m_positionMap
std::array< int, kTrackTypeCount > m_currentTrack
virtual bool DoRewindSeek(long long desiredFrame)
bool m_recordingHasPositionMap
virtual bool DoRewind(long long desiredFrame, bool discardFrames=true)
ProgramInfo * m_playbackInfo
std::array< StreamInfo, kTrackTypeCount > m_selectedTrack
bool stateChanged(void) const
bool onFrameStart(void) const
bool onKeyFrameStart(void) const
static desc_list_t ParseOnlyInclude(const unsigned char *data, uint len, int excluded_descid)
C++ wrapper for AVBufferRef.
MythAVFrame little utility class that act as a safe way to allocate an AVFrame which can then be allo...
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)
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)
AVCodecContext * GetCodecContext(const AVStream *Stream, const AVCodec *Codec=nullptr, bool NullCodec=false)
void FreeCodecContext(const AVStream *Stream)
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
void SetDuration(std::chrono::seconds duration)
virtual void ReleaseNextVideoFrame(MythVideoFrame *buffer, std::chrono::milliseconds timecode, bool wrap=true)
Places frame on the queue of frames ready for display.
virtual void SetVideoParams(int w, int h, double fps, float aspect, bool ForceUpdate, int ReferenceFrames, FrameScanType=kScan_Ignore, const QString &codecName=QString())
void SetFramesPlayed(uint64_t played)
virtual InteractiveTV * GetInteractiveTV()
void DiscardVideoFrames(bool KeyFrame, bool Flushed)
Places frames in the available frames queue.
void SetErrored(const QString &reason)
void SetFrameRate(double fps)
void DeLimboFrame(MythVideoFrame *frame)
bool IsErrored(void) const
void EnableForcedSubtitles(bool enable)
void SetKeyframeDistance(int keyframedistance)
void SetFileLength(std::chrono::seconds total, int frames)
virtual SubtitleReader * GetSubReader(uint=0)
bool GetAllowForcedSubtitles(void) const
MythVideoFrame * GetNextVideoFrame(void)
Removes a frame from the available queue for decoding onto.
int GetFreeVideoFrames(void) const
Returns the number of frames available for decoding onto.
void DiscardVideoFrame(MythVideoFrame *buffer)
Places frame in the available frames queue.
A QElapsedTimer based timer to replace use of QTime as a timer.
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
static uint GetNumPlanes(VideoFrameType Type)
bool m_deinterlaceInuse2x
bool m_alreadyDeinterlaced
MythDeintType m_deinterlaceInuse
void ClearBufferToBlank()
void SetInput(QSize Size, float Framerate=0, const QString &CodecName=QString(), const QStringList &DisallowedDecoders=QStringList())
QString GetDecoder() const
bool IsSkipLoopEnabled() const
A PSIP table is a variant of a PES packet containing an MPEG, ATSC or DVB table.
Holds information on recordings and videos.
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...
uint StreamCount(void) const
uint StreamType(uint i) const
const unsigned char * ProgramInfo(void) const
const unsigned char * StreamInfo(uint i) const
uint ProgramInfoLength(void) const
bool IsVideo(uint i, const QString &sistandard) const
Returns true iff the stream at index i is a video stream.
uint StreamInfoLength(uint i) const
@ PrivData
ISO 13818-1 PES private data & ITU H.222.0.
static bool IsObjectCarousel(uint type)
Returns true iff stream contains DSMCC Object Carousel.
uint m_language_index
Audio, Subtitle, Teletext.
int m_language
ISO639 canonical language key; Audio, Subtitle, CC, Teletext, RawText.
int m_av_substream_index
Audio only; -1 for no substream, 0 for first dual audio stream, 1 for second dual.
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)
@ kAudioTypeAudioDescription
@ kAudioTypeHearingImpaired
std::vector< char > TestBufferVec
std::vector< StreamInfo > sinfo_vec_t
const int kDecoderProbeBufferSize
@ kTrackTypeTeletextCaptions
static const std::array< const uint64_t, 4 > samples
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.
int iso639_key_to_canonical_key(int iso639_2)
QString iso639_str2_to_str3(const QString &str2)
ISO 639-1 and ISO 639-2 support functions.
static int iso639_str3_to_key(const unsigned char *iso639_2)
static bool iso639_is_key_undefined(int code)
Returns true if the key is 0, 0xFFFFFF, or 'und'.
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.
MTV_PUBLIC std::string av_make_error_stdstring_unknown(int errnum)
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.
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.
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.
QString get_decoder_name(MythCodecID codec_id)
uint mpeg_version(AVCodecID codec_id)
static bool codec_is_std(MythCodecID id)
static bool CODEC_IS_H264(AVCodecID id)
static bool CODEC_IS_MPEG(AVCodecID id)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static constexpr uint8_t MYTH_WIDTH_ALIGNMENT
static constexpr uint8_t MYTH_HEIGHT_ALIGNMENT
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
static bool VERBOSE_LEVEL_NONE()
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
uint32_t readBigEndianU32(const uint8_t *x)
uint32_t readBigEndianU24(const uint8_t *x)
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...
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
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.
QString intToPaddedString(int n, int width=2)
Creates a zero padded string representation of an integer.
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
int64_t ptsdiff(uint64_t pts1, uint64_t pts2)
@ VBI_DVB_SUBTITLE
< DVB packet