1 /****************************************************************************** 2 QtAV: Media play library based on Qt and FFmpeg 3 Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com> 4 5 * This file is part of QtAV 6 7 This library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Lesser General Public 9 License as published by the Free Software Foundation; either 10 version 2.1 of the License, or (at your option) any later version. 11 12 This library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Lesser General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public 18 License along with this library; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 ******************************************************************************/ 21 22 #ifndef QAV_VIDEORENDERER_H 23 #define QAV_VIDEORENDERER_H 24 25 #include <QtCore/QByteArray> 26 #include <QtCore/QSize> 27 #include <QtCore/QRectF> 28 #include <QtGui/QColor> 29 #include <QtAV/AVOutput.h> 30 #include <QtAV/VideoFrame.h> 31 32 /*! 33 * A bridge for VideoOutput(QObject based) and video renderer backend classes 34 * Every public setter call it's virtual onSetXXX(...) which has default behavior. 35 * While VideoOutput.onSetXXX(...) simply calls backend's setXXX(...) and return whether the result is desired. 36 */ 37 QT_BEGIN_NAMESPACE 38 class QWidget; 39 class QWindow; 40 class QGraphicsItem; 41 QT_END_NAMESPACE 42 43 namespace QtAV { 44 45 typedef int VideoRendererId; 46 extern Q_AV_EXPORT VideoRendererId VideoRendererId_OpenGLWindow; 47 class Filter; 48 class OpenGLVideo; 49 class VideoFormat; 50 class VideoRendererPrivate; 51 class Q_AV_EXPORT VideoRenderer : public AVOutput 52 { 53 DPTR_DECLARE_PRIVATE(VideoRenderer) 54 public: 55 //TODO: original video size mode 56 // fillmode: keepsize 57 enum OutAspectRatioMode { 58 RendererAspectRatio //Use renderer's aspect ratio, i.e. stretch to fit the renderer rect 59 , VideoAspectRatio //Use video's aspect ratio and align center in renderer. 60 , CustomAspectRation //Use the ratio set by setOutAspectRatio(qreal). Mode will be set to this if that function is called 61 //, AspectRatio4_3, AspectRatio16_9 62 }; 63 enum Quality { //TODO: deprecated. simpily use int 0~100 64 QualityDefault, //good 65 QualityBest, 66 QualityFastest 67 }; 68 69 template<class C> Register(VideoRendererId id,const char * name)70 static bool Register(VideoRendererId id, const char* name) { return Register(id, create<C>, name);} 71 static VideoRenderer* create(VideoRendererId id); 72 static VideoRenderer* create(const char* name); 73 /*! 74 * \brief next 75 * \param id NULL to get the first id address 76 * \return address of id or NULL if not found/end 77 */ 78 static VideoRendererId* next(VideoRendererId* id = 0); 79 static const char* name(VideoRendererId id); 80 static VideoRendererId id(const char* name); 81 82 VideoRenderer(); 83 virtual ~VideoRenderer(); 84 virtual VideoRendererId id() const = 0; 85 86 bool receive(const VideoFrame& frame); 87 /*! 88 * \brief setPreferredPixelFormat 89 * \param pixfmt 90 * pixfmt will be used if decoded format is not supported by this renderer. otherwise, use decoded format. 91 * return false if \a pixfmt is not supported and not changed. 92 */ 93 bool setPreferredPixelFormat(VideoFormat::PixelFormat pixfmt); 94 /*! 95 * \brief preferredPixelFormat 96 * \return preferred pixel format. e.g. WidgetRenderer is rgb formats. 97 */ 98 virtual VideoFormat::PixelFormat preferredPixelFormat() const; //virtual? 99 /*! 100 * \brief forcePreferredPixelFormat 101 * force to use preferredPixelFormat() even if incoming format is supported 102 * \param force 103 */ 104 void forcePreferredPixelFormat(bool force = true); 105 bool isPreferredPixelFormatForced() const; 106 virtual bool isSupported(VideoFormat::PixelFormat pixfmt) const = 0; 107 108 /*! 109 * \brief sourceAspectRatio 110 * The display aspect ratio of received video frame. 0 for an invalid frame. 111 * sourceAspectRatioChanged() (a signal for QObject renderers) will be called if the new frame has a different DAR. 112 */ 113 qreal sourceAspectRatio() const; 114 115 void setOutAspectRatioMode(OutAspectRatioMode mode); 116 OutAspectRatioMode outAspectRatioMode() const; 117 //If setOutAspectRatio(qreal) is used, then OutAspectRatioMode is CustomAspectRation 118 void setOutAspectRatio(qreal ratio); 119 qreal outAspectRatio() const;// 120 121 void setQuality(Quality q); 122 Quality quality() const; 123 124 void resizeRenderer(const QSize& size); 125 void resizeRenderer(int width, int height); 126 QSize rendererSize() const; 127 int rendererWidth() const; 128 int rendererHeight() const; 129 //geometry size of current video frame. can not use frameSize because qwidget use it 130 QSize videoFrameSize() const; 131 132 /*! 133 * \brief orientation 134 * 0, 90, 180, 270. other values are ignored 135 * outAspectRatio() corresponds with orientation == 0. displayed aspect ratio may change if orientation is not 0 136 */ 137 int orientation() const; 138 void setOrientation(int value); 139 140 //The video frame rect in renderer you shoud paint to. e.g. in RendererAspectRatio mode, the rect equals to renderer's 141 QRect videoRect() const; 142 /* 143 * region of interest, ROI 144 * invalid rect means the whole source rect 145 * null rect is the whole available source rect. e.g. (0, 0, 0, 0) equals whole source rect 146 * (20, 30, 0, 0) equals (20, 30, sourceWidth - 20, sourceHeight - 30) 147 * if |x|<1, |y|<1, |width|<1, |height|<1 means the ratio of source rect(normalized value) 148 * |width| == 1 or |height| == 1 is a normalized value iff x or y is normalized 149 * call realROI() to get the frame rect actually to be render 150 * TODO: nagtive width or height means invert direction. is nagtive necessary? 151 */ 152 QRectF regionOfInterest() const; 153 // TODO: reset aspect ratio to roi.width/roi/heghit 154 void setRegionOfInterest(qreal x, qreal y, qreal width, qreal height); 155 void setRegionOfInterest(const QRectF& roi); 156 // compute the real ROI 157 QRect realROI() const; 158 // |w| <= 1, |x| < 1 159 QRectF normalizedROI() const; 160 161 // TODO: map normalized 162 /*! 163 * \brief mapToFrame 164 * map point in VideoRenderer coordinate to VideoFrame, with current ROI 165 */ 166 QPointF mapToFrame(const QPointF& p) const; 167 /*! 168 * \brief mapFromFrame 169 * map point in VideoFrame coordinate to VideoRenderer, with current ROI 170 */ 171 QPointF mapFromFrame(const QPointF& p) const; 172 // to avoid conflicting width QWidget::window() qwindow()173 virtual QWindow* qwindow() { return 0;} 174 /*! 175 * \brief widget 176 * \return default is 0. A QWidget subclass can return \a this 177 */ widget()178 virtual QWidget* widget() { return 0; } 179 /*! 180 * \brief graphicsItem 181 * \return default is 0. A QGraphicsItem subclass can return \a this 182 */ graphicsItem()183 virtual QGraphicsItem* graphicsItem() { return 0; } 184 /*! 185 * \brief brightness, contrast, hue, saturation 186 * values range between -1.0 and 1.0, the default is 0. 187 * value is not changed if does not implementd and onChangingXXX() returns false. 188 * video widget/item will update after if onChangingXXX/setXXX returns true 189 * \return \a false if failed to set (may be onChangingXXX not implemented or return false) 190 */ 191 qreal brightness() const; 192 bool setBrightness(qreal brightness); 193 qreal contrast() const; 194 bool setContrast(qreal contrast); 195 qreal hue() const; 196 bool setHue(qreal hue); 197 qreal saturation() const; 198 bool setSaturation(qreal saturation); 199 QColor backgroundColor() const; 200 void setBackgroundColor(const QColor& c); 201 202 /*! 203 * \brief opengl 204 * Currently you can only use it to set custom shader OpenGLVideo.setUserShader() 205 */ opengl()206 virtual OpenGLVideo* opengl() const { return NULL;} 207 protected: 208 VideoRenderer(VideoRendererPrivate &d); 209 //TODO: batch drawBackground(color, region)=>loop drawBackground(color,rect) 210 virtual bool receiveFrame(const VideoFrame& frame) = 0; 211 QRegion backgroundRegion() const; 212 virtual void drawBackground(); 213 //draw the current frame using the current paint engine. called by paintEvent() 214 // TODO: parameter VideoFrame 215 virtual void drawFrame() = 0; //You MUST reimplement this to display a frame. Other draw functions are not essential 216 virtual void handlePaintEvent(); //has default. User don't have to implement it 217 virtual void updateUi(); // by default post an UpdateRequest event for window and UpdateLater event for widget to ensure ui update 218 219 private: // property change. used as signals in subclasses. implemented by moc sourceAspectRatioChanged(qreal)220 virtual void sourceAspectRatioChanged(qreal) {} outAspectRatioChanged()221 virtual void outAspectRatioChanged() {} outAspectRatioModeChanged()222 virtual void outAspectRatioModeChanged() {} orientationChanged()223 virtual void orientationChanged() {} videoRectChanged()224 virtual void videoRectChanged() {} contentRectChanged()225 virtual void contentRectChanged() {} regionOfInterestChanged()226 virtual void regionOfInterestChanged() {} videoFrameSizeChanged()227 virtual void videoFrameSizeChanged() {} rendererSizeChanged()228 virtual void rendererSizeChanged() {} brightnessChanged(qreal)229 virtual void brightnessChanged(qreal) {} contrastChanged(qreal)230 virtual void contrastChanged(qreal) {} hueChanged(qreal)231 virtual void hueChanged(qreal) {} saturationChanged(qreal)232 virtual void saturationChanged(qreal) {} backgroundColorChanged()233 virtual void backgroundColorChanged() {} 234 private: // mainly used by VideoOutput class 235 /*! 236 * return false if value not changed. default is true 237 */ 238 virtual bool onSetPreferredPixelFormat(VideoFormat::PixelFormat pixfmt); 239 virtual bool onForcePreferredPixelFormat(bool force = true); 240 virtual void onSetOutAspectRatioMode(OutAspectRatioMode mode); 241 virtual void onSetOutAspectRatio(qreal ratio); 242 virtual bool onSetQuality(Quality q); 243 virtual void onResizeRenderer(int width, int height); 244 virtual bool onSetOrientation(int value); 245 virtual bool onSetRegionOfInterest(const QRectF& roi); 246 virtual QPointF onMapToFrame(const QPointF& p) const; 247 virtual QPointF onMapFromFrame(const QPointF& p) const; 248 /*! 249 * \brief onSetXX 250 * It's called when user call setXXX() with a new value. You should implement how to actually change the value, e.g. change brightness with shader. 251 * \return 252 * false: It's default. means not implemented. \a brightness() does not change. 253 * true: Implement this and return true. \a brightness() will change to new value 254 */ 255 virtual bool onSetBrightness(qreal brightness); 256 virtual bool onSetContrast(qreal contrast); 257 virtual bool onSetHue(qreal hue); 258 virtual bool onSetSaturation(qreal saturation); 259 virtual void onSetBackgroundColor(const QColor& color); 260 private: 261 template<class C> create()262 static VideoRenderer* create() { 263 return new C(); 264 } 265 typedef VideoRenderer* (*VideoRendererCreator)(); 266 static bool Register(VideoRendererId id, VideoRendererCreator, const char *name); 267 friend class VideoOutput; 268 //the size of decoded frame. get called in receiveFrame(). internal use only 269 void setInSize(const QSize& s); 270 void setInSize(int width, int height); 271 }; 272 273 } //namespace QtAV 274 #endif // QAV_VIDEORENDERER_H 275