12#include <QMutexLocker>
14#if QT_VERSION >= QT_VERSION_CHECK(6,5,0)
15#include <QtProcessorDetection>
20#include "libmythbase/mythconfig.h"
27#include "libavcodec/avcodec.h"
28#include "libavutil/imgutils.h"
29#include "libavformat/avformat.h"
36 case FMT_YV12:
return AV_PIX_FMT_YUV420P;
42 case FMT_NV12:
return AV_PIX_FMT_NV12;
43 case FMT_P010:
return AV_PIX_FMT_P010;
44 case FMT_P016:
return AV_PIX_FMT_P016;
58 case FMT_BGRA:
return AV_PIX_FMT_BGRA;
62 case FMT_YUY2:
return AV_PIX_FMT_UYVY422;
64 case FMT_VTB:
return AV_PIX_FMT_VIDEOTOOLBOX;
68 case FMT_DXVA2:
return AV_PIX_FMT_DXVA2_VLD;
69 case FMT_MMAL:
return AV_PIX_FMT_MMAL;
73 return AV_PIX_FMT_NONE;
80 case AV_PIX_FMT_YUVJ420P:
81 case AV_PIX_FMT_YUV420P:
return FMT_YV12;
87 case AV_PIX_FMT_NV12:
return FMT_NV12;
88 case AV_PIX_FMT_P010:
return FMT_P010;
89 case AV_PIX_FMT_P016:
return FMT_P016;
90 case AV_PIX_FMT_YUVJ422P:
97 case AV_PIX_FMT_YUVJ444P:
104 case AV_PIX_FMT_UYVY422:
return FMT_YUY2;
108 case AV_PIX_FMT_BGRA:
return FMT_BGRA;
110 case AV_PIX_FMT_MMAL:
return FMT_MMAL;
112 case AV_PIX_FMT_VIDEOTOOLBOX:
return FMT_VTB;
114 case AV_PIX_FMT_DXVA2_VLD:
return FMT_DXVA2;
127 case AVCOL_TRC_BT2020_10:
155 size_t b0 = tf->buf[0]->size;
156 size_t b1 = tf->buf[1]->size;
157 size_t b2 = tf->buf[2]->size;
160 size_t b0a = ((b0 + 15) / 16) * 16;
161 size_t b1a = ((b1 + 15) / 16) * 16;
162 size_t b2a = ((b2 + 15) / 16) * 16;
165 uint8_t *tbuf{
new uint8_t[b0a + b1a + b2a]{} };
168 tf->data[1] = tbuf + b0a;
169 tf->data[2] = tbuf + b0a + b1a;
170 memcpy(tf->data[0], tf->buf[0]->data, b0);
171 memcpy(tf->data[1], tf->buf[1]->data, b1);
172 memcpy(tf->data[2], tf->buf[2]->data, b2);
177 tf->width, tf->height);
179 mythframe.
m_offsets[1] = tf->data[1] - tf->data[0];
180 mythframe.
m_offsets[2] = tf->data[2] - tf->data[0];
181 mythframe.
m_pitches[0] = tf->linesize[0];
182 mythframe.
m_pitches[1] = tf->linesize[1];
183 mythframe.
m_pitches[2] = tf->linesize[2];
192 memcpy(
Frame->data[0], tf->data[0], b0);
193 memcpy(
Frame->data[1], tf->data[1], b1);
194 memcpy(
Frame->data[2], tf->data[2], b2);
205 if (Fmt == AV_PIX_FMT_NONE)
231 m_size = av_image_get_buffer_size(Fmt, Width, Height, IMAGE_ALIGN);
239 int Width,
int Height)
241 int newwidth = Width;
242#ifdef Q_PROCESSOR_ARM
253 if (FromFmt == AV_PIX_FMT_YUV420P && ToFmt == AV_PIX_FMT_BGRA)
254 newwidth = Width - 1;
257 newwidth, Height, ToFmt, SWS_FAST_BILINEAR,
258 nullptr,
nullptr,
nullptr);
261 sws_scale(
m_swsctx, From->data, From->linesize, 0, Height, To->data, To->linesize);
262 return SizeData(Width, Height, ToFmt);
272 unsigned char*
Buffer, AVPixelFormat Fmt)
279 av_image_fill_arrays(To->data, To->linesize,
Buffer, Fmt, From->
m_width, From->
m_height, IMAGE_ALIGN);
293 const AVCodec* Codec,
296 if (Stream ==
nullptr || Stream->codecpar ==
nullptr)
299 AVCodecContext* avctx =
m_streamMap.value(Stream,
nullptr);
300 if (avctx ==
nullptr)
306 else if (Codec ==
nullptr)
308 Codec = avcodec_find_decoder(Stream->codecpar->codec_id);
309 if (Codec ==
nullptr)
311 LOG(VB_GENERAL, LOG_WARNING, QString(
"avcodec_find_decoder fail for %1")
312 .arg(Stream->codecpar->codec_id));
316 avctx = avcodec_alloc_context3(Codec);
317 if (avctx !=
nullptr && avcodec_parameters_to_context(avctx, Stream->codecpar) < 0)
318 avcodec_free_context(&avctx);
320 if (avctx !=
nullptr)
322 avctx->pkt_timebase = Stream->time_base;
344 avcodec_flush_buffers(avctx);
345 avcodec_free_context(&avctx);
352 QMap<const AVStream*, AVCodecContext*>::iterator i =
m_streamMap.begin();
355 const AVStream *stream = i.key();
363 const int probeBufferSize = 8 * 1024;
364 const AVInputFormat *fmt =
nullptr;
366 memset(&probe, 0,
sizeof(AVProbeData));
368 probe.buf =
new unsigned char[probeBufferSize + AVPROBE_PADDING_SIZE];
369 probe.buf_size = probeBufferSize;
370 memset(probe.buf, 0, probeBufferSize + AVPROBE_PADDING_SIZE);
371 av_log_set_level(AV_LOG_FATAL);
375 if (
m_errorCode == 0 && !infile.open(QIODevice::ReadOnly))
378 int64_t leng = infile.read(
reinterpret_cast<char*
>(probe.buf), probeBufferSize);
379 probe.buf_size =
static_cast<int>(leng);
381 fmt = av_probe_input_format(&probe,
static_cast<int>(
true));
385 AVFormatContext *ctx =
nullptr;
388 ctx = avformat_alloc_context();
393 m_errorCode = avformat_find_stream_info(ctx,
nullptr);
397 for (
uint ix = 0; ix < ctx->nb_streams; ix++)
399 AVStream *stream = ctx->streams[ix];
400 if (stream ==
nullptr)
402 AVCodecParameters *codecpar = stream->codecpar;
403 const AVCodecDescriptor* desc =
nullptr;
405 info.m_codecType =
' ';
406 if (codecpar !=
nullptr)
408 desc = avcodec_descriptor_get(codecpar->codec_id);
409 switch (codecpar->codec_type)
411 case AVMEDIA_TYPE_VIDEO:
412 info.m_codecType =
'V';
414 case AVMEDIA_TYPE_AUDIO:
415 info.m_codecType =
'A';
417 case AVMEDIA_TYPE_SUBTITLE:
418 info.m_codecType =
'S';
425 info.m_codecName = desc->name;
426 if (stream->duration != AV_NOPTS_VALUE)
427 info.m_duration = stream->duration * stream->time_base.num / stream->time_base.den;
428 else if (ctx->duration != AV_NOPTS_VALUE)
429 info.m_duration = ctx->duration / AV_TIME_BASE;
432 if (
info.m_codecType ==
'V')
434 if (codecpar !=
nullptr)
436 info.m_width = codecpar->width;
437 info.m_height = codecpar->height;
438 info.m_SampleAspectRatio =
static_cast<float>(codecpar->sample_aspect_ratio.num)
439 /
static_cast<float>(codecpar->sample_aspect_ratio.den);
440 switch (codecpar->field_order)
442 case AV_FIELD_PROGRESSIVE:
443 info.m_fieldOrder =
"PR";
446 info.m_fieldOrder =
"TT";
449 info.m_fieldOrder =
"BB";
452 info.m_fieldOrder =
"TB";
455 info.m_fieldOrder =
"BT";
461 info.m_frameRate =
static_cast<float>(stream->r_frame_rate.num)
462 /
static_cast<float>(stream->r_frame_rate.den);
463 info.m_avgFrameRate =
static_cast<float>(stream->avg_frame_rate.num)
464 /
static_cast<float>(stream->avg_frame_rate.den);
466 if (
info.m_codecType ==
'A')
467 info.m_channels = codecpar->ch_layout.nb_channels;
478 m_errorMsg =
"av_probe_input_format returned no result";
486 LOG(VB_GENERAL, LOG_ERR,
487 QString(
"MythStreamInfoList failed for %1. Error code:%2 Message:%3")
494 avformat_close_input(&ctx);
495 avformat_free_context(ctx);
int Copy(AVFrame *To, const MythVideoFrame *From, unsigned char *Buffer, AVPixelFormat Fmt=AV_PIX_FMT_YUV420P)
Initialise AVFrame and copy contents of VideoFrame frame into it, performing any required conversion.
int SizeData(int Width, int Height, AVPixelFormat Fmt)
static void DeinterlaceAVFrame(AVFrame *Frame)
Deinterlace an AVFrame.
static VideoFrameType PixelFormatToFrameType(AVPixelFormat Fmt)
static MythHDR::HDRType FFmpegTransferToHDRType(int Transfer)
static int FillAVFrame(AVFrame *Frame, const MythVideoFrame *From, AVPixelFormat Fmt=AV_PIX_FMT_NONE)
Initialise AVFrame with content from MythVideoFrame.
static AVPixelFormat FrameTypeToPixelFormat(VideoFrameType Type)
AVCodecContext * FindCodecContext(const AVStream *Stream)
QRecursiveMutex m_mapLock
AVCodecContext * GetCodecContext(const AVStream *Stream, const AVCodec *Codec=nullptr, bool NullCodec=false)
void FreeCodecContext(const AVStream *Stream)
QMap< const AVStream *, AVCodecContext * > m_streamMap
Handles software based deinterlacing of video frames.
void Filter(MythVideoFrame *Frame, FrameScanType Scan, MythVideoProfile *Profile, bool Force=false)
Deinterlace Frame if needed.
QVector< MythStreamInfo > m_streamInfoList
MythStreamInfoList(const QString &filename)
static size_t GetBufferSize(VideoFrameType Type, int Width, int Height, int Aligned=MYTH_WIDTH_ALIGNMENT)
MythDeintType m_deinterlaceAllowed
MythDeintType m_deinterlaceSingle
static bool YUVFormat(VideoFrameType Type)
MTV_PUBLIC std::string av_make_error_stdstring_unknown(int errnum)
@ FMT_RGB32
endian dependent format, ARGB or BGRA
#define LOG(_MASK_, _LEVEL_, _QSTRING_)