14#include "libavutil/avutil.h"
15#include "libavutil/error.h"
16#include "libavutil/log.h"
17#include "libavutil/opt.h"
18#include "libavcodec/avcodec.h"
19#include "libavcodec/defs.h"
20#include "libavformat/avformat.h"
21#include "libavformat/avio.h"
22#include "libswscale/swscale.h"
23#include "libavutil/stereo3d.h"
24#include "libavutil/imgutils.h"
25#include "libavutil/display.h"
28#include "libmythbase/mythconfig.h"
30#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
31#include <QtSystemDetection>
32#include <QtVersionChecks>
37#include "libavcodec/jni.h"
39#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
40#include <QtAndroidExtras>
42#include <QJniEnvironment>
43#define QAndroidJniEnvironment QJniEnvironment
71#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
74#include <QStringDecoder>
118using namespace std::string_view_literals;
120#define LOC QString("AFD: ")
130#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
138 return {ctx.width >> ctx.lowres, ctx.height >> ctx.lowres};
142 float aspect_ratio = 0.0F;
144 if (ctx.sample_aspect_ratio.num && ctx.height)
146 aspect_ratio = av_q2d(ctx.sample_aspect_ratio) *
147 static_cast<double>(ctx.width);
148 aspect_ratio /= (float) ctx.height;
151 if (aspect_ratio <= 0.0F || aspect_ratio > 6.0F)
154 aspect_ratio = (float)ctx.width / (
float)ctx.height;
156 aspect_ratio = 4.0F / 3.0F;
163 static constexpr float kDefaultAspect = 4.0F / 3.0F;
164 int asp =
p.aspectRatio();
167 case 0:
return kDefaultAspect;
168 case 2:
return 4.0F / 3.0F;
169 case 3:
return 16.0F / 9.0F;
170 case 4:
return 2.21F;
174 float aspect_ratio = asp * 0.000001F;
175 if (aspect_ratio <= 0.0F || aspect_ratio > 6.0F)
177 if (
p.pictureHeight() &&
p.pictureWidth())
180 (float)
p.pictureWidth() /(float)
p.pictureHeight();
184 aspect_ratio = kDefaultAspect;
205#define FAIL(errmsg) do { \
206 LOG(VB_PLAYBACK, LOG_INFO, LOC + (errmsg)); \
217 switch (Stream->codecpar->codec_type)
221 case AVMEDIA_TYPE_VIDEO:
223 FAIL(
"No codec for video stream");
224 if (!Stream->codecpar->width || !Stream->codecpar->height)
225 FAIL(
"Unspecified video size");
226 if (Stream->codecpar->format == AV_PIX_FMT_NONE)
227 FAIL(
"Unspecified video pixel format");
234 case AVMEDIA_TYPE_AUDIO:
236 FAIL(
"No codec for audio stream");
254 case AVMEDIA_TYPE_SUBTITLE:
255 if (Stream->codecpar->codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE && !Stream->codecpar->width)
256 FAIL(
"Unspecified subtitle size");
258 case AVMEDIA_TYPE_DATA:
259 if (Stream->codecpar->codec_id == AV_CODEC_ID_NONE)
266 if (Stream->codecpar->codec_id == AV_CODEC_ID_NONE)
267 FAIL(
"Unknown codec");
271static void myth_av_log(
void *ptr,
int level,
const char* fmt, va_list vl)
276 static QString s_fullLine(
"");
277 static QMutex s_stringLock;
278 uint64_t verbose_mask = VB_LIBAV;
279 LogLevel_t verbose_level = LOG_EMERG;
285 verbose_level = LOG_EMERG;
286 verbose_mask |= VB_GENERAL;
289 verbose_level = LOG_CRIT;
290 verbose_mask |= VB_GENERAL;
293 verbose_level = LOG_ERR;
296 verbose_level = LOG_WARNING;
299 verbose_level = LOG_INFO;
303 verbose_level = LOG_DEBUG;
306 verbose_level = LOG_TRACE;
316 if (s_fullLine.isEmpty() && ptr) {
317 AVClass* avc = *(AVClass**)ptr;
318 s_fullLine = QString(
"[%1 @ %2] ")
319 .arg(avc->item_name(ptr))
320 .arg((quintptr)avc, QT_POINTER_SIZE * 2, 16, QChar(
'0'));
323 s_fullLine += QString::vasprintf(fmt, vl);
324 if (s_fullLine.endsWith(
"\n"))
326 LOG(verbose_mask, verbose_level, s_fullLine.trimmed());
327 s_fullLine.truncate(0);
329 s_stringLock.unlock();
334 if (lang_cstr[0] ==
'\0' || lang_cstr[1] ==
'\0')
338 if (lang_cstr[2] ==
'\0')
340 QString tmp2 = lang_cstr;
358 case AVMEDIA_TYPE_UNKNOWN:
return "Unknown";
359 case AVMEDIA_TYPE_VIDEO:
return "Video";
360 case AVMEDIA_TYPE_AUDIO:
return "Audio";
361 case AVMEDIA_TYPE_DATA:
return "Data";
362 case AVMEDIA_TYPE_SUBTITLE:
return "Subtitle";
363 case AVMEDIA_TYPE_ATTACHMENT:
return "Attachment";
364 default:
return "Invalid Codec Type";
374 m_playerFlags(flags),
379 m_itv(parent->GetInteractiveTV()),
380 m_audioSamples((uint8_t *)av_mallocz(
AudioOutput::kMaxSizeBuffer))
394 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"PlayerFlags: 0x%1, AudioReadAhead: %2 msec")
403 av_packet_free(&pkt);
421 lcd->setAudioFormatLEDs(
AUDIO_AC3,
false);
422 lcd->setVideoFormatLEDs(
VIDEO_MPG,
false);
439 for (
uint i = 0; i <
m_ic->nb_streams; i++)
441 AVStream *st =
m_ic->streams[i];
457 avformat_close_input(&
m_ic);
463static int64_t
lsb3full(int64_t lsb, int64_t base_ts,
int lsb_bits)
465 int64_t mask = (lsb_bits < 64) ? (1LL<<lsb_bits)-1 : -1LL;
466 return ((lsb - base_ts)&mask);
471 int64_t start_pts = 0;
473 AVStream *st =
nullptr;
474 for (
uint i = 0; i <
m_ic->nb_streams; i++)
476 AVStream *st1 =
m_ic->streams[i];
477 if (st1 && st1->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
486 if (
m_ic->start_time != AV_NOPTS_VALUE)
488 start_pts = av_rescale(
m_ic->start_time,
490 AV_TIME_BASE * (int64_t)st->time_base.num);
493 int64_t
pts = av_rescale(timecode.count() / 1000.0,
504 std::chrono::milliseconds timecode)
506 int64_t start_pts = 0;
508 if (
m_ic->start_time != AV_NOPTS_VALUE)
510 start_pts = av_rescale(
m_ic->start_time,
512 AV_TIME_BASE * (int64_t)st->time_base.num);
515 int64_t
pts = av_rescale(timecode.count() / 1000.0,
528 return m_ic->nb_chapters;
538 for (
int i = 0; i < total; i++)
540 int num =
m_ic->chapters[i]->time_base.num;
541 int den =
m_ic->chapters[i]->time_base.den;
542 int64_t start =
m_ic->chapters[i]->start;
543 long double total_secs = (
long double)start * (
long double)num /
545 times.push_back(std::chrono::seconds((
long long)total_secs));
554 for (
int i = (
m_ic->nb_chapters - 1); i > -1 ; i--)
556 int num =
m_ic->chapters[i]->time_base.num;
557 int den =
m_ic->chapters[i]->time_base.den;
558 int64_t start =
m_ic->chapters[i]->start;
559 long double total_secs = (
long double)start * (
long double)num /
561 auto framenum = (
long long)(total_secs *
m_fps);
562 if (framesPlayed >= framenum)
564 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
565 QString(
"GetCurrentChapter(selected chapter %1 framenum %2)")
566 .arg(i + 1).arg(framenum));
578 int num =
m_ic->chapters[chapter - 1]->time_base.num;
579 int den =
m_ic->chapters[chapter - 1]->time_base.den;
580 int64_t start =
m_ic->chapters[chapter - 1]->start;
581 long double total_secs = (
long double)start * (
long double)num /
583 auto framenum = (
long long)(total_secs *
m_fps);
584 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"GetChapter %1: framenum %2")
585 .arg(chapter).arg(framenum));
591 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DoRewind(%1, %2 discard frames)")
592 .arg(desiredFrame).arg( discardFrames ?
"do" :
"don't" ));
598 return do_av_seek(desiredFrame, discardFrames, AVSEEK_FLAG_BACKWARD);
603 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
604 QString(
"DoFastForward(%1 (%2), %3 discard frames)")
606 .arg((discardFrames) ?
"do" :
"don't"));
614 if (seekDelta >= 0 && seekDelta < 2 && m_parent->GetPlaySpeed() == 0.0F)
620 return do_av_seek(desiredFrame, discardFrames, 0);
626 if (
m_ic->start_time != AV_NOPTS_VALUE)
627 ts =
m_ic->start_time;
630 long double seekts = desiredFrame * AV_TIME_BASE /
m_fps;
631 ts += (
long long)seekts;
638 flags |= AVSEEK_FLAG_BACKWARD;
641 int ret = av_seek_frame(
m_ic, -1, ts, flags);
644 LOG(VB_GENERAL, LOG_ERR,
LOC +
645 QString(
"av_seek_frame(m_ic, -1, %1, 0b%2) error: %3").arg(
647 QString::number(flags, 2),
654 reader->SeekFrame(ts, flags);
656 int normalframes = 0;
674 bool doflush,
bool discardFrames)
679 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
680 QString(
"SeekReset(%1, %2, %3 flush, %4 discard)")
681 .arg(newKey).arg(skipFrames)
682 .arg((doflush) ?
"do" :
"don't",
683 (discardFrames) ?
"do" :
"don't"));
703 avformat_flush(
m_ic);
710 m_ic->pb->buf_ptr =
m_ic->pb->buffer;
711 m_ic->pb->buf_end =
m_ic->pb->buffer;
712 m_ic->pb->eof_reached = 0;
716 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"SeekReset() flushing");
717 for (
uint i = 0; i <
m_ic->nb_streams; i++)
723 if (codecContext && codecContext->internal)
724 avcodec_flush_buffers(codecContext);
731 av_packet_free(&pkt);
753 static constexpr std::chrono::milliseconds maxSeekTimeMs { 200ms };
754 int profileFrames = 0;
756 for (; (skipFrames > 0 && !
m_atEof &&
757 (exactSeeks || begin.
elapsed() < maxSeekTimeMs));
758 --skipFrames, ++profileFrames)
762 QElapsedTimer getframetimer;
763 getframetimer.start();
765 while (retry && !getframetimer.hasExpired(100))
770 std::this_thread::sleep_for(1ms);
778 if (!exactSeeks && profileFrames >= 5 && profileFrames < 10)
780 const int giveUpPredictionMs = 400;
781 int remainingTimeMs =
782 skipFrames * (float)begin.
elapsed().count() / profileFrames;
783 if (remainingTimeMs > giveUpPredictionMs)
785 LOG(VB_PLAYBACK, LOG_DEBUG,
786 QString(
"Frame-by-frame seeking would take "
787 "%1 ms to finish, skipping.").arg(remainingTimeMs));
804 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
805 QString(
"Resetting byte context eof (livetv %1 was eof %2)")
807 m_ic->pb->eof_reached = 0;
815 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
816 QString(
"Reset: Video %1, Seek %2, File %3")
817 .arg(reset_video_data).arg(seek_reset).arg(reset_file));
824 if (reset_video_data)
834 memset(&probe, 0,
sizeof(AVProbeData));
836 QByteArray fname =
filename.toLatin1();
837 probe.filename = fname.constData();
838 probe.buf = (
unsigned char *)testbuf.data();
839 probe.buf_size = testbuf.size();
841 int score = AVPROBE_SCORE_MAX/4;
853 memset(probe.buf + probe.buf_size, 0, AVPROBE_PADDING_SIZE);
855 return av_probe_input_format2(&probe,
static_cast<int>(
true), &score) !=
nullptr;
862 int cnt = decoder->
m_ic->nb_streams;
864 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
865 QString(
"streams_changed 0x%1 -- program_number %2 stream count %3")
866 .arg((uint64_t)data,0,16).arg(QString::number(avprogram_id), QString::number(cnt)));
868 auto* program = decoder->get_current_AVProgram();
869 if (program !=
nullptr && program->id != avprogram_id)
873 decoder->m_streamsChanged =
true;
910 const AVInputFormat *fmt =
nullptr;
912 QByteArray fnamea = fnames.toLatin1();
913 const char *
filename = fnamea.constData();
916 memset(&probe, 0,
sizeof(AVProbeData));
918 probe.buf =
reinterpret_cast<unsigned char *
>(testbuf.data());
920 probe.buf_size = testbuf.size();
923 memset(probe.buf + probe.buf_size, 0, AVPROBE_PADDING_SIZE);
925 fmt = av_probe_input_format(&probe,
static_cast<int>(
true));
928 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Probe failed for '%1'").arg(
filename));
932 if (strcmp(fmt->name,
"mpegts") == 0 &&
935 const AVInputFormat *fmt2 = av_find_input_format(
"mpegts-ffmpeg");
939 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Using FFmpeg MPEG-TS demuxer (forced)");
944 bool scancomplete =
false;
945 int remainingscans = 5;
947 while (!scancomplete && remainingscans--)
961 while (!found && --retries)
963 m_ic = avformat_alloc_context();
966 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Could not allocate format context.");
973 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
974 QString(
"Buffer size: %1 Streamed %2 Seekable %3 Available %4")
977 .arg(
m_ic->pb->seekable)
981 err = avformat_open_input(&
m_ic,
filename, fmt,
nullptr);
985 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Failed to open input ('%1')")
993 std::this_thread::sleep_for(100ms);
999 if (strcmp(fmt->name,
"mpegts") == 0)
1001 fmt = av_find_input_format(
"mpegts-ffmpeg");
1004 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Attempting to use original FFmpeg MPEG-TS demuxer.");
1017 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Fatal error opening input. Aborting");
1029 m_ic->max_analyze_duration = 60LL * AV_TIME_BASE;
1033 err = avformat_find_stream_info(
m_ic,
nullptr);
1037 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Could not find codec parameters for '%1'").arg(
filename));
1044 scancomplete =
true;
1049 scancomplete =
false;
1053 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Stream scan incomplete - retrying");
1054 std::this_thread::sleep_for(250ms);
1062 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Scan incomplete - playback may not work");
1065 m_ic->stream_change_data =
this;
1077 QString extension = QFileInfo(fnames).suffix();
1078 if (strcmp(fmt->name,
"mp3") == 0 || strcmp(fmt->name,
"flac") == 0 ||
1079 strcmp(fmt->name,
"ogg") == 0 ||
1080 (extension.compare(
"m4a", Qt::CaseInsensitive) == 0))
1095 int initialAudio = -1;
1096 int initialVideo = -1;
1097 if (
m_itv ==
nullptr)
1099 if (
m_itv !=
nullptr)
1100 m_itv->GetInitialStreams(initialAudio, initialVideo);
1101 if (initialAudio >= 0)
1103 if (initialVideo >= 0)
1124 std::chrono::seconds dur = 0s;
1133 dur = duration_cast<std::chrono::seconds>(av_duration(
m_ic->duration));
1144 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1145 "Recording has no position -- using libavformat seeking.");
1154 float bytespersec = (float)
m_bitrate / 8 / 2;
1157 (int)(secs *
static_cast<float>(
m_fps)));
1166 if (strcmp(fmt->name,
"avi") == 0)
1179 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Position map found");
1181 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Partial position map found");
1182 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1183 QString(
"Successfully opened decoder for file: \"%1\". novideo(%2)")
1187 for (
unsigned int i=0; i <
m_ic->nb_chapters; i++)
1189 int num =
m_ic->chapters[i]->time_base.num;
1190 int den =
m_ic->chapters[i]->time_base.den;
1191 int64_t start =
m_ic->chapters[i]->start;
1192 auto total_secs =
static_cast<long double>(start) *
static_cast<long double>(num) /
1193 static_cast<long double>(den);
1195 auto framenum =
static_cast<long long>(total_secs *
static_cast<long double>(
m_fps));
1196 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1197 QString(
"Chapter %1 found @ [%2]->%3")
1200 QString::number(framenum)));
1213 Reset(
true,
true,
true);
1227 double avg_fps = (Stream->avg_frame_rate.den == 0) ? 0.0 : av_q2d(Stream->avg_frame_rate);
1228 double codec_fps = av_q2d(Context->framerate);
1229 double container_fps = (Stream->time_base.num == 0) ? 0.0 : av_q2d(av_inv_q(Stream->time_base));
1231 double estimated_fps = (Stream->r_frame_rate.den == 0) ? 0.0 : av_q2d(Stream->r_frame_rate);
1235 static const std::vector<double> k_standard_rates =
1255 std::vector<double> rates;
1260 if (QString(
m_ic->iformat->name).contains(
"matroska") ||
1261 QString(
m_ic->iformat->name).contains(
"mov"))
1263 rates.emplace_back(avg_fps);
1267 if (QString(
m_ic->iformat->name).contains(
"avi"))
1269 rates.emplace_back(container_fps);
1272 rates.emplace_back(codec_fps);
1273 rates.emplace_back(container_fps);
1274 rates.emplace_back(avg_fps);
1276 rates.emplace_back(estimated_fps);
1278 rates.emplace_back(30000.0 / 1001.0);
1280 auto invalid_fps = [](
double rate) {
return rate < 3.0 || rate > 121.0; };
1281 rates.erase(std::remove_if(rates.begin(), rates.end(), invalid_fps), rates.end());
1283 auto FuzzyEquals = [](
double First,
double Second) {
return std::abs(First - Second) < 0.03; };
1286 if (!FuzzyEquals(rates.front(),
m_fps))
1288 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1289 QString(
"Selected FPS: %1 (Avg:%2 Mult:%3 Codec:%4 Container:%5 Estimated:%6)")
1290 .arg(
static_cast<double>(rates.front())).arg(avg_fps)
1291 .arg(
m_fpsMultiplier).arg(codec_fps).arg(container_fps).arg(estimated_fps));
1293 LOG(VB_GENERAL, LOG_INFO,
LOC +
1294 QString(
"Sanitise:%1").arg(Sanitise) +
1295 QString(
" avg_fps:%1").arg(avg_fps) +
1296 QString(
" codec_fps:%1").arg(codec_fps) +
1297 QString(
" container_fps:%1").arg(container_fps) +
1298 QString(
" estimated_fps:%1").arg(estimated_fps) +
1299 QString(
" m_fps:%1").arg(
m_fps));
1302 for (
auto rate : rates)
1303 rs.append(QString::number(rate));
1304 LOG(VB_GENERAL, LOG_INFO,
LOC +
1305 QString(
"Frame rates:%1").arg(rs.join(
' ')));
1308 auto IsStandard = [&FuzzyEquals](
double Rate)
1310 if (Rate > 23.0 && Rate < 121.0)
1312 for (
auto standard_rate : k_standard_rates)
1313 if (FuzzyEquals(Rate, standard_rate))
1321 auto NearestStandardFrameRate = [](
double rate,
double epsilon)
1323 double result = rate;
1324 double lowest_delta = rate;
1325 for (
auto standard_rate : k_standard_rates)
1327 double delta = std::abs(rate - standard_rate);
1328 if ((delta < lowest_delta) && (delta <
epsilon))
1330 lowest_delta = delta;
1331 result = standard_rate;
1338 double detected = rates.front();
1343 double nearest = NearestStandardFrameRate(detected, 3.0);
1344 LOG(VB_GENERAL, LOG_INFO,
LOC +
1345 QString(
"Frame rate %1 rounded to nearest standard rate %2")
1346 .arg(detected, 0,
'f', 2).arg(nearest, 0,
'f', 2));
1350 if (Sanitise && !IsStandard(detected))
1352 for (
auto rate : rates)
1354 if (IsStandard(rate))
1356 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"%1 is non-standard - using %2 instead.")
1357 .arg(rates.front()).arg(rate));
1365 if (rate > 33.0 && detected < 33.0)
1367 double half = rate / 2.0;
1368 if (std::abs(half - detected) < (half * 0.1))
1370 LOG(VB_GENERAL, LOG_INFO,
LOC +
1371 QString(
"Assuming %1 is a better choice than %2")
1372 .arg(half).arg(rate));
1373 return static_cast<float>(half);
1376 return static_cast<float>(rate);
1381 return static_cast<float>(detected);
1386 switch (Context->codec_id)
1388 case AV_CODEC_ID_H264:
1391 if (Context->extradata && (Context->extradata_size >= 7))
1394 if (Context->extradata[0] == 1)
1405 parser.parse_SPS(Context->extradata + offset,
1406 static_cast<uint>(Context->extradata_size - offset), dummy, result);
1411 case AV_CODEC_ID_H265:
return 16;
1412 case AV_CODEC_ID_VP9:
return 8;
1413 case AV_CODEC_ID_VP8:
return 3;
1419 bool selectedStream)
1421 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1422 QString(
"InitVideoCodec ID:%1 Type:%2 Size:%3x%4")
1423 .arg(avcodec_get_name(codecContext->codec_id),
1425 .arg(codecContext->width).arg(codecContext->height));
1430 codecContext->opaque =
static_cast<void*
>(
this);
1432 codecContext->slice_flags = 0;
1434 codecContext->err_recognition = AV_EF_COMPLIANT;
1435 codecContext->workaround_bugs = FF_BUG_AUTODETECT;
1436 codecContext->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
1437 codecContext->idct_algo = FF_IDCT_AUTO;
1438 codecContext->debug = 0;
1441 const AVCodec *codec1 = codecContext->codec;
1447 const AVPacketSideData *sd = av_packet_side_data_get(stream->codecpar->coded_side_data,
1448 stream->codecpar->nb_coded_side_data, AV_PKT_DATA_DISPLAYMATRIX);
1450 m_videoRotation =
static_cast<int>(-av_display_rotation_get(
reinterpret_cast<int32_t*
>(sd->data)));
1455 sd = av_packet_side_data_get(stream->codecpar->coded_side_data,
1456 stream->codecpar->nb_coded_side_data, AV_PKT_DATA_STEREO3D);
1459 auto * avstereo =
reinterpret_cast<AVStereo3D*
>(sd->data);
1484 bool doublerate =
true;
1488 if (codec1 && ((AV_CODEC_ID_MPEG2VIDEO == codec1->id) ||
1489 (AV_CODEC_ID_MPEG1VIDEO == codec1->id)))
1493 int total_blocks = (codecContext->height + 15) / 16;
1494 codecContext->skip_top = (total_blocks + 3) / 4;
1495 codecContext->skip_bottom = (total_blocks + 3) / 4;
1499 codecContext->lowres = 2;
1503 codecContext->flags &= ~AV_CODEC_FLAG_LOOP_FILTER;
1504 codecContext->skip_loop_filter = AVDISCARD_ALL;
1508 codecContext->skip_idct = AVDISCARD_ALL;
1520 if (!width || !height)
1522 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1523 "InitVideoCodec invalid dimensions, resetting decoder.");
1531 const AVCodec *codec2 = codecContext->codec;
1534 codecName = codec2->name;
1542 switch (codecContext->codec_id)
1544 case AV_CODEC_ID_H263:
1545 case AV_CODEC_ID_MPEG4:
1546 case AV_CODEC_ID_MSMPEG4V1:
1547 case AV_CODEC_ID_MSMPEG4V2:
1548 case AV_CODEC_ID_MSMPEG4V3:
1549 case AV_CODEC_ID_H263P:
1550 case AV_CODEC_ID_H263I:
1553 case AV_CODEC_ID_WMV1:
1554 case AV_CODEC_ID_WMV2:
1558 case AV_CODEC_ID_XVID:
1567 lcd->setVideoFormatLEDs(video_format,
true);
1579 static constexpr std::array<uint8_t, 256> odd_parity_LUT
1581 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1582 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1583 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1584 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1585 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1586 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1587 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1588 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1589 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1590 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1591 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1592 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1593 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1594 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1595 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1596 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1598 bool ret = (odd_parity_LUT[data & 0xff] == 1) &&
1599 (odd_parity_LUT[(data & 0xff00) >> 8] == 1);
1602 LOG(VB_VBI, LOG_ERR,
LOC +
1603 QString(
"VBI: Bad parity in EIA-608 data (%1)") .arg(data,0,16));
1610 if (program ==
nullptr)
1614 return program->pmt_section;
1619 AVProgram* program = av_find_program_from_stream(context,
nullptr, stream_index);
1633 if (!pmt_buffer.has_buffer())
1635 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1636 "ScanATSCCaptionStreams() called with no PMT");
1641 bool video_found =
false;
1665 desc_list.insert(desc_list.end(), desc_list2.begin(), desc_list2.end());
1667 for (
auto & desc : desc_list)
1709 std::array<std::map<int,uint>,2> lang_cc_cnt;
1726 else if (!pofr && sofr)
1752 LOG(VB_GENERAL, LOG_ERR,
LOC +
"in_tracks key too small");
1758 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1759 QString(
"%1 caption service #%2 is in the %3 language.")
1760 .arg((
type) ?
"EIA-708" :
"EIA-608")
1776 AVStream* st =
m_ic->streams[av_index];
1777 const AVDictionaryEntry* language_dictionary_entry =
1778 av_dict_get(st->metadata,
"language",
nullptr, 0);
1780 if (language_dictionary_entry ==
nullptr ||
1781 language_dictionary_entry->value ==
nullptr ||
1782 st->codecpar->extradata ==
nullptr
1788 std::vector<std::string_view> languages {
StringUtil::split_sv(language_dictionary_entry->value,
","sv)};
1790 if (st->codecpar->extradata_size !=
static_cast<int>(languages.size() * 2))
1794 for (
size_t i = 0; i < languages.size(); i++)
1796 if (languages[i].size() != 3)
1802 uint8_t teletext_type = st->codecpar->extradata[i * 2] >> 3;
1803 uint8_t teletext_magazine_number = st->codecpar->extradata[i * 2] & 0x7;
1804 if (teletext_magazine_number == 0)
1805 teletext_magazine_number = 8;
1806 uint8_t teletext_page_number = st->codecpar->extradata[(i * 2) + 1];
1807 if (teletext_type == 2 || teletext_type == 1)
1809 TrackType track = (teletext_type == 2) ?
1812 m_tracks[track].emplace_back(av_index, 0, language,
1813 (
static_cast<unsigned>(teletext_magazine_number) << 8) | teletext_page_number);
1814 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1815 QString(
"Teletext stream #%1 (%2) is in the %3 language on page %4 %5.")
1816 .arg(QString::number(i),
1817 (teletext_type == 2) ?
"Caption" :
"Menu",
1819 QString::number(teletext_magazine_number),
1820 QString::number(teletext_page_number)));
1829 AVDictionaryEntry *metatag =
1830 av_dict_get(
m_ic->streams[av_stream_index]->metadata,
"language",
nullptr,
1832 bool forced = (
m_ic->streams[av_stream_index]->disposition & AV_DISPOSITION_FORCED) != 0;
1835 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1836 QString(
"Text Subtitle track #%1 is A/V stream #%2 "
1837 "and is in the %3 language(%4), forced=%5.")
1840 StreamInfo si {av_stream_index, 0, lang, 0, forced};
1850 if (
m_itv ==
nullptr)
1852 if (
m_itv ==
nullptr)
1856 if (!pmt_buffer.has_buffer())
1867 LOG(VB_DSMCC, LOG_NOTICE, QString(
"ScanDSMCCStreams Found Object Carousel in Stream %1").arg(QString::number(i)));
1873 for (
const auto *desc : desc_list)
1876 uint length = *desc++;
1877 const unsigned char *endDesc = desc+length;
1878 uint dataBroadcastId = desc[0]<<8 | desc[1];
1879 LOG(VB_DSMCC, LOG_NOTICE, QString(
"ScanDSMCCStreams dataBroadcastId %1").arg(QString::number(dataBroadcastId)));
1880 if (dataBroadcastId != 0x0106)
1883 while (desc != endDesc)
1885 [[maybe_unused]]
uint appTypeCode = desc[0]<<8 | desc[1];
1887 uint appSpecDataLen = *desc++;
1889 LOG(VB_DSMCC, LOG_NOTICE, QString(
"ScanDSMCCStreams AppTypeCode %1").arg(QString::number(appTypeCode)));
1890 if (appTypeCode == 0x101)
1892 const unsigned char *subDescEnd = desc + appSpecDataLen;
1893 while (desc < subDescEnd)
1895 uint sub_desc_tag = *desc++;
1896 uint sub_desc_len = *desc++;
1898 if (sub_desc_tag == 1)
1899 m_itv->SetNetBootInfo(desc, sub_desc_len);
1900 desc += sub_desc_len;
1906 desc += appSpecDataLen;
1920 const AVCodec *codec =
nullptr;
1921 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Trying to select best video track");
1935 int stream_index = av_find_best_stream(
m_ic, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);
1937 if (stream_index < 0)
1939 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"No video track found/selected.");
1940 return stream_index;
1943 AVStream *stream =
m_ic->streams[stream_index];
1954 if (codecContext->codec_type == AVMEDIA_TYPE_VIDEO)
1955 codectype += QString(
"(%1x%2)").arg(codecContext->width).arg(codecContext->height);
1956 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1957 QString(
"Selected track #%1: ID: 0x%2 Codec ID: %3 Profile: %4 Type: %5 Bitrate: %6")
1958 .arg(stream_index).arg(
static_cast<uint64_t
>(stream->id), 0, 16)
1959 .arg(avcodec_get_name(codecContext->codec_id),
1960 avcodec_profile_name(codecContext->codec_id, codecContext->profile),
1962 QString::number(codecContext->bit_rate)));
1969 if ((codecContext->width != stream->codecpar->width) || (codecContext->height != stream->codecpar->height))
1971 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
1972 "Video resolution mismatch: Context: %1x%2 Stream: %3x%4 Codec: %5 Stream change: %6")
1973 .arg(codecContext->width).arg(codecContext->height)
1974 .arg(stream->codecpar->width).arg(stream->codecpar->height)
1981 int width = std::max(dim.width(), 16);
1982 int height = std::max(dim.height(), 16);
1983 QString dec =
"ffmpeg";
1984 uint thread_count = 1;
1986 if (codecContext->codec)
1987 codecName = codecContext->codec->name;
1992 if (codecContext->framerate.den && codecContext->framerate.num)
1993 m_fps = float(codecContext->framerate.num) / float(codecContext->framerate.den);
1997 bool foundgpudecoder =
false;
1998 QStringList unavailabledecoders;
2008 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
2009 "GPU/hardware decoder '%1' failed - forcing software decode")
2016 while (unavailabledecoders.size() < 10)
2020 if (!unavailabledecoders.isEmpty())
2022 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Unavailable decoders: %1")
2023 .arg(unavailabledecoders.join(
",")));
2029 if (!skip_loop_filter)
2030 codecContext->skip_loop_filter = AVDISCARD_NONKEY;
2038 if (
version && allowgpu && dec !=
"ffmpeg")
2042 codecContext->opaque =
static_cast<void*
>(
this);
2047 codecContext->opaque =
static_cast<void*
>(
this);
2049 foundgpudecoder =
true;
2054 unavailabledecoders.append(dec);
2062 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unknown video codec - defaulting to MPEG2");
2077 if (!foundgpudecoder)
2079 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Using %1 CPUs for decoding")
2080 .arg(thread_count));
2081 codecContext->thread_count =
static_cast<int>(thread_count);
2095 return stream_index;
2100 AVProgram* program = av_find_program_from_stream(
m_ic,
nullptr, stream_index);
2101 if (program ==
nullptr)
2106 LOG(VB_PLAYBACK, LOG_INFO,
2107 QString(
"Removing streams not in Program %1 from track selection.")
2108 .arg(QString::number(program->id)));
2110 const auto *
const begin = program->stream_index;
2111 const auto *
const end = program->stream_index + program->nb_stream_indexes;
2115 LOG(VB_PLAYBACK, LOG_DEBUG,
2116 QString(
"Size before: %1").arg(QString::number(track_list.size())));
2117 track_list.erase(std::remove_if(track_list.begin(), track_list.end(),
2120 return std::find(begin, end, i.m_av_stream_index) == end;
2121 }), track_list.end());
2122 LOG(VB_PLAYBACK, LOG_DEBUG,
2123 QString(
"Size after: %1").arg(QString::number(track_list.size())));
2129 return (ch_layout.order == AV_CHANNEL_ORDER_CUSTOM) &&
2130 (ch_layout.nb_channels == 2) &&
2131 (ch_layout.u.map[0].id == AV_CHAN_FRONT_CENTER) &&
2132 (ch_layout.u.map[1].id == AV_CHAN_FRONT_CENTER);
2140 bool unknownbitrate =
false;
2144 constexpr std::array<TrackType, 6>
types {
2158 std::map<int,uint> lang_sub_cnt;
2159 uint subtitleStreamCount = 0;
2160 std::map<int,uint> lang_aud_cnt;
2161 uint audioStreamCount = 0;
2170 if (
m_ic ==
nullptr)
2173 for (
uint strm = 0; strm <
m_ic->nb_streams; strm++)
2175 AVCodecParameters *par =
m_ic->streams[strm]->codecpar;
2178 if (par->codec_type == AVMEDIA_TYPE_VIDEO)
2179 codectype += QString(
"(%1x%2)").arg(par->width).arg(par->height);
2180 QString program_id =
"null";
2181 if (av_find_program_from_stream(
m_ic,
nullptr, strm) !=
nullptr)
2183 program_id = QString::number(av_find_program_from_stream(
m_ic,
nullptr, strm)->
id);
2185 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2186 QString(
"Stream #%1: ID: 0x%2 Program ID: %3 Codec ID: %4 Type: %5 Bitrate: %6").arg(
2187 QString::number(strm),
2188 QString::number(
static_cast<uint64_t
>(
m_ic->streams[strm]->id), 16),
2190 avcodec_get_name(par->codec_id),
2192 QString::number(par->bit_rate))
2195 switch (par->codec_type)
2197 case AVMEDIA_TYPE_VIDEO:
2205 if (ctx && (ctx->hw_frames_ctx || ctx->hw_device_ctx))
2212 LOG(VB_GENERAL, LOG_ERR,
LOC +
2213 QString(
"Stream #%1 has an unknown video "
2214 "codec id, skipping.").arg(strm));
2226 if (par->bit_rate == 0)
2228 static constexpr int64_t s_baseBitrate { 1000000LL };
2230 if (par->width && par->height)
2232 static const int s_baseSize = 1920 * 1080;
2233 multiplier = ((par->width * par->height) + s_baseSize - 1) / s_baseSize;
2234 multiplier = std::max(multiplier, 1);
2236 par->bit_rate = s_baseBitrate * multiplier;
2237 unknownbitrate =
true;
2243 case AVMEDIA_TYPE_AUDIO:
2245 LOG(VB_GENERAL, LOG_INFO,
LOC +
2246 QString(
"codec %1 has %2 channels")
2247 .arg(avcodec_get_name(par->codec_id))
2248 .arg(par->ch_layout.nb_channels));
2253 case AVMEDIA_TYPE_SUBTITLE:
2255 if (par->codec_id == AV_CODEC_ID_DVB_TELETEXT)
2257 if (par->codec_id == AV_CODEC_ID_TEXT)
2261 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"subtitle codec (%1)")
2265 case AVMEDIA_TYPE_DATA:
2267 if (par->codec_id == AV_CODEC_ID_DVB_VBI)
2270 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"data codec (%1)")
2274 case AVMEDIA_TYPE_ATTACHMENT:
2276 if (par->codec_id == AV_CODEC_ID_TTF)
2279 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2280 QString(
"Attachment codec (%1)")
2287 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
2288 QString(
"Unknown codec type (%1)")
2294 if (par->codec_type != AVMEDIA_TYPE_AUDIO &&
2295 par->codec_type != AVMEDIA_TYPE_SUBTITLE)
2299 if (par->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2300 (par->codec_id == AV_CODEC_ID_DVB_TELETEXT ||
2301 par->codec_id == AV_CODEC_ID_TEXT))
2304 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Looking for decoder for %1")
2305 .arg(avcodec_get_name(par->codec_id)));
2307 if (par->codec_id == AV_CODEC_ID_PROBE)
2309 LOG(VB_GENERAL, LOG_ERR,
LOC +
2310 QString(
"Probing of stream #%1 unsuccesful, ignoring.").arg(strm));
2316 if (codecContext ==
nullptr)
2318 LOG(VB_GENERAL, LOG_WARNING,
LOC +
2319 QString(
"Could not find decoder for codec (%1), ignoring.")
2320 .arg(avcodec_get_name(par->codec_id)));
2321 LOG(VB_LIBAV, LOG_INFO,
"For a list of all codecs, run `mythffmpeg -codecs`.");
2325 if (codecContext->codec && par->codec_id != codecContext->codec_id)
2327 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2328 QString(
"Already opened codec not matching (%1 vs %2). Reopening")
2329 .arg(avcodec_get_name(codecContext->codec_id),
2330 avcodec_get_name(codecContext->codec->id)));
2334 if (!
OpenAVCodec(codecContext, codecContext->codec))
2346 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2347 QString(
"Stream 0x%1 is not valid in this context - skipping")
2348 .arg(
m_ic->streams[strm]->id, 4, 16));
2352 if (par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2354 bool forced = (
m_ic->streams[strm]->disposition & AV_DISPOSITION_FORCED) != 0;
2356 uint lang_indx = lang_sub_cnt[lang]++;
2357 subtitleStreamCount++;
2360 static_cast<int>(strm),
m_ic->streams[strm]->id, lang, lang_indx, forced);
2362 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2363 QString(
"Subtitle track #%1 is A/V stream #%2 "
2364 "and is in the %3 language(%4).")
2369 if (par->codec_type == AVMEDIA_TYPE_AUDIO)
2373 uint lang_indx = lang_aud_cnt[lang]++;
2376 int stream_id =
m_ic->streams[strm]->id;
2380 if (stream_id == -1)
2388 static_cast<int>(strm), stream_id, lang, lang_indx,
type);
2392 lang_indx = lang_aud_cnt[lang]++;
2394 static_cast<int>(strm), stream_id, lang, lang_indx,
type);
2397 LOG(VB_AUDIO, LOG_INFO,
LOC +
2398 QString(
"Audio Track #%1, of type (%2) is A/V stream #%3 (id=0x%4) "
2399 "and has %5 channels in the %6 language(%7).")
2401 .arg(strm).arg(
m_ic->streams[strm]->id,0,16).arg(codecContext->ch_layout.nb_channels)
2427 QString(
m_ic->iformat->name).contains(
"matroska"));
2469 for (
unsigned i = 0; i <
m_ic->nb_programs; i++)
2481#if CONFIG_MEDIACODEC
2482 if (QString(
"mediacodec") == codec->wrapper_name)
2483 av_jni_set_java_vm(QAndroidJniEnvironment::javaVM(),
nullptr);
2485 int ret = avcodec_open2(avctx, codec,
nullptr);
2490 LOG(VB_GENERAL, LOG_ERR,
LOC +
2491 QString(
"Could not open codec 0x%1, id(%2) type(%3) "
2492 "ignoring. reason %4").arg((uint64_t)avctx,0,16)
2493 .arg(avcodec_get_name(avctx->codec_id),
2499 LOG(VB_GENERAL, LOG_INFO,
LOC +
2500 QString(
"Opened codec 0x%1, id(%2) type(%3)")
2501 .arg((uint64_t)avctx,0,16)
2502 .arg(avcodec_get_name(avctx->codec_id),
2527 if (si.m_language_index == Index)
2528 return si.m_language;
2535 AVDictionaryEntry *metatag = av_dict_get(
m_ic->streams[StreamIndex]->metadata,
"language",
nullptr, 0);
2578 AVStream *stream =
m_ic->streams[StreamIndex];
2582 if (stream->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
2584 else if (stream->disposition & AV_DISPOSITION_COMMENT)
2586 else if (stream->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
2588 else if (stream->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
2615 if (
current->m_av_stream_index == streamIndex)
2621 LOG(VB_GENERAL, LOG_WARNING,
LOC +
2622 QString(
"Invalid stream index passed to "
2623 "SetupAudioStreamSubIndexes: %1").arg(streamIndex));
2630 if (
current->m_av_substream_index == -1)
2643 (next->m_av_stream_index != streamIndex))
2645 QString msg = QString(
2646 "Expected substream 1 (Language I) of stream %1\n\t\t\t"
2647 "following substream 0, found end of list or another stream.")
2650 LOG(VB_GENERAL, LOG_WARNING,
LOC + msg);
2672 bool do_flush =
false;
2673 for (
uint i = 0; i <
m_ic->nb_streams; i++)
2675 AVStream *st =
m_ic->streams[i];
2678 if (avctx && avctx->codec_type == AVMEDIA_TYPE_AUDIO)
2681 LOG(VB_LIBAV, LOG_DEBUG, QString(
"removing audio stream (id: 0x%1, index: %2, nb_streams: %3)")
2682 .arg(QString::number(st->id, 16),
2684 QString::number(
m_ic->nb_streams)
2688 if ((
m_ic->nb_streams - i) > 0) {
2689 std::memmove(
reinterpret_cast<void*
>(&
m_ic->streams[i]),
2690 reinterpret_cast<const void*
>(&
m_ic->streams[i + 1]),
2691 (
m_ic->nb_streams - i) *
sizeof(AVFormatContext*));
2695 m_ic->streams[i] =
nullptr;
2703 avformat_flush(
m_ic);
2712 if (!std::any_of(decoder->m_renderFormats->cbegin(), decoder->m_renderFormats->cend(),
2713 [&
type](
auto Format) { return type == Format; }))
2715 decoder->m_directRendering =
false;
2716 return avcodec_default_get_buffer2(c, pic, flags);
2719 decoder->m_directRendering =
true;
2720 MythVideoFrame *frame = decoder->GetPlayer()->GetNextVideoFrame();
2730 if ((frame->
m_type !=
type) || (pic->width > width) || (pic->height > height))
2747 for (
uint i = 0; i < 3; i++)
2753 pic->opaque = frame;
2756 AVBufferRef *buffer = av_buffer_create(
reinterpret_cast<uint8_t*
>(frame), 0,
2757 [](
void* Opaque, uint8_t* Data)
2761 if (avfd && avfd->GetPlayer())
2762 avfd->GetPlayer()->DeLimboFrame(vf);
2765 pic->buf[0] = buffer;
2771int get_avf_buffer_dxva2(
struct AVCodecContext *c,
AVFrame *pic,
int )
2776 for (
int i = 0; i < 4; i++)
2778 pic->data[i] =
nullptr;
2779 pic->linesize[i] = 0;
2781 pic->opaque = frame;
2783 pic->data[0] = (uint8_t*)frame->
m_buffer;
2784 pic->data[3] = (uint8_t*)frame->
m_buffer;
2787 AVBufferRef *buffer =
2788 av_buffer_create((uint8_t*)frame, 0,
2789 [](
void* Opaque, uint8_t* Data)
2797 pic->buf[0] = buffer;
2808 bool had_608 =
false;
2809 bool had_708 =
false;
2810 for (
uint cur = 0; cur + 2 < buf_size; cur += 3)
2812 uint cc_code = buf[cur];
2813 bool cc_valid = (cc_code & 0x04) != 0U;
2815 uint data1 = buf[cur+1];
2816 uint data2 = buf[cur+2];
2817 uint data = (data2 << 8) | data1;
2818 uint cc_type = cc_code & 0x03;
2843 bool check_608,
bool check_708)
2845 bool need_change_608 =
false;
2850 for (
uint i = 0; i < 4; i++)
2857 bool need_change_708 =
false;
2859 if (check_708 || need_change_608)
2862 for (
uint i = 1; i < 64 && !need_change_608 && !need_change_708; i++)
2867 if (need_change_708 && !check_608)
2871 if (!need_change_608 && !need_change_708)
2882 for (
int i = 1; i < 64; i++)
2891 for (
int i = 0; i < 4; i++)
2912 AVPacket *pkt,
bool can_reliably_parse_keyframes)
2917 bool reset_kfd =
false;
2921 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2922 "gopset not set, syncing positionMap");
2924 if (tempKeyFrameDist > 0 && !
m_livetv)
2926 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2927 QString(
"Initial key frame distance: %1.")
2933 else if (
m_keyframeDist != tempKeyFrameDist && tempKeyFrameDist > 0)
2935 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2936 QString(
"Key frame distance changed from %1 to %2.")
2964 if (can_reliably_parse_keyframes &&
2967 long long last_frame = 0;
2975 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
2976 QString(
"framesRead: %1 last_frame: %2 keyframedist: %3")
2983 long long startpos = pkt->pos;
2985 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
2986 QString(
"positionMap[ %1 ] == %2.")
3016 float bytespersec = (float)
m_bitrate / 8;
3033 const uint8_t *bufptr = pkt->data;
3034 const uint8_t *bufend = pkt->data + pkt->size;
3036 while (bufptr < bufend)
3040 float aspect_override = -1.0F;
3049 if (bufptr + 11 >= pkt->data + pkt->size)
3051 const auto *seq =
reinterpret_cast<const SequenceHeader*
>(bufptr);
3053 int width =
static_cast<int>(seq->width()) >> context->lowres;
3054 int height =
static_cast<int>(seq->height()) >> context->lowres;
3055 float aspect = seq->
aspect(context->codec_id == AV_CODEC_ID_MPEG1VIDEO);
3056 if (stream->sample_aspect_ratio.num)
3057 aspect =
static_cast<float>(av_q2d(stream->sample_aspect_ratio) * width / height);
3058 if (aspect_override > 0.0F)
3059 aspect = aspect_override;
3060 float seqFPS = seq->fps();
3064 changed |= (seqFPS >
static_cast<float>(
m_fps)+0.01F) ||
3065 (seqFPS < static_cast<float>(
m_fps)-0.01F);
3069 bool forceaspectchange = !qFuzzyCompare(
m_currentAspect + 10.0F, aspect + 10.0F) &&
3073 if (changed || forceaspectchange)
3078 bool doublerate =
false;
3081 forceaspectchange, 2,
3084 if (context->hw_frames_ctx)
3085 if (context->internal)
3086 avcodec_flush_buffers(context);
3100 if ((seqFPS > avFPS+0.01F) || (seqFPS < avFPS-0.01F))
3102 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"avFPS(%1) != seqFPS(%2)")
3103 .arg(
static_cast<double>(avFPS)).arg(
static_cast<double>(seqFPS)));
3112 pkt->flags |= AV_PKT_FLAG_KEY;
3119 pkt->flags |= AV_PKT_FLAG_KEY;
3127 const uint8_t *buf = pkt->data;
3128 const uint8_t *buf_end = pkt->data + pkt->size;
3133 if (context->extradata && (context->extradata_size >= 7) && (context->extradata[0] == 0x01))
3135 if (pkt->flags & AV_PKT_FLAG_KEY)
3140 while (buf < buf_end)
3171 bool fps_changed = (seqFPS > 0.0) && ((seqFPS >
m_fps + 0.01) ||
3172 (seqFPS <
m_fps - 0.01));
3177 if (fps_changed || res_changed || forcechange)
3182 bool doublerate =
false;
3195 if (context->hw_frames_ctx && (forcechange || res_changed))
3196 if (context->internal)
3197 avcodec_flush_buffers(context);
3203 m_fps =
static_cast<float>(seqFPS);
3213 if ((seqFPS > avFPS + 0.01) || (seqFPS < avFPS - 0.01))
3215 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
3216 QString(
"avFPS(%1) != seqFPS(%2)").arg(avFPS).arg(seqFPS));
3221 pkt->flags |= AV_PKT_FLAG_KEY;
3241 if (pkt->flags & AV_PKT_FLAG_KEY)
3257 !(pkt->flags & AV_PKT_FLAG_KEY))
3259 av_packet_unref(pkt);
3293 bool sentPacket =
false;
3313 if (ret == AVERROR(EAGAIN))
3317 if (ret==0 && !gotpicture)
3319 ret2 = avcodec_send_packet(context, pkt);
3320 if (ret2 == AVERROR(EAGAIN))
3332 if (ret < 0 || ret2 < 0)
3337 LOG(VB_GENERAL, LOG_ERR,
LOC +
3338 QString(
"video avcodec_receive_frame error: %1 (%2) gotpicture:%3")
3340 .arg(ret).arg(gotpicture));
3345 LOG(VB_GENERAL, LOG_ERR,
LOC +
3346 QString(
"video avcodec_send_packet error: %1 (%2) gotpicture:%3")
3348 .arg(ret2).arg(gotpicture));
3362 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Decoder needs reset");
3366 if (ret == AVERROR_EXTERNAL || ret2 == AVERROR_EXTERNAL)
3368 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"FFmpeg external library error - assuming streams changed");
3380 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
3381 QString(
"video timecodes packet-pts:%1 frame-pts:%2 packet-dts: %3 frame-dts:%4")
3382 .arg(pkt->pts).arg(mpa_pic->pts).arg(pkt->dts)
3383 .arg(mpa_pic->pkt_dts));
3392 auto *newPkt = av_packet_clone(pkt);
3402 auto * side_data = av_frame_get_side_data(AvFrame, AV_FRAME_DATA_A53_CC);
3403 if (side_data && (side_data->size > 0))
3416 frame->m_directRendering =
false;
3427 av_image_fill_arrays(tmppicture.data, tmppicture.linesize,
3428 frame->m_buffer, AV_PIX_FMT_YUV420P, AvFrame->width,
3429 AvFrame->height, IMAGE_ALIGN);
3430 tmppicture.data[0] = frame->m_buffer + frame->m_offsets[0];
3431 tmppicture.data[1] = frame->m_buffer + frame->m_offsets[1];
3432 tmppicture.data[2] = frame->m_buffer + frame->m_offsets[2];
3433 tmppicture.linesize[0] = frame->m_pitches[0];
3434 tmppicture.linesize[1] = frame->m_pitches[1];
3435 tmppicture.linesize[2] = frame->m_pitches[2];
3439 AvFrame->height,
static_cast<AVPixelFormat
>(AvFrame->format),
3440 AvFrame->width, AvFrame->height,
3441 AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
3442 nullptr,
nullptr,
nullptr);
3445 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to allocate sws context");
3448 sws_scale(
m_swsCtx, AvFrame->data, AvFrame->linesize, 0, dim.height(),
3449 tmppicture.data, tmppicture.linesize);
3457 oldframe->
m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3458 oldframe->
m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3484 LOG(VB_GENERAL, LOG_ERR,
LOC +
"NULL videoframe - direct rendering not "
3485 "correctly initialized.");
3490 if (AvFrame->best_effort_timestamp == AV_NOPTS_VALUE)
3492 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No PTS found - unable to process video.");
3496 AvFrame->best_effort_timestamp * 1000);
3497 std::chrono::milliseconds temppts =
pts;
3514 double calcfps = 1000.0 /
ptsdiff.count();
3515 if (calcfps < 121.0 && calcfps > 3.0)
3519 double fpschange = calcfps /
m_fps;
3521 if (fpschange > 1.9 && fpschange < 2.1)
3523 if (fpschange > 0.9 && fpschange < 1.1)
3529 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
3530 QString(
"video timecode %1 %2 %3 %4%5")
3531 .arg(AvFrame->best_effort_timestamp)
3532 .arg(
pts.count()).arg(temppts.count()).arg(
m_lastVPts.count())
3533 .arg((
pts != temppts) ?
" fixup" :
""));
3535 frame->m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3536 frame->m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3538 frame->m_repeatPic = AvFrame->repeat_pict != 0;
3543 frame->m_colorspace = AvFrame->colorspace;
3544 frame->m_colorrange = AvFrame->color_range;
3545 frame->m_colorprimaries = AvFrame->color_primaries;
3546 frame->m_colortransfer = AvFrame->color_trc;
3547 frame->m_chromalocation = AvFrame->chroma_location;
3548 frame->m_pixFmt = AvFrame->format;
3553 frame->m_dummy =
false;
3554 frame->m_pauseFrame =
false;
3555 frame->m_deinterlaceInuse2x =
false;
3556 frame->m_alreadyDeinterlaced =
false;
3557 frame->m_interlacedReverse =
false;
3587 [[maybe_unused]]
const AVStream *stream,
const AVPacket *pkt)
3589 const uint8_t *buf = pkt->data;
3590 uint64_t linemask = 0;
3595 if ((buf[0]==
't') && (buf[1]==
'v') && (buf[2] ==
'0'))
3598 memcpy(&linemask, buf + 3, 8);
3601 else if ((buf[0]==
'T') && (buf[1]==
'V') && (buf[2] ==
'0'))
3603 linemask = 0xffffffffffffffffLL;
3608 LOG(VB_VBI, LOG_ERR,
LOC + QString(
"Unknown VBI data stream '%1%2%3'")
3609 .arg(QChar(buf[0])).arg(QChar(buf[1])).arg(QChar(buf[2])));
3613 static constexpr uint kMinBlank = 6;
3614 for (
uint i = 0; i < 36; i++)
3616 if (!((linemask >> i) & 0x1))
3619 const uint line = ((i < 18) ? i : i-18) + kMinBlank;
3620 const uint field = (i<18) ? 0 : 1;
3621 const uint id2 = *buf & 0xf;
3645 int data = (buf[2] << 8) | buf[1];
3672 const AVStream* ,
const AVPacket *pkt)
3681 const uint8_t *buf = pkt->data;
3682 const uint8_t *buf_end = pkt->data + pkt->size;
3684 if (*buf >= 0x10 && *buf <= 0x1F)
3690 LOG(VB_VBI, LOG_WARNING,
LOC +
3691 QString(
"VBI: Unknown data_identier: %1 discarded").arg(*buf));
3696 while (buf < buf_end)
3701 if ((buf_end - buf) >= 42)
3705 else if (*buf == 0x03)
3708 if ((buf_end - buf) >= 42)
3712 else if (*buf == 0xff)
3718 LOG(VB_VBI, LOG_WARNING,
LOC +
3719 QString(
"VBI: Unsupported data_unit_id: %1 discarded").arg(*buf));
3729 [[maybe_unused]]
const AVPacket *pkt)
3732 if (
m_itv ==
nullptr)
3734 if (
m_itv ==
nullptr)
3738 uint8_t *data = pkt->data;
3739 int length = pkt->size;
3740 int componentTag = 0;
3741 int dataBroadcastId = 0;
3742 unsigned carouselId = 0;
3745 componentTag = str->component_tag;
3746 dataBroadcastId = str->data_id;
3747 carouselId = (unsigned) str->carousel_id;
3752 uint16_t sectionLen = (((data[1] & 0xF) << 8) | data[2]) + 3;
3754 if (sectionLen > length)
3757 m_itv->ProcessDSMCCSection(data, sectionLen,
3758 componentTag, carouselId,
3760 length -= sectionLen;
3771 long long pts = pkt->pts;
3772 if (
pts == AV_NOPTS_VALUE)
3774 if (
pts == AV_NOPTS_VALUE)
3776 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No PTS found - unable to process subtitle.");
3779 pts =
static_cast<long long>(av_q2d(curstream->time_base) *
pts * 1000);
3785 bool isForcedTrack =
false;
3788 int gotSubtitles = 0;
3789 AVSubtitle subtitle;
3790 memset(&subtitle, 0,
sizeof(AVSubtitle));
3797 curstream->id,
pts);
3801 if (pkt->stream_index == subIdx)
3805 pkt->data, pkt->size,
pts);
3811 || pkt->stream_index == forcedSubIdx)
3814 avcodec_decode_subtitle2(codecContext, &subtitle, &gotSubtitles, pkt);
3817 subtitle.start_display_time +=
pts;
3818 subtitle.end_display_time +=
pts;
3820 if (pkt->stream_index != subIdx)
3821 isForcedTrack =
true;
3828 for (
unsigned i = 0; i < subtitle.num_rects; i++)
3830 subtitle.rects[i]->flags |= AV_SUBTITLE_FLAG_FORCED;
3833 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
3834 QString(
"subtl timecode %1 %2 %3 %4")
3835 .arg(pkt->pts).arg(pkt->dts)
3836 .arg(subtitle.start_display_time)
3837 .arg(subtitle.end_display_time));
3840 subtitle, curstream->codecpar->codec_id == AV_CODEC_ID_XSUB,
3854 auto id =
static_cast<uint>(Packet->stream_index + 0x2000);
3858#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
3859 const auto * codec = QTextCodec::codecForName(
"utf-8");
3860 auto text = codec->toUnicode(
reinterpret_cast<const char *
>(Packet->data), Packet->size - 1);
3862 auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);
3863 QString text = toUtf16.decode(Packet->data);
3865 auto list = text.split(
'\n', Qt::SkipEmptyParts);
3873 enum AVCodecID codec_id = curstream->codecpar->codec_id;
3877 case AV_CODEC_ID_DVB_VBI:
3880 case AV_CODEC_ID_DSMCC_B:
3905 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio stream type " + msg +
"changed.");
3919 QString forcedString = forced ? QObject::tr(
" (forced)") :
"";
3921 int av_index =
m_tracks[
type][TrackNo].m_av_stream_index;
3922 AVStream *stream {
nullptr };
3923 if (av_index >= 0 && av_index < (
int)
m_ic->nb_streams)
3924 stream =
m_ic->streams[av_index];
3925 AVDictionaryEntry *entry =
3926 stream ? av_dict_get(stream->metadata,
"title",
nullptr, 0) :
nullptr;
3927 QString user_title = entry ? QString(R
"( "%1")").arg(entry->value) : "";
3939 AVCodecParameters *par = stream->codecpar;
3941 if (par->codec_id == AV_CODEC_ID_MP3)
3942 msg += QString(
" MP3");
3943 else if (ctx && ctx->codec)
3944 msg += QString(
" %1").arg(ctx->codec->name).toUpper();
3945 if (!user_title.isEmpty())
3948 int channels = par->ch_layout.nb_channels;
3951 msg += QString(
" ?ch");
3952 else if((channels > 4) && !(channels & 1))
3953 msg += QString(
" %1.1ch").arg(channels - 1);
3955 msg += QString(
" %1ch").arg(channels);
3965 if (!user_title.isEmpty())
3968 msg += QString(
" (%1)")
3972 return QString(
"%1: %2").arg(TrackNo + 1).arg(msg);
3976 return QObject::tr(
"Subtitle") + QString(
" %1: %2%3%4")
3977 .arg(QString::number(TrackNo + 1),
4005 return ctx ? QByteArray(
reinterpret_cast<char*
>(ctx->subtitle_header), ctx->subtitle_header_size) :
4016 AVDictionaryEntry *tag = av_dict_get(
m_ic->streams[index]->metadata,
"filename",
nullptr, 0);
4018 Filename = QByteArray(tag->value);
4019 AVCodecParameters *par =
m_ic->streams[index]->codecpar;
4020 Data = QByteArray(
reinterpret_cast<char*
>(par->extradata), par->extradata_size);
4030 if ((stream->component_tag == Tag) || ((Tag <= 0) && stream->component_tag <= 0))
4039 for (
uint i = 0; i <
m_ic->nb_streams; i++)
4041 AVStream *stream =
m_ic->streams[i];
4044 if (stream->component_tag == Tag)
4068 const std::vector<int> &ftype)
4070 std::vector<int> ret;
4072 for (
int index : ftype)
4074 if ((lang_key < 0) || tracks[index].m_language == lang_key)
4075 ret.push_back(index);
4083 std::vector<int> ret;
4085 for (
size_t i = 0; i < tracks.size(); i++)
4087 if (tracks[i].m_audio_type ==
type)
4096 const std::vector<int>&fs,
4097 enum AVCodecID codecId,
4100 int selectedTrack = -1;
4105 const int stream_index = tracks[f].m_av_stream_index;
4106 AVCodecParameters *par = ic->streams[stream_index]->codecpar;
4107 if ((codecId == AV_CODEC_ID_NONE || codecId == par->codec_id) &&
4108 (max_seen < par->ch_layout.nb_channels))
4110 if (codecId == AV_CODEC_ID_DTS &&
profile > 0)
4117 max_seen = par->ch_layout.nb_channels;
4121 return selectedTrack;
4129 std::vector<int> flang =
filter_lang(atracks, lang_key, ftype);
4134 AV_PROFILE_DTS_HD_MA);
4145 AV_PROFILE_DTS_HD_HRA);
4221 uint numStreams = atracks.size();
4225 if ((ctrack >= 0) && (ctrack < (
int)numStreams))
4228 LOG(VB_AUDIO, LOG_DEBUG, QString(
"%1 available audio streams").arg(numStreams));
4229 for (
const auto & track : atracks)
4231 AVCodecParameters *codecpar =
m_ic->streams[track.m_av_stream_index]->codecpar;
4232 LOG(VB_AUDIO, LOG_DEBUG, QString(
"%1: %2 bps, %3 Hz, %4 channels, passthrough(%5)")
4233 .arg(avcodec_get_name(codecpar->codec_id), QString::number(codecpar->bit_rate),
4234 QString::number(codecpar->sample_rate), QString::number(codecpar->ch_layout.nb_channels),
4239 if (1 == numStreams)
4249 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Trying to reselect audio sub-stream");
4255 for (
uint i = 0; i < numStreams; i++)
4257 if (atracks[i].m_av_substream_index == substream_index)
4265 if ((selTrack < 0) && wlang >= -1)
4267 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Trying to reselect audio track");
4272 for (
uint i = 0; i < numStreams; i++)
4274 if (wlang == atracks[i].m_language)
4278 if (windx == atracks[i].m_language_index)
4286 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Trying to select audio track (w/lang)");
4293 LOG(VB_AUDIO, LOG_WARNING,
"No audio tracks matched the type filter, "
4294 "so trying all tracks.");
4295 for (
int i = 0; i < static_cast<int>(atracks.size()); i++)
4321 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Trying to select default track");
4322 for (
size_t i = 0; i < atracks.size(); i++) {
4323 int idx = atracks[i].m_av_stream_index;
4324 if (
m_ic->streams[idx]->disposition & AV_DISPOSITION_DEFAULT)
4335 LOG(VB_AUDIO, LOG_INFO,
LOC +
4336 "Trying to select audio track (wo/lang)");
4346 if (ctrack != selTrack)
4348 LOG(VB_AUDIO, LOG_INFO,
LOC +
"No suitable audio track exists.");
4355 strack = atracks[selTrack];
4360 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Selected track %1 (A/V Stream #%2)")
4369 char *buffer,
int bufsize)
4380 const uint halfsample = samplesize >> 1;
4382 const char *from = (channel == 1) ? buffer + halfsample : buffer;
4383 char *to = (channel == 0) ? buffer + halfsample : buffer;
4386 (sample++), (from += samplesize), (to += samplesize))
4388 memmove(to, from, halfsample);
4397 bool firstloop =
true;
4398 int decoded_size = -1;
4405 AVPacket *tmp_pkt = av_packet_alloc();
4406 tmp_pkt->data = pkt->data;
4407 tmp_pkt->size = pkt->size;
4408 while (tmp_pkt->size > 0)
4410 bool reselectAudioTrack =
false;
4415 LOG(VB_AUDIO, LOG_INFO,
LOC +
4416 "Audio is disabled - trying to restart it");
4417 reselectAudioTrack =
true;
4422 bool wasDual = audSubIdx != -1;
4424 if ((wasDual && !isDual) || (!wasDual && isDual))
4427 reselectAudioTrack =
true;
4432 bool already_decoded =
false;
4433 if (!context->ch_layout.nb_channels)
4445 AVChannelLayout channel_layout;
4447 av_opt_set_chlayout(context->priv_data,
"downmix", &channel_layout, 0);
4449 if (context->codec_id == AV_CODEC_ID_AC3)
4454 decoded_size = data_size;
4455 already_decoded =
true;
4456 reselectAudioTrack |= context->ch_layout.nb_channels;
4460 if (reselectAudioTrack)
4470 if (!(decodetype &
kDecodeAudio) || (pkt->stream_index != audIdx)
4474 if (firstloop && pkt->pts != AV_NOPTS_VALUE)
4487 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Audio stream changed");
4490 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Number of audio channels changed from %1 to %2")
4502 if (!already_decoded)
4507 decoded_size = data_size;
4515 data_size = tmp_pkt->size;
4521 if (!already_decoded)
4525 AVChannelLayout channel_layout;
4527 av_opt_set_chlayout(context->priv_data,
"downmix", &channel_layout, 0);
4531 decoded_size = data_size;
4538 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unknown audio decoding error");
4539 av_packet_free(&tmp_pkt);
4545 tmp_pkt->data += ret;
4546 tmp_pkt->size -= ret;
4550 std::chrono::milliseconds temppts =
m_lastAPts;
4557 int frames = (context->ch_layout.nb_channels <= 0 || decoded_size < 0 || !samplesize) ? -1 :
4558 decoded_size / (context->ch_layout.nb_channels * samplesize);
4567 ((
double)(frames * 1000) / context->sample_rate);
4570 LOG(VB_TIMESTAMP, LOG_INFO,
LOC + QString(
"audio timecode %1 %2 %3 %4")
4571 .arg(pkt->pts).arg(pkt->dts).arg(temppts.count()).arg(
m_lastAPts.count()));
4576 tmp_pkt->data += ret;
4577 tmp_pkt->size -= ret;
4581 av_packet_free(&tmp_pkt);
4588 AVPacket *pkt =
nullptr;
4589 bool have_err =
false;
4591 const DecodeType origDecodetype = decodetype;
4599 bool storevideoframes =
false;
4616 decodetype = (
DecodeType)((
int)decodetype & ~kDecodeVideo);
4632 decodetype = (
DecodeType)((
int)decodetype & ~kDecodeAudio);
4666 storevideoframes =
true;
4672 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4673 QString(
"Audio %1 ms behind video but already %2 "
4674 "video frames queued. AV-Sync might be broken.")
4685 av_packet_free(&pkt);
4691 pkt = av_packet_alloc();
4694 if (
m_ic !=
nullptr)
4696 if ((
m_ic ==
nullptr) || (retval < 0))
4698 if (retval == -EAGAIN)
4702 av_packet_free(&pkt);
4704 if (retval == AVERROR_EOF)
4707 LOG(VB_GENERAL, LOG_INFO, QString(
"decoding reached end of file"));
4711 LOG(VB_GENERAL, LOG_ERR, QString(
"decoding error %1 (%2)")
4713 QString::number(retval)));
4727 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No context");
4728 av_packet_unref(pkt);
4732 if (pkt->stream_index >= (
int)
m_ic->nb_streams)
4734 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bad stream");
4735 av_packet_unref(pkt);
4739 AVStream *curstream =
m_ic->streams[pkt->stream_index];
4743 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bad stream (NULL)");
4744 av_packet_unref(pkt);
4748 enum AVMediaType codec_type = curstream->codecpar->codec_type;
4749 const AVCodecID codec_id = curstream->codecpar->codec_id;
4755 case AVMEDIA_TYPE_VIDEO:
4756 if (storevideoframes)
4763 case AVMEDIA_TYPE_AUDIO:
4765 if (codec_id == AV_CODEC_ID_AC4)
4767 av_packet_unref(pkt);
4771 case AVMEDIA_TYPE_SUBTITLE:
4774 case AV_CODEC_ID_TEXT:
4776 av_packet_unref(pkt);
4778 case AV_CODEC_ID_DVB_TELETEXT:
4780 av_packet_unref(pkt);
4782 case AV_CODEC_ID_IVTV_VBI:
4784 av_packet_unref(pkt);
4790 case AVMEDIA_TYPE_DATA:
4792 av_packet_unref(pkt);
4800 if (context ==
nullptr)
4802 if (codec_type != AVMEDIA_TYPE_VIDEO)
4804 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
4805 QString(
"No codec for stream index %1, type(%2) id(%3:%4)")
4806 .arg(QString::number(pkt->stream_index),
4808 avcodec_get_name(codec_id),
4809 QString::number(codec_id)
4816 av_packet_unref(pkt);
4824 case AVMEDIA_TYPE_AUDIO:
4833 case AVMEDIA_TYPE_VIDEO:
4847 av_packet_free(&pkt);
4851 if (pkt->pts != AV_NOPTS_VALUE)
4854 (av_q2d(curstream->time_base)*pkt->pts*1000000);
4869 case AVMEDIA_TYPE_SUBTITLE:
4878 LOG(VB_GENERAL, LOG_ERR,
LOC +
4879 QString(
"Decoding - id(%1) type(%2)")
4880 .arg(avcodec_get_name(codec_id),
4887 if (!have_err && !Retry)
4889 av_packet_unref(pkt);
4894 av_packet_free(&pkt);
4902 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"StreamChangeCheck skip SeekReset"));
4912 int result = av_read_frame(ctx, pkt);
4920 if (pmt_buffer.has_buffer())
4977 if (stream < 0 || !
m_ic)
4979 return avcodec_get_name(
m_ic->streams[stream]->codecpar->codec_id);
4993 QString msg = (disable) ?
"Disabling" :
"Allowing";
4994 LOG(VB_AUDIO, LOG_INFO,
LOC + msg +
" pass through");
5017 switch (ctx->codec_id)
5019 case AV_CODEC_ID_AC3:
5020 case AV_CODEC_ID_TRUEHD:
5021 case AV_CODEC_ID_EAC3:
5022 case AV_CODEC_ID_MLP:
5023 case AV_CODEC_ID_DTS:
5032 bool passthru =
false;
5036 if (!withProfile && par->codec_id == AV_CODEC_ID_DTS && !
m_audio->
CanDTSHD())
5039 par->codec_id, AV_PROFILE_DTS);
5044 par->codec_id, par->profile);
5060 AVStream *curstream =
nullptr;
5061 AVCodecContext *ctx =
nullptr;
5063 int requested_channels = 0;
5067 (
int)
m_ic->nb_streams))
5070 .m_av_stream_index];
5071 if (curstream !=
nullptr)
5078 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"No codec context. Returning false");
5084 ctx->bits_per_raw_sample);
5086 if (av_sample_fmt_is_planar(ctx->sample_fmt))
5088 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Audio data is planar"));
5093 int bps = av_get_bytes_per_sample(ctx->sample_fmt) << 3;
5094 if (ctx->sample_fmt == AV_SAMPLE_FMT_S32 &&
5095 ctx->bits_per_raw_sample)
5096 bps = ctx->bits_per_raw_sample;
5097 LOG(VB_GENERAL, LOG_ERR,
LOC +
5098 QString(
"Unsupported sample format with %1 bits").arg(bps));
5102 bool using_passthru =
DoPassThrough(curstream->codecpar,
false);
5104 requested_channels = ctx->ch_layout.nb_channels;
5106 if (!using_passthru &&
5112 AVChannelLayout channel_layout;
5113 av_channel_layout_default(&channel_layout, requested_channels);
5114 av_opt_set_chlayout(ctx->priv_data,
"downmix", &channel_layout, 0);
5118 requested_channels, using_passthru, ctx->ch_layout.nb_channels,
5119 ctx->codec_id == AV_CODEC_ID_DTS ? ctx->profile : 0);
5123 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Initializing audio parms from " +
5128 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio format changed " +
5129 QString(
"\n\t\t\tfrom %1 to %2")
5145 switch (ctx->codec_id)
5147 case AV_CODEC_ID_MP2:
5150 case AV_CODEC_ID_MP3:
5153 case AV_CODEC_ID_AC3:
5156 case AV_CODEC_ID_DTS:
5159 case AV_CODEC_ID_VORBIS:
5162 case AV_CODEC_ID_WMAV1:
5165 case AV_CODEC_ID_WMAV2:
5173 lcd->setAudioFormatLEDs(audio_format,
true);
5208 int64_t start_time = INT64_MAX;
5209 int64_t end_time = INT64_MIN;
5210 AVStream *st =
nullptr;
5212 for (
uint i = 0; i < ic->nb_streams; i++)
5214 AVStream *st1 = ic->streams[i];
5215 if (st1 && st1->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5224 int64_t duration = INT64_MIN;
5225 if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {
5226 int64_t start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
5227 start_time = std::min(start_time1, start_time);
5228 if (st->duration != AV_NOPTS_VALUE) {
5229 int64_t end_time1 = start_time1 +
5230 av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
5231 end_time = std::max(end_time1, end_time);
5234 if (st->duration != AV_NOPTS_VALUE) {
5235 int64_t duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
5236 duration = std::max(duration1, duration);
5238 if (start_time != INT64_MAX) {
5239 ic->start_time = start_time;
5240 if (end_time != INT64_MIN) {
5241 duration = std::max(end_time - start_time, duration);
5244 if (duration != INT64_MIN) {
5245 ic->duration = duration;
5248 int64_t filesize = avio_size(ic->pb);
5251 ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE /
5252 (
double)ic->duration;
5268 if (
m_ic ==
nullptr)
5273 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