Go to the documentation of this file.
45 #ifdef USING_MEDIACODEC
60 #include "libavutil/pixdesc.h"
63 #define LOC QString("MythCodecContext: ")
92 #ifdef USING_MEDIACODEC
117 QStringList decoders;
125 #ifdef USING_MEDIACODEC
147 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Must be called from UI thread");
153 LOG(VB_GENERAL, LOG_INFO,
LOC +
"No window: Ignoring hardware decoders");
195 #ifdef USING_MEDIACODEC
198 Opts.
decoders->append(
"mediacodec");
200 Opts.
decoders->append(
"mediacodec-dec");
216 #ifdef USING_V4L2PRIME
247 AVCodecContext **Context,
const AVCodec **Codec)
273 #ifdef USING_MEDIACODEC
303 bool SelectedStream,
bool &DirectRendering)
305 const AVCodec *codec1 = Context->codec;
306 if (codec1 && codec1->capabilities & AV_CODEC_CAP_DR1)
313 DirectRendering =
false;
314 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
315 QString(
"Using software scaling to convert pixel format %1 for "
316 "codec %2").arg(av_get_pix_fmt_name(Context->pix_fmt),
317 avcodec_get_name(Context->codec_id)));
325 MythVideoFrame *videoframe = avfd->GetPlayer()->GetNextVideoFrame();
328 for (
int i = 0; i < 4; i++)
330 Frame->data[i] =
nullptr;
331 Frame->linesize[i] = 0;
333 Frame->opaque = videoframe;
334 videoframe->
m_pixFmt = Context->pix_fmt;
335 Frame->reordered_opaque = Context->reordered_opaque;
337 int ret = avcodec_default_get_buffer2(Context,
Frame, Flags);
342 if (
Frame->hw_frames_ctx)
344 auto *context =
reinterpret_cast<AVHWFramesContext*
>(
Frame->hw_frames_ctx->data);
359 videoframe->
m_priv[0] =
reinterpret_cast<unsigned char*
>(av_buffer_ref(
Frame->buf[0]));
363 videoframe->
m_priv[1] =
reinterpret_cast<unsigned char*
>(av_buffer_ref(
Frame->hw_frames_ctx));
366 Frame->buf[1] = av_buffer_create(
reinterpret_cast<uint8_t*
>(videoframe), 0,
376 if (!AvFrame || !Context || !
Frame)
381 Frame->m_pixFmt = Context->pix_fmt;
382 Frame->m_directRendering =
true;
383 Frame->m_colorshifted =
true;
385 AvFrame->reordered_opaque = Context->reordered_opaque;
386 AvFrame->opaque =
Frame;
389 if (AvFrame->hw_frames_ctx)
391 auto *context =
reinterpret_cast<AVHWFramesContext*
>(AvFrame->hw_frames_ctx->data);
393 Frame->m_swPixFmt = context->sw_format;
397 Frame->m_buffer = AvFrame->data[3];
401 Frame->m_priv[0] =
reinterpret_cast<unsigned char*
>(av_buffer_ref(AvFrame->buf[0]));
404 auto *devicectx =
reinterpret_cast<AVHWDeviceContext*
>(Context->hw_device_ctx->data);
405 Frame->m_priv[1] =
reinterpret_cast<unsigned char*
>(devicectx->user_opaque);
408 AvFrame->buf[1] = av_buffer_create(
reinterpret_cast<uint8_t*
>(
Frame), 0,
417 if (decoder && decoder->GetPlayer())
418 decoder->GetPlayer()->DeLimboFrame(frame);
432 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Error: %1 concurrent hardware frames contexts").arg(count));
438 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"%1 frames context finished")
439 .arg(av_hwdevice_get_type_name(Context->device_ctx->type)));
440 auto * interop =
reinterpret_cast<MythInteropGPU*
>(Context->user_opaque);
447 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"%1 device context finished")
448 .arg(av_hwdevice_get_type_name(Context->type)));
449 auto * interop =
reinterpret_cast<MythInteropGPU*
>(Context->user_opaque);
456 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Calling default device context free");
457 Context->user_opaque = interop->GetDefaultUserOpaque();
471 auto destroy = [](
void *Wait,
void *Interop2,
void* )
473 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Destroy interop callback");
474 auto *wait =
reinterpret_cast<QWaitCondition*
>(Wait);
484 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Cannot destroy interop - no player");
488 destroy, Interop,
nullptr);
493 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Create decoder callback");
494 auto *wait =
reinterpret_cast<QWaitCondition*
>(Wait);
495 auto *context =
reinterpret_cast<AVCodecContext*
>(Context);
497 if (context && callback)
498 (void)callback(context);
508 result =
dynamic_cast<MythPlayerUI*
>(decoder->GetPlayer());
514 if (
auto * player =
GetPlayerUI(Context); player !=
nullptr)
516 const auto & supported = player->GetInteropTypes();
517 return supported.find(
Format) != supported.cend();
524 const QString &Debug)
526 if (!Context || !Callback)
529 return Callback(Context);
535 Context,
reinterpret_cast<void*
>(Callback));
536 return Context->hw_frames_ctx ? 0 : -1;
541 const QString &Debug)
543 if (!Context || !Callback)
546 return Callback(Context);
552 Context,
reinterpret_cast<void*
>(Callback));
553 return Context->hw_device_ctx ? 0 : -1;
558 AVBufferRef* result =
nullptr;
559 int res = av_hwdevice_ctx_create(&result, Type,
Device.isEmpty() ?
nullptr :
560 Device.toLocal8Bit().constData(),
nullptr, 0);
563 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created hardware device '%1'%2")
564 .arg(av_hwdevice_get_type_name(Type),
565 Device ==
nullptr ?
"" : QString(
" (%1)").arg(
Device)));
566 auto *context =
reinterpret_cast<AVHWDeviceContext*
>(result->data);
568 if ((context->free || context->user_opaque) && !Interop)
570 LOG(VB_PLAYBACK, LOG_INFO,
"Creating dummy interop");
582 context->user_opaque = Interop;
587 LOG(VB_PLAYBACK, LOG_ERR,
LOC + QString(
"Failed to create hardware device '%1'%2 Error '%3'")
588 .arg(av_hwdevice_get_type_name(Type),
597 switch (Context->codec_id)
599 case AV_CODEC_ID_H264:
600 switch (Context->profile)
602 case FF_PROFILE_H264_HIGH_10:
603 case FF_PROFILE_H264_HIGH_10_INTRA:
604 case FF_PROFILE_H264_HIGH_422:
605 case FF_PROFILE_H264_HIGH_422_INTRA:
606 case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
607 case FF_PROFILE_H264_HIGH_444_INTRA:
608 case FF_PROFILE_H264_CAVLC_444:
return true;
622 return avcodec_receive_frame(Context,
Frame);
627 if (!
Frame || !AvFrame)
630 AVFrame *temp = av_frame_alloc();
634 AVPixelFormat *pixelformats =
nullptr;
635 int ret = av_hwframe_transfer_get_formats(AvFrame->hw_frames_ctx,
636 AV_HWFRAME_TRANSFER_DIRECTION_FROM,
641 if (best != AV_PIX_FMT_NONE)
645 if (!valid || (
Frame->m_width != AvFrame->width) || (
Frame->m_height != AvFrame->height))
647 AvFrame->width, AvFrame->height);
654 for (
uint i = 0; i < 3; i++)
656 temp->data[i] = (i < max) ? (
Frame->m_buffer +
Frame->m_offsets[i]) :
nullptr;
657 temp->linesize[i] =
Frame->m_pitches[i];
661 temp->buf[0] = av_buffer_create(
reinterpret_cast<uint8_t*
>(
Frame), 0,
662 [](
void* , uint8_t* ){},
this, 0);
663 temp->width = AvFrame->width;
664 temp->height = AvFrame->height;
668 av_freep(&pixelformats);
672 if ((ret = av_hwframe_transfer_data(temp, AvFrame, 0)) < 0)
673 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error %1 transferring the data to system memory").arg(ret));
675 Frame->m_colorshifted =
true;
676 av_frame_free(&temp);
684 case AV_CODEC_ID_MPEG1VIDEO:
return MPEG1;
685 case AV_CODEC_ID_MPEG2VIDEO:
688 case FF_PROFILE_MPEG2_422:
return MPEG2422;
689 case FF_PROFILE_MPEG2_HIGH:
return MPEG2High;
691 case FF_PROFILE_MPEG2_SNR_SCALABLE:
return MPEG2SNR;
693 case FF_PROFILE_MPEG2_MAIN:
return MPEG2Main;
697 case AV_CODEC_ID_MPEG4:
702 case FF_PROFILE_MPEG4_CORE:
return MPEG4Core;
703 case FF_PROFILE_MPEG4_MAIN:
return MPEG4Main;
704 case FF_PROFILE_MPEG4_N_BIT:
return MPEG4NBit;
718 case AV_CODEC_ID_H263:
return H263;
719 case AV_CODEC_ID_H264:
725 case FF_PROFILE_H264_MAIN:
return H264Main;
727 case FF_PROFILE_H264_HIGH:
return H264High;
728 case FF_PROFILE_H264_HIGH_10:
return H264High10;
740 case AV_CODEC_ID_HEVC:
743 case FF_PROFILE_HEVC_MAIN:
return HEVCMain;
744 case FF_PROFILE_HEVC_MAIN_10:
return HEVCMain10;
745 case FF_PROFILE_HEVC_MAIN_STILL_PICTURE:
return HEVCMainStill;
746 case FF_PROFILE_HEVC_REXT:
return HEVCRext;
749 case AV_CODEC_ID_VC1:
752 case FF_PROFILE_VC1_SIMPLE:
return VC1Simple;
753 case FF_PROFILE_VC1_MAIN:
return VC1Main;
754 case FF_PROFILE_VC1_COMPLEX:
return VC1Complex;
758 case AV_CODEC_ID_VP8:
return VP8;
759 case AV_CODEC_ID_VP9:
762 case FF_PROFILE_VP9_0:
return VP9_0;
763 case FF_PROFILE_VP9_1:
return VP9_1;
764 case FF_PROFILE_VP9_2:
return VP9_2;
765 case FF_PROFILE_VP9_3:
return VP9_3;
768 case AV_CODEC_ID_AV1:
771 case FF_PROFILE_AV1_MAIN:
return AV1Main;
772 case FF_PROFILE_AV1_HIGH:
return AV1High;
776 case AV_CODEC_ID_MJPEG:
return MJPEG;
859 return QObject::tr(
"%1%2%3 (Max size: %4x%5)")
862 ColorDepth > 8 ? QString(
" %1Bit").arg(ColorDepth) :
"")
863 .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 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)
static MythCodecID GetBestSupportedCodec(uint width, uint height, const QString &decoder, uint stream_type, bool no_acceleration, AVPixelFormat &pix_fmt)
@ 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)