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
25#include "libmyth/mythaverror.h"
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 DestroyInterop(interop);
456 FreeAVHWDeviceContext free = interop->GetDefaultFree();
457 if (free)
458 {
459 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Calling default device context free");
460 Context->user_opaque = interop->GetDefaultUserOpaque();
461 free(Context);
462 }
463 }
464}
465
467{
469 {
470 Interop->DecrRef();
471 return;
472 }
473
474 auto destroy = [](void *Wait, void *Interop2, void* /*unused*/)
475 {
476 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Destroy interop callback");
477 auto *wait = reinterpret_cast<QWaitCondition*>(Wait);
478 auto *interop = reinterpret_cast<MythInteropGPU*>(Interop2);
479 if (interop)
480 interop->DecrRef();
481 if (wait)
482 wait->wakeAll();
483 };
484
485 if (!Interop->GetPlayer())
486 {
487 LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot destroy interop - no player");
488 return;
489 }
490 Interop->GetPlayer()->HandleDecoderCallback("Destroy OpenGL interop",
491 destroy, Interop, nullptr);
492}
493
494void MythCodecContext::CreateDecoderCallback(void *Wait, void *Context, void *Callback)
495{
496 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Create decoder callback");
497 auto *wait = reinterpret_cast<QWaitCondition*>(Wait);
498 auto *context = reinterpret_cast<AVCodecContext*>(Context);
499 auto callback = reinterpret_cast<CreateHWDecoder>(Callback);
500 if (context && callback)
501 (void)callback(context);
502 if (wait)
503 wait->wakeAll();
504}
505
507{
508 MythPlayerUI* result = nullptr;
509 auto* decoder = reinterpret_cast<AvFormatDecoder*>(Context->opaque);
510 if (decoder)
511 result = dynamic_cast<MythPlayerUI*>(decoder->GetPlayer());
512 return result;
513}
514
516{
517 if (auto * player = GetPlayerUI(Context); player != nullptr)
518 {
519 const auto & supported = player->GetInteropTypes();
520 return supported.find(Format) != supported.cend();
521 }
522 return false;
523}
524
526int MythCodecContext::InitialiseDecoder(AVCodecContext *Context, CreateHWDecoder Callback,
527 const QString &Debug)
528{
529 if (!Context || !Callback)
530 return -1;
532 return Callback(Context);
533
534 // Callback to MythPlayer (which will fail without a MythPlayer instance)
535 MythPlayerUI* player = GetPlayerUI(Context);
536 if (player)
538 Context, reinterpret_cast<void*>(Callback));
539 return Context->hw_frames_ctx ? 0 : -1;
540}
541
543int MythCodecContext::InitialiseDecoder2(AVCodecContext *Context, CreateHWDecoder Callback,
544 const QString &Debug)
545{
546 if (!Context || !Callback)
547 return -1;
549 return Callback(Context);
550
551 // Callback to MythPlayer (which will fail without a MythPlayer instance)
552 MythPlayerUI* player = GetPlayerUI(Context);
553 if (player)
555 Context, reinterpret_cast<void*>(Callback));
556 return Context->hw_device_ctx ? 0 : -1;
557}
558
559AVBufferRef* MythCodecContext::CreateDevice(AVHWDeviceType Type, MythInteropGPU* Interop, const QString& Device)
560{
561 AVBufferRef* result = nullptr;
562 int res = av_hwdevice_ctx_create(&result, Type, Device.isEmpty() ? nullptr :
563 Device.toLocal8Bit().constData(), nullptr, 0);
564 if (res == 0)
565 {
566 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created hardware device '%1'%2")
567 .arg(av_hwdevice_get_type_name(Type),
568 Device == nullptr ? "" : QString(" (%1)").arg(Device)));
569 auto *context = reinterpret_cast<AVHWDeviceContext*>(result->data);
570
571 if ((context->free || context->user_opaque) && !Interop)
572 {
573 LOG(VB_PLAYBACK, LOG_INFO, "Creating dummy interop");
574 Interop = MythInteropGPU::CreateDummy();
575 }
576
577 if (Interop)
578 {
579 Interop->SetDefaultFree(context->free);
580 Interop->SetDefaultUserOpaque(context->user_opaque);
581 Interop->IncrRef();
582 }
583
585 context->user_opaque = Interop;
586 return result;
587 }
588
589 std::string error;
590 LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Failed to create hardware device '%1'%2 Error '%3'")
591 .arg(av_hwdevice_get_type_name(Type),
592 Device == nullptr ? "" : QString(" (%1)").arg(Device),
594 return nullptr;
595}
596
598bool MythCodecContext::IsUnsupportedProfile(AVCodecContext *Context)
599{
600 switch (Context->codec_id)
601 {
602 case AV_CODEC_ID_H264:
603 switch (Context->profile)
604 {
605 case FF_PROFILE_H264_HIGH_10:
606 case FF_PROFILE_H264_HIGH_10_INTRA:
607 case FF_PROFILE_H264_HIGH_422:
608 case FF_PROFILE_H264_HIGH_422_INTRA:
609 case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
610 case FF_PROFILE_H264_HIGH_444_INTRA:
611 case FF_PROFILE_H264_CAVLC_444: return true;
612 default: break;
613 }
614 break;
615 default: break;
616 }
617 return false;
618}
619
624{
625 return avcodec_receive_frame(Context, Frame);
626}
627
629{
630 if (!Frame || !AvFrame)
631 return false;
632
633 AVFrame *temp = av_frame_alloc();
634 if (!temp)
635 return false;
636
637 AVPixelFormat *pixelformats = nullptr;
638 int ret = av_hwframe_transfer_get_formats(AvFrame->hw_frames_ctx,
639 AV_HWFRAME_TRANSFER_DIRECTION_FROM,
640 &pixelformats, 0);
641 if (ret == 0)
642 {
643 AVPixelFormat best = DecoderBase::GetBestVideoFormat(pixelformats, Frame->m_renderFormats);
644 if (best != AV_PIX_FMT_NONE)
645 {
647 bool valid = Frame->m_type == type;
648 if (!valid || (Frame->m_width != AvFrame->width) || (Frame->m_height != AvFrame->height))
650 AvFrame->width, AvFrame->height);
651
652 if (valid)
653 {
654 // Retrieve the picture directly into the VideoFrame Buffer
655 temp->format = best;
657 for (uint i = 0; i < 3; i++)
658 {
659 temp->data[i] = (i < max) ? (Frame->m_buffer + Frame->m_offsets[i]) : nullptr;
660 temp->linesize[i] = Frame->m_pitches[i];
661 }
662
663 // Dummy release method - we do not want to free the buffer
664 temp->buf[0] = av_buffer_create(reinterpret_cast<uint8_t*>(Frame), 0,
665 [](void* /*unused*/, uint8_t* /*unused*/){}, this, 0);
666 temp->width = AvFrame->width;
667 temp->height = AvFrame->height;
668 }
669 }
670 }
671 av_freep(reinterpret_cast<void*>(&pixelformats));
672
673 // retrieve data from GPU to CPU
674 if (ret >= 0)
675 {
676 ret = av_hwframe_transfer_data(temp, AvFrame, 0);
677 if (ret < 0)
678 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error %1 transferring the data to system memory").arg(ret));
679 }
680
681 Frame->m_colorshifted = true;
682 av_frame_free(&temp);
683 return ret >= 0;
684}
685
687{
688 switch (CodecID)
689 {
690 case AV_CODEC_ID_MPEG1VIDEO: return MPEG1;
691 case AV_CODEC_ID_MPEG2VIDEO:
692 switch (Profile)
693 {
694 case FF_PROFILE_MPEG2_422: return MPEG2422;
695 case FF_PROFILE_MPEG2_HIGH: return MPEG2High;
696 case FF_PROFILE_MPEG2_SS: return MPEG2Spatial;
697 case FF_PROFILE_MPEG2_SNR_SCALABLE: return MPEG2SNR;
698 case FF_PROFILE_MPEG2_SIMPLE: return MPEG2Simple;
699 case FF_PROFILE_MPEG2_MAIN: return MPEG2Main;
700 default: break;
701 }
702 break;
703 case AV_CODEC_ID_MPEG4:
704 switch (Profile)
705 {
706 case FF_PROFILE_MPEG4_SIMPLE: return MPEG4Simple;
707 case FF_PROFILE_MPEG4_SIMPLE_SCALABLE: return MPEG4SimpleScaleable;
708 case FF_PROFILE_MPEG4_CORE: return MPEG4Core;
709 case FF_PROFILE_MPEG4_MAIN: return MPEG4Main;
710 case FF_PROFILE_MPEG4_N_BIT: return MPEG4NBit;
711 case FF_PROFILE_MPEG4_SCALABLE_TEXTURE: return MPEG4ScaleableTexture;
712 case FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION: return MPEG4SimpleFace;
713 case FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE: return MPEG4BasicAnimated;
714 case FF_PROFILE_MPEG4_HYBRID: return MPEG4Hybrid;
715 case FF_PROFILE_MPEG4_ADVANCED_REAL_TIME: return MPEG4AdvancedRT;
716 case FF_PROFILE_MPEG4_CORE_SCALABLE: return MPEG4CoreScaleable;
717 case FF_PROFILE_MPEG4_ADVANCED_CODING: return MPEG4AdvancedCoding;
718 case FF_PROFILE_MPEG4_ADVANCED_CORE: return MPEG4AdvancedCore;
719 case FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE: return MPEG4AdvancedScaleableTexture;
720 case FF_PROFILE_MPEG4_SIMPLE_STUDIO: return MPEG4SimpleStudio;
721 case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: return MPEG4AdvancedSimple;
722 }
723 break;
724 case AV_CODEC_ID_H263: return H263;
725 case AV_CODEC_ID_H264:
726 switch (Profile)
727 {
728 // Mapping of H264MainExtended, H264ConstrainedHigh?
729 case FF_PROFILE_H264_BASELINE: return H264Baseline;
730 case FF_PROFILE_H264_CONSTRAINED_BASELINE: return H264ConstrainedBaseline;
731 case FF_PROFILE_H264_MAIN: return H264Main;
732 case FF_PROFILE_H264_EXTENDED: return H264Extended;
733 case FF_PROFILE_H264_HIGH: return H264High;
734 case FF_PROFILE_H264_HIGH_10: return H264High10;
735 //case FF_PROFILE_H264_HIGH_10_INTRA:
736 //case FF_PROFILE_H264_MULTIVIEW_HIGH:
737 case FF_PROFILE_H264_HIGH_422: return H264High422;
738 //case FF_PROFILE_H264_HIGH_422_INTRA:
739 //case FF_PROFILE_H264_STEREO_HIGH:
740 case FF_PROFILE_H264_HIGH_444: return H264High444;
741 //case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
742 //case FF_PROFILE_H264_HIGH_444_INTRA:
743 //case FF_PROFILE_H264_CAVLC_444:
744 }
745 break;
746 case AV_CODEC_ID_HEVC:
747 switch (Profile)
748 {
749 case FF_PROFILE_HEVC_MAIN: return HEVCMain;
750 case FF_PROFILE_HEVC_MAIN_10: return HEVCMain10;
751 case FF_PROFILE_HEVC_MAIN_STILL_PICTURE: return HEVCMainStill;
752 case FF_PROFILE_HEVC_REXT: return HEVCRext;
753 }
754 break;
755 case AV_CODEC_ID_VC1:
756 switch (Profile)
757 {
758 case FF_PROFILE_VC1_SIMPLE: return VC1Simple;
759 case FF_PROFILE_VC1_MAIN: return VC1Main;
760 case FF_PROFILE_VC1_COMPLEX: return VC1Complex;
761 case FF_PROFILE_VC1_ADVANCED: return VC1Advanced;
762 }
763 break;
764 case AV_CODEC_ID_VP8: return VP8;
765 case AV_CODEC_ID_VP9:
766 switch (Profile)
767 {
768 case FF_PROFILE_VP9_0: return VP9_0;
769 case FF_PROFILE_VP9_1: return VP9_1;
770 case FF_PROFILE_VP9_2: return VP9_2;
771 case FF_PROFILE_VP9_3: return VP9_3;
772 }
773 break;
774 case AV_CODEC_ID_AV1:
775 switch (Profile)
776 {
777 case FF_PROFILE_AV1_MAIN: return AV1Main;
778 case FF_PROFILE_AV1_HIGH: return AV1High;
779 case FF_PROFILE_AV1_PROFESSIONAL: return AV1Professional;
780 }
781 break;
782 case AV_CODEC_ID_MJPEG: return MJPEG;
783 default: break;
784 }
785
786 return NoProfile;
787}
788
790 VideoFrameType Format, uint ColorDepth)
791{
792 QString profile;
793 switch (Profile)
794 {
795 case NoProfile: profile = QObject::tr("Unknown/Unsupported"); break;
796 case MPEG1: profile = "MPEG1"; break;
797 case MPEG2: profile = "MPEG2"; break;
798 case MPEG2Simple: profile = "MPEG2 Simple"; break;
799 case MPEG2Main: profile = "MPEG2 Main"; break;
800 case MPEG2422: profile = "MPEG2 422"; break;
801 case MPEG2High: profile = "MPEG2 High"; break;
802 case MPEG2Spatial: profile = "MPEG2 Spatial"; break;
803 case MPEG2SNR: profile = "MPEG2 SNR"; break;
804 case MPEG4: profile = "MPEG4"; break;
805 case MPEG4Simple: profile = "MPEG4 Simple"; break;
806 case MPEG4SimpleScaleable: profile = "MPEG4 Simple Scaleable"; break;
807 case MPEG4Core: profile = "MPEG4 Core"; break;
808 case MPEG4Main: profile = "MPEG4 Main"; break;
809 case MPEG4NBit: profile = "MPEG4 NBit"; break;
810 case MPEG4ScaleableTexture: profile = "MPEG4 Scaleable Texture"; break;
811 case MPEG4SimpleFace: profile = "MPEG4 Simple Face"; break;
812 case MPEG4BasicAnimated: profile = "MPEG4 Basic Animated"; break;
813 case MPEG4Hybrid: profile = "MPEG4 Hybrid"; break;
814 case MPEG4AdvancedRT: profile = "MPEG4 Advanced RT"; break;
815 case MPEG4CoreScaleable: profile = "MPEG4 Core Scaleable"; break;
816 case MPEG4AdvancedCoding: profile = "MPEG4 Advanced Coding"; break;
817 case MPEG4AdvancedCore: profile = "MPEG4 Advanced Core"; break;
818 case MPEG4AdvancedScaleableTexture: profile = "MPEG4 Advanced Scaleable Texture"; break;
819 case MPEG4SimpleStudio: profile = "MPEG4 Simple Studio"; break;
820 case MPEG4AdvancedSimple: profile = "MPEG4 Advanced Simple"; break;
821 case H263: profile = "H263"; break;
822 case H264: profile = "H264"; break;
823 case H264Baseline: profile = "H264 Baseline"; break;
824 case H264ConstrainedBaseline: profile = "H264 Constrained"; break;
825 case H264Main: profile = "H264 Main"; break;
826 case H264MainExtended: profile = "H264 Main Extended"; break;
827 case H264High: profile = "H264 High"; break;
828 case H264High10: profile = "H264 High10"; break;
829 case H264Extended: profile = "H264 Extended"; break;
830 case H264High422: profile = "H264 High 422"; break;
831 case H264High444: profile = "H264 High 444"; break;
832 case H264ConstrainedHigh: profile = "H264 Constrained High"; break;
833 case HEVC: profile = "HEVC"; break;
834 case HEVCMain: profile = "HEVC Main"; break;
835 case HEVCMain10: profile = "HEVC Main10"; break;
836 case HEVCMainStill: profile = "HEVC Main Still"; break;
837 case HEVCRext: profile = "HEVC Rext"; break;
838 case HEVCMain10HDR: profile = "HEVC Main10HDR"; break;
839 case HEVCMain10HDRPlus: profile = "HEVC Main10HDRPlus"; break;
840 case VC1: profile = "VC1"; break;
841 case VC1Simple: profile = "VC1 Simple"; break;
842 case VC1Main: profile = "VC1 Main"; break;
843 case VC1Complex: profile = "VC1 Complex"; break;
844 case VC1Advanced: profile = "VC1 Advanced"; break;
845 case VP8: profile = "VP8"; break;
846 case VP9: profile = "VP9"; break;
847 case VP9_0: profile = "VP9 Level 0"; break;
848 case VP9_1: profile = "VP9 Level 1"; break;
849 case VP9_2: profile = "VP9 Level 2"; break;
850 case VP9_2HDR: profile = "VP9 Level 2 HDR"; break;
851 case VP9_2HDRPlus: profile = "VP9 Level 2 HDRPlus"; break;
852 case VP9_3: profile = "VP9 Level 3"; break;
853 case VP9_3HDR: profile = "VP9 Level 3 HDR"; break;
854 case VP9_3HDRPlus: profile = "VP9 Level 3 HDRPlus"; break;
855 case AV1: profile = "AV1"; break;
856 case AV1Main: profile = "AV1 Main"; break;
857 case AV1High: profile = "AV1 High"; break;
858 case AV1Professional: profile = "AV1 Professional"; break;
859 case MJPEG: profile = "MJPEG";
860 }
861
862 if (Size.isEmpty())
863 return profile;
864
865 return QObject::tr("%1%2%3 (Max size: %4x%5)")
866 .arg(profile,
867 Format != FMT_NONE ? QString(" %1").arg(MythVideoFrame::FormatDescription(Format)) : "",
868 ColorDepth > 8 ? QString(" %1Bit").arg(ColorDepth) : "")
869 .arg(Size.width()).arg(Size.height());
870}
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)
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: freesurround.h:24
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