1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "DVDResource.h"
12 #include "cores/VideoPlayer/Buffers/VideoBuffer.h"
13 #include "cores/VideoPlayer/Interface/DemuxPacket.h"
14 #include "cores/VideoPlayer/Process/ProcessInfo.h"
15 
16 extern "C" {
17 #include <libavcodec/avcodec.h>
18 #include <libavutil/mastering_display_metadata.h>
19 }
20 
21 #include <vector>
22 #include <string>
23 #include <map>
24 
25 class CSetting;
26 
27 // when modifying these structures, make sure you update all codecs accordingly
28 #define FRAME_TYPE_UNDEF 0
29 #define FRAME_TYPE_I     1
30 #define FRAME_TYPE_P     2
31 #define FRAME_TYPE_B     3
32 #define FRAME_TYPE_D     4
33 
34 
35 // should be entirely filled by all codecs
36 struct VideoPicture
37 {
38 public:
39   VideoPicture();
40   ~VideoPicture();
41   VideoPicture& CopyRef(const VideoPicture &pic);
42   VideoPicture& SetParams(const VideoPicture &pic);
43   void Reset(); // reinitialize members, videoBuffer will be released if set!
44 
45   CVideoBuffer *videoBuffer = nullptr;
46 
47   double pts; // timestamp in seconds, used in the CVideoPlayer class to keep track of pts
48   double dts;
49   unsigned int iFlags;
50   double iRepeatPicture;
51   double iDuration;
52   unsigned int iFrameType         : 4;  //< see defines above // 1->I, 2->P, 3->B, 0->Undef
53   unsigned int color_space;
54   unsigned int color_range        : 1;  //< 1 indicate if we have a full range of color
55   unsigned int chroma_position;
56   unsigned int color_primaries;
57   unsigned int color_transfer;
58   unsigned int colorBits = 8;
59   std::string stereoMode;
60 
61   int8_t* qp_table;                //< Quantization parameters, primarily used by filters
62   int qstride;
63   int qscale_type;
64   int pict_type;
65 
66   bool hasDisplayMetadata = false;
67   AVMasteringDisplayMetadata displayMetadata;
68   bool hasLightMetadata = false;
69   AVContentLightMetadata lightMetadata;
70 
71   AVPixelFormat pixelFormat; //< source pixel format
72 
73   unsigned int iWidth;
74   unsigned int iHeight;
75   unsigned int iDisplayWidth;           //< width of the picture without black bars
76   unsigned int iDisplayHeight;          //< height of the picture without black bars
77 
78 private:
79   VideoPicture(VideoPicture const&);
80   VideoPicture& operator=(VideoPicture const&);
81 };
82 
83 #define DVP_FLAG_TOP_FIELD_FIRST    0x00000001
84 #define DVP_FLAG_REPEAT_TOP_FIELD   0x00000002  //< Set to indicate that the top field should be repeated
85 #define DVP_FLAG_INTERLACED         0x00000008  //< Set to indicate that this frame is interlaced
86 #define DVP_FLAG_DROPPED            0x00000010  //< indicate that this picture has been dropped in decoder stage, will have no data
87 
88 #define DVD_CODEC_CTRL_SKIPDEINT    0x01000000  //< request to skip a deinterlacing cycle, if possible
89 #define DVD_CODEC_CTRL_NO_POSTPROC  0x02000000  //< see GetCodecStats
90 #define DVD_CODEC_CTRL_HURRY        0x04000000  //< see GetCodecStats
91 #define DVD_CODEC_CTRL_DROP         0x08000000  //< drop in decoder or set DVP_FLAG_DROPPED, no render of frame
92 #define DVD_CODEC_CTRL_DROP_ANY     0x10000000  //< drop some non-reference frame
93 #define DVD_CODEC_CTRL_DRAIN        0x20000000  //< squeeze out pictured without feeding new packets
94 #define DVD_CODEC_CTRL_ROTATE       0x40000000  //< rotate if renderer does not support it
95 
96 // DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2!
97 
98 #define DVP_QSCALE_UNKNOWN          0
99 #define DVP_QSCALE_MPEG1            1
100 #define DVP_QSCALE_MPEG2            2
101 #define DVP_QSCALE_H264             3
102 
103 class CDVDStreamInfo;
104 class CDVDCodecOption;
105 class CDVDCodecOptions;
106 
107 class CDVDVideoCodec
108 {
109 public:
110 
111   enum VCReturn
112   {
113     VC_NONE = 0,
114     VC_ERROR,           //< an error occurred, no other messages will be returned
115     VC_FATAL,           //< non recoverable error
116     VC_BUFFER,          //< the decoder needs more data
117     VC_PICTURE,         //< the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data
118     VC_FLUSHED,         //< the decoder lost it's state, we need to restart decoding again
119     VC_NOBUFFER,        //< last FFmpeg GetBuffer failed
120     VC_REOPEN,          //< decoder request to re-open
121     VC_EOF              //< EOF
122   };
123 
CDVDVideoCodec(CProcessInfo & processInfo)124   explicit CDVDVideoCodec(CProcessInfo &processInfo) : m_processInfo(processInfo) {}
125   virtual ~CDVDVideoCodec() = default;
126 
127   /**
128    * Open the decoder, returns true on success
129    * Decoders not capable of runnung multiple instances should return false in case
130    * there is already a instance open
131    */
132   virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) = 0;
133 
134   /**
135    * Reconfigure the decoder, returns true on success
136    * Decoders not capable of runnung multiple instances may be capable of reconfiguring
137    * the running instance. If Reconfigure returns false, player will close / open
138    * the decoder
139    */
Reconfigure(CDVDStreamInfo & hints)140   virtual bool Reconfigure(CDVDStreamInfo &hints)
141   {
142     return false;
143   }
144 
145   /**
146    * add data, decoder has to consume the entire packet
147    * returns true if the packet was consumed or if resubmitting it is useless
148    */
149   virtual bool AddData(const DemuxPacket &packet) = 0;
150 
151   /**
152    * Reset the decoder.
153    * Should be the same as calling Dispose and Open after each other
154    */
155   virtual void Reset() = 0;
156 
157   /**
158    * GetPicture controls decoding. Player calls it on every cycle
159    * it can signal a picture, request a buffer, or return none, if nothing applies
160    * the data is valid until the next GetPicture return VC_PICTURE
161    */
162   virtual VCReturn GetPicture(VideoPicture* pVideoPicture) = 0;
163 
164   /**
165    * will be called by video player indicating the playback speed. see DVD_PLAYSPEED_NORMAL,
166    * DVD_PLAYSPEED_PAUSE and friends.
167    */
SetSpeed(int iSpeed)168   virtual void SetSpeed(int iSpeed) {};
169 
170   /**
171    * should return codecs name
172    */
173   virtual const char* GetName() = 0;
174 
175   /**
176    * How many packets should player remember, so codec can recover should
177    * something cause it to flush outside of players control
178    */
GetConvergeCount()179   virtual unsigned GetConvergeCount()
180   {
181     return 0;
182   }
183 
184   /**
185    * Number of references to old pictures that are allowed to be retained when
186    * calling decode on the next demux packet
187    */
GetAllowedReferences()188   virtual unsigned GetAllowedReferences() { return 0; }
189 
190   /**
191    * For calculation of dropping requirements player asks for some information.
192    * - pts : right after decoder, used to detect gaps (dropped frames in decoder)
193    * - droppedFrames : indicates if decoder has dropped a frame
194    *                 -1 means that decoder has no info on this.
195    * - skippedPics : indicates if postproc has skipped a already decoded picture
196    *                 -1 means that decoder has no info on this.
197    *
198    * If codec does not implement this method, pts of decoded frame at input
199    * video player is used. In case decoder does post-proc and de-interlacing there
200    * may be quite some frames queued up between exit decoder and entry player.
201    */
GetCodecStats(double & pts,int & droppedFrames,int & skippedPics)202   virtual bool GetCodecStats(double &pts, int &droppedFrames, int &skippedPics)
203   {
204     droppedFrames = -1;
205     skippedPics = -1;
206     return false;
207   }
208 
209   /**
210    * Codec can be informed by player with the following flags:
211    *
212    * DVD_CODEC_CTRL_NO_POSTPROC :
213    *                  if speed is not normal the codec can switch off
214    *                  postprocessing and de-interlacing
215    *
216    * DVD_CODEC_CTRL_HURRY :
217    *                  codecs may do postprocessing and de-interlacing.
218    *                  If video buffers in RenderManager are about to run dry,
219    *                  this is signaled to codec. Codec can wait for post-proc
220    *                  to be finished instead of returning empty and getting another
221    *                  packet.
222    *
223    * DVD_CODEC_CTRL_DRAIN :
224    *                  instruct decoder to deliver last pictures without requesting
225    *                  new packets
226    *
227    * DVD_CODEC_CTRL_DROP :
228    *                  this packet is going to be dropped. decoder is free to use it
229    *                  for decoding
230    *
231    */
SetCodecControl(int flags)232   virtual void SetCodecControl(int flags) {}
233 
234   /**
235    * Re-open the decoder.
236    * Decoder request to re-open
237    */
Reopen()238   virtual void Reopen() {};
239 
240 protected:
241   CProcessInfo &m_processInfo;
242 };
243 
244 // callback interface for ffmpeg hw accelerators
245 class IHardwareDecoder : public IDVDResourceCounted<IHardwareDecoder>
246 {
247 public:
248   IHardwareDecoder() = default;
249   ~IHardwareDecoder() override = default;
250   virtual bool Open(AVCodecContext* avctx, AVCodecContext* mainctx, const enum AVPixelFormat) = 0;
251   virtual CDVDVideoCodec::VCReturn Decode(AVCodecContext* avctx, AVFrame* frame) = 0;
252   virtual bool GetPicture(AVCodecContext* avctx, VideoPicture* picture) = 0;
253   virtual CDVDVideoCodec::VCReturn Check(AVCodecContext* avctx) = 0;
Reset()254   virtual void Reset() {}
GetAllowedReferences()255   virtual unsigned GetAllowedReferences() { return 0; }
CanSkipDeint()256   virtual bool CanSkipDeint() {return false; }
257   virtual const std::string Name() = 0;
SetCodecControl(int flags)258   virtual void SetCodecControl(int flags) {};
259 };
260 
261 class ICallbackHWAccel
262 {
263 public:
264   virtual ~ICallbackHWAccel() = default;
265   virtual IHardwareDecoder* GetHWAccel() = 0;
266   virtual bool GetPictureCommon(VideoPicture* pVideoPicture) = 0;
267 };
268