2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
23 * - improve performance
24 * max out hw resources: e.g. make 1080p60 play on ION2
25 * allow advanced de-interlacing on ION
27 * - add vdpau/opengl interop
29 * - remove tight dependency to render thread
30 * prior design needed to hijack render thread in order to do
31 * gl interop functions. In particular this was a problem for
32 * init and clear down. Introduction of GL_NV_vdpau_interop
33 * increased the need to be independent from render thread
35 * - move to an actor based design in order to reduce the number
41 #include "system_gl.h"
43 #include "DllAvUtil.h"
44 #include "DVDVideoCodec.h"
45 #include "DVDVideoCodecFFmpeg.h"
46 #include "libavcodec/vdpau.h"
48 #include <X11/Xutil.h>
49 #define GLX_GLXEXT_PROTOTYPES
52 #include "DllAvUtil.h"
53 #include "DVDVideoCodec.h"
54 #include "DVDVideoCodecFFmpeg.h"
55 #include "libavcodec/vdpau.h"
56 #include "threads/CriticalSection.h"
57 #include "threads/SharedSection.h"
58 #include "settings/VideoSettings.h"
59 #include "guilib/DispResource.h"
60 #include "threads/Event.h"
61 #include "threads/Thread.h"
62 #include "utils/ActorProtocol.h"
65 using namespace Actor;
68 #define FULLHD_WIDTH 1920
69 #define MAX_PIC_Q_LENGTH 20 //for non-interop_yuv this controls the max length of the decoded pic to render completion Q
75 * VDPAU interface to driver
80 VdpGetProcAddress * vdp_get_proc_address;
81 VdpDeviceDestroy * vdp_device_destroy;
83 VdpVideoSurfaceCreate * vdp_video_surface_create;
84 VdpVideoSurfaceDestroy * vdp_video_surface_destroy;
85 VdpVideoSurfacePutBitsYCbCr * vdp_video_surface_put_bits_y_cb_cr;
86 VdpVideoSurfaceGetBitsYCbCr * vdp_video_surface_get_bits_y_cb_cr;
88 VdpOutputSurfacePutBitsYCbCr * vdp_output_surface_put_bits_y_cb_cr;
89 VdpOutputSurfacePutBitsNative * vdp_output_surface_put_bits_native;
90 VdpOutputSurfaceCreate * vdp_output_surface_create;
91 VdpOutputSurfaceDestroy * vdp_output_surface_destroy;
92 VdpOutputSurfaceGetBitsNative * vdp_output_surface_get_bits_native;
93 VdpOutputSurfaceRenderOutputSurface * vdp_output_surface_render_output_surface;
94 VdpOutputSurfacePutBitsIndexed * vdp_output_surface_put_bits_indexed;
96 VdpVideoMixerCreate * vdp_video_mixer_create;
97 VdpVideoMixerSetFeatureEnables * vdp_video_mixer_set_feature_enables;
98 VdpVideoMixerQueryParameterSupport * vdp_video_mixer_query_parameter_support;
99 VdpVideoMixerQueryFeatureSupport * vdp_video_mixer_query_feature_support;
100 VdpVideoMixerDestroy * vdp_video_mixer_destroy;
101 VdpVideoMixerRender * vdp_video_mixer_render;
102 VdpVideoMixerSetAttributeValues * vdp_video_mixer_set_attribute_values;
104 VdpGenerateCSCMatrix * vdp_generate_csc_matrix;
106 VdpGetErrorString * vdp_get_error_string;
108 VdpDecoderCreate * vdp_decoder_create;
109 VdpDecoderDestroy * vdp_decoder_destroy;
110 VdpDecoderRender * vdp_decoder_render;
111 VdpDecoderQueryCapabilities * vdp_decoder_query_caps;
113 VdpPreemptionCallbackRegister * vdp_preemption_callback_register;
117 //-----------------------------------------------------------------------------
118 // VDPAU data structs
119 //-----------------------------------------------------------------------------
124 * Buffer statistics used to control number of frames in queue
127 class CVdpauBufferStats
130 uint16_t decodedPics;
131 uint16_t processedPics;
133 uint64_t latency; // time decoder has waited for a frame, ideally there is no latency
138 void IncDecoded() { CSingleLock l(m_sec); decodedPics++;}
139 void DecDecoded() { CSingleLock l(m_sec); decodedPics--;}
140 void IncProcessed() { CSingleLock l(m_sec); processedPics++;}
141 void DecProcessed() { CSingleLock l(m_sec); processedPics--;}
142 void IncRender() { CSingleLock l(m_sec); renderPics++;}
143 void DecRender() { CSingleLock l(m_sec); renderPics--;}
144 void Reset() { CSingleLock l(m_sec); decodedPics=0; processedPics=0;renderPics=0;latency=0;}
145 void Get(uint16_t &decoded, uint16_t &processed, uint16_t &render) {CSingleLock l(m_sec); decoded = decodedPics, processed=processedPics, render=renderPics;}
146 void SetParams(uint64_t time, int flags) { CSingleLock l(m_sec); latency = time; codecFlags = flags; }
147 void GetParams(uint64_t &lat, int &flags) { CSingleLock l(m_sec); lat = latency; flags = codecFlags; }
148 void SetCmd(int cmd) { CSingleLock l(m_sec); processCmd = cmd; }
149 void GetCmd(int &cmd) { CSingleLock l(m_sec); cmd = processCmd; processCmd = 0; }
150 void SetCanSkipDeint(bool canSkip) { CSingleLock l(m_sec); canSkipDeint = canSkip; }
151 bool CanSkipDeint() { CSingleLock l(m_sec); if (canSkipDeint) return true; else return false;}
153 CCriticalSection m_sec;
157 * CVdpauConfig holds all configuration parameters needed by vdpau
158 * The structure is sent to the internal classes CMixer and COutput
162 class CVideoSurfaces;
173 VdpDecoder vdpDecoder;
174 VdpChromaType vdpChromaType;
175 CVdpauBufferStats *stats;
178 CVideoSurfaces *videoSurfaces;
179 int numRenderBuffers;
180 uint32_t maxReferences;
182 CVDPAUContext *context;
186 * Holds a decoded frame
187 * Input to COutput for further processing
189 struct CVdpauDecodedPicture
191 DVDVideoPicture DVDPic;
192 VdpVideoSurface videoSurface;
196 * Frame after having been processed by vdpau mixer
198 struct CVdpauProcessedPicture
200 DVDVideoPicture DVDPic;
201 VdpVideoSurface videoSurface;
202 VdpOutputSurface outputSurface;
206 * Ready to render textures
207 * Sent from COutput back to CDecoder
208 * Objects are referenced by DVDVideoPicture and are sent
211 class CVdpauRenderPicture
213 friend class CDecoder;
214 friend class COutput;
216 CVdpauRenderPicture(CCriticalSection §ion)
217 : refCount(0), renderPicSection(section) { fence = None; }
219 DVDVideoPicture DVDPic;
220 int texWidth, texHeight;
226 CVdpauRenderPicture* Acquire();
233 CCriticalSection &renderPicSection;
236 //-----------------------------------------------------------------------------
238 //-----------------------------------------------------------------------------
240 class CMixerControlProtocol : public Protocol
243 CMixerControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
257 class CMixerDataProtocol : public Protocol
260 CMixerDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
273 * Embeds the vdpau video mixer
274 * Embedded by COutput class, gets decoded frames from COutput, processes
275 * them in mixer ands sends processed frames back to COutput
277 class CMixer : private CThread
280 CMixer(CEvent *inMsgEvent);
285 CMixerControlProtocol m_controlPort;
286 CMixerDataProtocol m_dataPort;
291 void StateMachine(int signal, Protocol *port, Message *msg);
295 void CreateVdpauMixer();
296 void ProcessPicture();
299 void CheckFeatures();
300 void SetPostProcFeatures(bool postProcEnabled);
302 void InitCSCMatrix(int Width);
303 bool GenerateStudioCSCMatrix(VdpColorStandard colorStandard, VdpCSCMatrix &studioCSCMatrix);
305 void SetNoiseReduction();
307 void SetDeintSkipChroma();
308 void SetDeinterlacing();
309 void SetHWUpscaling();
310 void DisableHQScaling();
311 EINTERLACEMETHOD GetDeinterlacingMethod(bool log = false);
312 bool CheckStatus(VdpStatus vdp_st, int line);
313 CEvent m_outMsgEvent;
314 CEvent *m_inMsgEvent;
316 bool m_bStateMachineSelfTrigger;
318 // extended state variables for state machine
321 CVdpauConfig m_config;
322 VdpVideoMixer m_videoMixer;
323 VdpProcamp m_Procamp;
324 VdpCSCMatrix m_CSCMatrix;
328 float m_NoiseReduction;
333 bool m_SeenInterlaceFlag;
334 unsigned int m_ColorMatrix : 4;
335 VdpVideoMixerPictureStructure m_mixerfield;
338 CVdpauProcessedPicture m_processPicture;
339 std::queue<VdpOutputSurface> m_outputSurfaces;
340 std::queue<CVdpauDecodedPicture> m_decodedPics;
341 std::deque<CVdpauDecodedPicture> m_mixerInput;
344 //-----------------------------------------------------------------------------
346 //-----------------------------------------------------------------------------
349 * Buffer pool holds allocated vdpau and gl resources
350 * Embedded in COutput
352 struct VdpauBufferPool
355 virtual ~VdpauBufferPool();
356 struct GLVideoSurface
359 #ifdef GL_NV_vdpau_interop
360 GLvdpauSurfaceNV glVdpauSurface;
362 VdpVideoSurface sourceVuv;
363 VdpOutputSurface sourceRgb;
365 std::vector<CVdpauRenderPicture*> allRenderPics;
366 unsigned short numOutputSurfaces;
367 std::vector<VdpOutputSurface> outputSurfaces;
368 std::map<VdpVideoSurface, GLVideoSurface> glVideoSurfaceMap;
369 std::map<VdpOutputSurface, GLVideoSurface> glOutputSurfaceMap;
370 std::queue<CVdpauProcessedPicture> processedPics;
371 std::deque<int> usedRenderPics;
372 std::deque<int> freeRenderPics;
373 std::deque<int> syncRenderPics;
374 CCriticalSection renderPicSec;
377 class COutputControlProtocol : public Protocol
380 COutputControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
396 class COutputDataProtocol : public Protocol
399 COutputDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
412 * COutput is embedded in CDecoder and embeds CMixer
413 * The class has its own OpenGl context which is shared with render thread
414 * COuput generated ready to render textures and passes them back to
417 class COutput : private CThread
420 COutput(CEvent *inMsgEvent);
424 COutputControlProtocol m_controlPort;
425 COutputDataProtocol m_dataPort;
430 void StateMachine(int signal, Protocol *port, Message *msg);
432 CVdpauRenderPicture *ProcessMixerPicture();
433 void QueueReturnPicture(CVdpauRenderPicture *pic);
434 void ProcessReturnPicture(CVdpauRenderPicture *pic);
435 bool ProcessSyncPicture();
439 bool CreateGlxContext();
440 bool DestroyGlxContext();
441 bool EnsureBufferPool();
442 void ReleaseBufferPool();
446 void GLMapSurface(bool yuv, uint32_t source);
447 void GLUnmapSurfaces();
448 bool CheckStatus(VdpStatus vdp_st, int line);
449 CEvent m_outMsgEvent;
450 CEvent *m_inMsgEvent;
452 bool m_bStateMachineSelfTrigger;
454 // extended state variables for state machine
457 CVdpauConfig m_config;
458 VdpauBufferPool m_bufferPool;
462 GLXContext m_glContext;
463 GLXWindow m_glWindow;
465 GLXPixmap m_glPixmap;
468 #ifdef GL_NV_vdpau_interop
469 PFNGLVDPAUINITNVPROC glVDPAUInitNV;
470 PFNGLVDPAUFININVPROC glVDPAUFiniNV;
471 PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC glVDPAURegisterOutputSurfaceNV;
472 PFNGLVDPAUREGISTERVIDEOSURFACENVPROC glVDPAURegisterVideoSurfaceNV;
473 PFNGLVDPAUISSURFACENVPROC glVDPAUIsSurfaceNV;
474 PFNGLVDPAUUNREGISTERSURFACENVPROC glVDPAUUnregisterSurfaceNV;
475 PFNGLVDPAUSURFACEACCESSNVPROC glVDPAUSurfaceAccessNV;
476 PFNGLVDPAUMAPSURFACESNVPROC glVDPAUMapSurfacesNV;
477 PFNGLVDPAUUNMAPSURFACESNVPROC glVDPAUUnmapSurfacesNV;
478 PFNGLVDPAUGETSURFACEIVNVPROC glVDPAUGetSurfaceivNV;
482 //-----------------------------------------------------------------------------
483 // VDPAU Video Surface states
484 //-----------------------------------------------------------------------------
489 void AddSurface(VdpVideoSurface surf);
490 void ClearReference(VdpVideoSurface surf);
491 bool MarkRender(VdpVideoSurface surf);
492 void ClearRender(VdpVideoSurface surf);
493 bool IsValid(VdpVideoSurface surf);
494 VdpVideoSurface GetFree(VdpVideoSurface surf);
495 VdpVideoSurface GetAtIndex(int idx);
496 VdpVideoSurface RemoveNext(bool skiprender = false);
500 std::map<VdpVideoSurface, int> m_state;
501 std::list<VdpVideoSurface> m_freeSurfaces;
502 CCriticalSection m_section;
505 //-----------------------------------------------------------------------------
507 //-----------------------------------------------------------------------------
512 static bool EnsureContext(CVDPAUContext **ctx);
514 VDPAU_procs& GetProcs();
515 VdpDevice GetDevice();
516 bool Supports(VdpVideoMixerFeature feature);
517 VdpVideoMixerFeature* GetFeatures();
518 int GetFeatureCount();
523 bool CreateContext();
524 void DestroyContext();
526 void SpewHardwareAvailable();
527 static CVDPAUContext *m_context;
528 static CCriticalSection m_section;
529 static Display *m_display;
531 VdpVideoMixerFeature m_vdpFeatures[14];
533 static void *m_dlHandle;
534 VdpDevice m_vdpDevice;
535 VDPAU_procs m_vdpProcs;
536 VdpStatus (*dl_vdp_device_create_x11)(Display* display, int screen, VdpDevice* device, VdpGetProcAddress **get_proc_address);
543 : public CDVDVideoCodecFFmpeg::IHardwareDecoder
544 , public IDispResource
546 friend class CVdpauRenderPicture;
554 uint32_t aux; /* optional extra parameter... */
560 virtual bool Open (AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces = 0);
561 virtual int Decode (AVCodecContext* avctx, AVFrame* frame);
562 virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
563 virtual void Reset();
564 virtual void Close();
565 virtual long Release();
566 virtual bool CanSkipDeint();
567 virtual unsigned GetAllowedReferences() { return 5; }
569 virtual int Check(AVCodecContext* avctx);
570 virtual const std::string Name() { return "vdpau"; }
572 bool Supports(VdpVideoMixerFeature feature);
573 bool Supports(EINTERLACEMETHOD method);
574 EINTERLACEMETHOD AutoInterlaceMethod();
575 static bool IsVDPAUFormat(PixelFormat fmt);
577 static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic);
578 static void FFDrawSlice(struct AVCodecContext *s,
579 const AVFrame *src, int offset[4],
580 int y, int type, int height);
581 static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic);
582 static VdpStatus Render( VdpDecoder decoder, VdpVideoSurface target,
583 VdpPictureInfo const *picture_info,
584 uint32_t bitstream_buffer_count,
585 VdpBitstreamBuffer const * bitstream_buffers);
587 virtual void OnLostDevice();
588 virtual void OnResetDevice();
591 void SetWidthHeight(int width, int height);
592 bool ConfigVDPAU(AVCodecContext *avctx, int ref_frames);
593 bool CheckStatus(VdpStatus vdp_st, int line);
594 void FiniVDPAUOutput();
595 void ReturnRenderPicture(CVdpauRenderPicture *renderPic);
596 long ReleasePicReference();
598 static void ReadFormatOf( AVCodecID codec
599 , VdpDecoderProfile &decoder_profile
600 , VdpChromaType &chroma_type);
602 // OnLostDevice triggers transition from all states to LOST
603 // internal errors trigger transition from OPEN to RESET
604 // OnResetDevice triggers transition from LOST to RESET
611 CCriticalSection m_DecoderSection;
612 CEvent m_DisplayEvent;
614 DllAvUtil m_dllAvUtil;
615 ThreadIdentifier m_decoderThread;
616 bool m_vdpauConfigured;
617 CVdpauConfig m_vdpauConfig;
618 CVideoSurfaces m_videoSurfaces;
619 AVVDPAUContext m_hwContext;
621 COutput m_vdpauOutput;
622 CVdpauBufferStats m_bufferStats;
624 CVdpauRenderPicture *m_presentPicture;