Files
fmviewer3/project/fm_viewer/fav/VideoRenderer.h
2026-02-21 17:11:31 +09:00

277 lines
11 KiB
C++

/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
* This file is part of QtAV
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
#ifndef QAV_VIDEORENDERER_H
#define QAV_VIDEORENDERER_H
#include <QtCore/QByteArray>
#include <QtCore/QSize>
#include <QtCore/QRectF>
#include <QtGui/QColor>
#include "AVOutput.h"
#include "VideoFrame.h"
/*!
* A bridge for VideoOutput(QObject based) and video renderer backend classes
* Every public setter call it's virtual onSetXXX(...) which has default behavior.
* While VideoOutput.onSetXXX(...) simply calls backend's setXXX(...) and return whether the result is desired.
*/
QT_BEGIN_NAMESPACE
class QWidget;
class QWindow;
class QGraphicsItem;
QT_END_NAMESPACE
namespace FAV {
typedef int VideoRendererId;
extern Q_AV_EXPORT VideoRendererId VideoRendererId_OpenGLWindow;
class Filter;
class OpenGLVideo;
class VideoFormat;
class VideoRendererPrivate;
class Q_AV_EXPORT VideoRenderer : public AVOutput
{
DPTR_DECLARE_PRIVATE(VideoRenderer)
public:
//TODO: original video size mode
// fillmode: keepsize
enum OutAspectRatioMode {
RendererAspectRatio //Use renderer's aspect ratio, i.e. stretch to fit the renderer rect
, VideoAspectRatio //Use video's aspect ratio and align center in renderer.
, CustomAspectRation //Use the ratio set by setOutAspectRatio(qreal). Mode will be set to this if that function is called
//, AspectRatio4_3, AspectRatio16_9
};
enum Quality { //TODO: deprecated. simpily use int 0~100
QualityDefault, //good
QualityBest,
QualityFastest
};
template<class C>
static bool Register(VideoRendererId id, const char* name) { return Register(id, create<C>, name);}
static VideoRenderer* create(VideoRendererId id);
static VideoRenderer* create(const char* name);
/*!
* \brief next
* \param id NULL to get the first id address
* \return address of id or NULL if not found/end
*/
static VideoRendererId* next(VideoRendererId* id = 0);
static const char* name(VideoRendererId id);
static VideoRendererId id(const char* name);
VideoRenderer();
virtual ~VideoRenderer();
virtual VideoRendererId id() const = 0;
bool receive(const VideoFrame& frame);
/*!
* \brief setPreferredPixelFormat
* \param pixfmt
* pixfmt will be used if decoded format is not supported by this renderer. otherwise, use decoded format.
* return false if \a pixfmt is not supported and not changed.
*/
bool setPreferredPixelFormat(VideoFormat::PixelFormat pixfmt);
/*!
* \brief preferredPixelFormat
* \return preferred pixel format. e.g. WidgetRenderer is rgb formats.
*/
virtual VideoFormat::PixelFormat preferredPixelFormat() const; //virtual?
/*!
* \brief forcePreferredPixelFormat
* force to use preferredPixelFormat() even if incoming format is supported
* \param force
*/
void forcePreferredPixelFormat(bool force = true);
bool isPreferredPixelFormatForced() const;
virtual bool isSupported(VideoFormat::PixelFormat pixfmt) const = 0;
/*!
* \brief sourceAspectRatio
* The display aspect ratio of received video frame. 0 for an invalid frame.
* sourceAspectRatioChanged() (a signal for QObject renderers) will be called if the new frame has a different DAR.
*/
qreal sourceAspectRatio() const;
void setSourceAspectRatio(qreal r);
void setOutAspectRatioMode(OutAspectRatioMode mode);
OutAspectRatioMode outAspectRatioMode() const;
//If setOutAspectRatio(qreal) is used, then OutAspectRatioMode is CustomAspectRation
void setOutAspectRatio(qreal ratio);
qreal outAspectRatio() const;//
void setQuality(Quality q);
Quality quality() const;
void resizeRenderer(const QSize& size);
void resizeRenderer(int width, int height);
QSize rendererSize() const;
int rendererWidth() const;
int rendererHeight() const;
//geometry size of current video frame. can not use frameSize because qwidget use it
QSize videoFrameSize() const;
/*!
* \brief orientation
* 0, 90, 180, 270. other values are ignored
* outAspectRatio() corresponds with orientation == 0. displayed aspect ratio may change if orientation is not 0
*/
int orientation() const;
void setOrientation(int value);
//The video frame rect in renderer you shoud paint to. e.g. in RendererAspectRatio mode, the rect equals to renderer's
QRect videoRect() const;
/*
* region of interest, ROI
* invalid rect means the whole source rect
* null rect is the whole available source rect. e.g. (0, 0, 0, 0) equals whole source rect
* (20, 30, 0, 0) equals (20, 30, sourceWidth - 20, sourceHeight - 30)
* if |x|<1, |y|<1, |width|<1, |height|<1 means the ratio of source rect(normalized value)
* |width| == 1 or |height| == 1 is a normalized value iff x or y is normalized
* call realROI() to get the frame rect actually to be render
* TODO: nagtive width or height means invert direction. is nagtive necessary?
*/
QRectF regionOfInterest() const;
// TODO: reset aspect ratio to roi.width/roi/heghit
void setRegionOfInterest(qreal x, qreal y, qreal width, qreal height);
void setRegionOfInterest(const QRectF& roi);
// compute the real ROI
QRect realROI() const;
// |w| <= 1, |x| < 1
QRectF normalizedROI() const;
// TODO: map normalized
/*!
* \brief mapToFrame
* map point in VideoRenderer coordinate to VideoFrame, with current ROI
*/
QPointF mapToFrame(const QPointF& p) const;
/*!
* \brief mapFromFrame
* map point in VideoFrame coordinate to VideoRenderer, with current ROI
*/
QPointF mapFromFrame(const QPointF& p) const;
// to avoid conflicting width QWidget::window()
virtual QWindow* qwindow() { return 0;}
/*!
* \brief widget
* \return default is 0. A QWidget subclass can return \a this
*/
virtual QWidget* widget() { return 0; }
/*!
* \brief graphicsItem
* \return default is 0. A QGraphicsItem subclass can return \a this
*/
virtual QGraphicsItem* graphicsItem() { return 0; }
/*!
* \brief brightness, contrast, hue, saturation
* values range between -1.0 and 1.0, the default is 0.
* value is not changed if does not implementd and onChangingXXX() returns false.
* video widget/item will update after if onChangingXXX/setXXX returns true
* \return \a false if failed to set (may be onChangingXXX not implemented or return false)
*/
qreal brightness() const;
bool setBrightness(qreal brightness);
qreal contrast() const;
bool setContrast(qreal contrast);
qreal hue() const;
bool setHue(qreal hue);
qreal saturation() const;
bool setSaturation(qreal saturation);
QColor backgroundColor() const;
void setBackgroundColor(const QColor& c);
/*!
* \brief opengl
* Currently you can only use it to set custom shader OpenGLVideo.setUserShader()
*/
virtual OpenGLVideo* opengl() const { return NULL;}
protected:
VideoRenderer(VideoRendererPrivate &d);
//TODO: batch drawBackground(color, region)=>loop drawBackground(color,rect)
virtual bool receiveFrame(const VideoFrame& frame) = 0;
QRegion backgroundRegion() const;
virtual void drawBackground();
//draw the current frame using the current paint engine. called by paintEvent()
// TODO: parameter VideoFrame
virtual void drawFrame() = 0; //You MUST reimplement this to display a frame. Other draw functions are not essential
virtual void handlePaintEvent(); //has default. User don't have to implement it
virtual void updateUi(); // by default post an UpdateRequest event for window and UpdateLater event for widget to ensure ui update
private: // property change. used as signals in subclasses. implemented by moc
virtual void sourceAspectRatioChanged(qreal) {}
virtual void outAspectRatioChanged() {}
virtual void outAspectRatioModeChanged() {}
virtual void orientationChanged() {}
virtual void videoRectChanged() {}
virtual void contentRectChanged() {}
virtual void regionOfInterestChanged() {}
virtual void videoFrameSizeChanged() {}
virtual void rendererSizeChanged() {}
virtual void brightnessChanged(qreal) {}
virtual void contrastChanged(qreal) {}
virtual void hueChanged(qreal) {}
virtual void saturationChanged(qreal) {}
virtual void backgroundColorChanged() {}
private: // mainly used by VideoOutput class
/*!
* return false if value not changed. default is true
*/
virtual bool onSetPreferredPixelFormat(VideoFormat::PixelFormat pixfmt);
virtual bool onForcePreferredPixelFormat(bool force = true);
virtual void onSetOutAspectRatioMode(OutAspectRatioMode mode);
virtual void onSetOutAspectRatio(qreal ratio);
virtual bool onSetQuality(Quality q);
virtual void onResizeRenderer(int width, int height);
virtual bool onSetOrientation(int value);
virtual bool onSetRegionOfInterest(const QRectF& roi);
virtual QPointF onMapToFrame(const QPointF& p) const;
virtual QPointF onMapFromFrame(const QPointF& p) const;
/*!
* \brief onSetXX
* 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.
* \return
* false: It's default. means not implemented. \a brightness() does not change.
* true: Implement this and return true. \a brightness() will change to new value
*/
virtual bool onSetBrightness(qreal brightness);
virtual bool onSetContrast(qreal contrast);
virtual bool onSetHue(qreal hue);
virtual bool onSetSaturation(qreal saturation);
virtual void onSetBackgroundColor(const QColor& color);
private:
template<class C>
static VideoRenderer* create() {
return new C();
}
typedef VideoRenderer* (*VideoRendererCreator)();
static bool Register(VideoRendererId id, VideoRendererCreator, const char *name);
friend class VideoOutput;
//the size of decoded frame. get called in receiveFrame(). internal use only
void setInSize(const QSize& s);
void setInSize(int width, int height);
};
} //namespace FAV
#endif // QAV_VIDEORENDERER_H