Go to the documentation of this file.
45 #ifdef USING_MEDIACODEC
63 #include "libavutil/pixdesc.h"
66 #define LOC QString("MythCodecContext: ")
96 #ifdef USING_MEDIACODEC
120 QStringList decoders;
128 #ifdef USING_MEDIACODEC
150 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Must be called from UI thread");
156 LOG(VB_GENERAL, LOG_INFO,
LOC +
"No window: Ignoring hardware decoders");
198 #ifdef USING_MEDIACODEC
201 Opts.
decoders->append(
"mediacodec");
203 Opts.
decoders->append(
"mediacodec-dec");
219 #ifdef USING_V4L2PRIME
250 [[maybe_unused]] AVStream *Stream,
251 AVCodecContext **Context,
252 const AVCodec **Codec)
277 #ifdef USING_MEDIACODEC
307 bool SelectedStream,
bool &DirectRendering)
309 const AVCodec *codec1 = Context->codec;
310 if (codec1 && codec1->capabilities & AV_CODEC_CAP_DR1)
317 DirectRendering =
false;
318 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
319 QString(
"Using software scaling to convert pixel format %1 for "
320 "codec %2").arg(av_get_pix_fmt_name(Context->pix_fmt),
321 avcodec_get_name(Context->codec_id)));
329 MythVideoFrame *videoframe = avfd->GetPlayer()->GetNextVideoFrame();
332 for (
int i = 0; i < 4; i++)
334 Frame->data[i] =
nullptr;
335 Frame->linesize[i] = 0;
337 Frame->opaque = videoframe;
338 videoframe->
m_pixFmt = Context->pix_fmt;
339 Frame->reordered_opaque = Context->reordered_opaque;
341 int ret = avcodec_default_get_buffer2(Context,
Frame, Flags);
346 if (
Frame->hw_frames_ctx)
348 auto *context =
reinterpret_cast<AVHWFramesContext*
>(
Frame->hw_frames_ctx->data);
363 videoframe->
m_priv[0] =
reinterpret_cast<unsigned char*
>(av_buffer_ref(
Frame->buf[0]));
367 videoframe->
m_priv[1] =
reinterpret_cast<unsigned char*
>(av_buffer_ref(
Frame->hw_frames_ctx));
370 Frame->buf[1] = av_buffer_create(
reinterpret_cast<uint8_t*
>(videoframe), 0,
380 if (!AvFrame || !Context || !
Frame)
385 Frame->m_pixFmt = Context->pix_fmt;
386 Frame->m_directRendering =
true;
387 Frame->m_colorshifted =
true;
389 AvFrame->reordered_opaque = Context->reordered_opaque;
390 AvFrame->opaque =
Frame;
393 if (AvFrame->hw_frames_ctx)
395 auto *context =
reinterpret_cast<AVHWFramesContext*
>(AvFrame->hw_frames_ctx->data);
397 Frame->m_swPixFmt = context->sw_format;
401 Frame->m_buffer = AvFrame->data[3];
405 Frame->m_priv[0] =
reinterpret_cast<unsigned char*
>(av_buffer_ref(AvFrame->buf[0]));
408 auto *devicectx =
reinterpret_cast<AVHWDeviceContext*
>(Context->hw_device_ctx->data);
409 Frame->m_priv[1] =
reinterpret_cast<unsigned char*
>(devicectx->user_opaque);
412 AvFrame->buf[1] = av_buffer_create(
reinterpret_cast<uint8_t*
>(
Frame), 0,
421 if (decoder && decoder->GetPlayer())
422 decoder->GetPlayer()->DeLimboFrame(frame);
436 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Error: %1 concurrent hardware frames contexts").arg(count));
442 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"%1 frames context finished")
443 .arg(av_hwdevice_get_type_name(Context->device_ctx->type)));
444 auto * interop =
reinterpret_cast<MythInteropGPU*
>(Context->user_opaque);
451 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"%1 device context finished")
452 .arg(av_hwdevice_get_type_name(Context->type)));
453 auto * interop =
reinterpret_cast<MythInteropGPU*
>(Context->user_opaque);
460 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Calling default device context free");
461 Context->user_opaque = interop->GetDefaultUserOpaque();
475 auto destroy = [](
void *Wait,
void *Interop2,
void* )
477 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Destroy interop callback");
478 auto *wait =
reinterpret_cast<QWaitCondition*
>(Wait);
488 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Cannot destroy interop - no player");
492 destroy, Interop,
nullptr);
497 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Create decoder callback");
498 auto *wait =
reinterpret_cast<QWaitCondition*
>(Wait);
499 auto *context =
reinterpret_cast<AVCodecContext*
>(Context);
501 if (context && callback)
502 (void)callback(context);
512 result =
dynamic_cast<MythPlayerUI*
>(decoder->GetPlayer());
518 if (
auto * player =
GetPlayerUI(Context); player !=
nullptr)
520 const auto & supported = player->GetInteropTypes();
521 return supported.find(
Format) != supported.cend();
528 const QString &Debug)
530 if (!Context || !Callback)
533 return Callback(Context);
539 Context,
reinterpret_cast<void*
>(Callback));
540 return Context->hw_frames_ctx ? 0 : -1;
545 const QString &Debug)
547 if (!Context || !Callback)
550 return Callback(Context);
556 Context,
reinterpret_cast<void*
>(Callback));
557 return Context->hw_device_ctx ? 0 : -1;
562 AVBufferRef* result =
nullptr;
563 int res = av_hwdevice_ctx_create(&result, Type,
Device.isEmpty() ?
nullptr :
564 Device.toLocal8Bit().constData(),
nullptr, 0);
567 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created hardware device '%1'%2")
568 .arg(av_hwdevice_get_type_name(Type),
569 Device ==
nullptr ?
"" : QString(
" (%1)").arg(
Device)));
570 auto *context =
reinterpret_cast<AVHWDeviceContext*
>(result->data);
572 if ((context->free || context->user_opaque) && !Interop)
574 LOG(VB_PLAYBACK, LOG_INFO,
"Creating dummy interop");
586 context->user_opaque = Interop;
591 LOG(VB_PLAYBACK, LOG_ERR,
LOC + QString(
"Failed to create hardware device '%1'%2 Error '%3'")
592 .arg(av_hwdevice_get_type_name(Type),
601 switch (Context->codec_id)
603 case AV_CODEC_ID_H264:
604 switch (Context->profile)
606 case FF_PROFILE_H264_HIGH_10:
607 case FF_PROFILE_H264_HIGH_10_INTRA:
608 case FF_PROFILE_H264_HIGH_422:
609 case FF_PROFILE_H264_HIGH_422_INTRA:
610 case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
611 case FF_PROFILE_H264_HIGH_444_INTRA:
612 case FF_PROFILE_H264_CAVLC_444:
return true;
626 return avcodec_receive_frame(Context,
Frame);
631 if (!
Frame || !AvFrame)
634 AVFrame *temp = av_frame_alloc();
638 AVPixelFormat *pixelformats =
nullptr;
639 int ret = av_hwframe_transfer_get_formats(AvFrame->hw_frames_ctx,
640 AV_HWFRAME_TRANSFER_DIRECTION_FROM,
645 if (best != AV_PIX_FMT_NONE)
649 if (!valid || (
Frame->m_width != AvFrame->width) || (
Frame->m_height != AvFrame->height))
651 AvFrame->width, AvFrame->height);
658 for (
uint i = 0; i < 3; i++)
660 temp->data[i] = (i < max) ? (
Frame->m_buffer +
Frame->m_offsets[i]) :
nullptr;
661 temp->linesize[i] =
Frame->m_pitches[i];
665 temp->buf[0] = av_buffer_create(
reinterpret_cast<uint8_t*
>(
Frame), 0,
666 [](
void* , uint8_t* ){},
this, 0);
667 temp->width = AvFrame->width;
668 temp->height = AvFrame->height;
672 av_freep(&pixelformats);
676 if ((ret = av_hwframe_transfer_data(temp, AvFrame, 0)) < 0)
677 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error %1 transferring the data to system memory").arg(ret));
679 Frame->m_colorshifted =
true;
680 av_frame_free(&temp);
688 case AV_CODEC_ID_MPEG1VIDEO:
return MPEG1;
689 case AV_CODEC_ID_MPEG2VIDEO:
692 case FF_PROFILE_MPEG2_422:
return MPEG2422;
693 case FF_PROFILE_MPEG2_HIGH:
return MPEG2High;
695 case FF_PROFILE_MPEG2_SNR_SCALABLE:
return MPEG2SNR;
697 case FF_PROFILE_MPEG2_MAIN:
return MPEG2Main;
701 case AV_CODEC_ID_MPEG4:
706 case FF_PROFILE_MPEG4_CORE:
return MPEG4Core;
707 case FF_PROFILE_MPEG4_MAIN:
return MPEG4Main;
708 case FF_PROFILE_MPEG4_N_BIT:
return MPEG4NBit;
722 case AV_CODEC_ID_H263:
return H263;
723 case AV_CODEC_ID_H264:
729 case FF_PROFILE_H264_MAIN:
return H264Main;
731 case FF_PROFILE_H264_HIGH:
return H264High;
732 case FF_PROFILE_H264_HIGH_10:
return H264High10;
744 case AV_CODEC_ID_HEVC:
747 case FF_PROFILE_HEVC_MAIN:
return HEVCMain;
748 case FF_PROFILE_HEVC_MAIN_10:
return HEVCMain10;
749 case FF_PROFILE_HEVC_MAIN_STILL_PICTURE:
return HEVCMainStill;
750 case FF_PROFILE_HEVC_REXT:
return HEVCRext;
753 case AV_CODEC_ID_VC1:
756 case FF_PROFILE_VC1_SIMPLE:
return VC1Simple;
757 case FF_PROFILE_VC1_MAIN:
return VC1Main;
758 case FF_PROFILE_VC1_COMPLEX:
return VC1Complex;
762 case AV_CODEC_ID_VP8:
return VP8;
763 case AV_CODEC_ID_VP9:
766 case FF_PROFILE_VP9_0:
return VP9_0;
767 case FF_PROFILE_VP9_1:
return VP9_1;
768 case FF_PROFILE_VP9_2:
return VP9_2;
769 case FF_PROFILE_VP9_3:
return VP9_3;
772 case AV_CODEC_ID_AV1:
775 case FF_PROFILE_AV1_MAIN:
return AV1Main;
776 case FF_PROFILE_AV1_HIGH:
return AV1High;
780 case AV_CODEC_ID_MJPEG:
return MJPEG;
863 return QObject::tr(
"%1%2%3 (Max size: %4x%5)")
866 ColorDepth > 8 ? QString(
" %1Bit").arg(ColorDepth) :
"")
867 .arg(Size.width()).arg(Size.height());
static bool HavePrimeDecoders(bool Reinit=false, AVCodecID Codec=AV_CODEC_ID_NONE)
QMap< QString, QStringList > * equiv_decoders
static bool codec_is_vdpau_hw(MythCodecID id)
static QAtomicInt s_hwFramesContextCount
MythCodecContext(DecoderBase *Parent, MythCodecID CodecID)
static void error(const char *str,...)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
static bool codec_is_v4l2(MythCodecID id)
static bool codec_is_vdpau_dechw(MythCodecID id)
static bool HaveMMAL(bool Reinit=false)
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &decoder, uint stream_type)
static bool codec_is_nvdec(MythCodecID id)
MythPlayerUI * GetPlayer()
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, uint StreamType)
Confirm whether VAAPI support is available given Decoder and Context.
int(*)(AVCodecContext *Context) CreateHWDecoder
static void NewHardwareFramesContext(void)
Track the number of concurrent frames contexts.
static bool codec_is_vaapi(MythCodecID id)
static bool codec_is_vtb(MythCodecID id)
static MythCodecContext * CreateContext(DecoderBase *Parent, MythCodecID Codec)
static bool HaveVDPAU(bool Reinit=false)
static void GetDecoderList(QStringList &Decoders)
static bool codec_is_vaapi_dec(MythCodecID id)
static const struct wl_interface * types[]
virtual void InitVideoCodec(AVCodecContext *Context, bool SelectedStream, bool &DirectRendering)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static void FramesContextFinished(AVHWFramesContext *Context)
static bool HaveV4L2Codecs(bool Reinit=false)
static void GetDecoderList(QStringList &Decoders)
static bool codec_is_mmal_dec(MythCodecID id)
A device containing images (ie. USB stick, CD, storage group etc)
static CodecProfile FFmpegToMythProfile(AVCodecID CodecID, int Profile)
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
virtual MythCodecID GetVideoCodecID(void) const =0
bool HasMythMainWindow(void)
static void GetDecoderList(QStringList &Decoders)
@ H264ConstrainedBaseline
static void GetDecoderList(QStringList &Decoders)
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, uint StreamType)
static void GetDecoderList(QStringList &Decoders)
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
static void DeviceContextFinished(AVHWDeviceContext *Context)
static bool codec_is_dxva2(MythCodecID id)
static void GetDecoderList(QStringList &Decoders)
static void DestroyInterop(MythInteropGPU *Interop)
static void ReleaseBuffer(void *Opaque, uint8_t *Data)
@ MPEG4AdvancedScaleableTexture
void HandleDecoderCallback(const QString &Debug, DecoderCallback::Callback Function, void *Opaque1, void *Opaque2)
Convenience function to request and wait for a callback into the main thread.
static int GetBuffer(struct AVCodecContext *Context, AVFrame *Frame, int Flags)
A generic hardware buffer initialisation method when using AVHWFramesContext.
static bool codec_is_nvdec_dec(MythCodecID id)
static QString HaveVAAPI(bool ReCheck=false)
Check whether VAAPI is available and not emulated via VDPAU.
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
virtual bool RetrieveHWFrame(MythVideoFrame *Frame, AVFrame *AvFrame)
uint mpeg_version(AVCodecID codec_id)
static MythCodecID GetBestSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
A generic context handler for codecs that return AV_PIX_FMT_DRM_PRIME frames.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static MythCodecID GetSupportedCodec(AVCodecContext **CodecContext, const AVCodec **Codec, const QString &Decoder, uint StreamType)
static bool IsUnsupportedProfile(AVCodecContext *Context)
Most hardware decoders do not support these codecs/profiles.
static VideoFrameType PixelFormatToFrameType(AVPixelFormat Fmt)
virtual int FilteredReceiveFrame(AVCodecContext *Context, AVFrame *Frame)
Retrieve and process/filter AVFrame.
static QStringList GetDecoderDescription(void)
static MythInteropGPU * CreateDummy()
static bool HaveMediaCodec(bool Reinit=false)
void(*)(struct AVHWDeviceContext *) FreeAVHWDeviceContext
static bool codec_is_vtb_dec(MythCodecID id)
static void CreateDecoderCallback(void *Wait, void *Context, void *Callback)
static bool codec_is_mediacodec_dec(MythCodecID id)
static QString FormatDescription(VideoFrameType Type)
A handler for V4L2 Memory2Memory codecs.
static AVBufferRef * CreateDevice(AVHWDeviceType Type, MythInteropGPU *Interop, const QString &Device=QString())
static bool codec_is_mmal(MythCodecID id)
static bool HaveNVDEC(bool Reinit=false)
static bool codec_is_v4l2_dec(MythCodecID id)
static bool FrameTypeIsSupported(AVCodecContext *Context, VideoFrameType Format)
static InteropMap GetTypes(MythRender *Render)
static MythRenderOpenGL * GetOpenGLRender(void)
static uint GetNumPlanes(VideoFrameType Type)
static int InitialiseDecoder2(AVCodecContext *Context, CreateHWDecoder Callback, const QString &Debug)
Initialise a hardware decoder that is NOT expected to use AVHWFramesContext.
static bool codec_is_mediacodec(MythCodecID id)
static AVPixelFormat GetBestVideoFormat(AVPixelFormat *Formats, const VideoFrameTypes *RenderFormats)
Find a suitable frame format that is mutually acceptable to the decoder and render device.
static bool ReinitBuffer(MythVideoFrame *Frame, VideoFrameType Type, MythCodecID CodecID, int Width, int Height)
static bool codec_is_drmprime(MythCodecID id)
static QString GetProfileDescription(CodecProfile Profile, QSize Size, VideoFrameType Format=FMT_NONE, uint ColorDepth=0)
void SetDefaultUserOpaque(void *UserOpaque)
void SetDefaultFree(FreeAVHWDeviceContext FreeContext)
static void GetDecoders(RenderOptions &Opts, bool Reinit=false)
virtual int IncrRef(void)
Increments reference count.
static int InitialiseDecoder(AVCodecContext *Context, CreateHWDecoder Callback, const QString &Debug)
Initialise a hardware decoder that is expected to use AVHWFramesContext.
char * av_make_error_stdstring(std::string &errbuf, int errnum)
static bool GetBuffer2(struct AVCodecContext *Context, MythVideoFrame *Frame, AVFrame *AvFrame, int Flags)
A generic hardware buffer initialisation method when AVHWFramesContext is NOT used.
static MythPlayerUI * GetPlayerUI(AVCodecContext *Context)
static void GetDecoderList(QStringList &Decoders)
std::array< uint8_t *, 4 > m_priv
static bool HaveVTB(bool Reinit=false)
static MythCodecID GetSupportedCodec(AVCodecContext **CodecContext, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
Determine whether NVDEC decoding is supported for this codec.
static MythCodecID FindDecoder(const QString &Decoder, AVStream *Stream, AVCodecContext **Context, const AVCodec **Codec)