Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
1d5c87d7
Unverified
Commit
1d5c87d7
authored
Feb 05, 2020
by
Gus Grubba
Committed by
GitHub
Feb 05, 2020
Browse files
Merge pull request #8266 from andrewvoznytsa/PR-qmlglsink-v2
Switch from builtin video sink to qmlglsink (v2)
parents
e36a8fbc
0f5be407
Changes
62
Hide whitespace changes
Inline
Side-by-side
src/VideoStreaming/VideoSurface.cc
deleted
100644 → 0
View file @
e36a8fbc
/****************************************************************************
*
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/**
* @file
* @brief QGC Video Surface
* @author Gus Grubba <gus@auterion.com>
*/
#if defined(QGC_GST_STREAMING)
#include
"VideoSurface_p.h"
#endif
#include
"VideoSurface.h"
#include
<QtCore/QDebug>
#include
<QtQuick/QQuickItem>
VideoSurface
::
VideoSurface
(
QObject
*
parent
)
:
QObject
(
parent
)
#if defined(QGC_GST_STREAMING)
,
_data
(
new
VideoSurfacePrivate
)
,
_lastFrame
(
0
)
,
_refed
(
false
)
#endif
{
}
VideoSurface
::~
VideoSurface
()
{
#if defined(QGC_GST_STREAMING)
if
(
!
_refed
&&
_data
->
videoSink
!=
nullptr
)
{
gst_element_set_state
(
_data
->
videoSink
,
GST_STATE_NULL
);
}
delete
_data
;
#endif
}
#if defined(QGC_GST_STREAMING)
GstElement
*
VideoSurface
::
videoSink
()
{
if
(
_data
->
videoSink
==
nullptr
)
{
if
((
_data
->
videoSink
=
gst_element_factory_make
(
"qtquick2videosink"
,
nullptr
))
==
nullptr
)
{
qCritical
(
"Failed to create qtquick2videosink. Make sure it is installed correctly"
);
return
nullptr
;
}
g_object_set
(
G_OBJECT
(
_data
->
videoSink
),
"sync"
,
gboolean
(
false
),
nullptr
);
g_signal_connect
(
_data
->
videoSink
,
"update"
,
G_CALLBACK
(
onUpdateThunk
),
(
void
*
)
this
);
_refed
=
true
;
}
return
_data
->
videoSink
;
}
void
VideoSurface
::
onUpdate
()
{
_lastFrame
=
time
(
nullptr
);
Q_FOREACH
(
QQuickItem
*
item
,
_data
->
items
)
{
item
->
update
();
}
}
void
VideoSurface
::
onUpdateThunk
(
GstElement
*
sink
,
gpointer
data
)
{
Q_UNUSED
(
sink
);
VideoSurface
*
pThis
=
(
VideoSurface
*
)
data
;
pThis
->
onUpdate
();
}
#endif
src/VideoStreaming/VideoSurface.h
deleted
100644 → 0
View file @
e36a8fbc
/****************************************************************************
*
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/**
* @file
* @brief QGC Video Surface
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
<QtCore/QObject>
#if defined(QGC_GST_STREAMING)
#include
<gst/gst.h>
#endif
#if defined(QGC_GST_STREAMING)
class
VideoSurfacePrivate
;
#endif
class
VideoSurface
:
public
QObject
{
Q_OBJECT
Q_DISABLE_COPY
(
VideoSurface
)
public:
explicit
VideoSurface
(
QObject
*
parent
=
0
);
virtual
~
VideoSurface
();
/*! Returns the video sink element that provides this surface's image.
* The element will be constructed the first time that this function
* is called. The surface will always keep a reference to this element.
*/
#if defined(QGC_GST_STREAMING)
GstElement
*
videoSink
();
time_t
lastFrame
()
{
return
_lastFrame
;
}
void
setLastFrame
(
time_t
t
)
{
_lastFrame
=
t
;
}
#endif
protected:
#if defined(QGC_GST_STREAMING)
void
onUpdate
();
static
void
onUpdateThunk
(
GstElement
*
sink
,
gpointer
data
);
#endif
private:
friend
class
VideoItem
;
#if defined(QGC_GST_STREAMING)
VideoSurfacePrivate
*
const
_data
;
time_t
_lastFrame
;
bool
_refed
;
#endif
};
Q_DECLARE_METATYPE
(
VideoSurface
*
)
src/VideoStreaming/VideoSurface_p.h
deleted
100644 → 0
View file @
e36a8fbc
/****************************************************************************
*
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/**
* @file
* @brief QGC Video Surface (Private Interface)
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
"VideoSurface.h"
#include
"VideoItem.h"
class
VideoSurfacePrivate
{
public:
VideoSurfacePrivate
()
:
videoSink
(
nullptr
)
{
}
QSet
<
VideoItem
*>
items
;
GstElement
*
videoSink
;
};
src/VideoStreaming/gstqtvideosink/delegates/basedelegate.cpp
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#include
"basedelegate.h"
#include
<QCoreApplication>
BaseDelegate
::
BaseDelegate
(
GstElement
*
sink
,
QObject
*
parent
)
:
QObject
(
parent
)
,
m_colorsDirty
(
true
)
,
m_brightness
(
0
)
,
m_contrast
(
0
)
,
m_hue
(
0
)
,
m_saturation
(
0
)
,
m_pixelAspectRatio
(
1
,
1
)
,
m_forceAspectRatioDirty
(
true
)
,
m_forceAspectRatio
(
false
)
,
m_formatDirty
(
true
)
,
m_isActive
(
false
)
,
m_buffer
(
nullptr
)
,
m_sink
(
sink
)
{
}
BaseDelegate
::~
BaseDelegate
()
{
Q_ASSERT
(
!
isActive
());
}
//-------------------------------------
bool
BaseDelegate
::
isActive
()
const
{
QReadLocker
l
(
&
m_isActiveLock
);
return
m_isActive
;
}
void
BaseDelegate
::
setActive
(
bool
active
)
{
GST_INFO_OBJECT
(
m_sink
,
active
?
"Activating"
:
"Deactivating"
);
QWriteLocker
l
(
&
m_isActiveLock
);
m_isActive
=
active
;
if
(
!
active
)
{
QCoreApplication
::
postEvent
(
this
,
new
DeactivateEvent
());
}
}
//-------------------------------------
int
BaseDelegate
::
brightness
()
const
{
QReadLocker
l
(
&
m_colorsLock
);
return
m_brightness
;
}
void
BaseDelegate
::
setBrightness
(
int
brightness
)
{
QWriteLocker
l
(
&
m_colorsLock
);
m_brightness
=
qBound
(
-
100
,
brightness
,
100
);
m_colorsDirty
=
true
;
}
int
BaseDelegate
::
contrast
()
const
{
QReadLocker
l
(
&
m_colorsLock
);
return
m_contrast
;
}
void
BaseDelegate
::
setContrast
(
int
contrast
)
{
QWriteLocker
l
(
&
m_colorsLock
);
m_contrast
=
qBound
(
-
100
,
contrast
,
100
);
m_colorsDirty
=
true
;
}
int
BaseDelegate
::
hue
()
const
{
QReadLocker
l
(
&
m_colorsLock
);
return
m_hue
;
}
void
BaseDelegate
::
setHue
(
int
hue
)
{
QWriteLocker
l
(
&
m_colorsLock
);
m_hue
=
qBound
(
-
100
,
hue
,
100
);
m_colorsDirty
=
true
;
}
int
BaseDelegate
::
saturation
()
const
{
QReadLocker
l
(
&
m_colorsLock
);
return
m_saturation
;
}
void
BaseDelegate
::
setSaturation
(
int
saturation
)
{
QWriteLocker
l
(
&
m_colorsLock
);
m_saturation
=
qBound
(
-
100
,
saturation
,
100
);
m_colorsDirty
=
true
;
}
//-------------------------------------
Fraction
BaseDelegate
::
pixelAspectRatio
()
const
{
QReadLocker
l
(
&
m_pixelAspectRatioLock
);
return
m_pixelAspectRatio
;
}
void
BaseDelegate
::
setPixelAspectRatio
(
const
Fraction
&
f
)
{
QWriteLocker
l
(
&
m_pixelAspectRatioLock
);
m_pixelAspectRatio
=
f
;
}
//-------------------------------------
bool
BaseDelegate
::
forceAspectRatio
()
const
{
QReadLocker
l
(
&
m_forceAspectRatioLock
);
return
m_forceAspectRatio
;
}
void
BaseDelegate
::
setForceAspectRatio
(
bool
force
)
{
QWriteLocker
l
(
&
m_forceAspectRatioLock
);
if
(
m_forceAspectRatio
!=
force
)
{
m_forceAspectRatio
=
force
;
m_forceAspectRatioDirty
=
true
;
}
}
//-------------------------------------
bool
BaseDelegate
::
event
(
QEvent
*
event
)
{
switch
((
int
)
event
->
type
())
{
case
BufferEventType
:
{
BufferEvent
*
bufEvent
=
dynamic_cast
<
BufferEvent
*>
(
event
);
Q_ASSERT
(
bufEvent
);
GST_TRACE_OBJECT
(
m_sink
,
"Received buffer %"
GST_PTR_FORMAT
,
bufEvent
->
buffer
);
if
(
isActive
())
{
gst_buffer_replace
(
&
m_buffer
,
bufEvent
->
buffer
);
update
();
}
return
true
;
}
case
BufferFormatEventType
:
{
BufferFormatEvent
*
bufFmtEvent
=
dynamic_cast
<
BufferFormatEvent
*>
(
event
);
Q_ASSERT
(
bufFmtEvent
);
GST_TRACE_OBJECT
(
m_sink
,
"Received buffer format event. New format: %s"
,
gst_video_format_to_string
(
bufFmtEvent
->
format
.
videoFormat
()));
m_formatDirty
=
true
;
m_bufferFormat
=
bufFmtEvent
->
format
;
return
true
;
}
case
DeactivateEventType
:
{
GST_LOG_OBJECT
(
m_sink
,
"Received deactivate event"
);
gst_buffer_replace
(
&
m_buffer
,
nullptr
);
update
();
return
true
;
}
default:
return
QObject
::
event
(
event
);
}
}
void
BaseDelegate
::
update
()
{
g_signal_emit_by_name
(
m_sink
,
"update"
);
}
src/VideoStreaming/gstqtvideosink/delegates/basedelegate.h
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
<gst/gst.h>
#include
"../gstqtvideosinkplugin.h"
//for debug category
#include
"../utils/bufferformat.h"
#include
"../utils/utils.h"
#include
<QObject>
#include
<QEvent>
#include
<QReadWriteLock>
class
BaseDelegate
:
public
QObject
{
Q_OBJECT
public:
enum
EventType
{
BufferEventType
=
QEvent
::
User
,
BufferFormatEventType
,
DeactivateEventType
};
//-------------------------------------
class
BufferEvent
:
public
QEvent
{
public:
inline
BufferEvent
(
GstBuffer
*
buf
)
:
QEvent
(
static_cast
<
QEvent
::
Type
>
(
BufferEventType
)),
buffer
(
gst_buffer_ref
(
buf
))
{}
virtual
~
BufferEvent
()
{
gst_buffer_unref
(
buffer
);
}
GstBuffer
*
buffer
;
};
class
BufferFormatEvent
:
public
QEvent
{
public:
inline
BufferFormatEvent
(
const
BufferFormat
&
format
)
:
QEvent
(
static_cast
<
QEvent
::
Type
>
(
BufferFormatEventType
)),
format
(
format
)
{}
BufferFormat
format
;
};
class
DeactivateEvent
:
public
QEvent
{
public:
inline
DeactivateEvent
()
:
QEvent
(
static_cast
<
QEvent
::
Type
>
(
DeactivateEventType
))
{
}
};
//-------------------------------------
explicit
BaseDelegate
(
GstElement
*
sink
,
QObject
*
parent
=
0
);
virtual
~
BaseDelegate
();
bool
isActive
()
const
;
void
setActive
(
bool
playing
);
// GstColorBalance interface
int
brightness
()
const
;
void
setBrightness
(
int
brightness
);
int
contrast
()
const
;
void
setContrast
(
int
contrast
);
int
hue
()
const
;
void
setHue
(
int
hue
);
int
saturation
()
const
;
void
setSaturation
(
int
saturation
);
// pixel-aspect-ratio property
Fraction
pixelAspectRatio
()
const
;
void
setPixelAspectRatio
(
const
Fraction
&
f
);
// force-aspect-ratio property
bool
forceAspectRatio
()
const
;
void
setForceAspectRatio
(
bool
force
);
protected:
// internal event handling
virtual
bool
event
(
QEvent
*
event
);
// tells the surface to repaint itself
virtual
void
update
();
protected:
// colorbalance interface properties
mutable
QReadWriteLock
m_colorsLock
;
bool
m_colorsDirty
;
int
m_brightness
;
int
m_contrast
;
int
m_hue
;
int
m_saturation
;
// pixel-aspect-ratio property
mutable
QReadWriteLock
m_pixelAspectRatioLock
;
Fraction
m_pixelAspectRatio
;
// force-aspect-ratio property
mutable
QReadWriteLock
m_forceAspectRatioLock
;
bool
m_forceAspectRatioDirty
;
bool
m_forceAspectRatio
;
// format caching
bool
m_formatDirty
;
BufferFormat
m_bufferFormat
;
PaintAreas
m_areas
;
// whether the sink is active (PAUSED or PLAYING)
mutable
QReadWriteLock
m_isActiveLock
;
bool
m_isActive
;
// the buffer to be drawn next
GstBuffer
*
m_buffer
;
// the video sink element
GstElement
*
const
m_sink
;
};
src/VideoStreaming/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#include
"qtquick2videosinkdelegate.h"
#include
"../painters/videonode.h"
QtQuick2VideoSinkDelegate
::
QtQuick2VideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
)
:
BaseDelegate
(
sink
,
parent
)
{
}
QSGNode
*
QtQuick2VideoSinkDelegate
::
updateNode
(
QSGNode
*
node
,
const
QRectF
&
targetArea
)
{
GST_TRACE_OBJECT
(
m_sink
,
"updateNode called"
);
bool
sgnodeFormatChanged
=
false
;
VideoNode
*
vnode
=
dynamic_cast
<
VideoNode
*>
(
node
);
if
(
!
vnode
)
{
GST_INFO_OBJECT
(
m_sink
,
"creating new VideoNode"
);
vnode
=
new
VideoNode
;
}
if
(
!
m_buffer
)
{
if
(
vnode
->
materialType
()
!=
VideoNode
::
MaterialTypeSolidBlack
)
{
vnode
->
setMaterialTypeSolidBlack
();
sgnodeFormatChanged
=
true
;
}
if
(
sgnodeFormatChanged
||
targetArea
!=
m_areas
.
targetArea
)
{
m_areas
.
targetArea
=
targetArea
;
vnode
->
updateGeometry
(
m_areas
);
}
}
else
{
//change format before geometry, so that we change QSGGeometry as well
if
(
m_formatDirty
)
{
vnode
->
changeFormat
(
m_bufferFormat
);
sgnodeFormatChanged
=
true
;
}
//recalculate the video area if needed
QReadLocker
forceAspectRatioLocker
(
&
m_forceAspectRatioLock
);
if
(
sgnodeFormatChanged
||
targetArea
!=
m_areas
.
targetArea
||
m_forceAspectRatioDirty
)
{
m_forceAspectRatioDirty
=
false
;
QReadLocker
pixelAspectRatioLocker
(
&
m_pixelAspectRatioLock
);
Qt
::
AspectRatioMode
aspectRatioMode
=
m_forceAspectRatio
?
Qt
::
KeepAspectRatio
:
Qt
::
IgnoreAspectRatio
;
m_areas
.
calculate
(
targetArea
,
m_bufferFormat
.
frameSize
(),
m_bufferFormat
.
pixelAspectRatio
(),
m_pixelAspectRatio
,
aspectRatioMode
);
pixelAspectRatioLocker
.
unlock
();
GST_LOG_OBJECT
(
m_sink
,
"Recalculated paint areas: "
"Frame size: "
QSIZE_FORMAT
", "
"target area: "
QRECTF_FORMAT
", "
"video area: "
QRECTF_FORMAT
", "
"black1: "
QRECTF_FORMAT
", "
"black2: "
QRECTF_FORMAT
,
QSIZE_FORMAT_ARGS
(
m_bufferFormat
.
frameSize
()),
QRECTF_FORMAT_ARGS
(
m_areas
.
targetArea
),
QRECTF_FORMAT_ARGS
(
m_areas
.
videoArea
),
QRECTF_FORMAT_ARGS
(
m_areas
.
blackArea1
),
QRECTF_FORMAT_ARGS
(
m_areas
.
blackArea2
)
);
vnode
->
updateGeometry
(
m_areas
);
}
forceAspectRatioLocker
.
unlock
();
if
(
m_formatDirty
)
{
m_formatDirty
=
false
;
//make sure to update the colors after changing material
m_colorsDirty
=
true
;
}
QReadLocker
colorsLocker
(
&
m_colorsLock
);
if
(
m_colorsDirty
)
{
vnode
->
updateColors
(
m_brightness
,
m_contrast
,
m_hue
,
m_saturation
);
m_colorsDirty
=
false
;
}
colorsLocker
.
unlock
();
vnode
->
setCurrentFrame
(
m_buffer
);
}
return
vnode
;
}
src/VideoStreaming/gstqtvideosink/delegates/qtquick2videosinkdelegate.h
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
"basedelegate.h"
#include
<QtQuick/QSGNode>
class
QtQuick2VideoSinkDelegate
:
public
BaseDelegate
{
Q_OBJECT
public:
explicit
QtQuick2VideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
=
0
);
QSGNode
*
updateNode
(
QSGNode
*
node
,
const
QRectF
&
targetArea
);
};
src/VideoStreaming/gstqtvideosink/delegates/qtvideosinkdelegate.cpp
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#include
"qtvideosinkdelegate.h"
#include
"../painters/genericsurfacepainter.h"
#include
"../painters/openglsurfacepainter.h"
#include
<QStack>
#include
<QPainter>
#include
"glutils.h"
QtVideoSinkDelegate
::
QtVideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
)
:
BaseDelegate
(
sink
,
parent
)
,
m_painter
(
0
)
,
m_supportedPainters
(
Generic
)
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
,
m_glContext
(
0
)
#endif
{
}
QtVideoSinkDelegate
::~
QtVideoSinkDelegate
()
{
destroyPainter
();
}
void
QtVideoSinkDelegate
::
paint
(
QPainter
*
painter
,
const
QRectF
&
targetArea
)
{
GST_TRACE_OBJECT
(
m_sink
,
"paint called"
);
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
if
(
m_glContext
)
{
Q_ASSERT_X
(
m_glContext
==
QGLContext
::
currentContext
(),
"qtvideosink - paint"
,
"Please use a QPainter that is initialized to paint on the "
"GL surface that has the same context as the one given on the glcontext property"
);
}
#endif
if
(
!
m_buffer
)
{
painter
->
fillRect
(
targetArea
,
Qt
::
black
);
}
else
{
//recalculate the video area if needed
QReadLocker
forceAspectRatioLocker
(
&
m_forceAspectRatioLock
);
if
(
targetArea
!=
m_areas
.
targetArea
||
m_formatDirty
||
m_forceAspectRatioDirty
)
{
m_forceAspectRatioDirty
=
false
;
QReadLocker
pixelAspectRatioLocker
(
&
m_pixelAspectRatioLock
);
Qt
::
AspectRatioMode
aspectRatioMode
=
m_forceAspectRatio
?
Qt
::
KeepAspectRatio
:
Qt
::
IgnoreAspectRatio
;
m_areas
.
calculate
(
targetArea
,
m_bufferFormat
.
frameSize
(),
m_bufferFormat
.
pixelAspectRatio
(),
m_pixelAspectRatio
,
aspectRatioMode
);
pixelAspectRatioLocker
.
unlock
();
GST_LOG_OBJECT
(
m_sink
,
"Recalculated paint areas: "
"Frame size: "
QSIZE_FORMAT
", "
"target area: "
QRECTF_FORMAT
", "
"video area: "
QRECTF_FORMAT
", "
"black1: "
QRECTF_FORMAT
", "
"black2: "
QRECTF_FORMAT
,
QSIZE_FORMAT_ARGS
(
m_bufferFormat
.
frameSize
()),
QRECTF_FORMAT_ARGS
(
m_areas
.
targetArea
),
QRECTF_FORMAT_ARGS
(
m_areas
.
videoArea
),
QRECTF_FORMAT_ARGS
(
m_areas
.
blackArea1
),
QRECTF_FORMAT_ARGS
(
m_areas
.
blackArea2
)
);
}
forceAspectRatioLocker
.
unlock
();
//if either pixelFormat or frameSize have changed, we need to reset the painter
//and/or change painter, in case the current one does not handle the requested format
if
((
m_formatDirty
)
||
!
m_painter
)
{
changePainter
(
m_bufferFormat
);
m_formatDirty
=
false
;
//make sure to update the colors after changing painter
m_colorsDirty
=
true
;
}
if
(
G_LIKELY
(
m_painter
))
{
QReadLocker
colorsLocker
(
&
m_colorsLock
);
if
(
m_colorsDirty
)
{
m_painter
->
updateColors
(
m_brightness
,
m_contrast
,
m_hue
,
m_saturation
);
m_colorsDirty
=
false
;
}
colorsLocker
.
unlock
();
GstMapInfo
mem_info
;
if
(
gst_buffer_map
(
m_buffer
,
&
mem_info
,
GST_MAP_READ
))
{
m_painter
->
paint
(
mem_info
.
data
,
m_bufferFormat
,
painter
,
m_areas
);
gst_buffer_unmap
(
m_buffer
,
&
mem_info
);
}
}
}
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
QGLContext
*
QtVideoSinkDelegate
::
glContext
()
const
{
return
m_glContext
;
}
void
QtVideoSinkDelegate
::
setGLContext
(
QGLContext
*
context
)
{
if
(
m_glContext
==
context
)
return
;
m_glContext
=
context
;
m_supportedPainters
=
Generic
;
if
(
m_glContext
)
{
m_glContext
->
makeCurrent
();
QOpenGLFunctionsDef
*
funcs
=
getQOpenGLFunctions
();
if
(
funcs
)
{
const
QByteArray
extensions
(
reinterpret_cast
<
const
char
*>
(
funcs
->
glGetString
(
GL_EXTENSIONS
)));
GST_LOG_OBJECT
(
m_sink
,
"Available GL extensions: %s"
,
extensions
.
constData
());
#ifndef QT_OPENGL_ES
if
(
extensions
.
contains
(
"ARB_fragment_program"
))
m_supportedPainters
|=
ArbFp
;
#endif
#ifndef QT_OPENGL_ES_2
if
(
QGLShaderProgram
::
hasOpenGLShaderPrograms
(
m_glContext
)
&&
extensions
.
contains
(
"ARB_shader_objects"
))
#endif
m_supportedPainters
|=
Glsl
;
}
}
GST_LOG_OBJECT
(
m_sink
,
"Done setting GL context. m_supportedPainters=%x"
,
(
int
)
m_supportedPainters
);
}
#endif
void
QtVideoSinkDelegate
::
changePainter
(
const
BufferFormat
&
format
)
{
if
(
m_painter
)
{
m_painter
->
cleanup
();
if
(
G_UNLIKELY
(
!
m_painter
->
supportsFormat
(
format
.
videoFormat
())))
{
destroyPainter
();
}
}
QStack
<
PainterType
>
possiblePainters
;
if
(
GenericSurfacePainter
::
supportedPixelFormats
().
contains
(
format
.
videoFormat
()))
{
possiblePainters
.
push
(
Generic
);
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
if
(
OpenGLSurfacePainter
::
supportedPixelFormats
().
contains
(
format
.
videoFormat
()))
{
if
(
m_supportedPainters
&
ArbFp
)
{
possiblePainters
.
push
(
ArbFp
);
}
if
(
m_supportedPainters
&
Glsl
)
{
possiblePainters
.
push
(
Glsl
);
}
}
#endif
while
(
!
possiblePainters
.
isEmpty
())
{
if
(
!
m_painter
)
{
PainterType
type
=
possiblePainters
.
pop
();
switch
(
type
)
{
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
case
Glsl
:
GST_LOG_OBJECT
(
m_sink
,
"Creating GLSL painter"
);
m_painter
=
new
GlslSurfacePainter
;
break
;
# ifndef QT_OPENGL_ES
case
ArbFp
:
GST_LOG_OBJECT
(
m_sink
,
"Creating ARB Fragment Shader painter"
);
m_painter
=
new
ArbFpSurfacePainter
;
break
;
# endif
#endif
case
Generic
:
GST_LOG_OBJECT
(
m_sink
,
"Creating Generic painter"
);
m_painter
=
new
GenericSurfacePainter
;
break
;
default:
Q_ASSERT
(
false
);
}
}
try
{
m_painter
->
init
(
format
);
return
;
}
catch
(
const
QString
&
error
)
{
GST_ELEMENT_WARNING
(
m_sink
,
RESOURCE
,
FAILED
,
(
"Failed to start painter"
),
(
"%s"
,
error
.
toUtf8
().
constData
()));
delete
m_painter
;
m_painter
=
0
;
}
}
GST_ELEMENT_ERROR
(
m_sink
,
RESOURCE
,
FAILED
,
(
"Failed to create a painter for the given format"
),
(
nullptr
));
}
void
QtVideoSinkDelegate
::
destroyPainter
()
{
GST_LOG_OBJECT
(
m_sink
,
"Destroying painter"
);
delete
m_painter
;
m_painter
=
0
;
}
bool
QtVideoSinkDelegate
::
event
(
QEvent
*
event
)
{
if
(
event
->
type
()
==
(
QEvent
::
Type
)
DeactivateEventType
)
{
if
(
m_painter
)
{
m_painter
->
cleanup
();
destroyPainter
();
}
}
return
BaseDelegate
::
event
(
event
);
}
src/VideoStreaming/gstqtvideosink/delegates/qtvideosinkdelegate.h
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
"basedelegate.h"
#include
"../painters/abstractsurfacepainter.h"
class
QGLContext
;
class
QtVideoSinkDelegate
:
public
BaseDelegate
{
Q_OBJECT
public:
enum
PainterType
{
Generic
=
0x00
,
ArbFp
=
0x01
,
Glsl
=
0x02
};
Q_DECLARE_FLAGS
(
PainterTypes
,
PainterType
);
explicit
QtVideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
=
0
);
virtual
~
QtVideoSinkDelegate
();
PainterTypes
supportedPainterTypes
()
const
{
return
m_supportedPainters
;
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
// glcontext property
QGLContext
*
glContext
()
const
;
void
setGLContext
(
QGLContext
*
context
);
#endif
// paint action
void
paint
(
QPainter
*
painter
,
const
QRectF
&
targetArea
);
protected:
// internal event handling
virtual
bool
event
(
QEvent
*
event
);
private:
void
changePainter
(
const
BufferFormat
&
format
);
void
destroyPainter
();
AbstractSurfacePainter
*
m_painter
;
PainterTypes
m_supportedPainters
;
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
QGLContext
*
m_glContext
;
#endif
};
Q_DECLARE_OPERATORS_FOR_FLAGS
(
QtVideoSinkDelegate
::
PainterTypes
)
src/VideoStreaming/gstqtvideosink/delegates/qwidgetvideosinkdelegate.cpp
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
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 program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#include
"qwidgetvideosinkdelegate.h"
#include
<QPainter>
QWidgetVideoSinkDelegate
::
QWidgetVideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
)
:
QtVideoSinkDelegate
(
sink
,
parent
)
{
}
QWidgetVideoSinkDelegate
::~
QWidgetVideoSinkDelegate
()
{
setWidget
(
nullptr
);
}
QWidget
*
QWidgetVideoSinkDelegate
::
widget
()
const
{
return
m_widget
.
data
();
}
void
QWidgetVideoSinkDelegate
::
setWidget
(
QWidget
*
widget
)
{
GST_LOG_OBJECT
(
m_sink
,
"Setting
\"
widget
\"
property to %"
GST_PTR_FORMAT
,
widget
);
if
(
m_widget
)
{
m_widget
.
data
()
->
removeEventFilter
(
this
);
m_widget
.
data
()
->
setAttribute
(
Qt
::
WA_OpaquePaintEvent
,
m_opaquePaintEventAttribute
);
m_widget
.
data
()
->
update
();
m_widget
=
nullptr
;
}
if
(
widget
)
{
widget
->
installEventFilter
(
this
);
m_opaquePaintEventAttribute
=
widget
->
testAttribute
(
Qt
::
WA_OpaquePaintEvent
);
widget
->
setAttribute
(
Qt
::
WA_OpaquePaintEvent
,
true
);
widget
->
update
();
m_widget
=
widget
;
}
}
bool
QWidgetVideoSinkDelegate
::
eventFilter
(
QObject
*
filteredObject
,
QEvent
*
event
)
{
if
(
filteredObject
==
m_widget
.
data
())
{
switch
(
event
->
type
())
{
case
QEvent
::
Paint
:
{
QPainter
painter
(
m_widget
.
data
());
paint
(
&
painter
,
m_widget
.
data
()
->
rect
());
return
true
;
}
default:
return
false
;
}
}
else
{
return
QtVideoSinkDelegate
::
eventFilter
(
filteredObject
,
event
);
}
}
void
QWidgetVideoSinkDelegate
::
update
()
{
if
(
m_widget
)
{
m_widget
.
data
()
->
update
();
}
}
src/VideoStreaming/gstqtvideosink/delegates/qwidgetvideosinkdelegate.h
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
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 program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
"qtvideosinkdelegate.h"
#include
<QEvent>
#include
<QPointer>
#include
<QWidget>
class
QWidgetVideoSinkDelegate
:
public
QtVideoSinkDelegate
{
Q_OBJECT
public:
explicit
QWidgetVideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
=
0
);
virtual
~
QWidgetVideoSinkDelegate
();
// "widget" property
QWidget
*
widget
()
const
;
void
setWidget
(
QWidget
*
widget
);
protected:
virtual
bool
eventFilter
(
QObject
*
filteredObject
,
QEvent
*
event
);
virtual
void
update
();
private:
// "widget" property
QPointer
<
QWidget
>
m_widget
;
// original value of the Qt::WA_OpaquePaintEvent attribute
bool
m_opaquePaintEventAttribute
;
};
src/VideoStreaming/gstqtvideosink/gstqtglvideosink.cpp
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
/*
* Note on the marshallers
*
* If it ever needs to be recreated, here is what you need to do:
*
* cat > marshaller.src
* VOID:POINTER,FLOAT,FLOAT,FLOAT,FLOAT
* VOID:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE
* POINTER:POINTER,FLOAT,FLOAT,FLOAT,FLOAT
* POINTER:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE
* Ctrl+D (EOF)
*
* glib-genmarshal --header marshaller.list > gstqtvideosinkmarshal.h
* glib-genmarshal --body marshaller.list > gstqtvideosinkmarshal.c
*
*/
#include
"gstqtglvideosink.h"
#include
"gstqtvideosinkmarshal.h"
#include
"delegates/qtvideosinkdelegate.h"
guint
GstQtGLVideoSink
::
s_signals
[];
DEFINE_TYPE
(
GstQtGLVideoSink
,
GST_TYPE_QT_GL_VIDEO_SINK_BASE
)
//------------------------------
void
GstQtGLVideoSink
::
emit_update
(
gpointer
sink
)
{
g_signal_emit
(
sink
,
GstQtGLVideoSink
::
s_signals
[
UPDATE_SIGNAL
],
0
,
NULL
);
}
//------------------------------
void
GstQtGLVideoSink
::
base_init
(
gpointer
g_class
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
gst_element_class_set_details_simple
(
element_class
,
"Qt GL video sink"
,
"Sink/Video"
,
"A video sink that can draw on any Qt GL surface"
,
"George Kiagiadakis <george.kiagiadakis@collabora.com>"
);
}
void
GstQtGLVideoSink
::
class_init
(
gpointer
g_class
,
gpointer
class_data
)
{
Q_UNUSED
(
class_data
);
GObjectClass
*
object_class
=
G_OBJECT_CLASS
(
g_class
);
object_class
->
set_property
=
GstQtGLVideoSink
::
set_property
;
GstQtGLVideoSinkClass
*
qt_video_sink_class
=
reinterpret_cast
<
GstQtGLVideoSinkClass
*>
(
g_class
);
qt_video_sink_class
->
paint
=
GstQtGLVideoSink
::
paint
;
/**
* GstQtGLVideoSink::paint
* @painter: A valid QPainter pointer that will be used to paint the video
* @x: The x coordinate of the target area rectangle
* @y: The y coordinate of the target area rectangle
* @width: The width of the target area rectangle
* @height: The height of the target area rectangle
*
* This is an action signal that you can call from your Qt surface class inside
* its paint function to render the video. It takes a QPainter* and the target
* area rectangle as arguments. You should schedule to call this function to
* repaint the surface whenever the ::update signal is emitted.
*
* Note that the x,y,width and height arguments are actually qreal. This means
* that on architectures like arm they will be float instead of double. You should
* cast the arguments to qreal if they are not already when emitting this signal.
*/
s_signals
[
PAINT_SIGNAL
]
=
g_signal_new
(
"paint"
,
G_TYPE_FROM_CLASS
(
g_class
),
static_cast
<
GSignalFlags
>
(
G_SIGNAL_RUN_LAST
|
G_SIGNAL_ACTION
),
G_STRUCT_OFFSET
(
GstQtGLVideoSinkClass
,
paint
),
nullptr
,
nullptr
,
qRealIsDouble
()
?
g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
:
g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
,
G_TYPE_NONE
,
5
,
G_TYPE_POINTER
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
);
/**
* GstQtGLVideoSink::update
*
* This signal is emitted when the surface should be repainted. It should
* be connected to QWidget::update() or QGraphicsItem::update() or any
* other similar function in your surface.
*/
s_signals
[
UPDATE_SIGNAL
]
=
g_signal_new
(
"update"
,
G_TYPE_FROM_CLASS
(
g_class
),
G_SIGNAL_RUN_LAST
,
0
,
nullptr
,
nullptr
,
g_cclosure_marshal_VOID__VOID
,
G_TYPE_NONE
,
0
);
/**
* GstQtGLVideoSink::glcontext
*
* This property holds a pointer to the QGLContext that will be used to render
* the video using OpenGL acceleration. You must set this to a valid QGLContext
* pointer before the element changes state to READY, or else the state change will fail.
**/
g_object_class_install_property
(
object_class
,
PROP_GLCONTEXT
,
g_param_spec_pointer
(
"glcontext"
,
"GL context"
,
"The QGLContext that will be used to do OpenGL-accelerated rendering"
,
static_cast
<
GParamFlags
>
(
G_PARAM_WRITABLE
)));
}
void
GstQtGLVideoSink
::
init
(
GTypeInstance
*
instance
,
gpointer
g_class
)
{
Q_UNUSED
(
g_class
);
GstQtVideoSinkBase
*
sinkBase
=
GST_QT_VIDEO_SINK_BASE
(
instance
);
sinkBase
->
delegate
=
new
QtVideoSinkDelegate
(
GST_ELEMENT
(
sinkBase
));
}
//------------------------------
void
GstQtGLVideoSink
::
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sinkBase
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_GLCONTEXT
:
sinkBase
->
delegate
->
setGLContext
(
static_cast
<
QGLContext
*>
(
g_value_get_pointer
(
value
)));
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
//------------------------------
void
GstQtGLVideoSink
::
paint
(
GstQtGLVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
)
{
GST_QT_VIDEO_SINK_BASE
(
sink
)
->
delegate
->
paint
(
static_cast
<
QPainter
*>
(
painter
),
QRectF
(
x
,
y
,
width
,
height
));
}
src/VideoStreaming/gstqtvideosink/gstqtglvideosink.h
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
"gstqtglvideosinkbase.h"
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
#define GST_TYPE_QT_GL_VIDEO_SINK \
(GstQtGLVideoSink::get_type())
struct
GstQtGLVideoSink
{
public:
GstQtGLVideoSinkBase
parent
;
static
GType
get_type
();
static
void
emit_update
(
gpointer
sink
);
private:
enum
{
PROP_0
,
PROP_GLCONTEXT
};
enum
{
PAINT_SIGNAL
,
UPDATE_SIGNAL
,
LAST_SIGNAL
};
static
void
base_init
(
gpointer
g_class
);
static
void
class_init
(
gpointer
g_class
,
gpointer
class_data
);
static
void
init
(
GTypeInstance
*
instance
,
gpointer
g_class
);
static
void
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
);
static
void
paint
(
GstQtGLVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
);
static
guint
s_signals
[
LAST_SIGNAL
];
};
struct
GstQtGLVideoSinkClass
{
GstQtGLVideoSinkBaseClass
parent_class
;
/* paint action signal */
void
(
*
paint
)
(
GstQtGLVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
);
};
#endif // GST_QT_VIDEO_SINK_NO_OPENGL
src/VideoStreaming/gstqtvideosink/gstqtglvideosinkbase.cpp
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#include
"gstqtglvideosinkbase.h"
#include
"painters/openglsurfacepainter.h"
#include
"delegates/qtvideosinkdelegate.h"
#include
<QCoreApplication>
#define CAPS_FORMATS "{ BGRA, BGRx, ARGB, xRGB, RGB, RGB16, BGR, v308, AYUV, YV12, I420 }"
const
char
*
const
GstQtGLVideoSinkBase
::
s_colorbalance_labels
[]
=
{
"contrast"
,
"brightness"
,
"hue"
,
"saturation"
};
GstQtVideoSinkBaseClass
*
GstQtGLVideoSinkBase
::
s_parent_class
=
nullptr
;
//------------------------------
DEFINE_TYPE_WITH_CODE
(
GstQtGLVideoSinkBase
,
GST_TYPE_QT_VIDEO_SINK_BASE
,
init_interfaces
)
void
GstQtGLVideoSinkBase
::
init_interfaces
(
GType
type
)
{
static
const
GInterfaceInfo
colorbalance_info
=
{
(
GInterfaceInitFunc
)
&
GstQtGLVideoSinkBase
::
colorbalance_init
,
nullptr
,
nullptr
};
g_type_add_interface_static
(
type
,
GST_TYPE_COLOR_BALANCE
,
&
colorbalance_info
);
}
//------------------------------
void
GstQtGLVideoSinkBase
::
base_init
(
gpointer
g_class
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
element_class
->
padtemplates
=
nullptr
;
//get rid of the pad template of the base class
static
GstStaticPadTemplate
sink_pad_template
=
GST_STATIC_PAD_TEMPLATE
(
"sink"
,
GST_PAD_SINK
,
GST_PAD_ALWAYS
,
GST_STATIC_CAPS
(
GST_VIDEO_CAPS_MAKE
(
CAPS_FORMATS
))
);
gst_element_class_add_pad_template
(
element_class
,
gst_static_pad_template_get
(
&
sink_pad_template
));
}
void
GstQtGLVideoSinkBase
::
class_init
(
gpointer
g_class
,
gpointer
class_data
)
{
Q_UNUSED
(
class_data
);
s_parent_class
=
reinterpret_cast
<
GstQtVideoSinkBaseClass
*>
(
g_type_class_peek_parent
(
g_class
));
GObjectClass
*
object_class
=
G_OBJECT_CLASS
(
g_class
);
object_class
->
finalize
=
GstQtGLVideoSinkBase
::
finalize
;
object_class
->
set_property
=
GstQtGLVideoSinkBase
::
set_property
;
object_class
->
get_property
=
GstQtGLVideoSinkBase
::
get_property
;
GstBaseSinkClass
*
base_sink_class
=
GST_BASE_SINK_CLASS
(
g_class
);
base_sink_class
->
start
=
GstQtGLVideoSinkBase
::
start
;
base_sink_class
->
set_caps
=
GstQtGLVideoSinkBase
::
set_caps
;
g_object_class_install_property
(
object_class
,
PROP_CONTRAST
,
g_param_spec_int
(
"contrast"
,
"Contrast"
,
"The contrast of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
object_class
,
PROP_BRIGHTNESS
,
g_param_spec_int
(
"brightness"
,
"Brightness"
,
"The brightness of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
object_class
,
PROP_HUE
,
g_param_spec_int
(
"hue"
,
"Hue"
,
"The hue of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
object_class
,
PROP_SATURATION
,
g_param_spec_int
(
"saturation"
,
"Saturation"
,
"The saturation of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
}
void
GstQtGLVideoSinkBase
::
init
(
GTypeInstance
*
instance
,
gpointer
g_class
)
{
Q_UNUSED
(
g_class
);
GstQtGLVideoSinkBase
*
self
=
GST_QT_GL_VIDEO_SINK_BASE
(
instance
);
GstColorBalanceChannel
*
channel
;
self
->
m_channels_list
=
nullptr
;
for
(
int
i
=
0
;
i
<
LABEL_LAST
;
i
++
)
{
channel
=
GST_COLOR_BALANCE_CHANNEL
(
g_object_new
(
GST_TYPE_COLOR_BALANCE_CHANNEL
,
nullptr
));
channel
->
label
=
g_strdup
(
s_colorbalance_labels
[
i
]);
channel
->
min_value
=
-
100
;
channel
->
max_value
=
100
;
self
->
m_channels_list
=
g_list_append
(
self
->
m_channels_list
,
channel
);
}
}
void
GstQtGLVideoSinkBase
::
finalize
(
GObject
*
object
)
{
GstQtGLVideoSinkBase
*
self
=
GST_QT_GL_VIDEO_SINK_BASE
(
object
);
while
(
self
->
m_channels_list
)
{
GstColorBalanceChannel
*
channel
=
GST_COLOR_BALANCE_CHANNEL
(
self
->
m_channels_list
->
data
);
g_object_unref
(
channel
);
self
->
m_channels_list
=
g_list_next
(
self
->
m_channels_list
);
}
g_list_free
(
self
->
m_channels_list
);
G_OBJECT_CLASS
(
s_parent_class
)
->
finalize
(
object
);
}
//------------------------------
void
GstQtGLVideoSinkBase
::
colorbalance_init
(
GstColorBalanceInterface
*
balance_interface
,
gpointer
data
)
{
Q_UNUSED
(
data
);
balance_interface
->
list_channels
=
GstQtGLVideoSinkBase
::
colorbalance_list_channels
;
balance_interface
->
set_value
=
GstQtGLVideoSinkBase
::
colorbalance_set_value
;
balance_interface
->
get_value
=
GstQtGLVideoSinkBase
::
colorbalance_get_value
;
balance_interface
->
get_balance_type
=
GstQtGLVideoSinkBase
::
colorbalance_get_balance_type
;
}
const
GList
*
GstQtGLVideoSinkBase
::
colorbalance_list_channels
(
GstColorBalance
*
balance
)
{
return
GST_QT_GL_VIDEO_SINK_BASE
(
balance
)
->
m_channels_list
;
}
void
GstQtGLVideoSinkBase
::
colorbalance_set_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
,
gint
value
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
balance
);
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_CONTRAST
]))
{
sink
->
delegate
->
setContrast
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_BRIGHTNESS
]))
{
sink
->
delegate
->
setBrightness
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_HUE
]))
{
sink
->
delegate
->
setHue
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_SATURATION
]))
{
sink
->
delegate
->
setSaturation
(
value
);
}
else
{
GST_WARNING_OBJECT
(
sink
,
"Unknown colorbalance channel %s"
,
channel
->
label
);
}
}
gint
GstQtGLVideoSinkBase
::
colorbalance_get_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
balance
);
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_CONTRAST
]))
{
return
sink
->
delegate
->
contrast
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_BRIGHTNESS
]))
{
return
sink
->
delegate
->
brightness
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_HUE
]))
{
return
sink
->
delegate
->
hue
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_SATURATION
]))
{
return
sink
->
delegate
->
saturation
();
}
else
{
GST_WARNING_OBJECT
(
sink
,
"Unknown colorbalance channel %s"
,
channel
->
label
);
}
return
0
;
}
GstColorBalanceType
GstQtGLVideoSinkBase
::
colorbalance_get_balance_type
(
GstColorBalance
*
balance
)
{
Q_UNUSED
(
balance
);
return
GST_COLOR_BALANCE_HARDWARE
;
}
//------------------------------
void
GstQtGLVideoSinkBase
::
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_CONTRAST
:
sink
->
delegate
->
setContrast
(
g_value_get_int
(
value
));
break
;
case
PROP_BRIGHTNESS
:
sink
->
delegate
->
setBrightness
(
g_value_get_int
(
value
));
break
;
case
PROP_HUE
:
sink
->
delegate
->
setHue
(
g_value_get_int
(
value
));
break
;
case
PROP_SATURATION
:
sink
->
delegate
->
setSaturation
(
g_value_get_int
(
value
));
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
void
GstQtGLVideoSinkBase
::
get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_CONTRAST
:
g_value_set_int
(
value
,
sink
->
delegate
->
contrast
());
break
;
case
PROP_BRIGHTNESS
:
g_value_set_int
(
value
,
sink
->
delegate
->
brightness
());
break
;
case
PROP_HUE
:
g_value_set_int
(
value
,
sink
->
delegate
->
hue
());
break
;
case
PROP_SATURATION
:
g_value_set_int
(
value
,
sink
->
delegate
->
saturation
());
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
//------------------------------
gboolean
GstQtGLVideoSinkBase
::
start
(
GstBaseSink
*
base
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
base
);
//fail on purpose if the user hasn't set a context
if
(
sink
->
delegate
->
supportedPainterTypes
()
==
QtVideoSinkDelegate
::
Generic
)
{
GST_WARNING_OBJECT
(
sink
,
"Neither GLSL nor ARB Fragment Program are supported "
"for painting. Did you forget to set a gl context?"
);
return
FALSE
;
}
else
{
return
TRUE
;
}
}
gboolean
GstQtGLVideoSinkBase
::
set_caps
(
GstBaseSink
*
base
,
GstCaps
*
caps
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
base
);
GST_LOG_OBJECT
(
sink
,
"new caps %"
GST_PTR_FORMAT
,
caps
);
BufferFormat
format
=
BufferFormat
::
fromCaps
(
caps
);
if
(
OpenGLSurfacePainter
::
supportedPixelFormats
().
contains
(
format
.
videoFormat
()))
{
QCoreApplication
::
postEvent
(
sink
->
delegate
,
new
BaseDelegate
::
BufferFormatEvent
(
format
));
return
TRUE
;
}
else
{
return
FALSE
;
}
}
src/VideoStreaming/gstqtvideosink/gstqtglvideosinkbase.h
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
"gstqtvideosinkbase.h"
#include
<gst/video/colorbalance.h>
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
#define GST_TYPE_QT_GL_VIDEO_SINK_BASE \
(GstQtGLVideoSinkBase::get_type())
#define GST_QT_GL_VIDEO_SINK_BASE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QT_GL_VIDEO_SINK_BASE, GstQtGLVideoSinkBase))
struct
GstQtGLVideoSinkBase
{
public:
GstQtVideoSinkBase
parent
;
static
GType
get_type
();
private:
enum
{
PROP_0
,
PROP_CONTRAST
,
PROP_BRIGHTNESS
,
PROP_HUE
,
PROP_SATURATION
};
//index for s_colorbalance_labels
enum
{
LABEL_CONTRAST
=
0
,
LABEL_BRIGHTNESS
,
LABEL_HUE
,
LABEL_SATURATION
,
LABEL_LAST
};
static
void
init_interfaces
(
GType
type
);
static
void
base_init
(
gpointer
g_class
);
static
void
class_init
(
gpointer
g_class
,
gpointer
class_data
);
static
void
init
(
GTypeInstance
*
instance
,
gpointer
g_class
);
static
void
finalize
(
GObject
*
object
);
static
void
colorbalance_init
(
GstColorBalanceInterface
*
balance_interface
,
gpointer
data
);
static
const
GList
*
colorbalance_list_channels
(
GstColorBalance
*
balance
);
static
void
colorbalance_set_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
,
gint
value
);
static
gint
colorbalance_get_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
);
static
GstColorBalanceType
colorbalance_get_balance_type
(
GstColorBalance
*
balance
);
static
void
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
);
static
void
get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
);
static
gboolean
start
(
GstBaseSink
*
sink
);
static
gboolean
set_caps
(
GstBaseSink
*
sink
,
GstCaps
*
caps
);
GList
*
m_channels_list
;
static
const
char
*
const
s_colorbalance_labels
[];
static
GstQtVideoSinkBaseClass
*
s_parent_class
;
};
struct
GstQtGLVideoSinkBaseClass
{
GstQtVideoSinkBaseClass
parent_class
;
};
#endif // GST_QT_VIDEO_SINK_NO_OPENGL
src/VideoStreaming/gstqtvideosink/gstqtquick2videosink.cpp
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#include
"gstqtquick2videosink.h"
#include
"gstqtvideosinkplugin.h"
#include
"gstqtvideosinkmarshal.h"
#include
"delegates/qtquick2videosinkdelegate.h"
#include
<gst/video/colorbalance.h>
#include
<cstring>
#include
<QCoreApplication>
#define CAPS_FORMATS "{ BGRA, BGRx, ARGB, xRGB, RGB, RGB16, BGR, v308, AYUV, YV12, I420 }"
#define GST_QT_QUICK2_VIDEO_SINK_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSinkPrivate))
struct
_GstQtQuick2VideoSinkPrivate
{
QtQuick2VideoSinkDelegate
*
delegate
;
GList
*
channels_list
;
};
static
void
gst_qt_quick2_video_sink_colorbalance_init
(
GstColorBalanceInterface
*
iface
,
gpointer
data
);
#define parent_class gst_qt_quick2_video_sink_parent_class
G_DEFINE_TYPE_WITH_CODE
(
GstQtQuick2VideoSink
,
gst_qt_quick2_video_sink
,
GST_TYPE_VIDEO_SINK
,
G_IMPLEMENT_INTERFACE
(
GST_TYPE_COLOR_BALANCE
,
gst_qt_quick2_video_sink_colorbalance_init
));
enum
{
PROP_0
,
PROP_PIXEL_ASPECT_RATIO
,
PROP_FORCE_ASPECT_RATIO
,
PROP_CONTRAST
,
PROP_BRIGHTNESS
,
PROP_HUE
,
PROP_SATURATION
,
};
enum
{
ACTION_UPDATE_NODE
,
SIGNAL_UPDATE
,
LAST_SIGNAL
};
static
guint
s_signals
[
LAST_SIGNAL
]
=
{
0
};
const
char
*
const
s_colorbalance_labels
[]
=
{
"contrast"
,
"brightness"
,
"hue"
,
"saturation"
};
//index for s_colorbalance_labels
enum
{
LABEL_CONTRAST
=
0
,
LABEL_BRIGHTNESS
,
LABEL_HUE
,
LABEL_SATURATION
,
LABEL_LAST
};
static
void
gst_qt_quick2_video_sink_init
(
GstQtQuick2VideoSink
*
self
)
{
self
->
priv
=
GST_QT_QUICK2_VIDEO_SINK_GET_PRIVATE
(
self
);
// delegate
self
->
priv
->
delegate
=
new
QtQuick2VideoSinkDelegate
(
GST_ELEMENT
(
self
));
// colorbalance
GstColorBalanceChannel
*
channel
;
self
->
priv
->
channels_list
=
nullptr
;
for
(
int
i
=
0
;
i
<
LABEL_LAST
;
i
++
)
{
channel
=
GST_COLOR_BALANCE_CHANNEL
(
g_object_new
(
GST_TYPE_COLOR_BALANCE_CHANNEL
,
nullptr
));
channel
->
label
=
g_strdup
(
s_colorbalance_labels
[
i
]);
channel
->
min_value
=
-
100
;
channel
->
max_value
=
100
;
self
->
priv
->
channels_list
=
g_list_append
(
self
->
priv
->
channels_list
,
channel
);
}
}
static
void
gst_qt_quick2_video_sink_finalize
(
GObject
*
gobject
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
gobject
);
delete
self
->
priv
->
delegate
;
self
->
priv
->
delegate
=
nullptr
;
while
(
self
->
priv
->
channels_list
)
{
GstColorBalanceChannel
*
channel
=
GST_COLOR_BALANCE_CHANNEL
(
self
->
priv
->
channels_list
->
data
);
g_object_unref
(
channel
);
self
->
priv
->
channels_list
=
g_list_next
(
self
->
priv
->
channels_list
);
}
g_list_free
(
self
->
priv
->
channels_list
);
G_OBJECT_CLASS
(
parent_class
)
->
finalize
(
gobject
);
}
static
void
gst_qt_quick2_video_sink_set_property
(
GObject
*
object
,
guint
property_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
object
);
switch
(
property_id
)
{
case
PROP_PIXEL_ASPECT_RATIO
:
{
GValue
tmp
;
std
::
memset
(
&
tmp
,
0
,
sizeof
(
GValue
));
g_value_init
(
&
tmp
,
GST_TYPE_FRACTION
);
if
(
g_value_transform
(
value
,
&
tmp
))
{
int
n
=
gst_value_get_fraction_numerator
(
&
tmp
);
int
d
=
gst_value_get_fraction_denominator
(
&
tmp
);
self
->
priv
->
delegate
->
setPixelAspectRatio
(
Fraction
(
n
,
d
));
}
else
{
GST_WARNING_OBJECT
(
object
,
"Could not transform string to aspect ratio"
);
}
g_value_unset
(
&
tmp
);
break
;
}
case
PROP_FORCE_ASPECT_RATIO
:
self
->
priv
->
delegate
->
setForceAspectRatio
(
g_value_get_boolean
(
value
));
break
;
case
PROP_CONTRAST
:
self
->
priv
->
delegate
->
setContrast
(
g_value_get_int
(
value
));
break
;
case
PROP_BRIGHTNESS
:
self
->
priv
->
delegate
->
setBrightness
(
g_value_get_int
(
value
));
break
;
case
PROP_HUE
:
self
->
priv
->
delegate
->
setHue
(
g_value_get_int
(
value
));
break
;
case
PROP_SATURATION
:
self
->
priv
->
delegate
->
setSaturation
(
g_value_get_int
(
value
));
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
property_id
,
pspec
);
break
;
}
}
static
void
gst_qt_quick2_video_sink_get_property
(
GObject
*
object
,
guint
property_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
object
);
switch
(
property_id
)
{
case
PROP_PIXEL_ASPECT_RATIO
:
{
GValue
tmp
;
Fraction
par
=
self
->
priv
->
delegate
->
pixelAspectRatio
();
std
::
memset
(
&
tmp
,
0
,
sizeof
(
GValue
));
g_value_init
(
&
tmp
,
GST_TYPE_FRACTION
);
gst_value_set_fraction
(
&
tmp
,
par
.
numerator
,
par
.
denominator
);
g_value_transform
(
&
tmp
,
value
);
g_value_unset
(
&
tmp
);
break
;
}
case
PROP_FORCE_ASPECT_RATIO
:
g_value_set_boolean
(
value
,
self
->
priv
->
delegate
->
forceAspectRatio
());
break
;
case
PROP_CONTRAST
:
g_value_set_int
(
value
,
self
->
priv
->
delegate
->
contrast
());
break
;
case
PROP_BRIGHTNESS
:
g_value_set_int
(
value
,
self
->
priv
->
delegate
->
brightness
());
break
;
case
PROP_HUE
:
g_value_set_int
(
value
,
self
->
priv
->
delegate
->
hue
());
break
;
case
PROP_SATURATION
:
g_value_set_int
(
value
,
self
->
priv
->
delegate
->
saturation
());
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
property_id
,
pspec
);
break
;
}
}
static
GstStateChangeReturn
gst_qt_quick2_video_sink_change_state
(
GstElement
*
element
,
GstStateChange
transition
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
element
);
switch
(
transition
)
{
case
GST_STATE_CHANGE_READY_TO_PAUSED
:
self
->
priv
->
delegate
->
setActive
(
true
);
break
;
case
GST_STATE_CHANGE_PAUSED_TO_READY
:
self
->
priv
->
delegate
->
setActive
(
false
);
break
;
default:
break
;
}
return
GST_ELEMENT_CLASS
(
parent_class
)
->
change_state
(
element
,
transition
);
}
static
gboolean
gst_qt_quick2_video_sink_set_caps
(
GstBaseSink
*
sink
,
GstCaps
*
caps
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
sink
);
GST_LOG_OBJECT
(
self
,
"new caps %"
GST_PTR_FORMAT
,
caps
);
BufferFormat
format
=
BufferFormat
::
fromCaps
(
caps
);
//too lazy to do proper checks. if the format is not UNKNOWN, then
//it should conform to the template caps formats, unless gstreamer
//core has a bug.
if
(
format
.
videoFormat
()
!=
GST_VIDEO_FORMAT_UNKNOWN
)
{
QCoreApplication
::
postEvent
(
self
->
priv
->
delegate
,
new
BaseDelegate
::
BufferFormatEvent
(
format
));
return
TRUE
;
}
else
{
return
FALSE
;
}
}
static
GstFlowReturn
gst_qt_quick2_video_sink_show_frame
(
GstVideoSink
*
sink
,
GstBuffer
*
buffer
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
sink
);
GST_TRACE_OBJECT
(
self
,
"Posting new buffer (%"
GST_PTR_FORMAT
") for rendering."
,
buffer
);
QCoreApplication
::
postEvent
(
self
->
priv
->
delegate
,
new
BaseDelegate
::
BufferEvent
(
buffer
));
return
GST_FLOW_OK
;
}
//------------------------------
static
gpointer
gst_qt_quick2_video_sink_update_node
(
GstQtQuick2VideoSink
*
self
,
gpointer
node
,
qreal
x
,
qreal
y
,
qreal
w
,
qreal
h
)
{
return
self
->
priv
->
delegate
->
updateNode
(
static_cast
<
QSGNode
*>
(
node
),
QRectF
(
x
,
y
,
w
,
h
));
}
//------------------------------
static
const
GList
*
gst_qt_quick2_video_sink_colorbalance_list_channels
(
GstColorBalance
*
balance
)
{
return
GST_QT_QUICK2_VIDEO_SINK
(
balance
)
->
priv
->
channels_list
;
}
static
void
gst_qt_quick2_video_sink_colorbalance_set_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
,
gint
value
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
balance
);
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_CONTRAST
]))
{
self
->
priv
->
delegate
->
setContrast
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_BRIGHTNESS
]))
{
self
->
priv
->
delegate
->
setBrightness
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_HUE
]))
{
self
->
priv
->
delegate
->
setHue
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_SATURATION
]))
{
self
->
priv
->
delegate
->
setSaturation
(
value
);
}
else
{
GST_WARNING_OBJECT
(
self
,
"Unknown colorbalance channel %s"
,
channel
->
label
);
}
}
static
gint
gst_qt_quick2_video_sink_colorbalance_get_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
balance
);
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_CONTRAST
]))
{
return
self
->
priv
->
delegate
->
contrast
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_BRIGHTNESS
]))
{
return
self
->
priv
->
delegate
->
brightness
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_HUE
]))
{
return
self
->
priv
->
delegate
->
hue
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_SATURATION
]))
{
return
self
->
priv
->
delegate
->
saturation
();
}
else
{
GST_WARNING_OBJECT
(
self
,
"Unknown colorbalance channel %s"
,
channel
->
label
);
}
return
0
;
}
static
GstColorBalanceType
gst_qt_quick2_video_sink_colorbalance_get_balance_type
(
GstColorBalance
*
balance
)
{
Q_UNUSED
(
balance
);
return
GST_COLOR_BALANCE_HARDWARE
;
}
static
void
gst_qt_quick2_video_sink_colorbalance_init
(
GstColorBalanceInterface
*
iface
,
gpointer
data
)
{
Q_UNUSED
(
data
);
iface
->
list_channels
=
gst_qt_quick2_video_sink_colorbalance_list_channels
;
iface
->
set_value
=
gst_qt_quick2_video_sink_colorbalance_set_value
;
iface
->
get_value
=
gst_qt_quick2_video_sink_colorbalance_get_value
;
iface
->
get_balance_type
=
gst_qt_quick2_video_sink_colorbalance_get_balance_type
;
}
//------------------------------
static
void
gst_qt_quick2_video_sink_class_init
(
GstQtQuick2VideoSinkClass
*
klass
)
{
GObjectClass
*
gobject_class
=
G_OBJECT_CLASS
(
klass
);
gobject_class
->
finalize
=
gst_qt_quick2_video_sink_finalize
;
gobject_class
->
set_property
=
gst_qt_quick2_video_sink_set_property
;
gobject_class
->
get_property
=
gst_qt_quick2_video_sink_get_property
;
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
klass
);
element_class
->
change_state
=
gst_qt_quick2_video_sink_change_state
;
GstBaseSinkClass
*
base_sink_class
=
GST_BASE_SINK_CLASS
(
klass
);
base_sink_class
->
set_caps
=
gst_qt_quick2_video_sink_set_caps
;
GstVideoSinkClass
*
video_sink_class
=
GST_VIDEO_SINK_CLASS
(
klass
);
video_sink_class
->
show_frame
=
gst_qt_quick2_video_sink_show_frame
;
GstQtQuick2VideoSinkClass
*
qtquick2_class
=
GST_QT_QUICK2_VIDEO_SINK_CLASS
(
klass
);
qtquick2_class
->
update_node
=
gst_qt_quick2_video_sink_update_node
;
/**
* GstQtQuick2VideoSink::pixel-aspect-ratio
*
* The pixel aspect ratio of the display device.
**/
g_object_class_install_property
(
gobject_class
,
PROP_PIXEL_ASPECT_RATIO
,
g_param_spec_string
(
"pixel-aspect-ratio"
,
"Pixel aspect ratio"
,
"The pixel aspect ratio of the display device"
,
"1/1"
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
/**
* GstQtQuick2VideoSink::force-aspect-ratio
*
* If set to TRUE, the sink will scale the video respecting its original aspect ratio
* and any remaining space will be filled with black.
* If set to FALSE, the sink will scale the video to fit the whole drawing area.
**/
g_object_class_install_property
(
gobject_class
,
PROP_FORCE_ASPECT_RATIO
,
g_param_spec_boolean
(
"force-aspect-ratio"
,
"Force aspect ratio"
,
"When enabled, scaling will respect original aspect ratio"
,
FALSE
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
gobject_class
,
PROP_CONTRAST
,
g_param_spec_int
(
"contrast"
,
"Contrast"
,
"The contrast of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
gobject_class
,
PROP_BRIGHTNESS
,
g_param_spec_int
(
"brightness"
,
"Brightness"
,
"The brightness of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
gobject_class
,
PROP_HUE
,
g_param_spec_int
(
"hue"
,
"Hue"
,
"The hue of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
gobject_class
,
PROP_SATURATION
,
g_param_spec_int
(
"saturation"
,
"Saturation"
,
"The saturation of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
/**
* GstQtQuick2VideoSink::update-node
* @node: The QSGNode to update
* @x: The x coordinate of the target area rectangle
* @y: The y coordinate of the target area rectangle
* @width: The width of the target area rectangle
* @height: The height of the target area rectangle
* @returns: The updated QGSNode
*
* This is an action signal that you can call from your QQuickItem subclass
* inside its updateNode function to render the video. It takes a QSGNode*
* and the item's area rectangle as arguments. You should schedule to call
* this function to repaint the surface whenever the ::update signal is
* emitted.
*
* Note that the x,y,width and height arguments are actually qreal.
* This means that on architectures like arm they will be float instead
* of double. You should cast the arguments to qreal if they are not
* already when emitting this signal.
*/
s_signals
[
ACTION_UPDATE_NODE
]
=
g_signal_new
(
"update-node"
,
G_TYPE_FROM_CLASS
(
klass
),
static_cast
<
GSignalFlags
>
(
G_SIGNAL_RUN_LAST
|
G_SIGNAL_ACTION
),
G_STRUCT_OFFSET
(
GstQtQuick2VideoSinkClass
,
update_node
),
nullptr
,
nullptr
,
qRealIsDouble
()
?
g_cclosure_user_marshal_POINTER__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
:
g_cclosure_user_marshal_POINTER__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
,
G_TYPE_POINTER
,
5
,
G_TYPE_POINTER
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
);
/**
* GstQtQuick2VideoSink::update
*
* This signal is emitted when the surface should be repainted. It should
* be connected to QQuickItem::update().
*/
s_signals
[
SIGNAL_UPDATE
]
=
g_signal_new
(
"update"
,
G_TYPE_FROM_CLASS
(
klass
),
G_SIGNAL_RUN_LAST
,
0
,
nullptr
,
nullptr
,
g_cclosure_marshal_VOID__VOID
,
G_TYPE_NONE
,
0
);
g_type_class_add_private
(
klass
,
sizeof
(
GstQtQuick2VideoSinkPrivate
));
static
GstStaticPadTemplate
sink_pad_template
=
GST_STATIC_PAD_TEMPLATE
(
"sink"
,
GST_PAD_SINK
,
GST_PAD_ALWAYS
,
GST_STATIC_CAPS
(
GST_VIDEO_CAPS_MAKE
(
CAPS_FORMATS
))
);
gst_element_class_add_pad_template
(
element_class
,
gst_static_pad_template_get
(
&
sink_pad_template
));
gst_element_class_set_details_simple
(
element_class
,
"QtQuick2 video sink"
,
"Sink/Video"
,
"A video sink that can draw on a QQuickItem"
,
"George Kiagiadakis <george.kiagiadakis@collabora.com>"
);
}
src/VideoStreaming/gstqtvideosink/gstqtquick2videosink.h
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2013 Collabora Ltd.
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 program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
<gst/video/gstvideosink.h>
#include
<QtGlobal>
#define GST_TYPE_QT_QUICK2_VIDEO_SINK \
(gst_qt_quick2_video_sink_get_type ())
#define GST_QT_QUICK2_VIDEO_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSink))
#define GST_IS_QT_QUICK2_VIDEO_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK))
#define GST_QT_QUICK2_VIDEO_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSinkClass))
#define GST_IS_QT_QUICK2_VIDEO_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_QT_QUICK2_VIDEO_SINK))
#define GST_QT_QUICK2_VIDEO_SINK_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSinkClass))
typedef
struct
_GstQtQuick2VideoSink
GstQtQuick2VideoSink
;
typedef
struct
_GstQtQuick2VideoSinkClass
GstQtQuick2VideoSinkClass
;
typedef
struct
_GstQtQuick2VideoSinkPrivate
GstQtQuick2VideoSinkPrivate
;
struct
_GstQtQuick2VideoSink
{
GstVideoSink
parent_instance
;
GstQtQuick2VideoSinkPrivate
*
priv
;
};
struct
_GstQtQuick2VideoSinkClass
{
GstVideoSinkClass
parent_class
;
gpointer
(
*
update_node
)(
GstQtQuick2VideoSink
*
self
,
gpointer
node
,
qreal
x
,
qreal
y
,
qreal
w
,
qreal
h
);
};
GType
gst_qt_quick2_video_sink_get_type
(
void
);
src/VideoStreaming/gstqtvideosink/gstqtvideosink.cpp
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#include
"gstqtvideosink.h"
#include
"gstqtvideosinkmarshal.h"
#include
"delegates/qtvideosinkdelegate.h"
guint
GstQtVideoSink
::
s_signals
[];
DEFINE_TYPE
(
GstQtVideoSink
,
GST_TYPE_QT_VIDEO_SINK_BASE
)
//------------------------------
void
GstQtVideoSink
::
emit_update
(
gpointer
sink
)
{
g_signal_emit
(
sink
,
GstQtVideoSink
::
s_signals
[
UPDATE_SIGNAL
],
0
,
NULL
);
}
//------------------------------
void
GstQtVideoSink
::
base_init
(
gpointer
g_class
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
gst_element_class_set_details_simple
(
element_class
,
"Qt video sink"
,
"Sink/Video"
,
"A video sink that can draw on any Qt surface"
,
"George Kiagiadakis <george.kiagiadakis@collabora.com>"
);
}
void
GstQtVideoSink
::
class_init
(
gpointer
g_class
,
gpointer
class_data
)
{
Q_UNUSED
(
class_data
);
GstQtVideoSinkClass
*
qt_video_sink_class
=
reinterpret_cast
<
GstQtVideoSinkClass
*>
(
g_class
);
qt_video_sink_class
->
paint
=
GstQtVideoSink
::
paint
;
/**
* GstQtVideoSink::paint
* @painter: A valid QPainter pointer that will be used to paint the video
* @x: The x coordinate of the target area rectangle
* @y: The y coordinate of the target area rectangle
* @width: The width of the target area rectangle
* @height: The height of the target area rectangle
*
* This is an action signal that you can call from your Qt surface class inside
* its paint function to render the video. It takes a QPainter* and the target
* area rectangle as arguments. You should schedule to call this function to
* repaint the surface whenever the ::update signal is emitted.
*
* Note that the x,y,width and height arguments are actually qreal. This means
* that on architectures like arm they will be float instead of double. You should
* cast the arguments to qreal if they are not already when emitting this signal.
*/
s_signals
[
PAINT_SIGNAL
]
=
g_signal_new
(
"paint"
,
G_TYPE_FROM_CLASS
(
g_class
),
static_cast
<
GSignalFlags
>
(
G_SIGNAL_RUN_LAST
|
G_SIGNAL_ACTION
),
G_STRUCT_OFFSET
(
GstQtVideoSinkClass
,
paint
),
nullptr
,
nullptr
,
qRealIsDouble
()
?
g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
:
g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
,
G_TYPE_NONE
,
5
,
G_TYPE_POINTER
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
);
/**
* GstQtVideoSink::update
*
* This signal is emitted when the surface should be repainted. It should
* be connected to QWidget::update() or QGraphicsItem::update() or any
* other similar function in your surface.
*/
s_signals
[
UPDATE_SIGNAL
]
=
g_signal_new
(
"update"
,
G_TYPE_FROM_CLASS
(
g_class
),
G_SIGNAL_RUN_LAST
,
0
,
nullptr
,
nullptr
,
g_cclosure_marshal_VOID__VOID
,
G_TYPE_NONE
,
0
);
}
void
GstQtVideoSink
::
init
(
GTypeInstance
*
instance
,
gpointer
g_class
)
{
Q_UNUSED
(
g_class
);
GstQtVideoSinkBase
*
sinkBase
=
GST_QT_VIDEO_SINK_BASE
(
instance
);
sinkBase
->
delegate
=
new
QtVideoSinkDelegate
(
GST_ELEMENT
(
sinkBase
));
}
//------------------------------
void
GstQtVideoSink
::
paint
(
GstQtVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
)
{
GST_QT_VIDEO_SINK_BASE
(
sink
)
->
delegate
->
paint
(
static_cast
<
QPainter
*>
(
painter
),
QRectF
(
x
,
y
,
width
,
height
));
}
src/VideoStreaming/gstqtvideosink/gstqtvideosink.h
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include
"gstqtvideosinkbase.h"
#define GST_TYPE_QT_VIDEO_SINK \
(GstQtVideoSink::get_type())
struct
GstQtVideoSink
{
public:
GstQtVideoSinkBase
parent
;
static
GType
get_type
();
static
void
emit_update
(
gpointer
sink
);
private:
enum
{
PAINT_SIGNAL
,
UPDATE_SIGNAL
,
LAST_SIGNAL
};
static
void
base_init
(
gpointer
g_class
);
static
void
class_init
(
gpointer
g_class
,
gpointer
class_data
);
static
void
init
(
GTypeInstance
*
instance
,
gpointer
g_class
);
static
void
paint
(
GstQtVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
);
static
guint
s_signals
[
LAST_SIGNAL
];
};
struct
GstQtVideoSinkClass
{
GstQtVideoSinkBaseClass
parent_class
;
/* paint action signal */
void
(
*
paint
)
(
GstQtVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
);
};
src/VideoStreaming/gstqtvideosink/gstqtvideosinkbase.cpp
deleted
100644 → 0
View file @
e36a8fbc
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <gus@auterion.com>
*/
#include
"gstqtvideosinkbase.h"
#include
"delegates/qtvideosinkdelegate.h"
#include
"painters/genericsurfacepainter.h"
#include
<cstring>
#include
<QCoreApplication>
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
# define CAPS_FORMATS "{ ARGB, xRGB, RGB, RGB16 }"
#else
# define CAPS_FORMATS "{ BGRA, BGRx, RGB, RGB16 }"
#endif
GstVideoSinkClass
*
GstQtVideoSinkBase
::
s_parent_class
=
nullptr
;
DEFINE_TYPE
(
GstQtVideoSinkBase
,
GST_TYPE_VIDEO_SINK
)
//------------------------------
void
GstQtVideoSinkBase
::
base_init
(
gpointer
g_class
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
static
GstStaticPadTemplate
sink_pad_template
=
GST_STATIC_PAD_TEMPLATE
(
"sink"
,
GST_PAD_SINK
,
GST_PAD_ALWAYS
,
GST_STATIC_CAPS
(
GST_VIDEO_CAPS_MAKE
(
CAPS_FORMATS
))
);
gst_element_class_add_pad_template
(
element_class
,
gst_static_pad_template_get
(
&
sink_pad_template
));
}
void
GstQtVideoSinkBase
::
class_init
(
gpointer
g_class
,
gpointer
class_data
)
{
Q_UNUSED
(
class_data
);
s_parent_class
=
reinterpret_cast
<
GstVideoSinkClass
*>
(
g_type_class_peek_parent
(
g_class
));
GObjectClass
*
object_class
=
G_OBJECT_CLASS
(
g_class
);
object_class
->
finalize
=
GstQtVideoSinkBase
::
finalize
;
object_class
->
set_property
=
GstQtVideoSinkBase
::
set_property
;
object_class
->
get_property
=
GstQtVideoSinkBase
::
get_property
;
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
element_class
->
change_state
=
GstQtVideoSinkBase
::
change_state
;
GstBaseSinkClass
*
base_sink_class
=
GST_BASE_SINK_CLASS
(
g_class
);
base_sink_class
->
set_caps
=
GstQtVideoSinkBase
::
set_caps
;
GstVideoSinkClass
*
video_sink_class
=
GST_VIDEO_SINK_CLASS
(
g_class
);
video_sink_class
->
show_frame
=
GstQtVideoSinkBase
::
show_frame
;
/**
* GstQtVideoSinkBase::pixel-aspect-ratio
*
* The pixel aspect ratio of the display device.
**/
g_object_class_install_property
(
object_class
,
PROP_PIXEL_ASPECT_RATIO
,
g_param_spec_string
(
"pixel-aspect-ratio"
,
"Pixel aspect ratio"
,
"The pixel aspect ratio of the display device"
,
"1/1"
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
/**
* GstQtVideoSinkBase::force-aspect-ratio
*
* If set to TRUE, the sink will scale the video respecting its original aspect ratio
* and any remaining space will be filled with black.
* If set to FALSE, the sink will scale the video to fit the whole drawing area.
**/
g_object_class_install_property
(
object_class
,
PROP_FORCE_ASPECT_RATIO
,
g_param_spec_boolean
(
"force-aspect-ratio"
,
"Force aspect ratio"
,
"When enabled, scaling will respect original aspect ratio"
,
FALSE
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
}
void
GstQtVideoSinkBase
::
init
(
GTypeInstance
*
instance
,
gpointer
g_class
)
{
Q_UNUSED
(
instance
);
Q_UNUSED
(
g_class
);
/* sink->delegate is initialized in the subclasses */
}
void
GstQtVideoSinkBase
::
finalize
(
GObject
*
object
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
delete
sink
->
delegate
;
sink
->
delegate
=
0
;
}
//------------------------------
void
GstQtVideoSinkBase
::
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_PIXEL_ASPECT_RATIO
:
{
GValue
tmp
;
std
::
memset
(
&
tmp
,
0
,
sizeof
(
GValue
));
g_value_init
(
&
tmp
,
GST_TYPE_FRACTION
);
if
(
g_value_transform
(
value
,
&
tmp
))
{
int
n
=
gst_value_get_fraction_numerator
(
&
tmp
);
int
d
=
gst_value_get_fraction_denominator
(
&
tmp
);
sink
->
delegate
->
setPixelAspectRatio
(
Fraction
(
n
,
d
));
}
else
{
GST_WARNING_OBJECT
(
object
,
"Could not transform string to aspect ratio"
);
}
g_value_unset
(
&
tmp
);
break
;
}
case
PROP_FORCE_ASPECT_RATIO
:
sink
->
delegate
->
setForceAspectRatio
(
g_value_get_boolean
(
value
));
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
void
GstQtVideoSinkBase
::
get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_PIXEL_ASPECT_RATIO
:
{
GValue
tmp
;
Fraction
par
=
sink
->
delegate
->
pixelAspectRatio
();
std
::
memset
(
&
tmp
,
0
,
sizeof
(
GValue
));
g_value_init
(
&
tmp
,
GST_TYPE_FRACTION
);
gst_value_set_fraction
(
&
tmp
,
par
.
numerator
,
par
.
denominator
);
g_value_transform
(
&
tmp
,
value
);
g_value_unset
(
&
tmp
);
break
;
}
case
PROP_FORCE_ASPECT_RATIO
:
g_value_set_boolean
(
value
,
sink
->
delegate
->
forceAspectRatio
());
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
//------------------------------
GstStateChangeReturn
GstQtVideoSinkBase
::
change_state
(
GstElement
*
element
,
GstStateChange
transition
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
element
);
switch
(
transition
)
{
case
GST_STATE_CHANGE_READY_TO_PAUSED
:
sink
->
delegate
->
setActive
(
true
);
break
;
case
GST_STATE_CHANGE_PAUSED_TO_READY
:
sink
->
delegate
->
setActive
(
false
);
break
;
default:
break
;
}
return
GST_ELEMENT_CLASS
(
s_parent_class
)
->
change_state
(
element
,
transition
);
}
//------------------------------
gboolean
GstQtVideoSinkBase
::
set_caps
(
GstBaseSink
*
base
,
GstCaps
*
caps
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
base
);
GST_LOG_OBJECT
(
sink
,
"new caps %"
GST_PTR_FORMAT
,
caps
);
BufferFormat
format
=
BufferFormat
::
fromCaps
(
caps
);
if
(
GenericSurfacePainter
::
supportedPixelFormats
().
contains
(
format
.
videoFormat
()))
{
QCoreApplication
::
postEvent
(
sink
->
delegate
,
new
BaseDelegate
::
BufferFormatEvent
(
format
));
return
TRUE
;
}
else
{
return
FALSE
;
}
}
//------------------------------
GstFlowReturn
GstQtVideoSinkBase
::
show_frame
(
GstVideoSink
*
video_sink
,
GstBuffer
*
buffer
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
video_sink
);
GST_TRACE_OBJECT
(
sink
,
"Posting new buffer (%"
GST_PTR_FORMAT
") for rendering."
,
buffer
);
QCoreApplication
::
postEvent
(
sink
->
delegate
,
new
BaseDelegate
::
BufferEvent
(
buffer
));
return
GST_FLOW_OK
;
}
Prev
1
2
3
4
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment