Merge pull request #4294 from FernetMenta/vdpau
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDCodecs / Video / VDPAU.h
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20
21 /**
22  * design goals:
23  * - improve performance
24  *   max out hw resources: e.g. make 1080p60 play on ION2
25  *   allow advanced de-interlacing on ION
26  *
27  * - add vdpau/opengl interop
28  *
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
34  *
35  * - move to an actor based design in order to reduce the number
36  *   of locks needed.
37  */
38
39 #pragma once
40
41 #include "system_gl.h"
42
43 #include "DllAvUtil.h"
44 #include "DVDVideoCodec.h"
45 #include "DVDVideoCodecFFmpeg.h"
46 #include "libavcodec/vdpau.h"
47 #include <X11/Xlib.h>
48 #include <X11/Xutil.h>
49 #define GLX_GLXEXT_PROTOTYPES
50 #include <GL/glx.h>
51
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"
63 #include <list>
64
65 using namespace Actor;
66
67
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
70
71 namespace VDPAU
72 {
73
74 /**
75  * VDPAU interface to driver
76  */
77
78 struct VDPAU_procs
79 {
80   VdpGetProcAddress *                   vdp_get_proc_address;
81   VdpDeviceDestroy *                    vdp_device_destroy;
82
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;
87
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;
95
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;
103
104   VdpGenerateCSCMatrix *                vdp_generate_csc_matrix;
105
106   VdpGetErrorString *                         vdp_get_error_string;
107
108   VdpDecoderCreate *             vdp_decoder_create;
109   VdpDecoderDestroy *            vdp_decoder_destroy;
110   VdpDecoderRender *             vdp_decoder_render;
111   VdpDecoderQueryCapabilities *  vdp_decoder_query_caps;
112
113   VdpPreemptionCallbackRegister * vdp_preemption_callback_register;
114
115 };
116
117 //-----------------------------------------------------------------------------
118 // VDPAU data structs
119 //-----------------------------------------------------------------------------
120
121 class CDecoder;
122
123 /**
124  * Buffer statistics used to control number of frames in queue
125  */
126
127 class CVdpauBufferStats
128 {
129 public:
130   uint16_t decodedPics;
131   uint16_t processedPics;
132   uint16_t renderPics;
133   uint64_t latency;         // time decoder has waited for a frame, ideally there is no latency
134   int codecFlags;
135   bool canSkipDeint;
136   int processCmd;
137
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;}
152 private:
153   CCriticalSection m_sec;
154 };
155
156 /**
157  *  CVdpauConfig holds all configuration parameters needed by vdpau
158  *  The structure is sent to the internal classes CMixer and COutput
159  *  for init.
160  */
161
162 class CVideoSurfaces;
163 class CVDPAUContext;
164
165 struct CVdpauConfig
166 {
167   int surfaceWidth;
168   int surfaceHeight;
169   int vidWidth;
170   int vidHeight;
171   int outWidth;
172   int outHeight;
173   VdpDecoder vdpDecoder;
174   VdpChromaType vdpChromaType;
175   CVdpauBufferStats *stats;
176   CDecoder *vdpau;
177   int upscale;
178   CVideoSurfaces *videoSurfaces;
179   int numRenderBuffers;
180   uint32_t maxReferences;
181   bool useInteropYuv;
182   CVDPAUContext *context;
183 };
184
185 /**
186  * Holds a decoded frame
187  * Input to COutput for further processing
188  */
189 struct CVdpauDecodedPicture
190 {
191   DVDVideoPicture DVDPic;
192   VdpVideoSurface videoSurface;
193 };
194
195 /**
196  * Frame after having been processed by vdpau mixer
197  */
198 struct CVdpauProcessedPicture
199 {
200   DVDVideoPicture DVDPic;
201   VdpVideoSurface videoSurface;
202   VdpOutputSurface outputSurface;
203 };
204
205 /**
206  * Ready to render textures
207  * Sent from COutput back to CDecoder
208  * Objects are referenced by DVDVideoPicture and are sent
209  * to renderer
210  */
211 class CVdpauRenderPicture
212 {
213   friend class CDecoder;
214   friend class COutput;
215 public:
216   CVdpauRenderPicture(CCriticalSection &section)
217     : refCount(0), renderPicSection(section) { fence = None; }
218   void Sync();
219   DVDVideoPicture DVDPic;
220   int texWidth, texHeight;
221   CRect crop;
222   GLuint texture[4];
223   uint32_t sourceIdx;
224   bool valid;
225   CDecoder *vdpau;
226   CVdpauRenderPicture* Acquire();
227   long Release();
228 private:
229   void ReturnUnused();
230   bool usefence;
231   GLsync fence;
232   int refCount;
233   CCriticalSection &renderPicSection;
234 };
235
236 //-----------------------------------------------------------------------------
237 // Mixer
238 //-----------------------------------------------------------------------------
239
240 class CMixerControlProtocol : public Protocol
241 {
242 public:
243   CMixerControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
244   enum OutSignal
245   {
246     INIT = 0,
247     FLUSH,
248     TIMEOUT,
249   };
250   enum InSignal
251   {
252     ACC,
253     ERROR,
254   };
255 };
256
257 class CMixerDataProtocol : public Protocol
258 {
259 public:
260   CMixerDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
261   enum OutSignal
262   {
263     FRAME,
264     BUFFER,
265   };
266   enum InSignal
267   {
268     PICTURE,
269   };
270 };
271
272 /**
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
276  */
277 class CMixer : private CThread
278 {
279 public:
280   CMixer(CEvent *inMsgEvent);
281   virtual ~CMixer();
282   void Start();
283   void Dispose();
284   bool IsActive();
285   CMixerControlProtocol m_controlPort;
286   CMixerDataProtocol m_dataPort;
287 protected:
288   void OnStartup();
289   void OnExit();
290   void Process();
291   void StateMachine(int signal, Protocol *port, Message *msg);
292   void Init();
293   void Uninit();
294   void Flush();
295   void CreateVdpauMixer();
296   void ProcessPicture();
297   void InitCycle();
298   void FiniCycle();
299   void CheckFeatures();
300   void SetPostProcFeatures(bool postProcEnabled);
301   void PostProcOff();
302   void InitCSCMatrix(int Width);
303   bool GenerateStudioCSCMatrix(VdpColorStandard colorStandard, VdpCSCMatrix &studioCSCMatrix);
304   void SetColor();
305   void SetNoiseReduction();
306   void SetSharpness();
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;
315   int m_state;
316   bool m_bStateMachineSelfTrigger;
317
318   // extended state variables for state machine
319   int m_extTimeout;
320   bool m_vdpError;
321   CVdpauConfig m_config;
322   VdpVideoMixer m_videoMixer;
323   VdpProcamp m_Procamp;
324   VdpCSCMatrix  m_CSCMatrix;
325   bool m_PostProc;
326   float m_Brightness;
327   float m_Contrast;
328   float m_NoiseReduction;
329   float m_Sharpness;
330   int m_DeintMode;
331   int m_Deint;
332   int m_Upscale;
333   bool m_SeenInterlaceFlag;
334   unsigned int m_ColorMatrix       : 4;
335   VdpVideoMixerPictureStructure m_mixerfield;
336   int m_mixerstep;
337   int m_mixersteps;
338   CVdpauProcessedPicture m_processPicture;
339   std::queue<VdpOutputSurface> m_outputSurfaces;
340   std::queue<CVdpauDecodedPicture> m_decodedPics;
341   std::deque<CVdpauDecodedPicture> m_mixerInput;
342 };
343
344 //-----------------------------------------------------------------------------
345 // Output
346 //-----------------------------------------------------------------------------
347
348 /**
349  * Buffer pool holds allocated vdpau and gl resources
350  * Embedded in COutput
351  */
352 struct VdpauBufferPool
353 {
354   VdpauBufferPool();
355   virtual ~VdpauBufferPool();
356   struct GLVideoSurface
357   {
358     GLuint texture[4];
359 #ifdef GL_NV_vdpau_interop
360     GLvdpauSurfaceNV glVdpauSurface;
361 #endif
362     VdpVideoSurface sourceVuv;
363     VdpOutputSurface sourceRgb;
364   };
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;
375 };
376
377 class COutputControlProtocol : public Protocol
378 {
379 public:
380   COutputControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
381   enum OutSignal
382   {
383     INIT,
384     FLUSH,
385     PRECLEANUP,
386     TIMEOUT,
387   };
388   enum InSignal
389   {
390     ACC,
391     ERROR,
392     STATS,
393   };
394 };
395
396 class COutputDataProtocol : public Protocol
397 {
398 public:
399   COutputDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
400   enum OutSignal
401   {
402     NEWFRAME = 0,
403     RETURNPIC,
404   };
405   enum InSignal
406   {
407     PICTURE,
408   };
409 };
410
411 /**
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
415  * CDecoder
416  */
417 class COutput : private CThread
418 {
419 public:
420   COutput(CEvent *inMsgEvent);
421   virtual ~COutput();
422   void Start();
423   void Dispose();
424   COutputControlProtocol m_controlPort;
425   COutputDataProtocol m_dataPort;
426 protected:
427   void OnStartup();
428   void OnExit();
429   void Process();
430   void StateMachine(int signal, Protocol *port, Message *msg);
431   bool HasWork();
432   CVdpauRenderPicture *ProcessMixerPicture();
433   void QueueReturnPicture(CVdpauRenderPicture *pic);
434   void ProcessReturnPicture(CVdpauRenderPicture *pic);
435   bool ProcessSyncPicture();
436   bool Init();
437   bool Uninit();
438   void Flush();
439   bool CreateGlxContext();
440   bool DestroyGlxContext();
441   bool EnsureBufferPool();
442   void ReleaseBufferPool();
443   void PreCleanup();
444   void InitMixer();
445   bool GLInit();
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;
451   int m_state;
452   bool m_bStateMachineSelfTrigger;
453
454   // extended state variables for state machine
455   int m_extTimeout;
456   bool m_vdpError;
457   CVdpauConfig m_config;
458   VdpauBufferPool m_bufferPool;
459   CMixer m_mixer;
460   Display *m_Display;
461   Window m_Window;
462   GLXContext m_glContext;
463   GLXWindow m_glWindow;
464   Pixmap    m_pixmap;
465   GLXPixmap m_glPixmap;
466
467   // gl functions
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;
479 #endif
480 };
481
482 //-----------------------------------------------------------------------------
483 // VDPAU Video Surface states
484 //-----------------------------------------------------------------------------
485
486 class CVideoSurfaces
487 {
488 public:
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);
497   void Reset();
498   int Size();
499 protected:
500   std::map<VdpVideoSurface, int> m_state;
501   std::list<VdpVideoSurface> m_freeSurfaces;
502   CCriticalSection m_section;
503 };
504
505 //-----------------------------------------------------------------------------
506 // VDPAU decoder
507 //-----------------------------------------------------------------------------
508
509 class CVDPAUContext
510 {
511 public:
512   static bool EnsureContext(CVDPAUContext **ctx);
513   void Release();
514   VDPAU_procs& GetProcs();
515   VdpDevice GetDevice();
516   bool Supports(VdpVideoMixerFeature feature);
517   VdpVideoMixerFeature* GetFeatures();
518   int GetFeatureCount();
519 private:
520   CVDPAUContext();
521   void Close();
522   bool LoadSymbols();
523   bool CreateContext();
524   void DestroyContext();
525   void QueryProcs();
526   void SpewHardwareAvailable();
527   static CVDPAUContext *m_context;
528   static CCriticalSection m_section;
529   static Display *m_display;
530   int m_refCount;
531   VdpVideoMixerFeature m_vdpFeatures[14];
532   int m_featureCount;
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);
537 };
538
539 /**
540  *  VDPAU main class
541  */
542 class CDecoder
543  : public CDVDVideoCodecFFmpeg::IHardwareDecoder
544  , public IDispResource
545 {
546    friend class CVdpauRenderPicture;
547
548 public:
549
550   struct Desc
551   {
552     const char *name;
553     uint32_t id;
554     uint32_t aux; /* optional extra parameter... */
555   };
556
557   CDecoder();
558   virtual ~CDecoder();
559
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; }
568
569   virtual int  Check(AVCodecContext* avctx);
570   virtual const std::string Name() { return "vdpau"; }
571
572   bool Supports(VdpVideoMixerFeature feature);
573   bool Supports(EINTERLACEMETHOD method);
574   EINTERLACEMETHOD AutoInterlaceMethod();
575   static bool IsVDPAUFormat(PixelFormat fmt);
576
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);
586
587   virtual void OnLostDevice();
588   virtual void OnResetDevice();
589
590 protected:
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();
597
598   static void ReadFormatOf( AVCodecID codec
599                           , VdpDecoderProfile &decoder_profile
600                           , VdpChromaType     &chroma_type);
601
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
605   enum EDisplayState
606   { VDPAU_OPEN
607   , VDPAU_RESET
608   , VDPAU_LOST
609   , VDPAU_ERROR
610   } m_DisplayState;
611   CCriticalSection m_DecoderSection;
612   CEvent         m_DisplayEvent;
613
614   DllAvUtil     m_dllAvUtil;
615   ThreadIdentifier m_decoderThread;
616   bool          m_vdpauConfigured;
617   CVdpauConfig  m_vdpauConfig;
618   CVideoSurfaces m_videoSurfaces;
619   AVVDPAUContext m_hwContext;
620
621   COutput       m_vdpauOutput;
622   CVdpauBufferStats m_bufferStats;
623   CEvent        m_inMsgEvent;
624   CVdpauRenderPicture *m_presentPicture;
625
626   int m_codecControl;
627 };
628
629 }