MythTV master
mythcodeccontext.cpp
Go to the documentation of this file.
1
2// Copyright (c) 2017-19 MythTV Developers <mythtv-dev@mythtv.org>
3//
4// This is part of MythTV (https://www.mythtv.org)
5//
6// This program is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 2 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19//
20// You should have received a copy of the GNU General Public License
21// along with this program. If not, see <http://www.gnu.org/licenses/>.
22//
24
29#include "mythinteropgpu.h"
30#include "avformatdecoder.h"
31#include "mythplayerui.h"
32
33#if CONFIG_VAAPI
34#include "mythvaapicontext.h"
35#endif
36#if CONFIG_VDPAU
37#include "mythvdpauhelper.h"
38#include "mythvdpaucontext.h"
39#endif
40#if CONFIG_NVDEC
41#include "mythnvdeccontext.h"
42#endif
43#if CONFIG_VIDEOTOOLBOX
44#include "mythvtbcontext.h"
45#endif
46#if CONFIG_MEDIACODEC
48#endif
49#if CONFIG_V4L2
50#include "mythv4l2m2mcontext.h"
51#endif
52#if CONFIG_MMAL
53#include "mythmmalcontext.h"
54#endif
55#if CONFIG_EGL
56#include "mythdrmprimecontext.h"
57#endif
58#if CONFIG_DXVA2
59#include "videoout_d3d.h"
60#endif
61#include "mythcodeccontext.h"
62
63extern "C" {
64#include "libavutil/pixdesc.h"
65}
66
67#define LOC QString("MythCodecContext: ")
68
70
72 : m_parent(Parent),
73 m_codecID(CodecID)
74{
75}
76
78 [[maybe_unused]] MythCodecID Codec)
79{
80 MythCodecContext *mctx = nullptr;
81#if CONFIG_VAAPI
82 if (codec_is_vaapi(Codec) || codec_is_vaapi_dec(Codec))
83 mctx = new MythVAAPIContext(Parent, Codec);
84#endif
85#if CONFIG_VDPAU
86 if (codec_is_vdpau_hw(Codec) || codec_is_vdpau_dechw(Codec))
87 mctx = new MythVDPAUContext(Parent, Codec);
88#endif
89#if CONFIG_NVDEC
90 if (codec_is_nvdec_dec(Codec) || codec_is_nvdec(Codec))
91 mctx = new MythNVDECContext(Parent, Codec);
92#endif
93#if CONFIG_VIDEOTOOLBOX
94 if (codec_is_vtb_dec(Codec) || codec_is_vtb(Codec))
95 mctx = new MythVTBContext(Parent, Codec);
96#endif
97#if CONFIG_MEDIACODEC
99 mctx = new MythMediaCodecContext(Parent, Codec);
100#endif
101#if CONFIG_V4L2
102 if (codec_is_v4l2_dec(Codec) || codec_is_v4l2(Codec))
103 mctx = new MythV4L2M2MContext(Parent, Codec);
104#endif
105#if CONFIG_MMAL
106 if (codec_is_mmal_dec(Codec) || codec_is_mmal(Codec))
107 mctx = new MythMMALContext(Parent, Codec);
108#endif
109#if CONFIG_EGL
110 if (codec_is_drmprime(Codec))
111 mctx = new MythDRMPRIMEContext(Parent, Codec);
112#endif
113
114 if (!mctx)
115 mctx = new MythCodecContext(Parent, Codec);
116 return mctx;
117}
118
120{
121 QStringList decoders;
122
123#if CONFIG_VDPAU
125#endif
126#if CONFIG_VAAPI
128#endif
129#if CONFIG_MEDIACODEC
131#endif
132#if CONFIG_NVDEC
134#endif
135#if CONFIG_MMAL
137#endif
138#if CONFIG_V4L2
140#endif
141#if CONFIG_VIDEOTOOLBOX
143#endif
144 return decoders;
145}
146
147void MythCodecContext::GetDecoders(RenderOptions &Opts, bool Reinit /*=false*/)
148{
149 if (!gCoreContext->IsUIThread())
150 {
151 LOG(VB_GENERAL, LOG_ERR, LOC + "Must be called from UI thread");
152 return;
153 }
154
155 if (!HasMythMainWindow())
156 {
157 LOG(VB_GENERAL, LOG_INFO, LOC + "No window: Ignoring hardware decoders");
158 return;
159 }
160
161 Opts.decoders->append("ffmpeg");
162 (*Opts.equiv_decoders)["ffmpeg"].append("dummy");
163
164#if CONFIG_VDPAU
165 // Only enable VDPAU support if it is actually present
166 if (MythVDPAUHelper::HaveVDPAU(Reinit))
167 {
168 Opts.decoders->append("vdpau");
169 (*Opts.equiv_decoders)["vdpau"].append("dummy");
170 Opts.decoders->append("vdpau-dec");
171 (*Opts.equiv_decoders)["vdpau-dec"].append("dummy");
172 }
173#endif
174#if CONFIG_DXVA2
175 Opts.decoders->append("dxva2");
176 (*Opts.equiv_decoders)["dxva2"].append("dummy");
177#endif
178
179#if CONFIG_VAAPI
180 // Only enable VAAPI if it is actually present and isn't actually VDPAU
181 if (!MythVAAPIContext::HaveVAAPI(Reinit).isEmpty())
182 {
183 Opts.decoders->append("vaapi");
184 (*Opts.equiv_decoders)["vaapi"].append("dummy");
185 Opts.decoders->append("vaapi-dec");
186 (*Opts.equiv_decoders)["vaapi-dec"].append("dummy");
187 }
188#endif
189#if CONFIG_NVDEC
190 // Only enable NVDec support if it is actually present
191 if (MythNVDECContext::HaveNVDEC(Reinit))
192 {
193 Opts.decoders->append("nvdec");
194 (*Opts.equiv_decoders)["nvdec"].append("dummy");
195 Opts.decoders->append("nvdec-dec");
196 (*Opts.equiv_decoders)["nvdec-dec"].append("dummy");
197 }
198#endif
199#if CONFIG_MEDIACODEC
201 {
202 Opts.decoders->append("mediacodec");
203 (*Opts.equiv_decoders)["mediacodec"].append("dummy");
204 Opts.decoders->append("mediacodec-dec");
205 (*Opts.equiv_decoders)["mediacodec-dec"].append("dummy");
206 }
207#endif
208#if CONFIG_VIDEOTOOLBOX
209 if (MythVTBContext::HaveVTB(Reinit))
210 {
211 Opts.decoders->append("vtb");
212 Opts.decoders->append("vtb-dec");
213 (*Opts.equiv_decoders)["vtb"].append("dummy");
214 (*Opts.equiv_decoders)["vtb-dec"].append("dummy");
215 }
216#endif
217#if CONFIG_V4L2
219 {
220#if CONFIG_V4L2PRIME
221 Opts.decoders->append("v4l2");
222 (*Opts.equiv_decoders)["v4l2"].append("dummy");
223#endif
224 Opts.decoders->append("v4l2-dec");
225 (*Opts.equiv_decoders)["v4l2-dec"].append("dummy");
226 }
227#endif
228#if CONFIG_EGL
230 {
231 Opts.decoders->append("drmprime");
232 (*Opts.equiv_decoders)["drmprime"].append("dummy");
233 }
234#endif
235#if CONFIG_MMAL
236 if (MythMMALContext::HaveMMAL(Reinit))
237 {
238 Opts.decoders->append("mmal-dec");
239 (*Opts.equiv_decoders)["mmal-dec"].append("dummy");
241 if (auto mmal = types.find(FMT_MMAL); (mmal != types.end()) && !mmal->second.empty())
242 {
243 Opts.decoders->append("mmal");
244 (*Opts.equiv_decoders)["mmal"].append("dummy");
245 }
246 }
247#endif
248}
249
251 [[maybe_unused]] AVStream *Stream,
252 AVCodecContext **Context,
253 const AVCodec **Codec)
254{
255 MythCodecID result = kCodec_NONE;
256 uint streamtype = mpeg_version((*Context)->codec_id);
257
258#if CONFIG_VDPAU
259 result = MythVDPAUContext::GetSupportedCodec(Context, Codec, Decoder, streamtype);
260 if (codec_is_vdpau_hw(result) || codec_is_vdpau_dechw(result))
261 return result;
262#endif
263#if CONFIG_VAAPI
264 result = MythVAAPIContext::GetSupportedCodec(Context, Codec, Decoder, streamtype);
265 if (codec_is_vaapi(result) || codec_is_vaapi_dec(result))
266 return result;
267#endif
268#if CONFIG_VIDEOTOOLBOX
269 result = MythVTBContext::GetSupportedCodec(Context, Codec, Decoder, streamtype);
270 if (codec_is_vtb(result) || codec_is_vtb_dec(result))
271 return result;
272#endif
273#if CONFIG_DXVA2
274 result = VideoOutputD3D::GetSupportedCodec(Context, Codec, Decoder, streamtype);
275 if (codec_is_dxva2(result))
276 return result;
277#endif
278#if CONFIG_MEDIACODEC
279 result = MythMediaCodecContext::GetBestSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
280 if (codec_is_mediacodec(result) || codec_is_mediacodec_dec(result))
281 return result;
282#endif
283#if CONFIG_NVDEC
284 result = MythNVDECContext::GetSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
285 if (codec_is_nvdec(result) || codec_is_nvdec_dec(result))
286 return result;
287#endif
288#if CONFIG_V4L2
289 result = MythV4L2M2MContext::GetSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
290 if (codec_is_v4l2_dec(result) || codec_is_v4l2(result))
291 return result;
292#endif
293#if CONFIG_MMAL
294 result = MythMMALContext::GetSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
295 if (codec_is_mmal_dec(result) || codec_is_mmal(result))
296 return result;
297#endif
298#if CONFIG_EGL
299 result = MythDRMPRIMEContext::GetSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
300 if (codec_is_drmprime(result))
301 return result;
302#endif
303
304 return kCodec_NONE;
305}
306
307void MythCodecContext::InitVideoCodec(AVCodecContext *Context,
308 bool SelectedStream, bool &DirectRendering)
309{
310 const AVCodec *codec1 = Context->codec;
311 if (codec1 && codec1->capabilities & AV_CODEC_CAP_DR1)
312 {
313 // Context->flags |= CODEC_FLAG_EMU_EDGE;
314 }
315 else
316 {
317 if (SelectedStream)
318 DirectRendering = false;
319 LOG(VB_PLAYBACK, LOG_INFO, LOC +
320 QString("Using software scaling to convert pixel format %1 for "
321 "codec %2").arg(av_get_pix_fmt_name(Context->pix_fmt),
322 avcodec_get_name(Context->codec_id)));
323 }
324}
325
327int MythCodecContext::GetBuffer(struct AVCodecContext *Context, AVFrame *Frame, int Flags)
328{
329 auto *avfd = static_cast<AvFormatDecoder*>(Context->opaque);
330 MythVideoFrame *videoframe = avfd->GetPlayer()->GetNextVideoFrame();
331
332 // set fields required for directrendering
333 for (int i = 0; i < 4; i++)
334 {
335 Frame->data[i] = nullptr;
336 Frame->linesize[i] = 0;
337 }
338 Frame->opaque = videoframe;
339 videoframe->m_pixFmt = Context->pix_fmt;
340
341 int ret = avcodec_default_get_buffer2(Context, Frame, Flags);
342 if (ret < 0)
343 return ret;
344
345 // set the underlying pixel format. Set here rather than guessing later.
346 if (Frame->hw_frames_ctx)
347 {
348 auto *context = reinterpret_cast<AVHWFramesContext*>(Frame->hw_frames_ctx->data);
349 if (context)
350 videoframe->m_swPixFmt = context->sw_format;
351 }
352
353 // VAAPI 'fixes' 10/12/16bit colour values. Irrelevant for VDPAU.
354 videoframe->m_colorshifted = true;
355
356 // avcodec_default_get_buffer2 will retrieve an AVBufferRef from the pool of
357 // hardware surfaces stored within AVHWFramesContext. The pointer to the surface is stored
358 // in Frame->data[3]. Store this in VideoFrame::buf for the interop class to use.
359 videoframe->m_buffer = Frame->data[3];
360 // Frame->buf(0) also contains a reference to the buffer. Take an additional reference to this
361 // buffer to retain the surface until it has been displayed (otherwise it is
362 // reused once the decoder is finished with it).
363 videoframe->m_priv[0] = reinterpret_cast<unsigned char*>(av_buffer_ref(Frame->buf[0]));
364 // frame->hw_frames_ctx contains a reference to the AVHWFramesContext. Take an additional
365 // reference to ensure AVHWFramesContext is not released until we are finished with it.
366 // This also contains the underlying MythInteropGPU class reference.
367 videoframe->m_priv[1] = reinterpret_cast<unsigned char*>(av_buffer_ref(Frame->hw_frames_ctx));
368
369 // Set release method
370 Frame->buf[1] = av_buffer_create(reinterpret_cast<uint8_t*>(videoframe), 0,
372 return ret;
373}
374
375
377bool MythCodecContext::GetBuffer2(struct AVCodecContext *Context, MythVideoFrame* Frame,
378 AVFrame *AvFrame, int /*Flags*/)
379{
380 if (!AvFrame || !Context || !Frame)
381 return false;
382
383 auto *avfd = static_cast<AvFormatDecoder*>(Context->opaque);
384
385 Frame->m_pixFmt = Context->pix_fmt;
386 Frame->m_directRendering = true;
387 Frame->m_colorshifted = true;
388
389 AvFrame->opaque = Frame;
390
391 // retrieve the software format
392 if (AvFrame->hw_frames_ctx)
393 {
394 auto *context = reinterpret_cast<AVHWFramesContext*>(AvFrame->hw_frames_ctx->data);
395 if (context)
396 Frame->m_swPixFmt = context->sw_format;
397 }
398
399 // the hardware surface is stored in Frame->data[3]
400 Frame->m_buffer = AvFrame->data[3];
401
402 // Frame->buf[0] contains the release method. Take another reference to
403 // ensure the frame is not released before it is displayed.
404 Frame->m_priv[0] = reinterpret_cast<unsigned char*>(av_buffer_ref(AvFrame->buf[0]));
405
406 // Retrieve and set the interop class
407 auto *devicectx = reinterpret_cast<AVHWDeviceContext*>(Context->hw_device_ctx->data);
408 Frame->m_priv[1] = reinterpret_cast<unsigned char*>(devicectx->user_opaque);
409
410 // Set release method
411 AvFrame->buf[1] = av_buffer_create(reinterpret_cast<uint8_t*>(Frame), 0,
413 return true;
414}
415
416void MythCodecContext::ReleaseBuffer(void *Opaque, uint8_t *Data)
417{
418 auto *decoder = static_cast<AvFormatDecoder*>(Opaque);
419 auto *frame = reinterpret_cast<MythVideoFrame*>(Data);
420 if (decoder && decoder->GetPlayer())
421 decoder->GetPlayer()->DeLimboFrame(frame);
422}
423
432{
433 int count = ++s_hwFramesContextCount;
434 if (count != 1)
435 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Error: %1 concurrent hardware frames contexts").arg(count));
436}
437
438void MythCodecContext::FramesContextFinished(AVHWFramesContext *Context)
439{
441 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1 frames context finished")
442 .arg(av_hwdevice_get_type_name(Context->device_ctx->type)));
443 auto * interop = reinterpret_cast<MythInteropGPU*>(Context->user_opaque);
444 if (interop)
445 DestroyInterop(interop);
446}
447
448void MythCodecContext::DeviceContextFinished(AVHWDeviceContext* Context)
449{
450 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1 device context finished")
451 .arg(av_hwdevice_get_type_name(Context->type)));
452 auto * interop = reinterpret_cast<MythInteropGPU*>(Context->user_opaque);
453 if (interop)
454 {
455 FreeAVHWDeviceContext free = interop->GetDefaultFree();
456 void *io_user_opaque = interop->GetDefaultUserOpaque();
457 DestroyInterop(interop);
458 if (free)
459 {
460 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Calling default device context free");
461 Context->user_opaque = io_user_opaque;
462 free(Context);
463 }
464 }
465}
466
468{
470 {
471 Interop->DecrRef();
472 return;
473 }
474
475 auto destroy = [](void *Wait, void *Interop2, void* /*unused*/)
476 {
477 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Destroy interop callback");
478 auto *wait = reinterpret_cast<QWaitCondition*>(Wait);
479 auto *interop = reinterpret_cast<MythInteropGPU*>(Interop2);
480 if (interop)
481 interop->DecrRef();
482 if (wait)
483 wait->wakeAll();
484 };
485
486 if (!Interop->GetPlayer())
487 {
488 LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot destroy interop - no player");
489 return;
490 }
491 Interop->GetPlayer()->HandleDecoderCallback("Destroy OpenGL interop",
492 destroy, Interop, nullptr);
493}
494
495void MythCodecContext::CreateDecoderCallback(void *Wait, void *Context, void *Callback)
496{
497 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Create decoder callback");
498 auto *wait = reinterpret_cast<QWaitCondition*>(Wait);
499 auto *context = reinterpret_cast<AVCodecContext*>(Context);
500 auto callback = reinterpret_cast<CreateHWDecoder>(Callback);
501 if (context && callback)
502 (void)callback(context);
503 if (wait)
504 wait->wakeAll();
505}
506
508{
509 MythPlayerUI* result = nullptr;
510 auto* decoder = reinterpret_cast<AvFormatDecoder*>(Context->opaque);
511 if (decoder)
512 result = dynamic_cast<MythPlayerUI*>(decoder->GetPlayer());
513 return result;
514}
515
517{
518 if (auto * player = GetPlayerUI(Context); player != nullptr)
519 {
520 const auto & supported = player->GetInteropTypes();
521 return supported.find(Format) != supported.cend();
522 }
523 return false;
524}
525
527int MythCodecContext::InitialiseDecoder(AVCodecContext *Context, CreateHWDecoder Callback,
528 const QString &Debug)
529{
530 if (!Context || !Callback)
531 return -1;
533 return Callback(Context);
534
535 // Callback to MythPlayer (which will fail without a MythPlayer instance)
536 MythPlayerUI* player = GetPlayerUI(Context);
537 if (player)
539 Context, reinterpret_cast<void*>(Callback));
540 return Context->hw_frames_ctx ? 0 : -1;
541}
542
544int MythCodecContext::InitialiseDecoder2(AVCodecContext *Context, CreateHWDecoder Callback,
545 const QString &Debug)
546{
547 if (!Context || !Callback)
548 return -1;
550 return Callback(Context);
551
552 // Callback to MythPlayer (which will fail without a MythPlayer instance)
553 MythPlayerUI* player = GetPlayerUI(Context);
554 if (player)
556 Context, reinterpret_cast<void*>(Callback));
557 return Context->hw_device_ctx ? 0 : -1;
558}
559
560AVBufferRef* MythCodecContext::CreateDevice(AVHWDeviceType Type, MythInteropGPU* Interop, const QString& Device)
561{
562 AVBufferRef* result = nullptr;
563 int res = av_hwdevice_ctx_create(&result, Type, Device.isEmpty() ? nullptr :
564 Device.toLocal8Bit().constData(), nullptr, 0);
565 if (res == 0)
566 {
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);
571
572 if ((context->free || context->user_opaque) && !Interop)
573 {
574 LOG(VB_PLAYBACK, LOG_INFO, "Creating dummy interop");
575 Interop = MythInteropGPU::CreateDummy();
576 }
577
578 if (Interop)
579 {
580 Interop->SetDefaultFree(context->free);
581 Interop->SetDefaultUserOpaque(context->user_opaque);
582 Interop->IncrRef();
583 }
584
586 context->user_opaque = Interop;
587 return result;
588 }
589
590 std::string error;
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),
593 Device == nullptr ? "" : QString(" (%1)").arg(Device),
595 return nullptr;
596}
597
599bool MythCodecContext::IsUnsupportedProfile(AVCodecContext *Context)
600{
601 switch (Context->codec_id)
602 {
603 case AV_CODEC_ID_H264:
604 switch (Context->profile)
605 {
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;
613 default: break;
614 }
615 break;
616 default: break;
617 }
618 return false;
619}
620
625{
626 return avcodec_receive_frame(Context, Frame);
627}
628
630{
631 if (!Frame || !AvFrame)
632 return false;
633
634 AVFrame *temp = av_frame_alloc();
635 if (!temp)
636 return false;
637
638 AVPixelFormat *pixelformats = nullptr;
639 int ret = av_hwframe_transfer_get_formats(AvFrame->hw_frames_ctx,
640 AV_HWFRAME_TRANSFER_DIRECTION_FROM,
641 &pixelformats, 0);
642 if (ret == 0)
643 {
644 AVPixelFormat best = DecoderBase::GetBestVideoFormat(pixelformats, Frame->m_renderFormats);
645 if (best != AV_PIX_FMT_NONE)
646 {
648 bool valid = Frame->m_type == type;
649 if (!valid || (Frame->m_width != AvFrame->width) || (Frame->m_height != AvFrame->height))
651 AvFrame->width, AvFrame->height);
652
653 if (valid)
654 {
655 // Retrieve the picture directly into the VideoFrame Buffer
656 temp->format = best;
658 for (uint i = 0; i < 3; i++)
659 {
660 temp->data[i] = (i < max) ? (Frame->m_buffer + Frame->m_offsets[i]) : nullptr;
661 temp->linesize[i] = Frame->m_pitches[i];
662 }
663
664 // Dummy release method - we do not want to free the buffer
665 temp->buf[0] = av_buffer_create(reinterpret_cast<uint8_t*>(Frame), 0,
666 [](void* /*unused*/, uint8_t* /*unused*/){}, this, 0);
667 temp->width = AvFrame->width;
668 temp->height = AvFrame->height;
669 }
670 }
671 }
672 av_freep(reinterpret_cast<void*>(&pixelformats));
673
674 // retrieve data from GPU to CPU
675 if (ret >= 0)
676 {
677 ret = av_hwframe_transfer_data(temp, AvFrame, 0);
678 if (ret < 0)
679 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error %1 transferring the data to system memory").arg(ret));
680 }
681
682 Frame->m_colorshifted = true;
683 av_frame_free(&temp);
684 return ret >= 0;
685}
686
688{
689 switch (CodecID)
690 {
691 case AV_CODEC_ID_MPEG1VIDEO: return MPEG1;
692 case AV_CODEC_ID_MPEG2VIDEO:
693 switch (Profile)
694 {
695 case FF_PROFILE_MPEG2_422: return MPEG2422;
696 case FF_PROFILE_MPEG2_HIGH: return MPEG2High;
697 case FF_PROFILE_MPEG2_SS: return MPEG2Spatial;
698 case FF_PROFILE_MPEG2_SNR_SCALABLE: return MPEG2SNR;
699 case FF_PROFILE_MPEG2_SIMPLE: return MPEG2Simple;
700 case FF_PROFILE_MPEG2_MAIN: return MPEG2Main;
701 default: break;
702 }
703 break;
704 case AV_CODEC_ID_MPEG4:
705 switch (Profile)
706 {
707 case FF_PROFILE_MPEG4_SIMPLE: return MPEG4Simple;
708 case FF_PROFILE_MPEG4_SIMPLE_SCALABLE: return MPEG4SimpleScaleable;
709 case FF_PROFILE_MPEG4_CORE: return MPEG4Core;
710 case FF_PROFILE_MPEG4_MAIN: return MPEG4Main;
711 case FF_PROFILE_MPEG4_N_BIT: return MPEG4NBit;
712 case FF_PROFILE_MPEG4_SCALABLE_TEXTURE: return MPEG4ScaleableTexture;
713 case FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION: return MPEG4SimpleFace;
714 case FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE: return MPEG4BasicAnimated;
715 case FF_PROFILE_MPEG4_HYBRID: return MPEG4Hybrid;
716 case FF_PROFILE_MPEG4_ADVANCED_REAL_TIME: return MPEG4AdvancedRT;
717 case FF_PROFILE_MPEG4_CORE_SCALABLE: return MPEG4CoreScaleable;
718 case FF_PROFILE_MPEG4_ADVANCED_CODING: return MPEG4AdvancedCoding;
719 case FF_PROFILE_MPEG4_ADVANCED_CORE: return MPEG4AdvancedCore;
720 case FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE: return MPEG4AdvancedScaleableTexture;
721 case FF_PROFILE_MPEG4_SIMPLE_STUDIO: return MPEG4SimpleStudio;
722 case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: return MPEG4AdvancedSimple;
723 }
724 break;
725 case AV_CODEC_ID_H263: return H263;
726 case AV_CODEC_ID_H264:
727 switch (Profile)
728 {
729 // Mapping of H264MainExtended, H264ConstrainedHigh?
730 case FF_PROFILE_H264_BASELINE: return H264Baseline;
731 case FF_PROFILE_H264_CONSTRAINED_BASELINE: return H264ConstrainedBaseline;
732 case FF_PROFILE_H264_MAIN: return H264Main;
733 case FF_PROFILE_H264_EXTENDED: return H264Extended;
734 case FF_PROFILE_H264_HIGH: return H264High;
735 case FF_PROFILE_H264_HIGH_10: return H264High10;
736 //case FF_PROFILE_H264_HIGH_10_INTRA:
737 //case FF_PROFILE_H264_MULTIVIEW_HIGH:
738 case FF_PROFILE_H264_HIGH_422: return H264High422;
739 //case FF_PROFILE_H264_HIGH_422_INTRA:
740 //case FF_PROFILE_H264_STEREO_HIGH:
741 case FF_PROFILE_H264_HIGH_444: return H264High444;
742 //case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
743 //case FF_PROFILE_H264_HIGH_444_INTRA:
744 //case FF_PROFILE_H264_CAVLC_444:
745 }
746 break;
747 case AV_CODEC_ID_HEVC:
748 switch (Profile)
749 {
750 case FF_PROFILE_HEVC_MAIN: return HEVCMain;
751 case FF_PROFILE_HEVC_MAIN_10: return HEVCMain10;
752 case FF_PROFILE_HEVC_MAIN_STILL_PICTURE: return HEVCMainStill;
753 case FF_PROFILE_HEVC_REXT: return HEVCRext;
754 }
755 break;
756 case AV_CODEC_ID_VC1:
757 switch (Profile)
758 {
759 case FF_PROFILE_VC1_SIMPLE: return VC1Simple;
760 case FF_PROFILE_VC1_MAIN: return VC1Main;
761 case FF_PROFILE_VC1_COMPLEX: return VC1Complex;
762 case FF_PROFILE_VC1_ADVANCED: return VC1Advanced;
763 }
764 break;
765 case AV_CODEC_ID_VP8: return VP8;
766 case AV_CODEC_ID_VP9:
767 switch (Profile)
768 {
769 case FF_PROFILE_VP9_0: return VP9_0;
770 case FF_PROFILE_VP9_1: return VP9_1;
771 case FF_PROFILE_VP9_2: return VP9_2;
772 case FF_PROFILE_VP9_3: return VP9_3;
773 }
774 break;
775 case AV_CODEC_ID_AV1:
776 switch (Profile)
777 {
778 case FF_PROFILE_AV1_MAIN: return AV1Main;
779 case FF_PROFILE_AV1_HIGH: return AV1High;
780 case FF_PROFILE_AV1_PROFESSIONAL: return AV1Professional;
781 }
782 break;
783 case AV_CODEC_ID_MJPEG: return MJPEG;
784 default: break;
785 }
786
787 return NoProfile;
788}
789
791 VideoFrameType Format, uint ColorDepth)
792{
793 QString profile;
794 switch (Profile)
795 {
796 case NoProfile: profile = QObject::tr("Unknown/Unsupported"); break;
797 case MPEG1: profile = "MPEG1"; break;
798 case MPEG2: profile = "MPEG2"; break;
799 case MPEG2Simple: profile = "MPEG2 Simple"; break;
800 case MPEG2Main: profile = "MPEG2 Main"; break;
801 case MPEG2422: profile = "MPEG2 422"; break;
802 case MPEG2High: profile = "MPEG2 High"; break;
803 case MPEG2Spatial: profile = "MPEG2 Spatial"; break;
804 case MPEG2SNR: profile = "MPEG2 SNR"; break;
805 case MPEG4: profile = "MPEG4"; break;
806 case MPEG4Simple: profile = "MPEG4 Simple"; break;
807 case MPEG4SimpleScaleable: profile = "MPEG4 Simple Scaleable"; break;
808 case MPEG4Core: profile = "MPEG4 Core"; break;
809 case MPEG4Main: profile = "MPEG4 Main"; break;
810 case MPEG4NBit: profile = "MPEG4 NBit"; break;
811 case MPEG4ScaleableTexture: profile = "MPEG4 Scaleable Texture"; break;
812 case MPEG4SimpleFace: profile = "MPEG4 Simple Face"; break;
813 case MPEG4BasicAnimated: profile = "MPEG4 Basic Animated"; break;
814 case MPEG4Hybrid: profile = "MPEG4 Hybrid"; break;
815 case MPEG4AdvancedRT: profile = "MPEG4 Advanced RT"; break;
816 case MPEG4CoreScaleable: profile = "MPEG4 Core Scaleable"; break;
817 case MPEG4AdvancedCoding: profile = "MPEG4 Advanced Coding"; break;
818 case MPEG4AdvancedCore: profile = "MPEG4 Advanced Core"; break;
819 case MPEG4AdvancedScaleableTexture: profile = "MPEG4 Advanced Scaleable Texture"; break;
820 case MPEG4SimpleStudio: profile = "MPEG4 Simple Studio"; break;
821 case MPEG4AdvancedSimple: profile = "MPEG4 Advanced Simple"; break;
822 case H263: profile = "H263"; break;
823 case H264: profile = "H264"; break;
824 case H264Baseline: profile = "H264 Baseline"; break;
825 case H264ConstrainedBaseline: profile = "H264 Constrained"; break;
826 case H264Main: profile = "H264 Main"; break;
827 case H264MainExtended: profile = "H264 Main Extended"; break;
828 case H264High: profile = "H264 High"; break;
829 case H264High10: profile = "H264 High10"; break;
830 case H264Extended: profile = "H264 Extended"; break;
831 case H264High422: profile = "H264 High 422"; break;
832 case H264High444: profile = "H264 High 444"; break;
833 case H264ConstrainedHigh: profile = "H264 Constrained High"; break;
834 case HEVC: profile = "HEVC"; break;
835 case HEVCMain: profile = "HEVC Main"; break;
836 case HEVCMain10: profile = "HEVC Main10"; break;
837 case HEVCMainStill: profile = "HEVC Main Still"; break;
838 case HEVCRext: profile = "HEVC Rext"; break;
839 case HEVCMain10HDR: profile = "HEVC Main10HDR"; break;
840 case HEVCMain10HDRPlus: profile = "HEVC Main10HDRPlus"; break;
841 case VC1: profile = "VC1"; break;
842 case VC1Simple: profile = "VC1 Simple"; break;
843 case VC1Main: profile = "VC1 Main"; break;
844 case VC1Complex: profile = "VC1 Complex"; break;
845 case VC1Advanced: profile = "VC1 Advanced"; break;
846 case VP8: profile = "VP8"; break;
847 case VP9: profile = "VP9"; break;
848 case VP9_0: profile = "VP9 Level 0"; break;
849 case VP9_1: profile = "VP9 Level 1"; break;
850 case VP9_2: profile = "VP9 Level 2"; break;
851 case VP9_2HDR: profile = "VP9 Level 2 HDR"; break;
852 case VP9_2HDRPlus: profile = "VP9 Level 2 HDRPlus"; break;
853 case VP9_3: profile = "VP9 Level 3"; break;
854 case VP9_3HDR: profile = "VP9 Level 3 HDR"; break;
855 case VP9_3HDRPlus: profile = "VP9 Level 3 HDRPlus"; break;
856 case AV1: profile = "AV1"; break;
857 case AV1Main: profile = "AV1 Main"; break;
858 case AV1High: profile = "AV1 High"; break;
859 case AV1Professional: profile = "AV1 Professional"; break;
860 case MJPEG: profile = "MJPEG";
861 }
862
863 if (Size.isEmpty())
864 return profile;
865
866 return QObject::tr("%1%2%3 (Max size: %4x%5)")
867 .arg(profile,
868 Format != FMT_NONE ? QString(" %1").arg(MythVideoFrame::FormatDescription(Format)) : "",
869 ColorDepth > 8 ? QString(" %1Bit").arg(ColorDepth) : "")
870 .arg(Size.width()).arg(Size.height());
871}
AVFrame AVFrame
A decoder for media files.
static AVPixelFormat GetBestVideoFormat(AVPixelFormat *Formats, const VideoFrameTypes *RenderFormats)
Find a suitable frame format that is mutually acceptable to the decoder and render device.
virtual MythCodecID GetVideoCodecID(void) const =0
A device containing images (ie. USB stick, CD, storage group etc)
static VideoFrameType PixelFormatToFrameType(AVPixelFormat Fmt)
Definition: mythavutil.cpp:72
static MythCodecID FindDecoder(const QString &Decoder, AVStream *Stream, AVCodecContext **Context, const AVCodec **Codec)
static void DeviceContextFinished(AVHWDeviceContext *Context)
static void GetDecoders(RenderOptions &Opts, bool Reinit=false)
static int InitialiseDecoder(AVCodecContext *Context, CreateHWDecoder Callback, const QString &Debug)
Initialise a hardware decoder that is expected to use AVHWFramesContext.
static bool IsUnsupportedProfile(AVCodecContext *Context)
Most hardware decoders do not support these codecs/profiles.
static QStringList GetDecoderDescription(void)
static bool FrameTypeIsSupported(AVCodecContext *Context, VideoFrameType Format)
static void ReleaseBuffer(void *Opaque, uint8_t *Data)
static int GetBuffer(struct AVCodecContext *Context, AVFrame *Frame, int Flags)
A generic hardware buffer initialisation method when using AVHWFramesContext.
virtual bool RetrieveHWFrame(MythVideoFrame *Frame, AVFrame *AvFrame)
static AVBufferRef * CreateDevice(AVHWDeviceType Type, MythInteropGPU *Interop, const QString &Device=QString())
static QAtomicInt s_hwFramesContextCount
static void DestroyInterop(MythInteropGPU *Interop)
static int InitialiseDecoder2(AVCodecContext *Context, CreateHWDecoder Callback, const QString &Debug)
Initialise a hardware decoder that is NOT expected to use AVHWFramesContext.
virtual void InitVideoCodec(AVCodecContext *Context, bool SelectedStream, bool &DirectRendering)
static void CreateDecoderCallback(void *Wait, void *Context, void *Callback)
static void FramesContextFinished(AVHWFramesContext *Context)
static void NewHardwareFramesContext(void)
Track the number of concurrent frames contexts.
static MythCodecContext * CreateContext(DecoderBase *Parent, MythCodecID Codec)
static QString GetProfileDescription(CodecProfile Profile, QSize Size, VideoFrameType Format=FMT_NONE, uint ColorDepth=0)
MythCodecContext(DecoderBase *Parent, MythCodecID CodecID)
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)
DecoderBase * m_parent
virtual int FilteredReceiveFrame(AVCodecContext *Context, AVFrame *Frame)
Retrieve and process/filter AVFrame.
static CodecProfile FFmpegToMythProfile(AVCodecID CodecID, int Profile)
A generic context handler for codecs that return AV_PIX_FMT_DRM_PRIME frames.
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
static bool HavePrimeDecoders(bool Reinit=false, AVCodecID Codec=AV_CODEC_ID_NONE)
void SetDefaultFree(FreeAVHWDeviceContext FreeContext)
FreeAVHWDeviceContext GetDefaultFree()
void SetDefaultUserOpaque(void *UserOpaque)
static MythInteropGPU * CreateDummy()
static InteropMap GetTypes(MythRender *Render)
MythPlayerUI * GetPlayer()
static bool HaveMMAL(bool Reinit=false)
static void GetDecoderList(QStringList &Decoders)
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
static MythCodecID GetBestSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
static bool HaveMediaCodec(bool Reinit=false)
static void GetDecoderList(QStringList &Decoders)
static void GetDecoderList(QStringList &Decoders)
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 bool HaveNVDEC(bool Reinit=false)
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 MythRenderOpenGL * GetOpenGLRender(void)
A handler for V4L2 Memory2Memory codecs.
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
static bool HaveV4L2Codecs(bool Reinit=false)
static void GetDecoderList(QStringList &Decoders)
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, uint StreamType)
Confirm whether VAAPI support is available given Decoder and Context.
static void GetDecoderList(QStringList &Decoders)
static MythCodecID GetSupportedCodec(AVCodecContext **CodecContext, const AVCodec **Codec, const QString &Decoder, uint StreamType)
static bool HaveVDPAU(bool Reinit=false)
static void GetDecoderList(QStringList &Decoders)
static bool HaveVTB(bool Reinit=false)
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &Decoder, uint StreamType)
static void GetDecoderList(QStringList &Decoders)
bool m_colorshifted
Definition: mythframe.h:152
static uint GetNumPlanes(VideoFrameType Type)
Definition: mythframe.h:213
static QString FormatDescription(VideoFrameType Type)
Definition: mythframe.cpp:368
uint8_t * m_buffer
Definition: mythframe.h:119
std::array< uint8_t *, 4 > m_priv
Definition: mythframe.h:132
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
static bool ReinitBuffer(MythVideoFrame *Frame, VideoFrameType Type, MythCodecID CodecID, int Width, int Height)
static MythCodecID GetSupportedCodec(AVCodecContext **Context, const AVCodec **Codec, const QString &decoder, uint stream_type)
unsigned int uint
Definition: compat.h:68
static const struct wl_interface * types[]
char * av_make_error_stdstring(std::string &errbuf, int errnum)
A C++ equivalent to av_make_error_string.
Definition: mythaverror.cpp:42
#define LOC
int(*)(AVCodecContext *Context) CreateHWDecoder
uint mpeg_version(AVCodecID codec_id)
static bool codec_is_v4l2_dec(MythCodecID id)
Definition: mythcodecid.h:360
static bool codec_is_vdpau_dechw(MythCodecID id)
Definition: mythcodecid.h:315
static bool codec_is_vdpau_hw(MythCodecID id)
Definition: mythcodecid.h:307
static bool codec_is_mediacodec_dec(MythCodecID id)
Definition: mythcodecid.h:340
MythCodecID
Definition: mythcodecid.h:14
@ kCodec_NONE
Definition: mythcodecid.h:17
static bool codec_is_mediacodec(MythCodecID id)
Definition: mythcodecid.h:337
static bool codec_is_vtb_dec(MythCodecID id)
Definition: mythcodecid.h:354
static bool codec_is_dxva2(MythCodecID id)
Definition: mythcodecid.h:328
static bool codec_is_mmal_dec(MythCodecID id)
Definition: mythcodecid.h:365
static bool codec_is_drmprime(MythCodecID id)
Definition: mythcodecid.h:301
static bool codec_is_mmal(MythCodecID id)
Definition: mythcodecid.h:363
static bool codec_is_nvdec(MythCodecID id)
Definition: mythcodecid.h:344
static bool codec_is_vtb(MythCodecID id)
Definition: mythcodecid.h:351
static bool codec_is_v4l2(MythCodecID id)
Definition: mythcodecid.h:358
static bool codec_is_nvdec_dec(MythCodecID id)
Definition: mythcodecid.h:347
static bool codec_is_vaapi(MythCodecID id)
Definition: mythcodecid.h:321
static bool codec_is_vaapi_dec(MythCodecID id)
Definition: mythcodecid.h:324
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
VideoFrameType
Definition: mythframe.h:20
@ FMT_NONE
Definition: mythframe.h:21
@ FMT_MMAL
Definition: mythframe.h:59
void(*)(struct AVHWDeviceContext *) FreeAVHWDeviceContext
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
bool HasMythMainWindow(void)
def error(message)
Definition: smolt.py:409
QStringList * decoders
QMap< QString, QStringList > * equiv_decoders