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
26#include "libmythbase/mythconfig.h"
30#include "mythinteropgpu.h"
31#include "avformatdecoder.h"
32#include "mythplayerui.h"
33
34#if CONFIG_VAAPI
35#include "mythvaapicontext.h"
36#endif
37#if CONFIG_VDPAU
38#include "mythvdpauhelper.h"
39#include "mythvdpaucontext.h"
40#endif
41#if CONFIG_NVDEC
42#include "mythnvdeccontext.h"
43#endif
44#if CONFIG_VIDEOTOOLBOX
45#include "mythvtbcontext.h"
46#endif
47#if CONFIG_MEDIACODEC
49#endif
50#if CONFIG_V4L2
51#include "mythv4l2m2mcontext.h"
52#endif
53#if CONFIG_MMAL
54#include "mythmmalcontext.h"
55#endif
56#if CONFIG_EGL
57#include "mythdrmprimecontext.h"
58#endif
59#if CONFIG_DXVA2
60#include "videoout_d3d.h"
61#endif
62#include "mythcodeccontext.h"
63
64extern "C" {
65#include "libavcodec/defs.h"
66#include "libavutil/pixdesc.h"
67}
68
69#define LOC QString("MythCodecContext: ")
70
72
74 : m_parent(Parent),
75 m_codecID(CodecID)
76{
77}
78
80 [[maybe_unused]] MythCodecID Codec)
81{
82 MythCodecContext *mctx = nullptr;
83#if CONFIG_VAAPI
84 if (codec_is_vaapi(Codec) || codec_is_vaapi_dec(Codec))
85 mctx = new MythVAAPIContext(Parent, Codec);
86#endif
87#if CONFIG_VDPAU
88 if (codec_is_vdpau_hw(Codec) || codec_is_vdpau_dechw(Codec))
89 mctx = new MythVDPAUContext(Parent, Codec);
90#endif
91#if CONFIG_NVDEC
92 if (codec_is_nvdec_dec(Codec) || codec_is_nvdec(Codec))
93 mctx = new MythNVDECContext(Parent, Codec);
94#endif
95#if CONFIG_VIDEOTOOLBOX
96 if (codec_is_vtb_dec(Codec) || codec_is_vtb(Codec))
97 mctx = new MythVTBContext(Parent, Codec);
98#endif
99#if CONFIG_MEDIACODEC
100 if (codec_is_mediacodec(Codec) || codec_is_mediacodec_dec(Codec))
101 mctx = new MythMediaCodecContext(Parent, Codec);
102#endif
103#if CONFIG_V4L2
104 if (codec_is_v4l2_dec(Codec) || codec_is_v4l2(Codec))
105 mctx = new MythV4L2M2MContext(Parent, Codec);
106#endif
107#if CONFIG_MMAL
108 if (codec_is_mmal_dec(Codec) || codec_is_mmal(Codec))
109 mctx = new MythMMALContext(Parent, Codec);
110#endif
111#if CONFIG_EGL
112 if (codec_is_drmprime(Codec))
113 mctx = new MythDRMPRIMEContext(Parent, Codec);
114#endif
115
116 if (!mctx)
117 mctx = new MythCodecContext(Parent, Codec);
118 return mctx;
119}
120
122{
123 QStringList decoders;
124
125#if CONFIG_VDPAU
127#endif
128#if CONFIG_VAAPI
130#endif
131#if CONFIG_MEDIACODEC
133#endif
134#if CONFIG_NVDEC
136#endif
137#if CONFIG_MMAL
139#endif
140#if CONFIG_V4L2
142#endif
143#if CONFIG_VIDEOTOOLBOX
145#endif
146 return decoders;
147}
148
149void MythCodecContext::GetDecoders(RenderOptions &Opts, bool Reinit /*=false*/)
150{
151 if (!gCoreContext->IsUIThread())
152 {
153 LOG(VB_GENERAL, LOG_ERR, LOC + "Must be called from UI thread");
154 return;
155 }
156
157 if (!HasMythMainWindow())
158 {
159 LOG(VB_GENERAL, LOG_INFO, LOC + "No window: Ignoring hardware decoders");
160 return;
161 }
162
163 Opts.decoders->append("ffmpeg");
164 (*Opts.equiv_decoders)["ffmpeg"].append("dummy");
165
166#if CONFIG_VDPAU
167 // Only enable VDPAU support if it is actually present
168 if (MythVDPAUHelper::HaveVDPAU(Reinit))
169 {
170 Opts.decoders->append("vdpau");
171 (*Opts.equiv_decoders)["vdpau"].append("dummy");
172 Opts.decoders->append("vdpau-dec");
173 (*Opts.equiv_decoders)["vdpau-dec"].append("dummy");
174 }
175#endif
176#if CONFIG_DXVA2
177 Opts.decoders->append("dxva2");
178 (*Opts.equiv_decoders)["dxva2"].append("dummy");
179#endif
180
181#if CONFIG_VAAPI
182 // Only enable VAAPI if it is actually present and isn't actually VDPAU
183 if (!MythVAAPIContext::HaveVAAPI(Reinit).isEmpty())
184 {
185 Opts.decoders->append("vaapi");
186 (*Opts.equiv_decoders)["vaapi"].append("dummy");
187 Opts.decoders->append("vaapi-dec");
188 (*Opts.equiv_decoders)["vaapi-dec"].append("dummy");
189 }
190#endif
191#if CONFIG_NVDEC
192 // Only enable NVDec support if it is actually present
193 if (MythNVDECContext::HaveNVDEC(Reinit))
194 {
195 Opts.decoders->append("nvdec");
196 (*Opts.equiv_decoders)["nvdec"].append("dummy");
197 Opts.decoders->append("nvdec-dec");
198 (*Opts.equiv_decoders)["nvdec-dec"].append("dummy");
199 }
200#endif
201#if CONFIG_MEDIACODEC
203 {
204 Opts.decoders->append("mediacodec");
205 (*Opts.equiv_decoders)["mediacodec"].append("dummy");
206 Opts.decoders->append("mediacodec-dec");
207 (*Opts.equiv_decoders)["mediacodec-dec"].append("dummy");
208 }
209#endif
210#if CONFIG_VIDEOTOOLBOX
211 if (MythVTBContext::HaveVTB(Reinit))
212 {
213 Opts.decoders->append("vtb");
214 Opts.decoders->append("vtb-dec");
215 (*Opts.equiv_decoders)["vtb"].append("dummy");
216 (*Opts.equiv_decoders)["vtb-dec"].append("dummy");
217 }
218#endif
219#if CONFIG_V4L2
221 {
222#if CONFIG_V4L2PRIME
223 Opts.decoders->append("v4l2");
224 (*Opts.equiv_decoders)["v4l2"].append("dummy");
225#endif
226 Opts.decoders->append("v4l2-dec");
227 (*Opts.equiv_decoders)["v4l2-dec"].append("dummy");
228 }
229#endif
230#if CONFIG_EGL
232 {
233 Opts.decoders->append("drmprime");
234 (*Opts.equiv_decoders)["drmprime"].append("dummy");
235 }
236#endif
237#if CONFIG_MMAL
238 if (MythMMALContext::HaveMMAL(Reinit))
239 {
240 Opts.decoders->append("mmal-dec");
241 (*Opts.equiv_decoders)["mmal-dec"].append("dummy");
243 if (auto mmal = types.find(FMT_MMAL); (mmal != types.end()) && !mmal->second.empty())
244 {
245 Opts.decoders->append("mmal");
246 (*Opts.equiv_decoders)["mmal"].append("dummy");
247 }
248 }
249#endif
250}
251
253 [[maybe_unused]] AVStream *Stream,
254 AVCodecContext **Context,
255 const AVCodec **Codec)
256{
257 MythCodecID result = kCodec_NONE;
258 uint streamtype = mpeg_version((*Context)->codec_id);
259
260#if CONFIG_VDPAU
261 result = MythVDPAUContext::GetSupportedCodec(Context, Codec, Decoder, streamtype);
262 if (codec_is_vdpau_hw(result) || codec_is_vdpau_dechw(result))
263 return result;
264#endif
265#if CONFIG_VAAPI
266 result = MythVAAPIContext::GetSupportedCodec(Context, Codec, Decoder, streamtype);
267 if (codec_is_vaapi(result) || codec_is_vaapi_dec(result))
268 return result;
269#endif
270#if CONFIG_VIDEOTOOLBOX
271 result = MythVTBContext::GetSupportedCodec(Context, Codec, Decoder, streamtype);
272 if (codec_is_vtb(result) || codec_is_vtb_dec(result))
273 return result;
274#endif
275#if CONFIG_DXVA2
276 result = VideoOutputD3D::GetSupportedCodec(Context, Codec, Decoder, streamtype);
277 if (codec_is_dxva2(result))
278 return result;
279#endif
280#if CONFIG_MEDIACODEC
281 result = MythMediaCodecContext::GetBestSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
282 if (codec_is_mediacodec(result) || codec_is_mediacodec_dec(result))
283 return result;
284#endif
285#if CONFIG_NVDEC
286 result = MythNVDECContext::GetSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
287 if (codec_is_nvdec(result) || codec_is_nvdec_dec(result))
288 return result;
289#endif
290#if CONFIG_V4L2
291 result = MythV4L2M2MContext::GetSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
292 if (codec_is_v4l2_dec(result) || codec_is_v4l2(result))
293 return result;
294#endif
295#if CONFIG_MMAL
296 result = MythMMALContext::GetSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
297 if (codec_is_mmal_dec(result) || codec_is_mmal(result))
298 return result;
299#endif
300#if CONFIG_EGL
301 result = MythDRMPRIMEContext::GetSupportedCodec(Context, Codec, Decoder, Stream, streamtype);
302 if (codec_is_drmprime(result))
303 return result;
304#endif
305
306 return kCodec_NONE;
307}
308
309void MythCodecContext::InitVideoCodec(AVCodecContext *Context,
310 bool SelectedStream, bool &DirectRendering)
311{
312 const AVCodec *codec1 = Context->codec;
313 if (codec1 && codec1->capabilities & AV_CODEC_CAP_DR1)
314 {
315 // Context->flags |= CODEC_FLAG_EMU_EDGE;
316 }
317 else
318 {
319 if (SelectedStream)
320 DirectRendering = false;
321 LOG(VB_PLAYBACK, LOG_INFO, LOC +
322 QString("Using software scaling to convert pixel format %1 for "
323 "codec %2").arg(av_get_pix_fmt_name(Context->pix_fmt),
324 avcodec_get_name(Context->codec_id)));
325 }
326}
327
329int MythCodecContext::GetBuffer(struct AVCodecContext *Context, AVFrame *Frame, int Flags)
330{
331 auto *avfd = static_cast<AvFormatDecoder*>(Context->opaque);
332 MythVideoFrame *videoframe = avfd->GetPlayer()->GetNextVideoFrame();
333
334 // set fields required for directrendering
335 for (int i = 0; i < 4; i++)
336 {
337 Frame->data[i] = nullptr;
338 Frame->linesize[i] = 0;
339 }
340 Frame->opaque = videoframe;
341 videoframe->m_pixFmt = Context->pix_fmt;
342
343 int ret = avcodec_default_get_buffer2(Context, Frame, Flags);
344 if (ret < 0)
345 return ret;
346
347 // set the underlying pixel format. Set here rather than guessing later.
348 if (Frame->hw_frames_ctx)
349 {
350 auto *context = reinterpret_cast<AVHWFramesContext*>(Frame->hw_frames_ctx->data);
351 if (context)
352 videoframe->m_swPixFmt = context->sw_format;
353 }
354
355 // VAAPI 'fixes' 10/12/16bit colour values. Irrelevant for VDPAU.
356 videoframe->m_colorshifted = true;
357
358 // avcodec_default_get_buffer2 will retrieve an AVBufferRef from the pool of
359 // hardware surfaces stored within AVHWFramesContext. The pointer to the surface is stored
360 // in Frame->data[3]. Store this in VideoFrame::buf for the interop class to use.
361 videoframe->m_buffer = Frame->data[3];
362 // Frame->buf(0) also contains a reference to the buffer. Take an additional reference to this
363 // buffer to retain the surface until it has been displayed (otherwise it is
364 // reused once the decoder is finished with it).
365 videoframe->m_priv[0] = reinterpret_cast<unsigned char*>(av_buffer_ref(Frame->buf[0]));
366 // frame->hw_frames_ctx contains a reference to the AVHWFramesContext. Take an additional
367 // reference to ensure AVHWFramesContext is not released until we are finished with it.
368 // This also contains the underlying MythInteropGPU class reference.
369 videoframe->m_priv[1] = reinterpret_cast<unsigned char*>(av_buffer_ref(Frame->hw_frames_ctx));
370
371 // Set release method
372 Frame->buf[1] = av_buffer_create(reinterpret_cast<uint8_t*>(videoframe), 0,
374 return ret;
375}
376
377
379bool MythCodecContext::GetBuffer2(struct AVCodecContext *Context, MythVideoFrame* Frame,
380 AVFrame *AvFrame, int /*Flags*/)
381{
382 if (!AvFrame || !Context || !Frame)
383 return false;
384
385 auto *avfd = static_cast<AvFormatDecoder*>(Context->opaque);
386
387 Frame->m_pixFmt = Context->pix_fmt;
388 Frame->m_directRendering = true;
389 Frame->m_colorshifted = true;
390
391 AvFrame->opaque = Frame;
392
393 // retrieve the software format
394 if (AvFrame->hw_frames_ctx)
395 {
396 auto *context = reinterpret_cast<AVHWFramesContext*>(AvFrame->hw_frames_ctx->data);
397 if (context)
398 Frame->m_swPixFmt = context->sw_format;
399 }
400
401 // the hardware surface is stored in Frame->data[3]
402 Frame->m_buffer = AvFrame->data[3];
403
404 // Frame->buf[0] contains the release method. Take another reference to
405 // ensure the frame is not released before it is displayed.
406 Frame->m_priv[0] = reinterpret_cast<unsigned char*>(av_buffer_ref(AvFrame->buf[0]));
407
408 // Retrieve and set the interop class
409 auto *devicectx = reinterpret_cast<AVHWDeviceContext*>(Context->hw_device_ctx->data);
410 Frame->m_priv[1] = reinterpret_cast<unsigned char*>(devicectx->user_opaque);
411
412 // Set release method
413 AvFrame->buf[1] = av_buffer_create(reinterpret_cast<uint8_t*>(Frame), 0,
415 return true;
416}
417
418void MythCodecContext::ReleaseBuffer(void *Opaque, uint8_t *Data)
419{
420 auto *decoder = static_cast<AvFormatDecoder*>(Opaque);
421 auto *frame = reinterpret_cast<MythVideoFrame*>(Data);
422 if (decoder && decoder->GetPlayer())
423 decoder->GetPlayer()->DeLimboFrame(frame);
424}
425
434{
435 int count = ++s_hwFramesContextCount;
436 if (count != 1)
437 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Error: %1 concurrent hardware frames contexts").arg(count));
438}
439
440void MythCodecContext::FramesContextFinished(AVHWFramesContext *Context)
441{
443 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1 frames context finished")
444 .arg(av_hwdevice_get_type_name(Context->device_ctx->type)));
445 auto * interop = reinterpret_cast<MythInteropGPU*>(Context->user_opaque);
446 if (interop)
447 DestroyInterop(interop);
448}
449
450void MythCodecContext::DeviceContextFinished(AVHWDeviceContext* Context)
451{
452 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1 device context finished")
453 .arg(av_hwdevice_get_type_name(Context->type)));
454 auto * interop = reinterpret_cast<MythInteropGPU*>(Context->user_opaque);
455 if (interop)
456 {
457 FreeAVHWDeviceContext free = interop->GetDefaultFree();
458 void *io_user_opaque = interop->GetDefaultUserOpaque();
459 DestroyInterop(interop);
460 if (free)
461 {
462 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Calling default device context free");
463 Context->user_opaque = io_user_opaque;
464 free(Context);
465 }
466 }
467}
468
470{
472 {
473 Interop->DecrRef();
474 return;
475 }
476
477 auto destroy = [](void *Wait, void *Interop2, void* /*unused*/)
478 {
479 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Destroy interop callback");
480 auto *wait = reinterpret_cast<QWaitCondition*>(Wait);
481 auto *interop = reinterpret_cast<MythInteropGPU*>(Interop2);
482 if (interop)
483 interop->DecrRef();
484 if (wait)
485 wait->wakeAll();
486 };
487
488 if (!Interop->GetPlayer())
489 {
490 LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot destroy interop - no player");
491 return;
492 }
493 Interop->GetPlayer()->HandleDecoderCallback("Destroy OpenGL interop",
494 destroy, Interop, nullptr);
495}
496
497void MythCodecContext::CreateDecoderCallback(void *Wait, void *Context, void *Callback)
498{
499 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Create decoder callback");
500 auto *wait = reinterpret_cast<QWaitCondition*>(Wait);
501 auto *context = reinterpret_cast<AVCodecContext*>(Context);
502 auto callback = reinterpret_cast<CreateHWDecoder>(Callback);
503 if (context && callback)
504 (void)callback(context);
505 if (wait)
506 wait->wakeAll();
507}
508
510{
511 MythPlayerUI* result = nullptr;
512 auto* decoder = reinterpret_cast<AvFormatDecoder*>(Context->opaque);
513 if (decoder)
514 result = dynamic_cast<MythPlayerUI*>(decoder->GetPlayer());
515 return result;
516}
517
519{
520 if (auto * player = GetPlayerUI(Context); player != nullptr)
521 {
522 const auto & supported = player->GetInteropTypes();
523 return supported.find(Format) != supported.cend();
524 }
525 return false;
526}
527
529int MythCodecContext::InitialiseDecoder(AVCodecContext *Context, CreateHWDecoder Callback,
530 const QString &Debug)
531{
532 if (!Context || !Callback)
533 return -1;
535 return Callback(Context);
536
537 // Callback to MythPlayer (which will fail without a MythPlayer instance)
538 MythPlayerUI* player = GetPlayerUI(Context);
539 if (player)
541 Context, reinterpret_cast<void*>(Callback));
542 return Context->hw_frames_ctx ? 0 : -1;
543}
544
546int MythCodecContext::InitialiseDecoder2(AVCodecContext *Context, CreateHWDecoder Callback,
547 const QString &Debug)
548{
549 if (!Context || !Callback)
550 return -1;
552 return Callback(Context);
553
554 // Callback to MythPlayer (which will fail without a MythPlayer instance)
555 MythPlayerUI* player = GetPlayerUI(Context);
556 if (player)
558 Context, reinterpret_cast<void*>(Callback));
559 return Context->hw_device_ctx ? 0 : -1;
560}
561
562AVBufferRef* MythCodecContext::CreateDevice(AVHWDeviceType Type, MythInteropGPU* Interop, const QString& Device)
563{
564 AVBufferRef* result = nullptr;
565 int res = av_hwdevice_ctx_create(&result, Type, Device.isEmpty() ? nullptr :
566 Device.toLocal8Bit().constData(), nullptr, 0);
567 if (res == 0)
568 {
569 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created hardware device '%1'%2")
570 .arg(av_hwdevice_get_type_name(Type),
571 Device == nullptr ? "" : QString(" (%1)").arg(Device)));
572 auto *context = reinterpret_cast<AVHWDeviceContext*>(result->data);
573
574 if ((context->free || context->user_opaque) && !Interop)
575 {
576 LOG(VB_PLAYBACK, LOG_INFO, "Creating dummy interop");
577 Interop = MythInteropGPU::CreateDummy();
578 }
579
580 if (Interop)
581 {
582 Interop->SetDefaultFree(context->free);
583 Interop->SetDefaultUserOpaque(context->user_opaque);
584 Interop->IncrRef();
585 }
586
588 context->user_opaque = Interop;
589 return result;
590 }
591
592 std::string error;
593 LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Failed to create hardware device '%1'%2 Error '%3'")
594 .arg(av_hwdevice_get_type_name(Type),
595 Device == nullptr ? "" : QString(" (%1)").arg(Device),
597 return nullptr;
598}
599
601bool MythCodecContext::IsUnsupportedProfile(AVCodecContext *Context)
602{
603 switch (Context->codec_id)
604 {
605 case AV_CODEC_ID_H264:
606 switch (Context->profile)
607 {
608 case AV_PROFILE_H264_HIGH_10:
609 case AV_PROFILE_H264_HIGH_10_INTRA:
610 case AV_PROFILE_H264_HIGH_422:
611 case AV_PROFILE_H264_HIGH_422_INTRA:
612 case AV_PROFILE_H264_HIGH_444_PREDICTIVE:
613 case AV_PROFILE_H264_HIGH_444_INTRA:
614 case AV_PROFILE_H264_CAVLC_444: return true;
615 default: break;
616 }
617 break;
618 default: break;
619 }
620 return false;
621}
622
627{
628 return avcodec_receive_frame(Context, Frame);
629}
630
632{
633 if (!Frame || !AvFrame)
634 return false;
635
636 AVFrame *temp = av_frame_alloc();
637 if (!temp)
638 return false;
639
640 AVPixelFormat *pixelformats = nullptr;
641 int ret = av_hwframe_transfer_get_formats(AvFrame->hw_frames_ctx,
642 AV_HWFRAME_TRANSFER_DIRECTION_FROM,
643 &pixelformats, 0);
644 if (ret == 0)
645 {
646 AVPixelFormat best = DecoderBase::GetBestVideoFormat(pixelformats, Frame->m_renderFormats);
647 if (best != AV_PIX_FMT_NONE)
648 {
650 bool valid = Frame->m_type == type;
651 if (!valid || (Frame->m_width != AvFrame->width) || (Frame->m_height != AvFrame->height))
653 AvFrame->width, AvFrame->height);
654
655 if (valid)
656 {
657 // Retrieve the picture directly into the VideoFrame Buffer
658 temp->format = best;
660 for (uint i = 0; i < 3; i++)
661 {
662 temp->data[i] = (i < max) ? (Frame->m_buffer + Frame->m_offsets[i]) : nullptr;
663 temp->linesize[i] = Frame->m_pitches[i];
664 }
665
666 // Dummy release method - we do not want to free the buffer
667 temp->buf[0] = av_buffer_create(reinterpret_cast<uint8_t*>(Frame), 0,
668 [](void* /*unused*/, uint8_t* /*unused*/){}, this, 0);
669 temp->width = AvFrame->width;
670 temp->height = AvFrame->height;
671 }
672 }
673 }
674 av_freep(reinterpret_cast<void*>(&pixelformats));
675
676 // retrieve data from GPU to CPU
677 if (ret >= 0)
678 {
679 ret = av_hwframe_transfer_data(temp, AvFrame, 0);
680 if (ret < 0)
681 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error %1 transferring the data to system memory").arg(ret));
682 }
683
684 Frame->m_colorshifted = true;
685 av_frame_free(&temp);
686 return ret >= 0;
687}
688
690{
691 switch (CodecID)
692 {
693 case AV_CODEC_ID_MPEG1VIDEO: return MPEG1;
694 case AV_CODEC_ID_MPEG2VIDEO:
695 switch (Profile)
696 {
697 case AV_PROFILE_MPEG2_422: return MPEG2422;
698 case AV_PROFILE_MPEG2_HIGH: return MPEG2High;
699 case AV_PROFILE_MPEG2_SS: return MPEG2Spatial;
700 case AV_PROFILE_MPEG2_SNR_SCALABLE: return MPEG2SNR;
701 case AV_PROFILE_MPEG2_SIMPLE: return MPEG2Simple;
702 case AV_PROFILE_MPEG2_MAIN: return MPEG2Main;
703 default: break;
704 }
705 break;
706 case AV_CODEC_ID_MPEG4:
707 switch (Profile)
708 {
709 case AV_PROFILE_MPEG4_SIMPLE: return MPEG4Simple;
710 case AV_PROFILE_MPEG4_SIMPLE_SCALABLE: return MPEG4SimpleScaleable;
711 case AV_PROFILE_MPEG4_CORE: return MPEG4Core;
712 case AV_PROFILE_MPEG4_MAIN: return MPEG4Main;
713 case AV_PROFILE_MPEG4_N_BIT: return MPEG4NBit;
714 case AV_PROFILE_MPEG4_SCALABLE_TEXTURE: return MPEG4ScaleableTexture;
715 case AV_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION: return MPEG4SimpleFace;
716 case AV_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE: return MPEG4BasicAnimated;
717 case AV_PROFILE_MPEG4_HYBRID: return MPEG4Hybrid;
718 case AV_PROFILE_MPEG4_ADVANCED_REAL_TIME: return MPEG4AdvancedRT;
719 case AV_PROFILE_MPEG4_CORE_SCALABLE: return MPEG4CoreScaleable;
720 case AV_PROFILE_MPEG4_ADVANCED_CODING: return MPEG4AdvancedCoding;
721 case AV_PROFILE_MPEG4_ADVANCED_CORE: return MPEG4AdvancedCore;
722 case AV_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE: return MPEG4AdvancedScaleableTexture;
723 case AV_PROFILE_MPEG4_SIMPLE_STUDIO: return MPEG4SimpleStudio;
724 case AV_PROFILE_MPEG4_ADVANCED_SIMPLE: return MPEG4AdvancedSimple;
725 }
726 break;
727 case AV_CODEC_ID_H263: return H263;
728 case AV_CODEC_ID_H264:
729 switch (Profile)
730 {
731 // Mapping of H264MainExtended, H264ConstrainedHigh?
732 case AV_PROFILE_H264_BASELINE: return H264Baseline;
733 case AV_PROFILE_H264_CONSTRAINED_BASELINE: return H264ConstrainedBaseline;
734 case AV_PROFILE_H264_MAIN: return H264Main;
735 case AV_PROFILE_H264_EXTENDED: return H264Extended;
736 case AV_PROFILE_H264_HIGH: return H264High;
737 case AV_PROFILE_H264_HIGH_10: return H264High10;
738 //case AV_PROFILE_H264_HIGH_10_INTRA:
739 //case AV_PROFILE_H264_MULTIVIEW_HIGH:
740 case AV_PROFILE_H264_HIGH_422: return H264High422;
741 //case AV_PROFILE_H264_HIGH_422_INTRA:
742 //case AV_PROFILE_H264_STEREO_HIGH:
743 case AV_PROFILE_H264_HIGH_444: return H264High444;
744 //case AV_PROFILE_H264_HIGH_444_PREDICTIVE:
745 //case AV_PROFILE_H264_HIGH_444_INTRA:
746 //case AV_PROFILE_H264_CAVLC_444:
747 }
748 break;
749 case AV_CODEC_ID_HEVC:
750 switch (Profile)
751 {
752 case AV_PROFILE_HEVC_MAIN: return HEVCMain;
753 case AV_PROFILE_HEVC_MAIN_10: return HEVCMain10;
754 case AV_PROFILE_HEVC_MAIN_STILL_PICTURE: return HEVCMainStill;
755 case AV_PROFILE_HEVC_REXT: return HEVCRext;
756 }
757 break;
758 case AV_CODEC_ID_VC1:
759 switch (Profile)
760 {
761 case AV_PROFILE_VC1_SIMPLE: return VC1Simple;
762 case AV_PROFILE_VC1_MAIN: return VC1Main;
763 case AV_PROFILE_VC1_COMPLEX: return VC1Complex;
764 case AV_PROFILE_VC1_ADVANCED: return VC1Advanced;
765 }
766 break;
767 case AV_CODEC_ID_VP8: return VP8;
768 case AV_CODEC_ID_VP9:
769 switch (Profile)
770 {
771 case AV_PROFILE_VP9_0: return VP9_0;
772 case AV_PROFILE_VP9_1: return VP9_1;
773 case AV_PROFILE_VP9_2: return VP9_2;
774 case AV_PROFILE_VP9_3: return VP9_3;
775 }
776 break;
777 case AV_CODEC_ID_AV1:
778 switch (Profile)
779 {
780 case AV_PROFILE_AV1_MAIN: return AV1Main;
781 case AV_PROFILE_AV1_HIGH: return AV1High;
782 case AV_PROFILE_AV1_PROFESSIONAL: return AV1Professional;
783 }
784 break;
785 case AV_CODEC_ID_MJPEG: return MJPEG;
786 default: break;
787 }
788
789 return NoProfile;
790}
791
793 VideoFrameType Format, uint ColorDepth)
794{
795 QString profile;
796 switch (Profile)
797 {
798 case NoProfile: profile = QObject::tr("Unknown/Unsupported"); break;
799 case MPEG1: profile = "MPEG1"; break;
800 case MPEG2: profile = "MPEG2"; break;
801 case MPEG2Simple: profile = "MPEG2 Simple"; break;
802 case MPEG2Main: profile = "MPEG2 Main"; break;
803 case MPEG2422: profile = "MPEG2 422"; break;
804 case MPEG2High: profile = "MPEG2 High"; break;
805 case MPEG2Spatial: profile = "MPEG2 Spatial"; break;
806 case MPEG2SNR: profile = "MPEG2 SNR"; break;
807 case MPEG4: profile = "MPEG4"; break;
808 case MPEG4Simple: profile = "MPEG4 Simple"; break;
809 case MPEG4SimpleScaleable: profile = "MPEG4 Simple Scaleable"; break;
810 case MPEG4Core: profile = "MPEG4 Core"; break;
811 case MPEG4Main: profile = "MPEG4 Main"; break;
812 case MPEG4NBit: profile = "MPEG4 NBit"; break;
813 case MPEG4ScaleableTexture: profile = "MPEG4 Scaleable Texture"; break;
814 case MPEG4SimpleFace: profile = "MPEG4 Simple Face"; break;
815 case MPEG4BasicAnimated: profile = "MPEG4 Basic Animated"; break;
816 case MPEG4Hybrid: profile = "MPEG4 Hybrid"; break;
817 case MPEG4AdvancedRT: profile = "MPEG4 Advanced RT"; break;
818 case MPEG4CoreScaleable: profile = "MPEG4 Core Scaleable"; break;
819 case MPEG4AdvancedCoding: profile = "MPEG4 Advanced Coding"; break;
820 case MPEG4AdvancedCore: profile = "MPEG4 Advanced Core"; break;
821 case MPEG4AdvancedScaleableTexture: profile = "MPEG4 Advanced Scaleable Texture"; break;
822 case MPEG4SimpleStudio: profile = "MPEG4 Simple Studio"; break;
823 case MPEG4AdvancedSimple: profile = "MPEG4 Advanced Simple"; break;
824 case H263: profile = "H263"; break;
825 case H264: profile = "H264"; break;
826 case H264Baseline: profile = "H264 Baseline"; break;
827 case H264ConstrainedBaseline: profile = "H264 Constrained"; break;
828 case H264Main: profile = "H264 Main"; break;
829 case H264MainExtended: profile = "H264 Main Extended"; break;
830 case H264High: profile = "H264 High"; break;
831 case H264High10: profile = "H264 High10"; break;
832 case H264Extended: profile = "H264 Extended"; break;
833 case H264High422: profile = "H264 High 422"; break;
834 case H264High444: profile = "H264 High 444"; break;
835 case H264ConstrainedHigh: profile = "H264 Constrained High"; break;
836 case HEVC: profile = "HEVC"; break;
837 case HEVCMain: profile = "HEVC Main"; break;
838 case HEVCMain10: profile = "HEVC Main10"; break;
839 case HEVCMainStill: profile = "HEVC Main Still"; break;
840 case HEVCRext: profile = "HEVC Rext"; break;
841 case HEVCMain10HDR: profile = "HEVC Main10HDR"; break;
842 case HEVCMain10HDRPlus: profile = "HEVC Main10HDRPlus"; break;
843 case VC1: profile = "VC1"; break;
844 case VC1Simple: profile = "VC1 Simple"; break;
845 case VC1Main: profile = "VC1 Main"; break;
846 case VC1Complex: profile = "VC1 Complex"; break;
847 case VC1Advanced: profile = "VC1 Advanced"; break;
848 case VP8: profile = "VP8"; break;
849 case VP9: profile = "VP9"; break;
850 case VP9_0: profile = "VP9 Level 0"; break;
851 case VP9_1: profile = "VP9 Level 1"; break;
852 case VP9_2: profile = "VP9 Level 2"; break;
853 case VP9_2HDR: profile = "VP9 Level 2 HDR"; break;
854 case VP9_2HDRPlus: profile = "VP9 Level 2 HDRPlus"; break;
855 case VP9_3: profile = "VP9 Level 3"; break;
856 case VP9_3HDR: profile = "VP9 Level 3 HDR"; break;
857 case VP9_3HDRPlus: profile = "VP9 Level 3 HDRPlus"; break;
858 case AV1: profile = "AV1"; break;
859 case AV1Main: profile = "AV1 Main"; break;
860 case AV1High: profile = "AV1 High"; break;
861 case AV1Professional: profile = "AV1 Professional"; break;
862 case MJPEG: profile = "MJPEG";
863 }
864
865 if (Size.isEmpty())
866 return profile;
867
868 return QObject::tr("%1%2%3 (Max size: %4x%5)")
869 .arg(profile,
870 Format != FMT_NONE ? QString(" %1").arg(MythVideoFrame::FormatDescription(Format)) : "",
871 ColorDepth > 8 ? QString(" %1Bit").arg(ColorDepth) : "")
872 .arg(Size.width()).arg(Size.height());
873}
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:60
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