15#include "libavutil/avutil.h"
16#include "libavutil/error.h"
17#include "libavutil/intreadwrite.h"
18#include "libavutil/log.h"
19#include "libavutil/opt.h"
20#include "libavcodec/avcodec.h"
21#include "libavformat/avformat.h"
22#include "libavformat/avio.h"
23#include "libswscale/swscale.h"
24#include "libavutil/stereo3d.h"
25#include "libavutil/imgutils.h"
26#include "libavutil/display.h"
31#include "libavcodec/jni.h"
33#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
34#include <QtAndroidExtras>
36#include <QJniEnvironment>
37#define QAndroidJniEnvironment QJniEnvironment
65#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
68#include <QStringDecoder>
83#include "libmythbase/mythconfig.h"
112using namespace std::string_view_literals;
114#define LOC QString("AFD: ")
124#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
132 return {ctx.width >> ctx.lowres, ctx.height >> ctx.lowres};
136 float aspect_ratio = 0.0F;
138 if (ctx.sample_aspect_ratio.num && ctx.height)
140 aspect_ratio = av_q2d(ctx.sample_aspect_ratio) *
141 static_cast<double>(ctx.width);
142 aspect_ratio /= (float) ctx.height;
145 if (aspect_ratio <= 0.0F || aspect_ratio > 6.0F)
148 aspect_ratio = (float)ctx.width / (
float)ctx.height;
150 aspect_ratio = 4.0F / 3.0F;
157 static constexpr float kDefaultAspect = 4.0F / 3.0F;
158 int asp =
p.aspectRatio();
161 case 0:
return kDefaultAspect;
162 case 2:
return 4.0F / 3.0F;
163 case 3:
return 16.0F / 9.0F;
164 case 4:
return 2.21F;
168 float aspect_ratio = asp * 0.000001F;
169 if (aspect_ratio <= 0.0F || aspect_ratio > 6.0F)
171 if (
p.pictureHeight() &&
p.pictureWidth())
174 (float)
p.pictureWidth() /(float)
p.pictureHeight();
178 aspect_ratio = kDefaultAspect;
199#define FAIL(errmsg) do { \
200 LOG(VB_PLAYBACK, LOG_INFO, LOC + (errmsg)); \
211 switch (Stream->codecpar->codec_type)
215 case AVMEDIA_TYPE_VIDEO:
217 FAIL(
"No codec for video stream");
218 if (!Stream->codecpar->width || !Stream->codecpar->height)
219 FAIL(
"Unspecified video size");
220 if (Stream->codecpar->format == AV_PIX_FMT_NONE)
221 FAIL(
"Unspecified video pixel format");
228 case AVMEDIA_TYPE_AUDIO:
230 FAIL(
"No codec for audio stream");
248 case AVMEDIA_TYPE_SUBTITLE:
249 if (Stream->codecpar->codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE && !Stream->codecpar->width)
250 FAIL(
"Unspecified subtitle size");
252 case AVMEDIA_TYPE_DATA:
253 if (Stream->codecpar->codec_id == AV_CODEC_ID_NONE)
260 if (Stream->codecpar->codec_id == AV_CODEC_ID_NONE)
261 FAIL(
"Unknown codec");
265static void myth_av_log(
void *ptr,
int level,
const char* fmt, va_list vl)
270 static QString s_fullLine(
"");
271 static QMutex s_stringLock;
272 uint64_t verbose_mask = VB_LIBAV;
273 LogLevel_t verbose_level = LOG_EMERG;
279 verbose_level = LOG_EMERG;
280 verbose_mask |= VB_GENERAL;
283 verbose_level = LOG_CRIT;
284 verbose_mask |= VB_GENERAL;
287 verbose_level = LOG_ERR;
290 verbose_level = LOG_WARNING;
293 verbose_level = LOG_INFO;
297 verbose_level = LOG_DEBUG;
300 verbose_level = LOG_TRACE;
310 if (s_fullLine.isEmpty() && ptr) {
311 AVClass* avc = *(AVClass**)ptr;
312 s_fullLine = QString(
"[%1 @ %2] ")
313 .arg(avc->item_name(ptr))
314 .arg((quintptr)avc, QT_POINTER_SIZE * 2, 16, QChar(
'0'));
317 s_fullLine += QString::vasprintf(fmt, vl);
318 if (s_fullLine.endsWith(
"\n"))
320 LOG(verbose_mask, verbose_level, s_fullLine.trimmed());
321 s_fullLine.truncate(0);
323 s_stringLock.unlock();
328 if (lang_cstr[0] ==
'\0' || lang_cstr[1] ==
'\0')
332 if (lang_cstr[2] ==
'\0')
334 QString tmp2 = lang_cstr;
352 case AVMEDIA_TYPE_UNKNOWN:
return "Unknown";
353 case AVMEDIA_TYPE_VIDEO:
return "Video";
354 case AVMEDIA_TYPE_AUDIO:
return "Audio";
355 case AVMEDIA_TYPE_DATA:
return "Data";
356 case AVMEDIA_TYPE_SUBTITLE:
return "Subtitle";
357 case AVMEDIA_TYPE_ATTACHMENT:
return "Attachment";
358 default:
return "Invalid Codec Type";
368 m_playerFlags(flags),
373 m_itv(parent->GetInteractiveTV()),
374 m_audioSamples((uint8_t *)av_mallocz(
AudioOutput::kMaxSizeBuffer))
388 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"PlayerFlags: 0x%1, AudioReadAhead: %2 msec")
397 av_packet_free(&pkt);
415 lcd->setAudioFormatLEDs(
AUDIO_AC3,
false);
416 lcd->setVideoFormatLEDs(
VIDEO_MPG,
false);
433 for (
uint i = 0; i <
m_ic->nb_streams; i++)
435 AVStream *st =
m_ic->streams[i];
451 avformat_close_input(&
m_ic);
457static int64_t
lsb3full(int64_t lsb, int64_t base_ts,
int lsb_bits)
459 int64_t mask = (lsb_bits < 64) ? (1LL<<lsb_bits)-1 : -1LL;
460 return ((lsb - base_ts)&mask);
465 int64_t start_pts = 0;
467 AVStream *st =
nullptr;
468 for (
uint i = 0; i <
m_ic->nb_streams; i++)
470 AVStream *st1 =
m_ic->streams[i];
471 if (st1 && st1->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
480 if (
m_ic->start_time != AV_NOPTS_VALUE)
482 start_pts = av_rescale(
m_ic->start_time,
484 AV_TIME_BASE * (int64_t)st->time_base.num);
487 int64_t
pts = av_rescale(timecode.count() / 1000.0,
498 std::chrono::milliseconds timecode)
500 int64_t start_pts = 0;
502 if (
m_ic->start_time != AV_NOPTS_VALUE)
504 start_pts = av_rescale(
m_ic->start_time,
506 AV_TIME_BASE * (int64_t)st->time_base.num);
509 int64_t
pts = av_rescale(timecode.count() / 1000.0,
522 return m_ic->nb_chapters;
532 for (
int i = 0; i < total; i++)
534 int num =
m_ic->chapters[i]->time_base.num;
535 int den =
m_ic->chapters[i]->time_base.den;
536 int64_t start =
m_ic->chapters[i]->start;
537 long double total_secs = (
long double)start * (
long double)num /
539 times.push_back(std::chrono::seconds((
long long)total_secs));
548 for (
int i = (
m_ic->nb_chapters - 1); i > -1 ; i--)
550 int num =
m_ic->chapters[i]->time_base.num;
551 int den =
m_ic->chapters[i]->time_base.den;
552 int64_t start =
m_ic->chapters[i]->start;
553 long double total_secs = (
long double)start * (
long double)num /
555 auto framenum = (
long long)(total_secs *
m_fps);
556 if (framesPlayed >= framenum)
558 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
559 QString(
"GetCurrentChapter(selected chapter %1 framenum %2)")
560 .arg(i + 1).arg(framenum));
572 int num =
m_ic->chapters[chapter - 1]->time_base.num;
573 int den =
m_ic->chapters[chapter - 1]->time_base.den;
574 int64_t start =
m_ic->chapters[chapter - 1]->start;
575 long double total_secs = (
long double)start * (
long double)num /
577 auto framenum = (
long long)(total_secs *
m_fps);
578 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"GetChapter %1: framenum %2")
579 .arg(chapter).arg(framenum));
585 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DoRewind(%1, %2 discard frames)")
586 .arg(desiredFrame).arg( discardFrames ?
"do" :
"don't" ));
592 return do_av_seek(desiredFrame, discardFrames, AVSEEK_FLAG_BACKWARD);
597 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
598 QString(
"DoFastForward(%1 (%2), %3 discard frames)")
600 .arg((discardFrames) ?
"do" :
"don't"));
608 if (seekDelta >= 0 && seekDelta < 2 && m_parent->GetPlaySpeed() == 0.0F)
614 return do_av_seek(desiredFrame, discardFrames, 0);
620 if (
m_ic->start_time != AV_NOPTS_VALUE)
621 ts =
m_ic->start_time;
624 long double seekts = desiredFrame * AV_TIME_BASE /
m_fps;
625 ts += (
long long)seekts;
632 flags |= AVSEEK_FLAG_BACKWARD;
635 int ret = av_seek_frame(
m_ic, -1, ts, flags);
638 LOG(VB_GENERAL, LOG_ERR,
LOC +
639 QString(
"av_seek_frame(m_ic, -1, %1, 0b%2) error: %3").arg(
641 QString::number(flags, 2),
648 reader->SeekFrame(ts, flags);
650 int normalframes = 0;
668 bool doflush,
bool discardFrames)
673 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
674 QString(
"SeekReset(%1, %2, %3 flush, %4 discard)")
675 .arg(newKey).arg(skipFrames)
676 .arg((doflush) ?
"do" :
"don't",
677 (discardFrames) ?
"do" :
"don't"));
697 avformat_flush(
m_ic);
704 m_ic->pb->buf_ptr =
m_ic->pb->buffer;
705 m_ic->pb->buf_end =
m_ic->pb->buffer;
706 m_ic->pb->eof_reached = 0;
710 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"SeekReset() flushing");
711 for (
uint i = 0; i <
m_ic->nb_streams; i++)
717 if (codecContext && codecContext->internal)
718 avcodec_flush_buffers(codecContext);
725 av_packet_free(&pkt);
747 static constexpr std::chrono::milliseconds maxSeekTimeMs { 200ms };
748 int profileFrames = 0;
750 for (; (skipFrames > 0 && !
m_atEof &&
751 (exactSeeks || begin.
elapsed() < maxSeekTimeMs));
752 --skipFrames, ++profileFrames)
756 QElapsedTimer getframetimer;
757 getframetimer.start();
759 while (retry && !getframetimer.hasExpired(100))
764 std::this_thread::sleep_for(1ms);
772 if (!exactSeeks && profileFrames >= 5 && profileFrames < 10)
774 const int giveUpPredictionMs = 400;
775 int remainingTimeMs =
776 skipFrames * (float)begin.
elapsed().count() / profileFrames;
777 if (remainingTimeMs > giveUpPredictionMs)
779 LOG(VB_PLAYBACK, LOG_DEBUG,
780 QString(
"Frame-by-frame seeking would take "
781 "%1 ms to finish, skipping.").arg(remainingTimeMs));
798 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
799 QString(
"Resetting byte context eof (livetv %1 was eof %2)")
801 m_ic->pb->eof_reached = 0;
809 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
810 QString(
"Reset: Video %1, Seek %2, File %3")
811 .arg(reset_video_data).arg(seek_reset).arg(reset_file));
818 if (reset_video_data)
828 memset(&probe, 0,
sizeof(AVProbeData));
830 QByteArray fname =
filename.toLatin1();
831 probe.filename = fname.constData();
832 probe.buf = (
unsigned char *)testbuf.data();
833 probe.buf_size = testbuf.size();
835 int score = AVPROBE_SCORE_MAX/4;
847 memset(probe.buf + probe.buf_size, 0, AVPROBE_PADDING_SIZE);
849 return av_probe_input_format2(&probe,
static_cast<int>(
true), &score) !=
nullptr;
856 int cnt = decoder->
m_ic->nb_streams;
858 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
859 QString(
"streams_changed 0x%1 -- program_number %2 stream count %3")
860 .arg((uint64_t)data,0,16).arg(QString::number(avprogram_id), QString::number(cnt)));
862 auto* program = decoder->get_current_AVProgram();
863 if (program !=
nullptr && program->id != avprogram_id)
867 decoder->m_streamsChanged =
true;
904 const AVInputFormat *fmt =
nullptr;
906 QByteArray fnamea = fnames.toLatin1();
907 const char *
filename = fnamea.constData();
910 memset(&probe, 0,
sizeof(AVProbeData));
912 probe.buf =
reinterpret_cast<unsigned char *
>(testbuf.data());
914 probe.buf_size = testbuf.size();
917 memset(probe.buf + probe.buf_size, 0, AVPROBE_PADDING_SIZE);
919 fmt = av_probe_input_format(&probe,
static_cast<int>(
true));
922 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Probe failed for '%1'").arg(
filename));
926 if (strcmp(fmt->name,
"mpegts") == 0 &&
929 const AVInputFormat *fmt2 = av_find_input_format(
"mpegts-ffmpeg");
933 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Using FFmpeg MPEG-TS demuxer (forced)");
938 bool scancomplete =
false;
939 int remainingscans = 5;
941 while (!scancomplete && remainingscans--)
955 while (!found && --retries)
957 m_ic = avformat_alloc_context();
960 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Could not allocate format context.");
967 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
968 QString(
"Buffer size: %1 Streamed %2 Seekable %3 Available %4")
971 .arg(
m_ic->pb->seekable)
975 err = avformat_open_input(&
m_ic,
filename, fmt,
nullptr);
979 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Failed to open input ('%1')")
987 QThread::usleep(100000);
993 if (strcmp(fmt->name,
"mpegts") == 0)
995 fmt = av_find_input_format(
"mpegts-ffmpeg");
998 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Attempting to use original FFmpeg MPEG-TS demuxer.");
1011 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Fatal error opening input. Aborting");
1023 m_ic->max_analyze_duration = 60LL * AV_TIME_BASE;
1027 err = avformat_find_stream_info(
m_ic,
nullptr);
1031 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Could not find codec parameters for '%1'").arg(
filename));
1038 scancomplete =
true;
1043 scancomplete =
false;
1047 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Stream scan incomplete - retrying");
1048 QThread::usleep(250000);
1056 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Scan incomplete - playback may not work");
1059 m_ic->stream_change_data =
this;
1071 QString extension = QFileInfo(fnames).suffix();
1072 if (strcmp(fmt->name,
"mp3") == 0 || strcmp(fmt->name,
"flac") == 0 ||
1073 strcmp(fmt->name,
"ogg") == 0 ||
1074 (extension.compare(
"m4a", Qt::CaseInsensitive) == 0))
1089 int initialAudio = -1;
1090 int initialVideo = -1;
1091 if (
m_itv ==
nullptr)
1093 if (
m_itv !=
nullptr)
1094 m_itv->GetInitialStreams(initialAudio, initialVideo);
1095 if (initialAudio >= 0)
1097 if (initialVideo >= 0)
1118 std::chrono::seconds dur = 0s;
1127 dur = duration_cast<std::chrono::seconds>(av_duration(
m_ic->duration));
1138 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1139 "Recording has no position -- using libavformat seeking.");
1148 float bytespersec = (float)
m_bitrate / 8 / 2;
1151 (int)(secs *
static_cast<float>(
m_fps)));
1160 if (strcmp(fmt->name,
"avi") == 0)
1173 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Position map found");
1175 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Partial position map found");
1176 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1177 QString(
"Successfully opened decoder for file: \"%1\". novideo(%2)")
1181 for (
unsigned int i=0; i <
m_ic->nb_chapters; i++)
1183 int num =
m_ic->chapters[i]->time_base.num;
1184 int den =
m_ic->chapters[i]->time_base.den;
1185 int64_t start =
m_ic->chapters[i]->start;
1186 auto total_secs =
static_cast<long double>(start) *
static_cast<long double>(num) /
1187 static_cast<long double>(den);
1189 auto framenum =
static_cast<long long>(total_secs *
static_cast<long double>(
m_fps));
1190 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1191 QString(
"Chapter %1 found @ [%2]->%3")
1194 QString::number(framenum)));
1207 Reset(
true,
true,
true);
1221 double avg_fps = (Stream->avg_frame_rate.den == 0) ? 0.0 : av_q2d(Stream->avg_frame_rate);
1222 double codec_fps = av_q2d(Context->framerate);
1223 double container_fps = (Stream->time_base.num == 0) ? 0.0 : av_q2d(av_inv_q(Stream->time_base));
1225 double estimated_fps = (Stream->r_frame_rate.den == 0) ? 0.0 : av_q2d(Stream->r_frame_rate);
1229 static const std::vector<double> k_standard_rates =
1249 std::vector<double> rates;
1254 if (QString(
m_ic->iformat->name).contains(
"matroska") ||
1255 QString(
m_ic->iformat->name).contains(
"mov"))
1257 rates.emplace_back(avg_fps);
1261 if (QString(
m_ic->iformat->name).contains(
"avi"))
1263 rates.emplace_back(container_fps);
1266 rates.emplace_back(codec_fps);
1267 rates.emplace_back(container_fps);
1268 rates.emplace_back(avg_fps);
1270 rates.emplace_back(estimated_fps);
1272 rates.emplace_back(30000.0 / 1001.0);
1274 auto invalid_fps = [](
double rate) {
return rate < 3.0 || rate > 121.0; };
1275 rates.erase(std::remove_if(rates.begin(), rates.end(), invalid_fps), rates.end());
1277 auto FuzzyEquals = [](
double First,
double Second) {
return std::abs(First - Second) < 0.03; };
1280 if (!FuzzyEquals(rates.front(),
m_fps))
1282 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1283 QString(
"Selected FPS: %1 (Avg:%2 Mult:%3 Codec:%4 Container:%5 Estimated:%6)")
1284 .arg(
static_cast<double>(rates.front())).arg(avg_fps)
1285 .arg(
m_fpsMultiplier).arg(codec_fps).arg(container_fps).arg(estimated_fps));
1287 LOG(VB_GENERAL, LOG_INFO,
LOC +
1288 QString(
"Sanitise:%1").arg(Sanitise) +
1289 QString(
" avg_fps:%1").arg(avg_fps) +
1290 QString(
" codec_fps:%1").arg(codec_fps) +
1291 QString(
" container_fps:%1").arg(container_fps) +
1292 QString(
" estimated_fps:%1").arg(estimated_fps) +
1293 QString(
" m_fps:%1").arg(
m_fps));
1296 for (
auto rate : rates)
1297 rs.append(QString::number(rate));
1298 LOG(VB_GENERAL, LOG_INFO,
LOC +
1299 QString(
"Frame rates:%1").arg(rs.join(
' ')));
1302 auto IsStandard = [&FuzzyEquals](
double Rate)
1304 if (Rate > 23.0 && Rate < 121.0)
1306 for (
auto standard_rate : k_standard_rates)
1307 if (FuzzyEquals(Rate, standard_rate))
1315 auto NearestStandardFrameRate = [](
double rate,
double epsilon)
1317 double result = rate;
1318 double lowest_delta = rate;
1319 for (
auto standard_rate : k_standard_rates)
1321 double delta = std::abs(rate - standard_rate);
1322 if ((delta < lowest_delta) && (delta <
epsilon))
1324 lowest_delta = delta;
1325 result = standard_rate;
1332 double detected = rates.front();
1337 double nearest = NearestStandardFrameRate(detected, 3.0);
1338 LOG(VB_GENERAL, LOG_INFO,
LOC +
1339 QString(
"Frame rate %1 rounded to nearest standard rate %2")
1340 .arg(detected, 0,
'f', 2).arg(nearest, 0,
'f', 2));
1344 if (Sanitise && !IsStandard(detected))
1346 for (
auto rate : rates)
1348 if (IsStandard(rate))
1350 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"%1 is non-standard - using %2 instead.")
1351 .arg(rates.front()).arg(rate));
1359 if (rate > 33.0 && detected < 33.0)
1361 double half = rate / 2.0;
1362 if (std::abs(half - detected) < (half * 0.1))
1364 LOG(VB_GENERAL, LOG_INFO,
LOC +
1365 QString(
"Assuming %1 is a better choice than %2")
1366 .arg(half).arg(rate));
1367 return static_cast<float>(half);
1370 return static_cast<float>(rate);
1375 return static_cast<float>(detected);
1380 switch (Context->codec_id)
1382 case AV_CODEC_ID_H264:
1385 if (Context->extradata && (Context->extradata_size >= 7))
1388 if (Context->extradata[0] == 1)
1390 else if (AV_RB24(Context->extradata) == 0x01)
1392 else if (AV_RB32(Context->extradata) == 0x01)
1399 parser.parse_SPS(Context->extradata + offset,
1400 static_cast<uint>(Context->extradata_size - offset), dummy, result);
1405 case AV_CODEC_ID_H265:
return 16;
1406 case AV_CODEC_ID_VP9:
return 8;
1407 case AV_CODEC_ID_VP8:
return 3;
1413 bool selectedStream)
1415 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1416 QString(
"InitVideoCodec ID:%1 Type:%2 Size:%3x%4")
1417 .arg(avcodec_get_name(codecContext->codec_id),
1419 .arg(codecContext->width).arg(codecContext->height));
1424 codecContext->opaque =
static_cast<void*
>(
this);
1426 codecContext->slice_flags = 0;
1428 codecContext->err_recognition = AV_EF_COMPLIANT;
1429 codecContext->workaround_bugs = FF_BUG_AUTODETECT;
1430 codecContext->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
1431 codecContext->idct_algo = FF_IDCT_AUTO;
1432 codecContext->debug = 0;
1435 const AVCodec *codec1 = codecContext->codec;
1441 const AVPacketSideData *sd = av_packet_side_data_get(stream->codecpar->coded_side_data,
1442 stream->codecpar->nb_coded_side_data, AV_PKT_DATA_DISPLAYMATRIX);
1444 m_videoRotation =
static_cast<int>(-av_display_rotation_get(
reinterpret_cast<int32_t*
>(sd->data)));
1449 sd = av_packet_side_data_get(stream->codecpar->coded_side_data,
1450 stream->codecpar->nb_coded_side_data, AV_PKT_DATA_STEREO3D);
1453 auto * avstereo =
reinterpret_cast<AVStereo3D*
>(sd->data);
1478 bool doublerate =
true;
1482 if (codec1 && ((AV_CODEC_ID_MPEG2VIDEO == codec1->id) ||
1483 (AV_CODEC_ID_MPEG1VIDEO == codec1->id)))
1487 int total_blocks = (codecContext->height + 15) / 16;
1488 codecContext->skip_top = (total_blocks + 3) / 4;
1489 codecContext->skip_bottom = (total_blocks + 3) / 4;
1493 codecContext->lowres = 2;
1497 codecContext->flags &= ~AV_CODEC_FLAG_LOOP_FILTER;
1498 codecContext->skip_loop_filter = AVDISCARD_ALL;
1502 codecContext->skip_idct = AVDISCARD_ALL;
1514 if (!width || !height)
1516 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1517 "InitVideoCodec invalid dimensions, resetting decoder.");
1525 const AVCodec *codec2 = codecContext->codec;
1528 codecName = codec2->name;
1536 switch (codecContext->codec_id)
1538 case AV_CODEC_ID_H263:
1539 case AV_CODEC_ID_MPEG4:
1540 case AV_CODEC_ID_MSMPEG4V1:
1541 case AV_CODEC_ID_MSMPEG4V2:
1542 case AV_CODEC_ID_MSMPEG4V3:
1543 case AV_CODEC_ID_H263P:
1544 case AV_CODEC_ID_H263I:
1547 case AV_CODEC_ID_WMV1:
1548 case AV_CODEC_ID_WMV2:
1552 case AV_CODEC_ID_XVID:
1561 lcd->setVideoFormatLEDs(video_format,
true);
1573 static constexpr std::array<uint8_t, 256> odd_parity_LUT
1575 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1576 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1577 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1578 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1579 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1580 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1581 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1582 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1583 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1584 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1585 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1586 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1587 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1588 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1589 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1590 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1592 bool ret = (odd_parity_LUT[data & 0xff] == 1) &&
1593 (odd_parity_LUT[(data & 0xff00) >> 8] == 1);
1596 LOG(VB_VBI, LOG_ERR,
LOC +
1597 QString(
"VBI: Bad parity in EIA-608 data (%1)") .arg(data,0,16));
1604 if (program ==
nullptr)
1608 return program->pmt_section;
1613 AVProgram* program = av_find_program_from_stream(context,
nullptr, stream_index);
1627 if (!pmt_buffer.has_buffer())
1629 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1630 "ScanATSCCaptionStreams() called with no PMT");
1635 bool video_found =
false;
1659 desc_list.insert(desc_list.end(), desc_list2.begin(), desc_list2.end());
1661 for (
auto & desc : desc_list)
1703 std::array<std::map<int,uint>,2> lang_cc_cnt;
1720 else if (!pofr && sofr)
1746 LOG(VB_GENERAL, LOG_ERR,
LOC +
"in_tracks key too small");
1752 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1753 QString(
"%1 caption service #%2 is in the %3 language.")
1754 .arg((
type) ?
"EIA-708" :
"EIA-608")
1770 AVStream* st =
m_ic->streams[av_index];
1771 const AVDictionaryEntry* language_dictionary_entry =
1772 av_dict_get(st->metadata,
"language",
nullptr, 0);
1774 if (language_dictionary_entry ==
nullptr ||
1775 language_dictionary_entry->value ==
nullptr ||
1776 st->codecpar->extradata ==
nullptr
1782 std::vector<std::string_view> languages {
StringUtil::split_sv(language_dictionary_entry->value,
","sv)};
1784 if (st->codecpar->extradata_size !=
static_cast<int>(languages.size() * 2))
1788 for (
size_t i = 0; i < languages.size(); i++)
1790 if (languages[i].size() != 3)
1796 uint8_t teletext_type = st->codecpar->extradata[i * 2] >> 3;
1797 uint8_t teletext_magazine_number = st->codecpar->extradata[i * 2] & 0x7;
1798 if (teletext_magazine_number == 0)
1799 teletext_magazine_number = 8;
1800 uint8_t teletext_page_number = st->codecpar->extradata[(i * 2) + 1];
1801 if (teletext_type == 2 || teletext_type == 1)
1803 TrackType track = (teletext_type == 2) ?
1806 m_tracks[track].emplace_back(av_index, 0, language,
1807 (
static_cast<unsigned>(teletext_magazine_number) << 8) | teletext_page_number);
1808 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1809 QString(
"Teletext stream #%1 (%2) is in the %3 language on page %4 %5.")
1810 .arg(QString::number(i),
1811 (teletext_type == 2) ?
"Caption" :
"Menu",
1813 QString::number(teletext_magazine_number),
1814 QString::number(teletext_page_number)));
1823 AVDictionaryEntry *metatag =
1824 av_dict_get(
m_ic->streams[av_stream_index]->metadata,
"language",
nullptr,
1826 bool forced = (
m_ic->streams[av_stream_index]->disposition & AV_DISPOSITION_FORCED) != 0;
1829 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1830 QString(
"Text Subtitle track #%1 is A/V stream #%2 "
1831 "and is in the %3 language(%4), forced=%5.")
1834 StreamInfo si {av_stream_index, 0, lang, 0, forced};
1844 if (
m_itv ==
nullptr)
1846 if (
m_itv ==
nullptr)
1850 if (!pmt_buffer.has_buffer())
1861 LOG(VB_DSMCC, LOG_NOTICE, QString(
"ScanDSMCCStreams Found Object Carousel in Stream %1").arg(QString::number(i)));
1867 for (
const auto *desc : desc_list)
1870 uint length = *desc++;
1871 const unsigned char *endDesc = desc+length;
1872 uint dataBroadcastId = desc[0]<<8 | desc[1];
1873 LOG(VB_DSMCC, LOG_NOTICE, QString(
"ScanDSMCCStreams dataBroadcastId %1").arg(QString::number(dataBroadcastId)));
1874 if (dataBroadcastId != 0x0106)
1877 while (desc != endDesc)
1879 [[maybe_unused]]
uint appTypeCode = desc[0]<<8 | desc[1];
1881 uint appSpecDataLen = *desc++;
1883 LOG(VB_DSMCC, LOG_NOTICE, QString(
"ScanDSMCCStreams AppTypeCode %1").arg(QString::number(appTypeCode)));
1884 if (appTypeCode == 0x101)
1886 const unsigned char *subDescEnd = desc + appSpecDataLen;
1887 while (desc < subDescEnd)
1889 uint sub_desc_tag = *desc++;
1890 uint sub_desc_len = *desc++;
1892 if (sub_desc_tag == 1)
1893 m_itv->SetNetBootInfo(desc, sub_desc_len);
1894 desc += sub_desc_len;
1900 desc += appSpecDataLen;
1914 const AVCodec *codec =
nullptr;
1915 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Trying to select best video track");
1929 int stream_index = av_find_best_stream(
m_ic, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);
1931 if (stream_index < 0)
1933 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"No video track found/selected.");
1934 return stream_index;
1937 AVStream *stream =
m_ic->streams[stream_index];
1948 if (codecContext->codec_type == AVMEDIA_TYPE_VIDEO)
1949 codectype += QString(
"(%1x%2)").arg(codecContext->width).arg(codecContext->height);
1950 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1951 QString(
"Selected track #%1: ID: 0x%2 Codec ID: %3 Profile: %4 Type: %5 Bitrate: %6")
1952 .arg(stream_index).arg(
static_cast<uint64_t
>(stream->id), 0, 16)
1953 .arg(avcodec_get_name(codecContext->codec_id),
1954 avcodec_profile_name(codecContext->codec_id, codecContext->profile),
1956 QString::number(codecContext->bit_rate)));
1963 if ((codecContext->width != stream->codecpar->width) || (codecContext->height != stream->codecpar->height))
1965 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
1966 "Video resolution mismatch: Context: %1x%2 Stream: %3x%4 Codec: %5 Stream change: %6")
1967 .arg(codecContext->width).arg(codecContext->height)
1968 .arg(stream->codecpar->width).arg(stream->codecpar->height)
1975 int width = std::max(dim.width(), 16);
1976 int height = std::max(dim.height(), 16);
1977 QString dec =
"ffmpeg";
1978 uint thread_count = 1;
1980 if (codecContext->codec)
1981 codecName = codecContext->codec->name;
1986 if (codecContext->framerate.den && codecContext->framerate.num)
1987 m_fps = float(codecContext->framerate.num) / float(codecContext->framerate.den);
1991 bool foundgpudecoder =
false;
1992 QStringList unavailabledecoders;
2002 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
2003 "GPU/hardware decoder '%1' failed - forcing software decode")
2010 while (unavailabledecoders.size() < 10)
2014 if (!unavailabledecoders.isEmpty())
2016 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Unavailable decoders: %1")
2017 .arg(unavailabledecoders.join(
",")));
2023 if (!skip_loop_filter)
2024 codecContext->skip_loop_filter = AVDISCARD_NONKEY;
2032 if (
version && allowgpu && dec !=
"ffmpeg")
2036 codecContext->opaque =
static_cast<void*
>(
this);
2041 codecContext->opaque =
static_cast<void*
>(
this);
2043 foundgpudecoder =
true;
2048 unavailabledecoders.append(dec);
2056 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Unknown video codec - defaulting to MPEG2");
2073 if (!foundgpudecoder)
2075 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Using %1 CPUs for decoding")
2076 .arg(HAVE_THREADS ? thread_count : 1));
2077 codecContext->thread_count =
static_cast<int>(thread_count);
2092 return stream_index;
2097 AVProgram* program = av_find_program_from_stream(
m_ic,
nullptr, stream_index);
2098 if (program ==
nullptr)
2103 LOG(VB_PLAYBACK, LOG_INFO,
2104 QString(
"Removing streams not in Program %1 from track selection.")
2105 .arg(QString::number(program->id)));
2107 const auto *
const begin = program->stream_index;
2108 const auto *
const end = program->stream_index + program->nb_stream_indexes;
2112 LOG(VB_PLAYBACK, LOG_DEBUG,
2113 QString(
"Size before: %1").arg(QString::number(track_list.size())));
2114 track_list.erase(std::remove_if(track_list.begin(), track_list.end(),
2117 return std::find(begin, end, i.m_av_stream_index) == end;
2118 }), track_list.end());
2119 LOG(VB_PLAYBACK, LOG_DEBUG,
2120 QString(
"Size after: %1").arg(QString::number(track_list.size())));
2126 return (ch_layout.order == AV_CHANNEL_ORDER_CUSTOM) &&
2127 (ch_layout.nb_channels == 2) &&
2128 (ch_layout.u.map[0].id == AV_CHAN_FRONT_CENTER) &&
2129 (ch_layout.u.map[1].id == AV_CHAN_FRONT_CENTER);
2137 bool unknownbitrate =
false;
2141 constexpr std::array<TrackType, 6>
types {
2155 std::map<int,uint> lang_sub_cnt;
2156 uint subtitleStreamCount = 0;
2157 std::map<int,uint> lang_aud_cnt;
2158 uint audioStreamCount = 0;
2167 if (
m_ic ==
nullptr)
2170 for (
uint strm = 0; strm <
m_ic->nb_streams; strm++)
2172 AVCodecParameters *par =
m_ic->streams[strm]->codecpar;
2175 if (par->codec_type == AVMEDIA_TYPE_VIDEO)
2176 codectype += QString(
"(%1x%2)").arg(par->width).arg(par->height);
2177 QString program_id =
"null";
2178 if (av_find_program_from_stream(
m_ic,
nullptr, strm) !=
nullptr)
2180 program_id = QString::number(av_find_program_from_stream(
m_ic,
nullptr, strm)->
id);
2182 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2183 QString(
"Stream #%1: ID: 0x%2 Program ID: %3 Codec ID: %4 Type: %5 Bitrate: %6").arg(
2184 QString::number(strm),
2185 QString::number(
static_cast<uint64_t
>(
m_ic->streams[strm]->id), 16),
2187 avcodec_get_name(par->codec_id),
2189 QString::number(par->bit_rate))
2192 switch (par->codec_type)
2194 case AVMEDIA_TYPE_VIDEO:
2202 if (ctx && (ctx->hw_frames_ctx || ctx->hw_device_ctx))
2209 LOG(VB_GENERAL, LOG_ERR,
LOC +
2210 QString(
"Stream #%1 has an unknown video "
2211 "codec id, skipping.").arg(strm));
2223 if (par->bit_rate == 0)
2225 static constexpr int64_t s_baseBitrate { 1000000LL };
2227 if (par->width && par->height)
2229 static const int s_baseSize = 1920 * 1080;
2230 multiplier = ((par->width * par->height) + s_baseSize - 1) / s_baseSize;
2231 multiplier = std::max(multiplier, 1);
2233 par->bit_rate = s_baseBitrate * multiplier;
2234 unknownbitrate =
true;
2240 case AVMEDIA_TYPE_AUDIO:
2242 LOG(VB_GENERAL, LOG_INFO,
LOC +
2243 QString(
"codec %1 has %2 channels")
2244 .arg(avcodec_get_name(par->codec_id))
2245 .arg(par->ch_layout.nb_channels));
2250 case AVMEDIA_TYPE_SUBTITLE:
2252 if (par->codec_id == AV_CODEC_ID_DVB_TELETEXT)
2254 if (par->codec_id == AV_CODEC_ID_TEXT)
2258 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"subtitle codec (%1)")
2262 case AVMEDIA_TYPE_DATA:
2264 if (par->codec_id == AV_CODEC_ID_DVB_VBI)
2267 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"data codec (%1)")
2271 case AVMEDIA_TYPE_ATTACHMENT:
2273 if (par->codec_id == AV_CODEC_ID_TTF)
2276 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2277 QString(
"Attachment codec (%1)")
2284 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
2285 QString(
"Unknown codec type (%1)")
2291 if (par->codec_type != AVMEDIA_TYPE_AUDIO &&
2292 par->codec_type != AVMEDIA_TYPE_SUBTITLE)
2296 if (par->codec_type == AVMEDIA_TYPE_SUBTITLE &&
2297 (par->codec_id == AV_CODEC_ID_DVB_TELETEXT ||
2298 par->codec_id == AV_CODEC_ID_TEXT))
2301 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Looking for decoder for %1")
2302 .arg(avcodec_get_name(par->codec_id)));
2304 if (par->codec_id == AV_CODEC_ID_PROBE)
2306 LOG(VB_GENERAL, LOG_ERR,
LOC +
2307 QString(
"Probing of stream #%1 unsuccesful, ignoring.").arg(strm));
2313 if (codecContext ==
nullptr)
2315 LOG(VB_GENERAL, LOG_WARNING,
LOC +
2316 QString(
"Could not find decoder for codec (%1), ignoring.")
2317 .arg(avcodec_get_name(par->codec_id)));
2318 LOG(VB_LIBAV, LOG_INFO,
"For a list of all codecs, run `mythffmpeg -codecs`.");
2322 if (codecContext->codec && par->codec_id != codecContext->codec_id)
2324 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2325 QString(
"Already opened codec not matching (%1 vs %2). Reopening")
2326 .arg(avcodec_get_name(codecContext->codec_id),
2327 avcodec_get_name(codecContext->codec->id)));
2331 if (!
OpenAVCodec(codecContext, codecContext->codec))
2343 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2344 QString(
"Stream 0x%1 is not valid in this context - skipping")
2345 .arg(
m_ic->streams[strm]->id, 4, 16));
2349 if (par->codec_type == AVMEDIA_TYPE_SUBTITLE)
2351 bool forced = (
m_ic->streams[strm]->disposition & AV_DISPOSITION_FORCED) != 0;
2353 uint lang_indx = lang_sub_cnt[lang]++;
2354 subtitleStreamCount++;
2357 static_cast<int>(strm),
m_ic->streams[strm]->id, lang, lang_indx, forced);
2359 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2360 QString(
"Subtitle track #%1 is A/V stream #%2 "
2361 "and is in the %3 language(%4).")
2366 if (par->codec_type == AVMEDIA_TYPE_AUDIO)
2370 uint lang_indx = lang_aud_cnt[lang]++;
2373 int stream_id =
m_ic->streams[strm]->id;
2377 if (stream_id == -1)
2385 static_cast<int>(strm), stream_id, lang, lang_indx,
type);
2389 lang_indx = lang_aud_cnt[lang]++;
2391 static_cast<int>(strm), stream_id, lang, lang_indx,
type);
2394 LOG(VB_AUDIO, LOG_INFO,
LOC +
2395 QString(
"Audio Track #%1, of type (%2) is A/V stream #%3 (id=0x%4) "
2396 "and has %5 channels in the %6 language(%7).")
2398 .arg(strm).arg(
m_ic->streams[strm]->id,0,16).arg(codecContext->ch_layout.nb_channels)
2424 QString(
m_ic->iformat->name).contains(
"matroska"));
2466 for (
unsigned i = 0; i <
m_ic->nb_programs; i++)
2478#if CONFIG_MEDIACODEC
2479 if (QString(
"mediacodec") == codec->wrapper_name)
2480 av_jni_set_java_vm(QAndroidJniEnvironment::javaVM(),
nullptr);
2482 int ret = avcodec_open2(avctx, codec,
nullptr);
2487 LOG(VB_GENERAL, LOG_ERR,
LOC +
2488 QString(
"Could not open codec 0x%1, id(%2) type(%3) "
2489 "ignoring. reason %4").arg((uint64_t)avctx,0,16)
2490 .arg(avcodec_get_name(avctx->codec_id),
2496 LOG(VB_GENERAL, LOG_INFO,
LOC +
2497 QString(
"Opened codec 0x%1, id(%2) type(%3)")
2498 .arg((uint64_t)avctx,0,16)
2499 .arg(avcodec_get_name(avctx->codec_id),
2524 if (si.m_language_index == Index)
2525 return si.m_language;
2532 AVDictionaryEntry *metatag = av_dict_get(
m_ic->streams[StreamIndex]->metadata,
"language",
nullptr, 0);
2575 AVStream *stream =
m_ic->streams[StreamIndex];
2579 if (stream->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
2581 else if (stream->disposition & AV_DISPOSITION_COMMENT)
2583 else if (stream->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
2585 else if (stream->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
2612 if (
current->m_av_stream_index == streamIndex)
2618 LOG(VB_GENERAL, LOG_WARNING,
LOC +
2619 QString(
"Invalid stream index passed to "
2620 "SetupAudioStreamSubIndexes: %1").arg(streamIndex));
2627 if (
current->m_av_substream_index == -1)
2640 (next->m_av_stream_index != streamIndex))
2642 QString msg = QString(
2643 "Expected substream 1 (Language I) of stream %1\n\t\t\t"
2644 "following substream 0, found end of list or another stream.")
2647 LOG(VB_GENERAL, LOG_WARNING,
LOC + msg);
2669 bool do_flush =
false;
2670 for (
uint i = 0; i <
m_ic->nb_streams; i++)
2672 AVStream *st =
m_ic->streams[i];
2675 if (avctx && avctx->codec_type == AVMEDIA_TYPE_AUDIO)
2678 LOG(VB_LIBAV, LOG_DEBUG, QString(
"removing audio stream (id: 0x%1, index: %2, nb_streams: %3)")
2679 .arg(QString::number(st->id, 16),
2681 QString::number(
m_ic->nb_streams)
2685 if ((
m_ic->nb_streams - i) > 0) {
2686 std::memmove(
reinterpret_cast<void*
>(&
m_ic->streams[i]),
2687 reinterpret_cast<const void*
>(&
m_ic->streams[i + 1]),
2688 (
m_ic->nb_streams - i) *
sizeof(AVFormatContext*));
2692 m_ic->streams[i] =
nullptr;
2700 avformat_flush(
m_ic);
2709 if (!std::any_of(decoder->m_renderFormats->cbegin(), decoder->m_renderFormats->cend(),
2710 [&
type](
auto Format) { return type == Format; }))
2712 decoder->m_directRendering =
false;
2713 return avcodec_default_get_buffer2(c, pic, flags);
2716 decoder->m_directRendering =
true;
2717 MythVideoFrame *frame = decoder->GetPlayer()->GetNextVideoFrame();
2727 if ((frame->
m_type !=
type) || (pic->width > width) || (pic->height > height))
2744 for (
uint i = 0; i < 3; i++)
2750 pic->opaque = frame;
2753 AVBufferRef *buffer = av_buffer_create(
reinterpret_cast<uint8_t*
>(frame), 0,
2754 [](
void* Opaque, uint8_t* Data)
2758 if (avfd && avfd->GetPlayer())
2759 avfd->GetPlayer()->DeLimboFrame(vf);
2762 pic->buf[0] = buffer;
2768int get_avf_buffer_dxva2(
struct AVCodecContext *c,
AVFrame *pic,
int )
2773 for (
int i = 0; i < 4; i++)
2775 pic->data[i] =
nullptr;
2776 pic->linesize[i] = 0;
2778 pic->opaque = frame;
2780 pic->data[0] = (uint8_t*)frame->
m_buffer;
2781 pic->data[3] = (uint8_t*)frame->
m_buffer;
2784 AVBufferRef *buffer =
2785 av_buffer_create((uint8_t*)frame, 0,
2786 [](
void* Opaque, uint8_t* Data)
2794 pic->buf[0] = buffer;
2805 bool had_608 =
false;
2806 bool had_708 =
false;
2807 for (
uint cur = 0; cur + 2 < buf_size; cur += 3)
2809 uint cc_code = buf[cur];
2810 bool cc_valid = (cc_code & 0x04) != 0U;
2812 uint data1 = buf[cur+1];
2813 uint data2 = buf[cur+2];
2814 uint data = (data2 << 8) | data1;
2815 uint cc_type = cc_code & 0x03;
2840 bool check_608,
bool check_708)
2842 bool need_change_608 =
false;
2847 for (
uint i = 0; i < 4; i++)
2854 bool need_change_708 =
false;
2856 if (check_708 || need_change_608)
2859 for (
uint i = 1; i < 64 && !need_change_608 && !need_change_708; i++)
2864 if (need_change_708 && !check_608)
2868 if (!need_change_608 && !need_change_708)
2879 for (
int i = 1; i < 64; i++)
2888 for (
int i = 0; i < 4; i++)
2909 AVPacket *pkt,
bool can_reliably_parse_keyframes)
2914 bool reset_kfd =
false;
2918 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2919 "gopset not set, syncing positionMap");
2921 if (tempKeyFrameDist > 0 && !
m_livetv)
2923 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2924 QString(
"Initial key frame distance: %1.")
2930 else if (
m_keyframeDist != tempKeyFrameDist && tempKeyFrameDist > 0)
2932 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
2933 QString(
"Key frame distance changed from %1 to %2.")
2961 if (can_reliably_parse_keyframes &&
2964 long long last_frame = 0;
2972 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
2973 QString(
"framesRead: %1 last_frame: %2 keyframedist: %3")
2980 long long startpos = pkt->pos;
2982 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
2983 QString(
"positionMap[ %1 ] == %2.")
3013 float bytespersec = (float)
m_bitrate / 8;
3030 const uint8_t *bufptr = pkt->data;
3031 const uint8_t *bufend = pkt->data + pkt->size;
3033 while (bufptr < bufend)
3037 float aspect_override = -1.0F;
3046 if (bufptr + 11 >= pkt->data + pkt->size)
3048 const auto *seq =
reinterpret_cast<const SequenceHeader*
>(bufptr);
3050 int width =
static_cast<int>(seq->width()) >> context->lowres;
3051 int height =
static_cast<int>(seq->height()) >> context->lowres;
3052 float aspect = seq->
aspect(context->codec_id == AV_CODEC_ID_MPEG1VIDEO);
3053 if (stream->sample_aspect_ratio.num)
3054 aspect =
static_cast<float>(av_q2d(stream->sample_aspect_ratio) * width / height);
3055 if (aspect_override > 0.0F)
3056 aspect = aspect_override;
3057 float seqFPS = seq->fps();
3061 changed |= (seqFPS >
static_cast<float>(
m_fps)+0.01F) ||
3062 (seqFPS < static_cast<float>(
m_fps)-0.01F);
3066 bool forceaspectchange = !qFuzzyCompare(
m_currentAspect + 10.0F, aspect + 10.0F) &&
3070 if (changed || forceaspectchange)
3075 bool doublerate =
false;
3078 forceaspectchange, 2,
3081 if (context->hw_frames_ctx)
3082 if (context->internal)
3083 avcodec_flush_buffers(context);
3097 if ((seqFPS > avFPS+0.01F) || (seqFPS < avFPS-0.01F))
3099 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"avFPS(%1) != seqFPS(%2)")
3100 .arg(
static_cast<double>(avFPS)).arg(
static_cast<double>(seqFPS)));
3109 pkt->flags |= AV_PKT_FLAG_KEY;
3116 pkt->flags |= AV_PKT_FLAG_KEY;
3124 const uint8_t *buf = pkt->data;
3125 const uint8_t *buf_end = pkt->data + pkt->size;
3130 if (context->extradata && (context->extradata_size >= 7) && (context->extradata[0] == 0x01))
3132 if (pkt->flags & AV_PKT_FLAG_KEY)
3137 while (buf < buf_end)
3168 bool fps_changed = (seqFPS > 0.0) && ((seqFPS >
m_fps + 0.01) ||
3169 (seqFPS <
m_fps - 0.01));
3174 if (fps_changed || res_changed || forcechange)
3179 bool doublerate =
false;
3192 if (context->hw_frames_ctx && (forcechange || res_changed))
3193 if (context->internal)
3194 avcodec_flush_buffers(context);
3200 m_fps =
static_cast<float>(seqFPS);
3210 if ((seqFPS > avFPS + 0.01) || (seqFPS < avFPS - 0.01))
3212 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
3213 QString(
"avFPS(%1) != seqFPS(%2)").arg(avFPS).arg(seqFPS));
3218 pkt->flags |= AV_PKT_FLAG_KEY;
3238 if (pkt->flags & AV_PKT_FLAG_KEY)
3254 !(pkt->flags & AV_PKT_FLAG_KEY))
3256 av_packet_unref(pkt);
3290 bool sentPacket =
false;
3310 if (ret == AVERROR(EAGAIN))
3314 if (ret==0 && !gotpicture)
3316 ret2 = avcodec_send_packet(context, pkt);
3317 if (ret2 == AVERROR(EAGAIN))
3329 if (ret < 0 || ret2 < 0)
3334 LOG(VB_GENERAL, LOG_ERR,
LOC +
3335 QString(
"video avcodec_receive_frame error: %1 (%2) gotpicture:%3")
3337 .arg(ret).arg(gotpicture));
3342 LOG(VB_GENERAL, LOG_ERR,
LOC +
3343 QString(
"video avcodec_send_packet error: %1 (%2) gotpicture:%3")
3345 .arg(ret2).arg(gotpicture));
3359 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Decoder needs reset");
3363 if (ret == AVERROR_EXTERNAL || ret2 == AVERROR_EXTERNAL)
3365 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"FFmpeg external library error - assuming streams changed");
3377 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
3378 QString(
"video timecodes packet-pts:%1 frame-pts:%2 packet-dts: %3 frame-dts:%4")
3379 .arg(pkt->pts).arg(mpa_pic->pts).arg(pkt->dts)
3380 .arg(mpa_pic->pkt_dts));
3389 auto *newPkt = av_packet_clone(pkt);
3399 auto * side_data = av_frame_get_side_data(AvFrame, AV_FRAME_DATA_A53_CC);
3400 if (side_data && (side_data->size > 0))
3413 frame->m_directRendering =
false;
3424 av_image_fill_arrays(tmppicture.data, tmppicture.linesize,
3425 frame->m_buffer, AV_PIX_FMT_YUV420P, AvFrame->width,
3426 AvFrame->height, IMAGE_ALIGN);
3427 tmppicture.data[0] = frame->m_buffer + frame->m_offsets[0];
3428 tmppicture.data[1] = frame->m_buffer + frame->m_offsets[1];
3429 tmppicture.data[2] = frame->m_buffer + frame->m_offsets[2];
3430 tmppicture.linesize[0] = frame->m_pitches[0];
3431 tmppicture.linesize[1] = frame->m_pitches[1];
3432 tmppicture.linesize[2] = frame->m_pitches[2];
3436 AvFrame->height,
static_cast<AVPixelFormat
>(AvFrame->format),
3437 AvFrame->width, AvFrame->height,
3438 AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
3439 nullptr,
nullptr,
nullptr);
3442 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to allocate sws context");
3445 sws_scale(
m_swsCtx, AvFrame->data, AvFrame->linesize, 0, dim.height(),
3446 tmppicture.data, tmppicture.linesize);
3454 oldframe->
m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3455 oldframe->
m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3481 LOG(VB_GENERAL, LOG_ERR,
LOC +
"NULL videoframe - direct rendering not "
3482 "correctly initialized.");
3487 if (AvFrame->best_effort_timestamp == AV_NOPTS_VALUE)
3489 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No PTS found - unable to process video.");
3493 AvFrame->best_effort_timestamp * 1000);
3494 std::chrono::milliseconds temppts =
pts;
3511 double calcfps = 1000.0 /
ptsdiff.count();
3512 if (calcfps < 121.0 && calcfps > 3.0)
3516 double fpschange = calcfps /
m_fps;
3518 if (fpschange > 1.9 && fpschange < 2.1)
3520 if (fpschange > 0.9 && fpschange < 1.1)
3526 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
3527 QString(
"video timecode %1 %2 %3 %4%5")
3528 .arg(AvFrame->best_effort_timestamp)
3529 .arg(
pts.count()).arg(temppts.count()).arg(
m_lastVPts.count())
3530 .arg((
pts != temppts) ?
" fixup" :
""));
3532 frame->m_interlaced = (AvFrame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
3533 frame->m_topFieldFirst = (AvFrame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) != 0;
3535 frame->m_repeatPic = AvFrame->repeat_pict != 0;
3540 frame->m_colorspace = AvFrame->colorspace;
3541 frame->m_colorrange = AvFrame->color_range;
3542 frame->m_colorprimaries = AvFrame->color_primaries;
3543 frame->m_colortransfer = AvFrame->color_trc;
3544 frame->m_chromalocation = AvFrame->chroma_location;
3545 frame->m_pixFmt = AvFrame->format;
3550 frame->m_dummy =
false;
3551 frame->m_pauseFrame =
false;
3552 frame->m_deinterlaceInuse2x =
false;
3553 frame->m_alreadyDeinterlaced =
false;
3554 frame->m_interlacedReverse =
false;
3584 [[maybe_unused]]
const AVStream *stream,
const AVPacket *pkt)
3586 const uint8_t *buf = pkt->data;
3587 uint64_t linemask = 0;
3592 if ((buf[0]==
't') && (buf[1]==
'v') && (buf[2] ==
'0'))
3595 memcpy(&linemask, buf + 3, 8);
3598 else if ((buf[0]==
'T') && (buf[1]==
'V') && (buf[2] ==
'0'))
3600 linemask = 0xffffffffffffffffLL;
3605 LOG(VB_VBI, LOG_ERR,
LOC + QString(
"Unknown VBI data stream '%1%2%3'")
3606 .arg(QChar(buf[0])).arg(QChar(buf[1])).arg(QChar(buf[2])));
3610 static constexpr uint kMinBlank = 6;
3611 for (
uint i = 0; i < 36; i++)
3613 if (!((linemask >> i) & 0x1))
3616 const uint line = ((i < 18) ? i : i-18) + kMinBlank;
3617 const uint field = (i<18) ? 0 : 1;
3618 const uint id2 = *buf & 0xf;
3642 int data = (buf[2] << 8) | buf[1];
3669 const AVStream* ,
const AVPacket *pkt)
3678 const uint8_t *buf = pkt->data;
3679 const uint8_t *buf_end = pkt->data + pkt->size;
3681 if (*buf >= 0x10 && *buf <= 0x1F)
3687 LOG(VB_VBI, LOG_WARNING,
LOC +
3688 QString(
"VBI: Unknown data_identier: %1 discarded").arg(*buf));
3693 while (buf < buf_end)
3698 if ((buf_end - buf) >= 42)
3702 else if (*buf == 0x03)
3705 if ((buf_end - buf) >= 42)
3709 else if (*buf == 0xff)
3715 LOG(VB_VBI, LOG_WARNING,
LOC +
3716 QString(
"VBI: Unsupported data_unit_id: %1 discarded").arg(*buf));
3726 [[maybe_unused]]
const AVPacket *pkt)
3729 if (
m_itv ==
nullptr)
3731 if (
m_itv ==
nullptr)
3735 uint8_t *data = pkt->data;
3736 int length = pkt->size;
3737 int componentTag = 0;
3738 int dataBroadcastId = 0;
3739 unsigned carouselId = 0;
3742 componentTag = str->component_tag;
3743 dataBroadcastId = str->data_id;
3744 carouselId = (unsigned) str->carousel_id;
3749 uint16_t sectionLen = (((data[1] & 0xF) << 8) | data[2]) + 3;
3751 if (sectionLen > length)
3754 m_itv->ProcessDSMCCSection(data, sectionLen,
3755 componentTag, carouselId,
3757 length -= sectionLen;
3768 long long pts = pkt->pts;
3769 if (
pts == AV_NOPTS_VALUE)
3771 if (
pts == AV_NOPTS_VALUE)
3773 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No PTS found - unable to process subtitle.");
3776 pts =
static_cast<long long>(av_q2d(curstream->time_base) *
pts * 1000);
3782 bool isForcedTrack =
false;
3785 int gotSubtitles = 0;
3786 AVSubtitle subtitle;
3787 memset(&subtitle, 0,
sizeof(AVSubtitle));
3794 curstream->id,
pts);
3798 if (pkt->stream_index == subIdx)
3802 pkt->data, pkt->size,
pts);
3808 || pkt->stream_index == forcedSubIdx)
3811 avcodec_decode_subtitle2(codecContext, &subtitle, &gotSubtitles, pkt);
3814 subtitle.start_display_time +=
pts;
3815 subtitle.end_display_time +=
pts;
3817 if (pkt->stream_index != subIdx)
3818 isForcedTrack =
true;
3825 for (
unsigned i = 0; i < subtitle.num_rects; i++)
3827 subtitle.rects[i]->flags |= AV_SUBTITLE_FLAG_FORCED;
3830 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
3831 QString(
"subtl timecode %1 %2 %3 %4")
3832 .arg(pkt->pts).arg(pkt->dts)
3833 .arg(subtitle.start_display_time)
3834 .arg(subtitle.end_display_time));
3837 subtitle, curstream->codecpar->codec_id == AV_CODEC_ID_XSUB,
3851 auto id =
static_cast<uint>(Packet->stream_index + 0x2000);
3855#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
3856 const auto * codec = QTextCodec::codecForName(
"utf-8");
3857 auto text = codec->toUnicode(
reinterpret_cast<const char *
>(Packet->data), Packet->size - 1);
3859 auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);
3860 QString text = toUtf16.decode(Packet->data);
3862 auto list = text.split(
'\n', Qt::SkipEmptyParts);
3870 enum AVCodecID codec_id = curstream->codecpar->codec_id;
3874 case AV_CODEC_ID_MPEG2VBI:
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 FF_PROFILE_DTS_HD_MA);
4145 FF_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 LOG(VB_GENERAL, LOG_ERR, QString(
"decoding error %1 (%2)")
4706 QString::number(retval)));
4719 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No context");
4720 av_packet_unref(pkt);
4724 if (pkt->stream_index >= (
int)
m_ic->nb_streams)
4726 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bad stream");
4727 av_packet_unref(pkt);
4731 AVStream *curstream =
m_ic->streams[pkt->stream_index];
4735 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Bad stream (NULL)");
4736 av_packet_unref(pkt);
4740 enum AVMediaType codec_type = curstream->codecpar->codec_type;
4741 const AVCodecID codec_id = curstream->codecpar->codec_id;
4747 case AVMEDIA_TYPE_VIDEO:
4748 if (storevideoframes)
4755 case AVMEDIA_TYPE_AUDIO:
4757 if (codec_id == AV_CODEC_ID_AC4)
4759 av_packet_unref(pkt);
4763 case AVMEDIA_TYPE_SUBTITLE:
4766 case AV_CODEC_ID_TEXT:
4768 av_packet_unref(pkt);
4770 case AV_CODEC_ID_DVB_TELETEXT:
4772 av_packet_unref(pkt);
4778 case AVMEDIA_TYPE_DATA:
4780 av_packet_unref(pkt);
4788 if (context ==
nullptr)
4790 if (codec_type != AVMEDIA_TYPE_VIDEO)
4792 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
4793 QString(
"No codec for stream index %1, type(%2) id(%3:%4)")
4794 .arg(QString::number(pkt->stream_index),
4796 avcodec_get_name(codec_id),
4797 QString::number(codec_id)
4804 av_packet_unref(pkt);
4812 case AVMEDIA_TYPE_AUDIO:
4821 case AVMEDIA_TYPE_VIDEO:
4835 av_packet_free(&pkt);
4839 if (pkt->pts != AV_NOPTS_VALUE)
4842 (av_q2d(curstream->time_base)*pkt->pts*1000000);
4857 case AVMEDIA_TYPE_SUBTITLE:
4866 LOG(VB_GENERAL, LOG_ERR,
LOC +
4867 QString(
"Decoding - id(%1) type(%2)")
4868 .arg(avcodec_get_name(codec_id),
4875 if (!have_err && !Retry)
4877 av_packet_unref(pkt);
4882 av_packet_free(&pkt);
4890 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"StreamChangeCheck skip SeekReset"));
4900 int result = av_read_frame(ctx, pkt);
4908 if (pmt_buffer.has_buffer())
4965 if (stream < 0 || !
m_ic)
4967 return avcodec_get_name(
m_ic->streams[stream]->codecpar->codec_id);
4981 QString msg = (disable) ?
"Disabling" :
"Allowing";
4982 LOG(VB_AUDIO, LOG_INFO,
LOC + msg +
" pass through");
5005 switch (ctx->codec_id)
5007 case AV_CODEC_ID_AC3:
5008 case AV_CODEC_ID_TRUEHD:
5009 case AV_CODEC_ID_EAC3:
5010 case AV_CODEC_ID_MLP:
5011 case AV_CODEC_ID_DTS:
5020 bool passthru =
false;
5024 if (!withProfile && par->codec_id == AV_CODEC_ID_DTS && !
m_audio->
CanDTSHD())
5027 par->codec_id, FF_PROFILE_DTS);
5032 par->codec_id, par->profile);
5048 AVStream *curstream =
nullptr;
5049 AVCodecContext *ctx =
nullptr;
5051 int requested_channels = 0;
5055 (
int)
m_ic->nb_streams))
5058 .m_av_stream_index];
5059 if (curstream !=
nullptr)
5066 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"No codec context. Returning false");
5072 ctx->bits_per_raw_sample);
5074 if (av_sample_fmt_is_planar(ctx->sample_fmt))
5076 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Audio data is planar"));
5081 int bps = av_get_bytes_per_sample(ctx->sample_fmt) << 3;
5082 if (ctx->sample_fmt == AV_SAMPLE_FMT_S32 &&
5083 ctx->bits_per_raw_sample)
5084 bps = ctx->bits_per_raw_sample;
5085 LOG(VB_GENERAL, LOG_ERR,
LOC +
5086 QString(
"Unsupported sample format with %1 bits").arg(bps));
5090 bool using_passthru =
DoPassThrough(curstream->codecpar,
false);
5092 requested_channels = ctx->ch_layout.nb_channels;
5094 if (!using_passthru &&
5100 AVChannelLayout channel_layout;
5101 av_channel_layout_default(&channel_layout, requested_channels);
5102 av_opt_set_chlayout(ctx->priv_data,
"downmix", &channel_layout, 0);
5106 requested_channels, using_passthru, ctx->ch_layout.nb_channels,
5107 ctx->codec_id == AV_CODEC_ID_DTS ? ctx->profile : 0);
5111 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Initializing audio parms from " +
5116 LOG(VB_AUDIO, LOG_INFO,
LOC +
"Audio format changed " +
5117 QString(
"\n\t\t\tfrom %1 to %2")
5133 switch (ctx->codec_id)
5135 case AV_CODEC_ID_MP2:
5138 case AV_CODEC_ID_MP3:
5141 case AV_CODEC_ID_AC3:
5144 case AV_CODEC_ID_DTS:
5147 case AV_CODEC_ID_VORBIS:
5150 case AV_CODEC_ID_WMAV1:
5153 case AV_CODEC_ID_WMAV2:
5161 lcd->setAudioFormatLEDs(audio_format,
true);
5196 int64_t start_time = INT64_MAX;
5197 int64_t end_time = INT64_MIN;
5198 AVStream *st =
nullptr;
5200 for (
uint i = 0; i < ic->nb_streams; i++)
5202 AVStream *st1 = ic->streams[i];
5203 if (st1 && st1->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
5212 int64_t duration = INT64_MIN;
5213 if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {
5214 int64_t start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
5215 start_time = std::min(start_time1, start_time);
5216 if (st->duration != AV_NOPTS_VALUE) {
5217 int64_t end_time1 = start_time1 +
5218 av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
5219 end_time = std::max(end_time1, end_time);
5222 if (st->duration != AV_NOPTS_VALUE) {
5223 int64_t duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
5224 duration = std::max(duration1, duration);
5226 if (start_time != INT64_MAX) {
5227 ic->start_time = start_time;
5228 if (end_time != INT64_MIN) {
5229 duration = std::max(end_time - start_time, duration);
5232 if (duration != INT64_MIN) {
5233 ic->duration = duration;
5236 int64_t filesize = avio_size(ic->pb);
5239 ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE /
5240 (
double)ic->duration;
5256 if (
m_ic ==
nullptr)
5261 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_)
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