Merge remote-tracking branch 'origin/5.5' into dev
Change-Id: I7ac7db69c37cc9e5c5241a25b9a874986a23a886
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 12 KiB |
@@ -28,11 +28,13 @@
|
|||||||
/*!
|
/*!
|
||||||
\example declarative-radio
|
\example declarative-radio
|
||||||
\title Declarative Radio Example
|
\title Declarative Radio Example
|
||||||
\brief Demonstrates the radio functionality
|
\brief Demonstrates using the Radio QML type from Qt Multimedia.
|
||||||
\ingroup multimedia_examples
|
\ingroup multimedia_examples
|
||||||
|
|
||||||
This examples uses the \l{Qt Multimedia} \l Radio QML type to list the
|
This examples uses the \l{Qt Multimedia} \l Radio QML type to list the
|
||||||
available channels on the FM frequency.
|
available channels on the FM frequency.
|
||||||
|
|
||||||
|
\image declarative-radio-example.png
|
||||||
|
|
||||||
\include examples-run.qdocinc
|
\include examples-run.qdocinc
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -98,6 +98,9 @@ QGstreamerVideoWidgetControl::QGstreamerVideoWidgetControl(QObject *parent)
|
|||||||
, m_widget(0)
|
, m_widget(0)
|
||||||
, m_fullScreen(false)
|
, m_fullScreen(false)
|
||||||
{
|
{
|
||||||
|
// The QWidget needs to have a native X window handle to be able to use xvimagesink.
|
||||||
|
// Bail out if Qt is not using xcb (the control will then be ignored by the plugin)
|
||||||
|
if (QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0)
|
||||||
m_videoSink = gst_element_factory_make ("xvimagesink", NULL);
|
m_videoSink = gst_element_factory_make ("xvimagesink", NULL);
|
||||||
|
|
||||||
if (m_videoSink) {
|
if (m_videoSink) {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include <private/qgstutils_p.h>
|
#include <private/qgstutils_p.h>
|
||||||
|
|
||||||
#include <QtCore/qdebug.h>
|
#include <QtCore/qdebug.h>
|
||||||
|
#include <QtGui/qguiapplication.h>
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
@@ -57,7 +58,9 @@ QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elemen
|
|||||||
{
|
{
|
||||||
if (elementName) {
|
if (elementName) {
|
||||||
m_videoSink = gst_element_factory_make(elementName, NULL);
|
m_videoSink = gst_element_factory_make(elementName, NULL);
|
||||||
} else {
|
} else if (QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0) {
|
||||||
|
// We need a native X window handle to be able to use xvimagesink.
|
||||||
|
// Bail out if Qt is not using xcb (the control will then be ignored by the plugin)
|
||||||
m_videoSink = gst_element_factory_make("xvimagesink", NULL);
|
m_videoSink = gst_element_factory_make("xvimagesink", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,8 +71,6 @@ QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elemen
|
|||||||
addProbeToPad(pad);
|
addProbeToPad(pad);
|
||||||
gst_object_unref(GST_OBJECT(pad));
|
gst_object_unref(GST_OBJECT(pad));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
qDebug() << "No m_videoSink available!";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QGstreamerVideoWindow::~QGstreamerVideoWindow()
|
QGstreamerVideoWindow::~QGstreamerVideoWindow()
|
||||||
|
|||||||
@@ -222,6 +222,17 @@ bool QVideoSurfaceGstDelegate::proposeAllocation(GstQuery *query)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QVideoSurfaceGstDelegate::flush()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
|
m_flush = true;
|
||||||
|
m_renderBuffer = 0;
|
||||||
|
m_renderCondition.wakeAll();
|
||||||
|
|
||||||
|
notify();
|
||||||
|
}
|
||||||
|
|
||||||
GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
|
GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
@@ -388,6 +399,8 @@ QGstVideoRendererSink *QGstVideoRendererSink::createSink(QAbstractVideoSurface *
|
|||||||
|
|
||||||
sink->delegate = new QVideoSurfaceGstDelegate(surface);
|
sink->delegate = new QVideoSurfaceGstDelegate(surface);
|
||||||
|
|
||||||
|
g_signal_connect(G_OBJECT(sink), "notify::show-preroll-frame", G_CALLBACK(handleShowPrerollChange), sink);
|
||||||
|
|
||||||
return sink;
|
return sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,13 +485,41 @@ void QGstVideoRendererSink::finalize(GObject *object)
|
|||||||
G_OBJECT_CLASS(sink_parent_class)->finalize(object);
|
G_OBJECT_CLASS(sink_parent_class)->finalize(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QGstVideoRendererSink::handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d)
|
||||||
|
{
|
||||||
|
Q_UNUSED(o);
|
||||||
|
Q_UNUSED(p);
|
||||||
|
QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(d);
|
||||||
|
|
||||||
|
gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
|
||||||
|
g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL);
|
||||||
|
|
||||||
|
if (!showPrerollFrame) {
|
||||||
|
GstState state = GST_STATE_VOID_PENDING;
|
||||||
|
gst_element_get_state(GST_ELEMENT(sink), &state, NULL, GST_CLOCK_TIME_NONE);
|
||||||
|
// show-preroll-frame being set to 'false' while in GST_STATE_PAUSED means
|
||||||
|
// the QMediaPlayer was stopped from the paused state.
|
||||||
|
// We need to flush the current frame.
|
||||||
|
if (state == GST_STATE_PAUSED)
|
||||||
|
sink->delegate->flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GstStateChangeReturn QGstVideoRendererSink::change_state(
|
GstStateChangeReturn QGstVideoRendererSink::change_state(
|
||||||
GstElement *element, GstStateChange transition)
|
GstElement *element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
Q_UNUSED(element);
|
QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(element);
|
||||||
|
|
||||||
return GST_ELEMENT_CLASS(sink_parent_class)->change_state(
|
gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
|
||||||
element, transition);
|
g_object_get(G_OBJECT(element), "show-preroll-frame", &showPrerollFrame, NULL);
|
||||||
|
|
||||||
|
// If show-preroll-frame is 'false' when transitioning from GST_STATE_PLAYING to
|
||||||
|
// GST_STATE_PAUSED, it means the QMediaPlayer was stopped.
|
||||||
|
// We need to flush the current frame.
|
||||||
|
if (transition == GST_STATE_CHANGE_PLAYING_TO_PAUSED && !showPrerollFrame)
|
||||||
|
sink->delegate->flush();
|
||||||
|
|
||||||
|
return GST_ELEMENT_CLASS(sink_parent_class)->change_state(element, transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
GstCaps *QGstVideoRendererSink::get_caps(GstBaseSink *base, GstCaps *filter)
|
GstCaps *QGstVideoRendererSink::get_caps(GstBaseSink *base, GstCaps *filter)
|
||||||
|
|||||||
@@ -184,6 +184,21 @@ void QVideoSurfaceGstDelegate::clearPoolBuffers()
|
|||||||
m_pool->clear();
|
m_pool->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QVideoSurfaceGstDelegate::flush()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
|
m_frame = QVideoFrame();
|
||||||
|
m_renderCondition.wakeAll();
|
||||||
|
|
||||||
|
if (QThread::currentThread() == thread()) {
|
||||||
|
if (!m_surface.isNull())
|
||||||
|
m_surface->present(m_frame);
|
||||||
|
} else {
|
||||||
|
QMetaObject::invokeMethod(this, "queuedFlush", Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
|
GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
|
||||||
{
|
{
|
||||||
if (!m_surface) {
|
if (!m_surface) {
|
||||||
@@ -244,6 +259,14 @@ void QVideoSurfaceGstDelegate::queuedStop()
|
|||||||
m_setupCondition.wakeAll();
|
m_setupCondition.wakeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QVideoSurfaceGstDelegate::queuedFlush()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
|
||||||
|
if (!m_surface.isNull())
|
||||||
|
m_surface->present(QVideoFrame());
|
||||||
|
}
|
||||||
|
|
||||||
void QVideoSurfaceGstDelegate::queuedRender()
|
void QVideoSurfaceGstDelegate::queuedRender()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
@@ -316,6 +339,8 @@ QVideoSurfaceGstSink *QVideoSurfaceGstSink::createSink(QAbstractVideoSurface *su
|
|||||||
|
|
||||||
sink->delegate = new QVideoSurfaceGstDelegate(surface);
|
sink->delegate = new QVideoSurfaceGstDelegate(surface);
|
||||||
|
|
||||||
|
g_signal_connect(G_OBJECT(sink), "notify::show-preroll-frame", G_CALLBACK(handleShowPrerollChange), sink);
|
||||||
|
|
||||||
return sink;
|
return sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,13 +445,40 @@ void QVideoSurfaceGstSink::finalize(GObject *object)
|
|||||||
G_OBJECT_CLASS(sink_parent_class)->finalize(object);
|
G_OBJECT_CLASS(sink_parent_class)->finalize(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
GstStateChangeReturn QVideoSurfaceGstSink::change_state(
|
void QVideoSurfaceGstSink::handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d)
|
||||||
GstElement *element, GstStateChange transition)
|
|
||||||
{
|
{
|
||||||
Q_UNUSED(element);
|
Q_UNUSED(o);
|
||||||
|
Q_UNUSED(p);
|
||||||
|
QVideoSurfaceGstSink *sink = reinterpret_cast<QVideoSurfaceGstSink *>(d);
|
||||||
|
|
||||||
return GST_ELEMENT_CLASS(sink_parent_class)->change_state(
|
gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
|
||||||
element, transition);
|
g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL);
|
||||||
|
|
||||||
|
if (!showPrerollFrame) {
|
||||||
|
GstState state = GST_STATE_VOID_PENDING;
|
||||||
|
gst_element_get_state(GST_ELEMENT(sink), &state, NULL, GST_CLOCK_TIME_NONE);
|
||||||
|
// show-preroll-frame being set to 'false' while in GST_STATE_PAUSED means
|
||||||
|
// the QMediaPlayer was stopped from the paused state.
|
||||||
|
// We need to flush the current frame.
|
||||||
|
if (state == GST_STATE_PAUSED)
|
||||||
|
sink->delegate->flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GstStateChangeReturn QVideoSurfaceGstSink::change_state(GstElement *element, GstStateChange transition)
|
||||||
|
{
|
||||||
|
QVideoSurfaceGstSink *sink = reinterpret_cast<QVideoSurfaceGstSink *>(element);
|
||||||
|
|
||||||
|
gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
|
||||||
|
g_object_get(G_OBJECT(element), "show-preroll-frame", &showPrerollFrame, NULL);
|
||||||
|
|
||||||
|
// If show-preroll-frame is 'false' when transitioning from GST_STATE_PLAYING to
|
||||||
|
// GST_STATE_PAUSED, it means the QMediaPlayer was stopped.
|
||||||
|
// We need to flush the current frame.
|
||||||
|
if (transition == GST_STATE_CHANGE_PLAYING_TO_PAUSED && !showPrerollFrame)
|
||||||
|
sink->delegate->flush();
|
||||||
|
|
||||||
|
return GST_ELEMENT_CLASS(sink_parent_class)->change_state(element, transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
|
GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
|
||||||
|
|||||||
@@ -113,7 +113,10 @@ bool QDeclarativeCameraFlash::isFlashReady() const
|
|||||||
\row \li Camera.FlashAuto \li Automatic flash.
|
\row \li Camera.FlashAuto \li Automatic flash.
|
||||||
\row \li Camera.FlashRedEyeReduction \li Red eye reduction flash.
|
\row \li Camera.FlashRedEyeReduction \li Red eye reduction flash.
|
||||||
\row \li Camera.FlashFill \li Use flash to fillin shadows.
|
\row \li Camera.FlashFill \li Use flash to fillin shadows.
|
||||||
\row \li Camera.FlashTorch \li Constant light source, useful for focusing and video capture.
|
\row \li Camera.FlashTorch \li Constant light source. If supported, torch can be
|
||||||
|
enabled without loading the camera.
|
||||||
|
\row \li Camera.FlashVideoLight \li Constant light source, useful for video capture.
|
||||||
|
The light is turned on only while the camera is active.
|
||||||
\row \li Camera.FlashSlowSyncFrontCurtain
|
\row \li Camera.FlashSlowSyncFrontCurtain
|
||||||
\li Use the flash in conjunction with a slow shutter speed.
|
\li Use the flash in conjunction with a slow shutter speed.
|
||||||
This mode allows better exposure of distant objects and/or motion blur effect.
|
This mode allows better exposure of distant objects and/or motion blur effect.
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ QCameraViewfinderSettingsControl::~QCameraViewfinderSettingsControl()
|
|||||||
Viewfinder pixel format, QVideoFrame::PixelFormat
|
Viewfinder pixel format, QVideoFrame::PixelFormat
|
||||||
\value UserParameter
|
\value UserParameter
|
||||||
The base value for platform specific extended parameters.
|
The base value for platform specific extended parameters.
|
||||||
For such parameters the sequential values starting from UserParameter shuld be used.
|
For such parameters the sequential values starting from UserParameter should be used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -130,6 +130,11 @@
|
|||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\section2 Platform Notes
|
\section2 Platform Notes
|
||||||
|
|
||||||
|
The \l{Qt Multimedia Backends} wiki provides a summary of features
|
||||||
|
supported by each platform plugin made available by this module. The
|
||||||
|
following topics provide more platform-specific information.
|
||||||
|
|
||||||
\list
|
\list
|
||||||
\li \l{Qt Multimedia on BlackBerry}{BlackBerry}
|
\li \l{Qt Multimedia on BlackBerry}{BlackBerry}
|
||||||
\li \l{Qt Multimedia on Windows}{Windows}
|
\li \l{Qt Multimedia on Windows}{Windows}
|
||||||
|
|||||||
@@ -99,6 +99,8 @@ public:
|
|||||||
void unlock();
|
void unlock();
|
||||||
bool proposeAllocation(GstQuery *query);
|
bool proposeAllocation(GstQuery *query);
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
|
||||||
GstFlowReturn render(GstBuffer *buffer);
|
GstFlowReturn render(GstBuffer *buffer);
|
||||||
|
|
||||||
bool event(QEvent *event);
|
bool event(QEvent *event);
|
||||||
@@ -145,6 +147,8 @@ private:
|
|||||||
|
|
||||||
static void finalize(GObject *object);
|
static void finalize(GObject *object);
|
||||||
|
|
||||||
|
static void handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d);
|
||||||
|
|
||||||
static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
|
static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
|
||||||
|
|
||||||
static GstCaps *get_caps(GstBaseSink *sink, GstCaps *filter);
|
static GstCaps *get_caps(GstBaseSink *sink, GstCaps *filter);
|
||||||
|
|||||||
@@ -96,11 +96,14 @@ public:
|
|||||||
QMutex *poolMutex() { return &m_poolMutex; }
|
QMutex *poolMutex() { return &m_poolMutex; }
|
||||||
void clearPoolBuffers();
|
void clearPoolBuffers();
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
|
||||||
GstFlowReturn render(GstBuffer *buffer);
|
GstFlowReturn render(GstBuffer *buffer);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void queuedStart();
|
void queuedStart();
|
||||||
void queuedStop();
|
void queuedStop();
|
||||||
|
void queuedFlush();
|
||||||
void queuedRender();
|
void queuedRender();
|
||||||
|
|
||||||
void updateSupportedFormats();
|
void updateSupportedFormats();
|
||||||
@@ -139,6 +142,8 @@ private:
|
|||||||
|
|
||||||
static void finalize(GObject *object);
|
static void finalize(GObject *object);
|
||||||
|
|
||||||
|
static void handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d);
|
||||||
|
|
||||||
static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
|
static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
|
||||||
|
|
||||||
static GstCaps *get_caps(GstBaseSink *sink);
|
static GstCaps *get_caps(GstBaseSink *sink);
|
||||||
|
|||||||
@@ -277,17 +277,18 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QSize currentViewfinderResolution = m_camera->previewSize();
|
QSize currentViewfinderResolution = m_camera->previewSize();
|
||||||
const qreal aspectRatio = qreal(captureSize.width()) / qreal(captureSize.height());
|
|
||||||
if (currentViewfinderResolution.isValid() &&
|
|
||||||
qAbs(aspectRatio - (qreal(currentViewfinderResolution.width()) / currentViewfinderResolution.height())) < 0.01) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize adjustedViewfinderResolution;
|
QSize adjustedViewfinderResolution;
|
||||||
|
|
||||||
|
if (m_captureMode.testFlag(QCamera::CaptureVideo) && m_camera->getPreferredPreviewSizeForVideo().isEmpty()) {
|
||||||
|
// According to the Android doc, if getPreferredPreviewSizeForVideo() returns null, it means
|
||||||
|
// the preview size cannot be different from the capture size
|
||||||
|
adjustedViewfinderResolution = captureSize;
|
||||||
|
} else {
|
||||||
|
// search for viewfinder resolution with the same aspect ratio
|
||||||
|
const qreal aspectRatio = qreal(captureSize.width()) / qreal(captureSize.height());
|
||||||
QList<QSize> previewSizes = m_camera->getSupportedPreviewSizes();
|
QList<QSize> previewSizes = m_camera->getSupportedPreviewSizes();
|
||||||
for (int i = previewSizes.count() - 1; i >= 0; --i) {
|
for (int i = previewSizes.count() - 1; i >= 0; --i) {
|
||||||
const QSize &size = previewSizes.at(i);
|
const QSize &size = previewSizes.at(i);
|
||||||
// search for viewfinder resolution with the same aspect ratio
|
|
||||||
if (qAbs(aspectRatio - (qreal(size.width()) / size.height())) < 0.01) {
|
if (qAbs(aspectRatio - (qreal(size.width()) / size.height())) < 0.01) {
|
||||||
adjustedViewfinderResolution = size;
|
adjustedViewfinderResolution = size;
|
||||||
break;
|
break;
|
||||||
@@ -298,6 +299,7 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool
|
|||||||
qWarning("Cannot find a viewfinder resolution matching the capture aspect ratio.");
|
qWarning("Cannot find a viewfinder resolution matching the capture aspect ratio.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (currentViewfinderResolution != adjustedViewfinderResolution) {
|
if (currentViewfinderResolution != adjustedViewfinderResolution) {
|
||||||
if (m_videoOutput)
|
if (m_videoOutput)
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ QAndroidCaptureSession::QAndroidCaptureSession(QAndroidCameraSession *cameraSess
|
|||||||
, m_duration(0)
|
, m_duration(0)
|
||||||
, m_state(QMediaRecorder::StoppedState)
|
, m_state(QMediaRecorder::StoppedState)
|
||||||
, m_status(QMediaRecorder::UnloadedStatus)
|
, m_status(QMediaRecorder::UnloadedStatus)
|
||||||
, m_resolutionDirty(false)
|
|
||||||
, m_containerFormatDirty(true)
|
, m_containerFormatDirty(true)
|
||||||
, m_videoSettingsDirty(true)
|
, m_videoSettingsDirty(true)
|
||||||
, m_audioSettingsDirty(true)
|
, m_audioSettingsDirty(true)
|
||||||
@@ -321,9 +320,6 @@ void QAndroidCaptureSession::setVideoSettings(const QVideoEncoderSettings &setti
|
|||||||
if (!m_cameraSession || m_videoSettings == settings)
|
if (!m_cameraSession || m_videoSettings == settings)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_videoSettings.resolution() != settings.resolution())
|
|
||||||
m_resolutionDirty = true;
|
|
||||||
|
|
||||||
m_videoSettings = settings;
|
m_videoSettings = settings;
|
||||||
m_videoSettingsDirty = true;
|
m_videoSettingsDirty = true;
|
||||||
}
|
}
|
||||||
@@ -376,7 +372,6 @@ void QAndroidCaptureSession::applySettings()
|
|||||||
if (m_cameraSession && m_cameraSession->camera() && m_videoSettingsDirty) {
|
if (m_cameraSession && m_cameraSession->camera() && m_videoSettingsDirty) {
|
||||||
if (m_videoSettings.resolution().isEmpty()) {
|
if (m_videoSettings.resolution().isEmpty()) {
|
||||||
m_videoSettings.setResolution(m_defaultSettings.videoResolution);
|
m_videoSettings.setResolution(m_defaultSettings.videoResolution);
|
||||||
m_resolutionDirty = true;
|
|
||||||
} else if (!m_supportedResolutions.contains(m_videoSettings.resolution())) {
|
} else if (!m_supportedResolutions.contains(m_videoSettings.resolution())) {
|
||||||
// if the requested resolution is not supported, find the closest one
|
// if the requested resolution is not supported, find the closest one
|
||||||
QSize reqSize = m_videoSettings.resolution();
|
QSize reqSize = m_videoSettings.resolution();
|
||||||
@@ -388,7 +383,6 @@ void QAndroidCaptureSession::applySettings()
|
|||||||
}
|
}
|
||||||
int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount);
|
int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount);
|
||||||
m_videoSettings.setResolution(m_supportedResolutions.at(closestIndex));
|
m_videoSettings.setResolution(m_supportedResolutions.at(closestIndex));
|
||||||
m_resolutionDirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_videoSettings.frameRate() <= 0)
|
if (m_videoSettings.frameRate() <= 0)
|
||||||
@@ -413,12 +407,8 @@ void QAndroidCaptureSession::applySettings()
|
|||||||
|
|
||||||
void QAndroidCaptureSession::updateViewfinder()
|
void QAndroidCaptureSession::updateViewfinder()
|
||||||
{
|
{
|
||||||
if (!m_resolutionDirty)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_cameraSession->camera()->stopPreview();
|
m_cameraSession->camera()->stopPreview();
|
||||||
m_cameraSession->adjustViewfinderSize(m_videoSettings.resolution(), false);
|
m_cameraSession->adjustViewfinderSize(m_videoSettings.resolution(), false);
|
||||||
m_resolutionDirty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidCaptureSession::restartViewfinder()
|
void QAndroidCaptureSession::restartViewfinder()
|
||||||
|
|||||||
@@ -161,7 +161,6 @@ private:
|
|||||||
QString m_containerFormat;
|
QString m_containerFormat;
|
||||||
QAudioEncoderSettings m_audioSettings;
|
QAudioEncoderSettings m_audioSettings;
|
||||||
QVideoEncoderSettings m_videoSettings;
|
QVideoEncoderSettings m_videoSettings;
|
||||||
bool m_resolutionDirty;
|
|
||||||
bool m_containerFormatDirty;
|
bool m_containerFormatDirty;
|
||||||
bool m_videoSettingsDirty;
|
bool m_videoSettingsDirty;
|
||||||
bool m_audioSettingsDirty;
|
bool m_audioSettingsDirty;
|
||||||
|
|||||||
@@ -786,6 +786,9 @@ QSize AndroidCameraPrivate::getPreferredPreviewSizeForVideo()
|
|||||||
QJNIObjectPrivate size = m_parameters.callObjectMethod("getPreferredPreviewSizeForVideo",
|
QJNIObjectPrivate size = m_parameters.callObjectMethod("getPreferredPreviewSizeForVideo",
|
||||||
"()Landroid/hardware/Camera$Size;");
|
"()Landroid/hardware/Camera$Size;");
|
||||||
|
|
||||||
|
if (!size.isValid())
|
||||||
|
return QSize();
|
||||||
|
|
||||||
return QSize(size.getField<jint>("width"), size.getField<jint>("height"));
|
return QSize(size.getField<jint>("width"), size.getField<jint>("height"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ public:
|
|||||||
|
|
||||||
AVCaptureVideoDataOutput *videoDataOutput() const;
|
AVCaptureVideoDataOutput *videoDataOutput() const;
|
||||||
|
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
AVFCaptureFramesDelegate *captureDelegate() const;
|
||||||
|
void resetCaptureDelegate() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void surfaceChanged(QAbstractVideoSurface *surface);
|
void surfaceChanged(QAbstractVideoSurface *surface);
|
||||||
|
|
||||||
@@ -80,6 +85,7 @@ private:
|
|||||||
|
|
||||||
QVideoFrame m_lastViewfinderFrame;
|
QVideoFrame m_lastViewfinderFrame;
|
||||||
QMutex m_vfMutex;
|
QMutex m_vfMutex;
|
||||||
|
dispatch_queue_t m_delegateQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ private:
|
|||||||
- (void) captureOutput:(AVCaptureOutput *)captureOutput
|
- (void) captureOutput:(AVCaptureOutput *)captureOutput
|
||||||
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
fromConnection:(AVCaptureConnection *)connection;
|
fromConnection:(AVCaptureConnection *)connection;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AVFCaptureFramesDelegate
|
@implementation AVFCaptureFramesDelegate
|
||||||
@@ -163,25 +164,23 @@ private:
|
|||||||
Q_UNUSED(connection);
|
Q_UNUSED(connection);
|
||||||
Q_UNUSED(captureOutput);
|
Q_UNUSED(captureOutput);
|
||||||
|
|
||||||
|
// NB: on iOS captureOutput/connection can be nil (when recording a video -
|
||||||
|
// avfmediaassetwriter).
|
||||||
|
|
||||||
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
||||||
|
|
||||||
int width = CVPixelBufferGetWidth(imageBuffer);
|
int width = CVPixelBufferGetWidth(imageBuffer);
|
||||||
int height = CVPixelBufferGetHeight(imageBuffer);
|
int height = CVPixelBufferGetHeight(imageBuffer);
|
||||||
|
QVideoFrame::PixelFormat format =
|
||||||
|
AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat(CVPixelBufferGetPixelFormatType(imageBuffer));
|
||||||
|
|
||||||
QAbstractVideoBuffer *buffer = new CVPixelBufferVideoBuffer(imageBuffer);
|
if (format == QVideoFrame::Format_Invalid)
|
||||||
|
return;
|
||||||
|
|
||||||
QVideoFrame::PixelFormat format = QVideoFrame::Format_RGB32;
|
QVideoFrame frame(new CVPixelBufferVideoBuffer(imageBuffer), QSize(width, height), format);
|
||||||
if ([captureOutput isKindOfClass:[AVCaptureVideoDataOutput class]]) {
|
|
||||||
NSDictionary *settings = ((AVCaptureVideoDataOutput *)captureOutput).videoSettings;
|
|
||||||
if (settings && [settings objectForKey:(id)kCVPixelBufferPixelFormatTypeKey]) {
|
|
||||||
NSNumber *avf = [settings objectForKey:(id)kCVPixelBufferPixelFormatTypeKey];
|
|
||||||
format = AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat([avf unsignedIntValue]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVideoFrame frame(buffer, QSize(width, height), format);
|
|
||||||
m_renderer->syncHandleViewfinderFrame(frame);
|
m_renderer->syncHandleViewfinderFrame(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@@ -197,6 +196,8 @@ AVFCameraRendererControl::~AVFCameraRendererControl()
|
|||||||
{
|
{
|
||||||
[m_cameraSession->captureSession() removeOutput:m_videoDataOutput];
|
[m_cameraSession->captureSession() removeOutput:m_videoDataOutput];
|
||||||
[m_viewfinderFramesDelegate release];
|
[m_viewfinderFramesDelegate release];
|
||||||
|
if (m_delegateQueue)
|
||||||
|
dispatch_release(m_delegateQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAbstractVideoSurface *AVFCameraRendererControl::surface() const
|
QAbstractVideoSurface *AVFCameraRendererControl::surface() const
|
||||||
@@ -223,17 +224,10 @@ void AVFCameraRendererControl::configureAVCaptureSession(AVFCameraSession *camer
|
|||||||
m_videoDataOutput = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
|
m_videoDataOutput = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
|
||||||
|
|
||||||
// Configure video output
|
// Configure video output
|
||||||
dispatch_queue_t queue = dispatch_queue_create("vf_queue", NULL);
|
m_delegateQueue = dispatch_queue_create("vf_queue", NULL);
|
||||||
[m_videoDataOutput
|
[m_videoDataOutput
|
||||||
setSampleBufferDelegate:m_viewfinderFramesDelegate
|
setSampleBufferDelegate:m_viewfinderFramesDelegate
|
||||||
queue:queue];
|
queue:m_delegateQueue];
|
||||||
dispatch_release(queue);
|
|
||||||
|
|
||||||
// Specify the pixel format
|
|
||||||
m_videoDataOutput.videoSettings =
|
|
||||||
[NSDictionary dictionaryWithObject:
|
|
||||||
[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
|
|
||||||
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
|
|
||||||
|
|
||||||
[m_cameraSession->captureSession() addOutput:m_videoDataOutput];
|
[m_cameraSession->captureSession() addOutput:m_videoDataOutput];
|
||||||
}
|
}
|
||||||
@@ -291,6 +285,20 @@ AVCaptureVideoDataOutput *AVFCameraRendererControl::videoDataOutput() const
|
|||||||
return m_videoDataOutput;
|
return m_videoDataOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
|
||||||
|
AVFCaptureFramesDelegate *AVFCameraRendererControl::captureDelegate() const
|
||||||
|
{
|
||||||
|
return m_viewfinderFramesDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFCameraRendererControl::resetCaptureDelegate() const
|
||||||
|
{
|
||||||
|
[m_videoDataOutput setSampleBufferDelegate:m_viewfinderFramesDelegate queue:m_delegateQueue];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void AVFCameraRendererControl::handleViewfinderFrame()
|
void AVFCameraRendererControl::handleViewfinderFrame()
|
||||||
{
|
{
|
||||||
QVideoFrame frame;
|
QVideoFrame frame;
|
||||||
@@ -301,8 +309,10 @@ void AVFCameraRendererControl::handleViewfinderFrame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_surface && frame.isValid()) {
|
if (m_surface && frame.isValid()) {
|
||||||
if (m_surface->isActive() && m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat())
|
if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat()
|
||||||
|
|| m_surface->surfaceFormat().frameSize() != frame.size())) {
|
||||||
m_surface->stop();
|
m_surface->stop();
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_surface->isActive()) {
|
if (!m_surface->isActive()) {
|
||||||
QVideoSurfaceFormat format(frame.size(), frame.pixelFormat());
|
QVideoSurfaceFormat format(frame.size(), frame.pixelFormat());
|
||||||
|
|||||||
@@ -41,13 +41,13 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QCameraControl;
|
class QCameraControl;
|
||||||
|
class QMediaRecorderControl;
|
||||||
class AVFCameraControl;
|
class AVFCameraControl;
|
||||||
class AVFCameraInfoControl;
|
class AVFCameraInfoControl;
|
||||||
class AVFCameraMetaDataControl;
|
class AVFCameraMetaDataControl;
|
||||||
class AVFVideoWindowControl;
|
class AVFVideoWindowControl;
|
||||||
class AVFVideoWidgetControl;
|
class AVFVideoWidgetControl;
|
||||||
class AVFCameraRendererControl;
|
class AVFCameraRendererControl;
|
||||||
class AVFMediaRecorderControl;
|
|
||||||
class AVFImageCaptureControl;
|
class AVFImageCaptureControl;
|
||||||
class AVFCameraSession;
|
class AVFCameraSession;
|
||||||
class AVFCameraDeviceControl;
|
class AVFCameraDeviceControl;
|
||||||
@@ -59,6 +59,8 @@ class AVFCameraViewfinderSettingsControl2;
|
|||||||
class AVFCameraViewfinderSettingsControl;
|
class AVFCameraViewfinderSettingsControl;
|
||||||
class AVFImageEncoderControl;
|
class AVFImageEncoderControl;
|
||||||
class AVFCameraFlashControl;
|
class AVFCameraFlashControl;
|
||||||
|
class AVFMediaRecorderControl;
|
||||||
|
class AVFMediaRecorderControlIOS;
|
||||||
|
|
||||||
class AVFCameraService : public QMediaService
|
class AVFCameraService : public QMediaService
|
||||||
{
|
{
|
||||||
@@ -75,7 +77,8 @@ public:
|
|||||||
AVFCameraDeviceControl *videoDeviceControl() const { return m_videoDeviceControl; }
|
AVFCameraDeviceControl *videoDeviceControl() const { return m_videoDeviceControl; }
|
||||||
AVFAudioInputSelectorControl *audioInputSelectorControl() const { return m_audioInputSelectorControl; }
|
AVFAudioInputSelectorControl *audioInputSelectorControl() const { return m_audioInputSelectorControl; }
|
||||||
AVFCameraMetaDataControl *metaDataControl() const { return m_metaDataControl; }
|
AVFCameraMetaDataControl *metaDataControl() const { return m_metaDataControl; }
|
||||||
AVFMediaRecorderControl *recorderControl() const { return m_recorderControl; }
|
AVFMediaRecorderControl *recorderControl() const;
|
||||||
|
AVFMediaRecorderControlIOS *recorderControlIOS() const;
|
||||||
AVFImageCaptureControl *imageCaptureControl() const { return m_imageCaptureControl; }
|
AVFImageCaptureControl *imageCaptureControl() const { return m_imageCaptureControl; }
|
||||||
AVFCameraFocusControl *cameraFocusControl() const { return m_cameraFocusControl; }
|
AVFCameraFocusControl *cameraFocusControl() const { return m_cameraFocusControl; }
|
||||||
AVFCameraExposureControl *cameraExposureControl() const {return m_cameraExposureControl; }
|
AVFCameraExposureControl *cameraExposureControl() const {return m_cameraExposureControl; }
|
||||||
@@ -94,7 +97,7 @@ private:
|
|||||||
AVFAudioInputSelectorControl *m_audioInputSelectorControl;
|
AVFAudioInputSelectorControl *m_audioInputSelectorControl;
|
||||||
AVFCameraRendererControl *m_videoOutput;
|
AVFCameraRendererControl *m_videoOutput;
|
||||||
AVFCameraMetaDataControl *m_metaDataControl;
|
AVFCameraMetaDataControl *m_metaDataControl;
|
||||||
AVFMediaRecorderControl *m_recorderControl;
|
QMediaRecorderControl *m_recorderControl;
|
||||||
AVFImageCaptureControl *m_imageCaptureControl;
|
AVFImageCaptureControl *m_imageCaptureControl;
|
||||||
AVFCameraFocusControl *m_cameraFocusControl;
|
AVFCameraFocusControl *m_cameraFocusControl;
|
||||||
AVFCameraExposureControl *m_cameraExposureControl;
|
AVFCameraExposureControl *m_cameraExposureControl;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
|
|
||||||
#ifdef Q_OS_IOS
|
#ifdef Q_OS_IOS
|
||||||
#include "avfcamerazoomcontrol.h"
|
#include "avfcamerazoomcontrol.h"
|
||||||
|
#include "avfmediarecordercontrol_ios.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <private/qmediaplaylistnavigator_p.h>
|
#include <private/qmediaplaylistnavigator_p.h>
|
||||||
@@ -74,7 +75,14 @@ AVFCameraService::AVFCameraService(QObject *parent):
|
|||||||
m_audioInputSelectorControl = new AVFAudioInputSelectorControl(this);
|
m_audioInputSelectorControl = new AVFAudioInputSelectorControl(this);
|
||||||
|
|
||||||
m_metaDataControl = new AVFCameraMetaDataControl(this);
|
m_metaDataControl = new AVFCameraMetaDataControl(this);
|
||||||
|
#ifndef Q_OS_IOS
|
||||||
|
// This will connect a slot to 'captureModeChanged'
|
||||||
|
// and will break viewfinder by attaching AVCaptureMovieFileOutput
|
||||||
|
// in this slot.
|
||||||
m_recorderControl = new AVFMediaRecorderControl(this);
|
m_recorderControl = new AVFMediaRecorderControl(this);
|
||||||
|
#else
|
||||||
|
m_recorderControl = new AVFMediaRecorderControlIOS(this);
|
||||||
|
#endif
|
||||||
m_imageCaptureControl = new AVFImageCaptureControl(this);
|
m_imageCaptureControl = new AVFImageCaptureControl(this);
|
||||||
m_cameraFocusControl = new AVFCameraFocusControl(this);
|
m_cameraFocusControl = new AVFCameraFocusControl(this);
|
||||||
m_cameraExposureControl = 0;
|
m_cameraExposureControl = 0;
|
||||||
@@ -97,6 +105,10 @@ AVFCameraService::~AVFCameraService()
|
|||||||
{
|
{
|
||||||
m_cameraControl->setState(QCamera::UnloadedState);
|
m_cameraControl->setState(QCamera::UnloadedState);
|
||||||
|
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
delete m_recorderControl;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (m_videoOutput) {
|
if (m_videoOutput) {
|
||||||
m_session->setVideoOutput(0);
|
m_session->setVideoOutput(0);
|
||||||
delete m_videoOutput;
|
delete m_videoOutput;
|
||||||
@@ -205,4 +217,23 @@ void AVFCameraService::releaseControl(QMediaControl *control)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AVFMediaRecorderControl *AVFCameraService::recorderControl() const
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_IOS
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return static_cast<AVFMediaRecorderControl *>(m_recorderControl);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
AVFMediaRecorderControlIOS *AVFCameraService::recorderControlIOS() const
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_OSX
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return static_cast<AVFMediaRecorderControlIOS *>(m_recorderControl);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "moc_avfcameraservice.cpp"
|
#include "moc_avfcameraservice.cpp"
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ public:
|
|||||||
void removeProbe(AVFMediaVideoProbeControl *probe);
|
void removeProbe(AVFMediaVideoProbeControl *probe);
|
||||||
FourCharCode defaultCodec();
|
FourCharCode defaultCodec();
|
||||||
|
|
||||||
|
AVCaptureDeviceInput *videoInput() const {return m_videoInput;}
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void setState(QCamera::State state);
|
void setState(QCamera::State state);
|
||||||
|
|
||||||
|
|||||||
@@ -283,12 +283,12 @@ void AVFCameraSession::setState(QCamera::State newState)
|
|||||||
|
|
||||||
if (m_state == QCamera::ActiveState) {
|
if (m_state == QCamera::ActiveState) {
|
||||||
Q_EMIT readyToConfigureConnections();
|
Q_EMIT readyToConfigureConnections();
|
||||||
[m_captureSession commitConfiguration];
|
|
||||||
[m_captureSession startRunning];
|
|
||||||
m_defaultCodec = 0;
|
m_defaultCodec = 0;
|
||||||
defaultCodec();
|
defaultCodec();
|
||||||
applyImageEncoderSettings();
|
applyImageEncoderSettings();
|
||||||
applyViewfinderSettings();
|
applyViewfinderSettings();
|
||||||
|
[m_captureSession commitConfiguration];
|
||||||
|
[m_captureSession startRunning];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldState == QCamera::ActiveState) {
|
if (oldState == QCamera::ActiveState) {
|
||||||
@@ -374,7 +374,6 @@ void AVFCameraSession::applyViewfinderSettings()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vfSettings.isNull())
|
|
||||||
vfControl->applySettings();
|
vfControl->applySettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,74 @@ private:
|
|||||||
bool m_locked;
|
bool m_locked;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AVFObjectDeleter {
|
||||||
|
static void cleanup(NSObject *obj)
|
||||||
|
{
|
||||||
|
if (obj)
|
||||||
|
[obj release];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class AVFScopedPointer : public QScopedPointer<NSObject, AVFObjectDeleter>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AVFScopedPointer() {}
|
||||||
|
explicit AVFScopedPointer(T *ptr) : QScopedPointer(ptr) {}
|
||||||
|
operator T*() const
|
||||||
|
{
|
||||||
|
// Quite handy operator to enable Obj-C messages: [ptr someMethod];
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
|
T *data() const
|
||||||
|
{
|
||||||
|
return static_cast<T *>(QScopedPointer::data());
|
||||||
|
}
|
||||||
|
|
||||||
|
T *take()
|
||||||
|
{
|
||||||
|
return static_cast<T *>(QScopedPointer::take());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class AVFScopedPointer<dispatch_queue_t>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AVFScopedPointer() : m_queue(0) {}
|
||||||
|
explicit AVFScopedPointer(dispatch_queue_t q) : m_queue(q) {}
|
||||||
|
|
||||||
|
~AVFScopedPointer()
|
||||||
|
{
|
||||||
|
if (m_queue)
|
||||||
|
dispatch_release(m_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator dispatch_queue_t() const
|
||||||
|
{
|
||||||
|
// Quite handy operator to enable Obj-C messages: [ptr someMethod];
|
||||||
|
return m_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch_queue_t data() const
|
||||||
|
{
|
||||||
|
return m_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(dispatch_queue_t q = 0)
|
||||||
|
{
|
||||||
|
if (m_queue)
|
||||||
|
dispatch_release(m_queue);
|
||||||
|
m_queue = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
dispatch_queue_t m_queue;
|
||||||
|
|
||||||
|
Q_DISABLE_COPY(AVFScopedPointer);
|
||||||
|
};
|
||||||
|
|
||||||
inline QSysInfo::MacVersion qt_OS_limit(QSysInfo::MacVersion osxVersion,
|
inline QSysInfo::MacVersion qt_OS_limit(QSysInfo::MacVersion osxVersion,
|
||||||
QSysInfo::MacVersion iosVersion)
|
QSysInfo::MacVersion iosVersion)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ AVFPSRange qt_connection_framerates(AVCaptureConnection *videoConnection)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_5_0)
|
||||||
|
#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
|
||||||
|
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
if (videoConnection.supportsVideoMaxFrameDuration) {
|
if (videoConnection.supportsVideoMaxFrameDuration) {
|
||||||
const CMTime cmMax = videoConnection.videoMaxFrameDuration;
|
const CMTime cmMax = videoConnection.videoMaxFrameDuration;
|
||||||
if (CMTimeCompare(cmMax, kCMTimeInvalid)) {
|
if (CMTimeCompare(cmMax, kCMTimeInvalid)) {
|
||||||
@@ -66,6 +71,8 @@ AVFPSRange qt_connection_framerates(AVCaptureConnection *videoConnection)
|
|||||||
newRange.first = 1. / maxSeconds;
|
newRange.first = 1. / maxSeconds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return newRange;
|
return newRange;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,32 +76,41 @@ void qt_set_framerate_limits(AVCaptureConnection *videoConnection,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const qreal minFPS = settings.minimumFrameRate();
|
|
||||||
const qreal maxFPS = settings.maximumFrameRate();
|
const qreal maxFPS = settings.maximumFrameRate();
|
||||||
|
|
||||||
CMTime minDuration = kCMTimeInvalid;
|
CMTime minDuration = kCMTimeInvalid;
|
||||||
CMTime maxDuration = kCMTimeInvalid;
|
if (maxFPS > 0.) {
|
||||||
if (minFPS > 0. || maxFPS > 0.) {
|
|
||||||
if (maxFPS) {
|
|
||||||
if (!videoConnection.supportsVideoMinFrameDuration)
|
if (!videoConnection.supportsVideoMinFrameDuration)
|
||||||
qDebugCamera() << Q_FUNC_INFO << "maximum framerate is not supported";
|
qDebugCamera() << Q_FUNC_INFO << "maximum framerate is not supported";
|
||||||
else
|
else
|
||||||
minDuration = CMTimeMake(1, maxFPS);
|
minDuration = CMTimeMake(1, maxFPS);
|
||||||
}
|
}
|
||||||
|
if (videoConnection.supportsVideoMinFrameDuration)
|
||||||
|
videoConnection.videoMinFrameDuration = minDuration;
|
||||||
|
|
||||||
if (minFPS) {
|
const qreal minFPS = settings.minimumFrameRate();
|
||||||
|
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_5_0)
|
||||||
|
#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
|
||||||
|
if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_9) {
|
||||||
|
if (minFPS > 0.)
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
CMTime maxDuration = kCMTimeInvalid;
|
||||||
|
if (minFPS > 0.) {
|
||||||
if (!videoConnection.supportsVideoMaxFrameDuration)
|
if (!videoConnection.supportsVideoMaxFrameDuration)
|
||||||
qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
|
qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
|
||||||
else
|
else
|
||||||
maxDuration = CMTimeMake(1, minFPS);
|
maxDuration = CMTimeMake(1, minFPS);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (videoConnection.supportsVideoMinFrameDuration)
|
|
||||||
videoConnection.videoMinFrameDuration = minDuration;
|
|
||||||
if (videoConnection.supportsVideoMaxFrameDuration)
|
if (videoConnection.supportsVideoMaxFrameDuration)
|
||||||
videoConnection.videoMaxFrameDuration = maxDuration;
|
videoConnection.videoMaxFrameDuration = maxDuration;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (minFPS > 0.)
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
|
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
|
||||||
|
|
||||||
@@ -171,12 +180,21 @@ void qt_set_framerate_limits(AVCaptureDevice *captureDevice,
|
|||||||
#ifdef Q_OS_IOS
|
#ifdef Q_OS_IOS
|
||||||
[captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
|
[captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
|
||||||
[captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
|
[captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
|
||||||
#else
|
#else // Q_OS_OSX
|
||||||
|
|
||||||
if (CMTimeCompare(minFrameDuration, kCMTimeInvalid))
|
if (CMTimeCompare(minFrameDuration, kCMTimeInvalid))
|
||||||
[captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
|
[captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
|
||||||
|
|
||||||
|
#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
|
||||||
|
#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
|
||||||
|
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid))
|
if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid))
|
||||||
[captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
|
[captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
|
||||||
#endif
|
}
|
||||||
|
#endif // QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
|
||||||
|
#endif // Q_OS_OSX
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // Platform SDK >= 10.9, >= 7.0.
|
#endif // Platform SDK >= 10.9, >= 7.0.
|
||||||
@@ -197,15 +215,23 @@ AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnec
|
|||||||
fps.second = 1. / minSeconds; // Max FPS = 1 / MinDuration.
|
fps.second = 1. / minSeconds; // Max FPS = 1 / MinDuration.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
|
||||||
|
#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
|
||||||
|
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration;
|
const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration;
|
||||||
if (CMTimeCompare(maxDuration, kCMTimeInvalid)) {
|
if (CMTimeCompare(maxDuration, kCMTimeInvalid)) {
|
||||||
if (const Float64 maxSeconds = CMTimeGetSeconds(maxDuration))
|
if (const Float64 maxSeconds = CMTimeGetSeconds(maxDuration))
|
||||||
fps.first = 1. / maxSeconds; // Min FPS = 1 / MaxDuration.
|
fps.first = 1. / maxSeconds; // Min FPS = 1 / MaxDuration.
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif // QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
#else
|
#else // OSX < 10.7 or iOS < 7.0
|
||||||
{
|
{
|
||||||
#endif
|
#endif // QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
|
||||||
fps = qt_connection_framerates(videoConnection);
|
fps = qt_connection_framerates(videoConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,13 +485,7 @@ QVector<QVideoFrame::PixelFormat> AVFCameraViewfinderSettingsControl2::viewfinde
|
|||||||
Q_ASSERT(m_videoOutput);
|
Q_ASSERT(m_videoOutput);
|
||||||
|
|
||||||
QVector<QVideoFrame::PixelFormat> qtFormats;
|
QVector<QVideoFrame::PixelFormat> qtFormats;
|
||||||
QList<QVideoFrame::PixelFormat> filter;
|
|
||||||
|
|
||||||
NSArray *pixelFormats = [m_videoOutput availableVideoCVPixelFormatTypes];
|
NSArray *pixelFormats = [m_videoOutput availableVideoCVPixelFormatTypes];
|
||||||
const QAbstractVideoSurface *surface = m_service->videoOutput() ? m_service->videoOutput()->surface() : 0;
|
|
||||||
|
|
||||||
if (surface)
|
|
||||||
filter = surface->supportedPixelFormats();
|
|
||||||
|
|
||||||
for (NSObject *obj in pixelFormats) {
|
for (NSObject *obj in pixelFormats) {
|
||||||
if (![obj isKindOfClass:[NSNumber class]])
|
if (![obj isKindOfClass:[NSNumber class]])
|
||||||
@@ -474,7 +494,7 @@ QVector<QVideoFrame::PixelFormat> AVFCameraViewfinderSettingsControl2::viewfinde
|
|||||||
NSNumber *formatAsNSNumber = static_cast<NSNumber *>(obj);
|
NSNumber *formatAsNSNumber = static_cast<NSNumber *>(obj);
|
||||||
// It's actually FourCharCode (== UInt32):
|
// It's actually FourCharCode (== UInt32):
|
||||||
const QVideoFrame::PixelFormat qtFormat(QtPixelFormatFromCVFormat([formatAsNSNumber unsignedIntValue]));
|
const QVideoFrame::PixelFormat qtFormat(QtPixelFormatFromCVFormat([formatAsNSNumber unsignedIntValue]));
|
||||||
if (qtFormat != QVideoFrame::Format_Invalid && (!surface || filter.contains(qtFormat))
|
if (qtFormat != QVideoFrame::Format_Invalid
|
||||||
&& !qtFormats.contains(qtFormat)) { // Can happen, for example, with 8BiPlanar existing in video/full range.
|
&& !qtFormats.contains(qtFormat)) { // Can happen, for example, with 8BiPlanar existing in video/full range.
|
||||||
qtFormats << qtFormat;
|
qtFormats << qtFormat;
|
||||||
}
|
}
|
||||||
@@ -550,22 +570,33 @@ void AVFCameraViewfinderSettingsControl2::applySettings()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned avfPixelFormat = 0;
|
unsigned avfPixelFormat = 0;
|
||||||
if (m_settings.pixelFormat() != QVideoFrame::Format_Invalid &&
|
if (!convertPixelFormatIfSupported(m_settings.pixelFormat(), avfPixelFormat)) {
|
||||||
convertPixelFormatIfSupported(m_settings.pixelFormat(), avfPixelFormat)) {
|
// If the the pixel format is not specified or invalid, pick the preferred video surface
|
||||||
[videoSettings setObject:[NSNumber numberWithUnsignedInt:avfPixelFormat]
|
// format, or if no surface is set, the preferred capture device format
|
||||||
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
|
const QVector<QVideoFrame::PixelFormat> deviceFormats = viewfinderPixelFormats();
|
||||||
} else {
|
QList<QVideoFrame::PixelFormat> surfaceFormats;
|
||||||
// We have to set the pixel format, otherwise AVFoundation can change it to something we do not support.
|
if (m_service->videoOutput() && m_service->videoOutput()->surface())
|
||||||
if (NSObject *oldFormat = [m_videoOutput.videoSettings objectForKey:(id)kCVPixelBufferPixelFormatTypeKey]) {
|
surfaceFormats = m_service->videoOutput()->surface()->supportedPixelFormats();
|
||||||
[videoSettings setObject:oldFormat forKey:(id)kCVPixelBufferPixelFormatTypeKey];
|
|
||||||
} else {
|
QVideoFrame::PixelFormat format = deviceFormats.first();
|
||||||
[videoSettings setObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA]
|
|
||||||
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
|
for (int i = 0; i < surfaceFormats.count(); ++i) {
|
||||||
|
const QVideoFrame::PixelFormat surfaceFormat = surfaceFormats.at(i);
|
||||||
|
if (deviceFormats.contains(surfaceFormat)) {
|
||||||
|
format = surfaceFormat;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videoSettings.count)
|
CVPixelFormatFromQtFormat(format, avfPixelFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avfPixelFormat != 0) {
|
||||||
|
[videoSettings setObject:[NSNumber numberWithUnsignedInt:avfPixelFormat]
|
||||||
|
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
|
||||||
|
|
||||||
m_videoOutput.videoSettings = videoSettings;
|
m_videoOutput.videoSettings = videoSettings;
|
||||||
|
}
|
||||||
|
|
||||||
qt_set_framerate_limits(m_captureDevice, m_videoConnection, m_settings);
|
qt_set_framerate_limits(m_captureDevice, m_videoConnection, m_settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,11 +128,11 @@ void AVFCameraZoomControl::cameraStateChanged()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (captureDevice.activeFormat.videoMaxZoomFactor > 1.
|
if (captureDevice.activeFormat.videoMaxZoomFactor > 1.) {
|
||||||
&& !qFuzzyCompare(m_maxZoomFactor, captureDevice.activeFormat.videoMaxZoomFactor)) {
|
if (!qFuzzyCompare(m_maxZoomFactor, captureDevice.activeFormat.videoMaxZoomFactor)) {
|
||||||
m_maxZoomFactor = captureDevice.activeFormat.videoMaxZoomFactor;
|
m_maxZoomFactor = captureDevice.activeFormat.videoMaxZoomFactor;
|
||||||
|
|
||||||
Q_EMIT maximumDigitalZoomChanged(m_maxZoomFactor);
|
Q_EMIT maximumDigitalZoomChanged(m_maxZoomFactor);
|
||||||
|
}
|
||||||
} else if (!qFuzzyCompare(m_maxZoomFactor, CGFloat(1.))) {
|
} else if (!qFuzzyCompare(m_maxZoomFactor, CGFloat(1.))) {
|
||||||
m_maxZoomFactor = 1.;
|
m_maxZoomFactor = 1.;
|
||||||
|
|
||||||
|
|||||||
119
src/plugins/avfoundation/camera/avfmediaassetwriter.h
Normal file
119
src/plugins/avfoundation/camera/avfmediaassetwriter.h
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef AVFMEDIAASSETWRITER_H
|
||||||
|
#define AVFMEDIAASSETWRITER_H
|
||||||
|
|
||||||
|
#include "avfcamerautility.h"
|
||||||
|
|
||||||
|
#include <QtCore/qglobal.h>
|
||||||
|
#include <QtCore/qatomic.h>
|
||||||
|
#include <QtCore/qmutex.h>
|
||||||
|
|
||||||
|
#include <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class AVFCameraService;
|
||||||
|
|
||||||
|
class AVFMediaAssetWriterDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~AVFMediaAssetWriterDelegate();
|
||||||
|
|
||||||
|
virtual void assetWriterStarted() = 0;
|
||||||
|
virtual void assetWriterFailedToStart() = 0;
|
||||||
|
virtual void assetWriterFailedToStop() = 0;
|
||||||
|
virtual void assetWriterFinished() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QAtomicInteger<bool> AVFAtomicBool;
|
||||||
|
typedef QAtomicInteger<qint64> AVFAtomicInt64;
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
// TODO: any reasonable error handling requires smart pointers, otherwise it's getting crappy immediately.
|
||||||
|
|
||||||
|
@interface QT_MANGLE_NAMESPACE(AVFMediaAssetWriter) : NSObject<AVCaptureVideoDataOutputSampleBufferDelegate,
|
||||||
|
AVCaptureAudioDataOutputSampleBufferDelegate>
|
||||||
|
{
|
||||||
|
@private
|
||||||
|
AVFCameraService *m_service;
|
||||||
|
|
||||||
|
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_cameraWriterInput;
|
||||||
|
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVCaptureDeviceInput> m_audioInput;
|
||||||
|
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVCaptureAudioDataOutput> m_audioOutput;
|
||||||
|
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_audioWriterInput;
|
||||||
|
|
||||||
|
// High priority serial queue for video output:
|
||||||
|
QT_MANGLE_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_videoQueue;
|
||||||
|
// Serial queue for audio output:
|
||||||
|
QT_MANGLE_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_audioQueue;
|
||||||
|
// Queue to write sample buffers:
|
||||||
|
__weak dispatch_queue_t m_writerQueue;
|
||||||
|
|
||||||
|
QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVAssetWriter> m_assetWriter;
|
||||||
|
// Delegate's queue.
|
||||||
|
__weak dispatch_queue_t m_delegateQueue;
|
||||||
|
// TODO: QPointer??
|
||||||
|
QT_PREPEND_NAMESPACE(AVFMediaAssetWriterDelegate) *m_delegate;
|
||||||
|
|
||||||
|
bool m_setStartTime;
|
||||||
|
QT_MANGLE_NAMESPACE(AVFAtomicBool) m_stopped;
|
||||||
|
bool m_stoppedInternal;
|
||||||
|
bool m_aborted;
|
||||||
|
|
||||||
|
QT_MANGLE_NAMESPACE(QMutex) m_writerMutex;
|
||||||
|
@public
|
||||||
|
QT_MANGLE_NAMESPACE(AVFAtomicInt64) m_durationInMs;
|
||||||
|
@private
|
||||||
|
CMTime m_startTime;
|
||||||
|
CMTime m_lastTimeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithQueue:(dispatch_queue_t)writerQueue
|
||||||
|
delegate:(QT_PREPEND_NAMESPACE(AVFMediaAssetWriterDelegate) *)delegate
|
||||||
|
delegateQueue:(dispatch_queue_t)delegateQueue;
|
||||||
|
|
||||||
|
- (bool)setupWithFileURL:(NSURL *)fileURL
|
||||||
|
cameraService:(QT_PREPEND_NAMESPACE(AVFCameraService) *)service;
|
||||||
|
|
||||||
|
- (void)start;
|
||||||
|
- (void)stop;
|
||||||
|
// This to be called if control's dtor gets called,
|
||||||
|
// on the control's thread.
|
||||||
|
- (void)abort;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif // AVFMEDIAASSETWRITER_H
|
||||||
474
src/plugins/avfoundation/camera/avfmediaassetwriter.mm
Normal file
474
src/plugins/avfoundation/camera/avfmediaassetwriter.mm
Normal file
@@ -0,0 +1,474 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "avfaudioinputselectorcontrol.h"
|
||||||
|
#include "avfcamerarenderercontrol.h"
|
||||||
|
#include "avfmediaassetwriter.h"
|
||||||
|
#include "avfcameraservice.h"
|
||||||
|
#include "avfcamerasession.h"
|
||||||
|
#include "avfcameradebug.h"
|
||||||
|
|
||||||
|
//#include <QtCore/qmutexlocker.h>
|
||||||
|
#include <QtCore/qsysinfo.h>
|
||||||
|
|
||||||
|
QT_USE_NAMESPACE
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool qt_camera_service_isValid(AVFCameraService *service)
|
||||||
|
{
|
||||||
|
if (!service || !service->session())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
AVFCameraSession *session = service->session();
|
||||||
|
if (!session->captureSession())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!session->videoInput())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!service->videoOutput()
|
||||||
|
|| !service->videoOutput()->videoDataOutput()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AVFMediaAssetWriterDelegate::~AVFMediaAssetWriterDelegate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@interface QT_MANGLE_NAMESPACE(AVFMediaAssetWriter) (PrivateAPI)
|
||||||
|
- (bool)addAudioCapture;
|
||||||
|
- (bool)addWriterInputs;
|
||||||
|
- (void)setQueues;
|
||||||
|
- (NSDictionary *)videoSettings;
|
||||||
|
- (NSDictionary *)audioSettings;
|
||||||
|
- (void)updateDuration:(CMTime)newTimeStamp;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation QT_MANGLE_NAMESPACE(AVFMediaAssetWriter)
|
||||||
|
|
||||||
|
- (id)initWithQueue:(dispatch_queue_t)writerQueue
|
||||||
|
delegate:(AVFMediaAssetWriterDelegate *)delegate
|
||||||
|
delegateQueue:(dispatch_queue_t)delegateQueue
|
||||||
|
{
|
||||||
|
Q_ASSERT(writerQueue);
|
||||||
|
Q_ASSERT(delegate);
|
||||||
|
Q_ASSERT(delegateQueue);
|
||||||
|
|
||||||
|
if (self = [super init]) {
|
||||||
|
m_writerQueue = writerQueue;
|
||||||
|
m_delegate = delegate;
|
||||||
|
m_delegateQueue = delegateQueue;
|
||||||
|
m_setStartTime = true;
|
||||||
|
m_stopped.store(true);
|
||||||
|
m_stoppedInternal = false;
|
||||||
|
m_aborted = false;
|
||||||
|
m_startTime = kCMTimeInvalid;
|
||||||
|
m_lastTimeStamp = kCMTimeInvalid;
|
||||||
|
m_durationInMs.store(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (bool)setupWithFileURL:(NSURL *)fileURL
|
||||||
|
cameraService:(AVFCameraService *)service
|
||||||
|
{
|
||||||
|
Q_ASSERT(fileURL);
|
||||||
|
|
||||||
|
if (!qt_camera_service_isValid(service)) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "invalid camera service";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_service = service;
|
||||||
|
|
||||||
|
m_videoQueue.reset(dispatch_queue_create("video-output-queue", DISPATCH_QUEUE_SERIAL));
|
||||||
|
if (!m_videoQueue) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to create video queue";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dispatch_set_target_queue(m_videoQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
|
||||||
|
m_audioQueue.reset(dispatch_queue_create("audio-output-queue", DISPATCH_QUEUE_SERIAL));
|
||||||
|
if (!m_audioQueue) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to create audio queue";
|
||||||
|
// But we still can write video!
|
||||||
|
}
|
||||||
|
|
||||||
|
m_assetWriter.reset([[AVAssetWriter alloc] initWithURL:fileURL fileType:AVFileTypeQuickTimeMovie error:nil]);
|
||||||
|
if (!m_assetWriter) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to create asset writer";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool audioCaptureOn = false;
|
||||||
|
|
||||||
|
if (m_audioQueue)
|
||||||
|
audioCaptureOn = [self addAudioCapture];
|
||||||
|
|
||||||
|
if (![self addWriterInputs]) {
|
||||||
|
if (audioCaptureOn) {
|
||||||
|
AVCaptureSession *session = m_service->session()->captureSession();
|
||||||
|
[session removeOutput:m_audioOutput];
|
||||||
|
[session removeInput:m_audioInput];
|
||||||
|
m_audioOutput.reset();
|
||||||
|
m_audioInput.reset();
|
||||||
|
}
|
||||||
|
m_assetWriter.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Ready to start ...
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)start
|
||||||
|
{
|
||||||
|
// To be executed on a writer's queue.
|
||||||
|
const QMutexLocker lock(&m_writerMutex);
|
||||||
|
if (m_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
[self setQueues];
|
||||||
|
|
||||||
|
m_setStartTime = true;
|
||||||
|
m_stopped.store(false);
|
||||||
|
m_stoppedInternal = false;
|
||||||
|
[m_assetWriter startWriting];
|
||||||
|
AVCaptureSession *session = m_service->session()->captureSession();
|
||||||
|
if (!session.running)
|
||||||
|
[session startRunning];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stop
|
||||||
|
{
|
||||||
|
// To be executed on a writer's queue.
|
||||||
|
const QMutexLocker lock(&m_writerMutex);
|
||||||
|
if (m_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_stopped.load()) {
|
||||||
|
// Should never happen, but ...
|
||||||
|
// if something went wrong in a recorder control
|
||||||
|
// and we set state stopped without starting first ...
|
||||||
|
// m_stoppedIntenal will be false, but m_stopped - true.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_stopped.store(true);
|
||||||
|
m_stoppedInternal = true;
|
||||||
|
[m_assetWriter finishWritingWithCompletionHandler:^{
|
||||||
|
// TODO: make sure the session exist and we can call stop/remove on it.
|
||||||
|
AVCaptureSession *session = m_service->session()->captureSession();
|
||||||
|
[session stopRunning];
|
||||||
|
[session removeOutput:m_audioOutput];
|
||||||
|
[session removeInput:m_audioInput];
|
||||||
|
dispatch_async(m_delegateQueue, ^{
|
||||||
|
m_delegate->assetWriterFinished();
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)abort
|
||||||
|
{
|
||||||
|
// To be executed on any thread, prevents writer from
|
||||||
|
// accessing any external object (probably deleted by this time)
|
||||||
|
const QMutexLocker lock(&m_writerMutex);
|
||||||
|
m_aborted = true;
|
||||||
|
if (m_stopped.load())
|
||||||
|
return;
|
||||||
|
[m_assetWriter finishWritingWithCompletionHandler:^{
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setStartTimeFrom:(CMSampleBufferRef)sampleBuffer
|
||||||
|
{
|
||||||
|
// Writer's queue only.
|
||||||
|
Q_ASSERT(m_setStartTime);
|
||||||
|
Q_ASSERT(sampleBuffer);
|
||||||
|
|
||||||
|
dispatch_async(m_delegateQueue, ^{
|
||||||
|
m_delegate->assetWriterStarted();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_durationInMs.store(0);
|
||||||
|
m_startTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
|
||||||
|
m_lastTimeStamp = m_startTime;
|
||||||
|
[m_assetWriter startSessionAtSourceTime:m_startTime];
|
||||||
|
m_setStartTime = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)writeVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
|
{
|
||||||
|
Q_ASSERT(sampleBuffer);
|
||||||
|
|
||||||
|
// This code is executed only on a writer's queue, but
|
||||||
|
// it can access potentially deleted objects, so we
|
||||||
|
// need a lock and m_aborted flag test.
|
||||||
|
{
|
||||||
|
const QMutexLocker lock(&m_writerMutex);
|
||||||
|
if (!m_aborted && !m_stoppedInternal) {
|
||||||
|
if (m_setStartTime)
|
||||||
|
[self setStartTimeFrom:sampleBuffer];
|
||||||
|
|
||||||
|
if (m_cameraWriterInput.data().readyForMoreMediaData) {
|
||||||
|
[self updateDuration:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
|
||||||
|
[m_cameraWriterInput appendSampleBuffer:sampleBuffer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(sampleBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)writeAudioSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
|
{
|
||||||
|
// This code is executed only on a writer's queue.
|
||||||
|
// it does not touch any shared/external data.
|
||||||
|
Q_ASSERT(sampleBuffer);
|
||||||
|
|
||||||
|
{
|
||||||
|
const QMutexLocker lock(&m_writerMutex);
|
||||||
|
if (!m_aborted && !m_stoppedInternal) {
|
||||||
|
if (m_setStartTime)
|
||||||
|
[self setStartTimeFrom:sampleBuffer];
|
||||||
|
|
||||||
|
if (m_audioWriterInput.data().readyForMoreMediaData) {
|
||||||
|
[self updateDuration:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
|
||||||
|
[m_audioWriterInput appendSampleBuffer:sampleBuffer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(sampleBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
||||||
|
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
|
fromConnection:(AVCaptureConnection *)connection
|
||||||
|
{
|
||||||
|
Q_UNUSED(connection)
|
||||||
|
|
||||||
|
// This method can be called on either video or audio queue, never on a writer's
|
||||||
|
// queue - it does not access any shared data except this atomic flag below.
|
||||||
|
if (m_stopped.load())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Even if we are stopped now, we still do not access any data.
|
||||||
|
|
||||||
|
if (!CMSampleBufferDataIsReady(sampleBuffer)) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "sample buffer is not ready, skipping.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRetain(sampleBuffer);
|
||||||
|
|
||||||
|
if (captureOutput != m_audioOutput.data()) {
|
||||||
|
{
|
||||||
|
const QMutexLocker lock(&m_writerMutex);
|
||||||
|
if (m_aborted || m_stoppedInternal) {
|
||||||
|
CFRelease(sampleBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find renderercontrol's delegate and invoke its method to
|
||||||
|
// show updated viewfinder's frame.
|
||||||
|
if (m_service && m_service->videoOutput()) {
|
||||||
|
NSObject<AVCaptureVideoDataOutputSampleBufferDelegate> *vfDelegate =
|
||||||
|
(NSObject<AVCaptureVideoDataOutputSampleBufferDelegate> *)m_service->videoOutput()->captureDelegate();
|
||||||
|
if (vfDelegate)
|
||||||
|
[vfDelegate captureOutput:nil didOutputSampleBuffer:sampleBuffer fromConnection:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch_async(m_writerQueue, ^{
|
||||||
|
[self writeVideoSampleBuffer:sampleBuffer];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dispatch_async(m_writerQueue, ^{
|
||||||
|
[self writeAudioSampleBuffer:sampleBuffer];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (bool)addAudioCapture
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_service && m_service->session() && m_service->session()->captureSession());
|
||||||
|
|
||||||
|
if (!m_service->audioInputSelectorControl())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
AVCaptureSession *captureSession = m_service->session()->captureSession();
|
||||||
|
|
||||||
|
AVCaptureDevice *audioDevice = m_service->audioInputSelectorControl()->createCaptureDevice();
|
||||||
|
if (!audioDevice) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "no audio input device available";
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
NSError *error = nil;
|
||||||
|
m_audioInput.reset([[AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error] retain]);
|
||||||
|
|
||||||
|
if (!m_audioInput || error) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "failed to create audio device input";
|
||||||
|
m_audioInput.reset();
|
||||||
|
return false;
|
||||||
|
} else if (![captureSession canAddInput:m_audioInput]) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "could not connect the audio input";
|
||||||
|
m_audioInput.reset();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
[captureSession addInput:m_audioInput];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
m_audioOutput.reset([[AVCaptureAudioDataOutput alloc] init]);
|
||||||
|
if (m_audioOutput && [captureSession canAddOutput:m_audioOutput]) {
|
||||||
|
[captureSession addOutput:m_audioOutput];
|
||||||
|
} else {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to add audio output";
|
||||||
|
[captureSession removeInput:m_audioInput];
|
||||||
|
m_audioInput.reset();
|
||||||
|
m_audioOutput.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (bool)addWriterInputs
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_service && m_service->videoOutput()
|
||||||
|
&& m_service->videoOutput()->videoDataOutput());
|
||||||
|
Q_ASSERT(m_assetWriter);
|
||||||
|
|
||||||
|
m_cameraWriterInput.reset([[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:[self videoSettings]]);
|
||||||
|
if (!m_cameraWriterInput) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to create camera writer input";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([m_assetWriter canAddInput:m_cameraWriterInput]) {
|
||||||
|
[m_assetWriter addInput:m_cameraWriterInput];
|
||||||
|
} else {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to add camera writer input";
|
||||||
|
m_cameraWriterInput.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cameraWriterInput.data().expectsMediaDataInRealTime = YES;
|
||||||
|
|
||||||
|
if (m_audioOutput) {
|
||||||
|
m_audioWriterInput.reset([[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:[self audioSettings]]);
|
||||||
|
if (!m_audioWriterInput) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to create audio writer input";
|
||||||
|
// But we still can record video.
|
||||||
|
} else if ([m_assetWriter canAddInput:m_audioWriterInput]) {
|
||||||
|
[m_assetWriter addInput:m_audioWriterInput];
|
||||||
|
m_audioWriterInput.data().expectsMediaDataInRealTime = YES;
|
||||||
|
} else {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to add audio writer input";
|
||||||
|
m_audioWriterInput.reset();
|
||||||
|
// We can (still) write video though ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setQueues
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_service && m_service->videoOutput() && m_service->videoOutput()->videoDataOutput());
|
||||||
|
Q_ASSERT(m_videoQueue);
|
||||||
|
|
||||||
|
[m_service->videoOutput()->videoDataOutput() setSampleBufferDelegate:self queue:m_videoQueue];
|
||||||
|
|
||||||
|
if (m_audioOutput) {
|
||||||
|
Q_ASSERT(m_audioQueue);
|
||||||
|
[m_audioOutput setSampleBufferDelegate:self queue:m_audioQueue];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (NSDictionary *)videoSettings
|
||||||
|
{
|
||||||
|
// TODO: these settings should be taken from
|
||||||
|
// the video encoding settings control.
|
||||||
|
// For now we either take recommended (iOS >= 7.0)
|
||||||
|
// or some hardcoded values - they are still better than nothing (nil).
|
||||||
|
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
|
||||||
|
AVCaptureVideoDataOutput *videoOutput = m_service->videoOutput()->videoDataOutput();
|
||||||
|
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0 && videoOutput)
|
||||||
|
return [videoOutput recommendedVideoSettingsForAssetWriterWithOutputFileType:AVFileTypeQuickTimeMovie];
|
||||||
|
#endif
|
||||||
|
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey,
|
||||||
|
[NSNumber numberWithInt:1280], AVVideoWidthKey,
|
||||||
|
[NSNumber numberWithInt:720], AVVideoHeightKey, nil];
|
||||||
|
|
||||||
|
return videoSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)audioSettings
|
||||||
|
{
|
||||||
|
// TODO: these settings should be taken from
|
||||||
|
// the video/audio encoder settings control.
|
||||||
|
// For now we either take recommended (iOS >= 7.0)
|
||||||
|
// or nil - this seems to be good enough.
|
||||||
|
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
|
||||||
|
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0 && m_audioOutput)
|
||||||
|
return [m_audioOutput recommendedAudioSettingsForAssetWriterWithOutputFileType:AVFileTypeQuickTimeMovie];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateDuration:(CMTime)newTimeStamp
|
||||||
|
{
|
||||||
|
Q_ASSERT(CMTimeCompare(m_startTime, kCMTimeInvalid));
|
||||||
|
Q_ASSERT(CMTimeCompare(m_lastTimeStamp, kCMTimeInvalid));
|
||||||
|
if (CMTimeCompare(newTimeStamp, m_lastTimeStamp) > 0) {
|
||||||
|
|
||||||
|
const CMTime duration = CMTimeSubtract(newTimeStamp, m_startTime);
|
||||||
|
if (!CMTimeCompare(duration, kCMTimeInvalid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_durationInMs.store(CMTimeGetSeconds(duration) * 1000);
|
||||||
|
m_lastTimeStamp = newTimeStamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
108
src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.h
Normal file
108
src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef AVFMEDIARECORDERCONTROL_IOS_H
|
||||||
|
#define AVFMEDIARECORDERCONTROL_IOS_H
|
||||||
|
|
||||||
|
#include "avfmediaassetwriter.h"
|
||||||
|
#include "avfstoragelocation.h"
|
||||||
|
#include "avfcamerautility.h"
|
||||||
|
|
||||||
|
#include <QtMultimedia/qmediarecordercontrol.h>
|
||||||
|
|
||||||
|
#include <QtCore/qglobal.h>
|
||||||
|
#include <QtCore/qurl.h>
|
||||||
|
|
||||||
|
#include <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class AVFCameraService;
|
||||||
|
class QString;
|
||||||
|
class QUrl;
|
||||||
|
|
||||||
|
class AVFMediaRecorderControlIOS : public QMediaRecorderControl, public AVFMediaAssetWriterDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
AVFMediaRecorderControlIOS(AVFCameraService *service, QObject *parent = 0);
|
||||||
|
~AVFMediaRecorderControlIOS();
|
||||||
|
|
||||||
|
QUrl outputLocation() const Q_DECL_OVERRIDE;
|
||||||
|
bool setOutputLocation(const QUrl &location) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QMediaRecorder::State state() const Q_DECL_OVERRIDE;
|
||||||
|
QMediaRecorder::Status status() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
qint64 duration() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isMuted() const Q_DECL_OVERRIDE;
|
||||||
|
qreal volume() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void applySettings() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void setState(QMediaRecorder::State state) Q_DECL_OVERRIDE;
|
||||||
|
void setMuted(bool muted) Q_DECL_OVERRIDE;
|
||||||
|
void setVolume(qreal volume) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
// Writer delegate:
|
||||||
|
private:
|
||||||
|
|
||||||
|
void assetWriterStarted() Q_DECL_OVERRIDE;
|
||||||
|
void assetWriterFailedToStart() Q_DECL_OVERRIDE;
|
||||||
|
void assetWriterFailedToStop() Q_DECL_OVERRIDE;
|
||||||
|
void assetWriterFinished() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void captureModeChanged(QCamera::CaptureModes);
|
||||||
|
void cameraStatusChanged(QCamera::Status newStatus);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void stopWriter();
|
||||||
|
|
||||||
|
AVFCameraService *m_service;
|
||||||
|
|
||||||
|
AVFScopedPointer<dispatch_queue_t> m_writerQueue;
|
||||||
|
AVFScopedPointer<QT_MANGLE_NAMESPACE(AVFMediaAssetWriter)> m_writer;
|
||||||
|
|
||||||
|
QUrl m_outputLocation;
|
||||||
|
AVFStorageLocation m_storageLocation;
|
||||||
|
|
||||||
|
QMediaRecorder::State m_state;
|
||||||
|
QMediaRecorder::Status m_lastStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // AVFMEDIARECORDERCONTROL_IOS_H
|
||||||
349
src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm
Normal file
349
src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "avfmediarecordercontrol_ios.h"
|
||||||
|
#include "avfcamerarenderercontrol.h"
|
||||||
|
#include "avfcamerasession.h"
|
||||||
|
#include "avfcameracontrol.h"
|
||||||
|
#include "avfcameraservice.h"
|
||||||
|
#include "avfcameradebug.h"
|
||||||
|
|
||||||
|
#include <QtCore/qdebug.h>
|
||||||
|
|
||||||
|
QT_USE_NAMESPACE
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool qt_is_writable_file_URL(NSURL *fileURL)
|
||||||
|
{
|
||||||
|
Q_ASSERT(fileURL);
|
||||||
|
|
||||||
|
if (![fileURL isFileURL])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (NSString *path = [[fileURL path] stringByExpandingTildeInPath]) {
|
||||||
|
return [[NSFileManager defaultManager]
|
||||||
|
isWritableFileAtPath:[path stringByDeletingLastPathComponent]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qt_file_exists(NSURL *fileURL)
|
||||||
|
{
|
||||||
|
Q_ASSERT(fileURL);
|
||||||
|
|
||||||
|
if (NSString *path = [[fileURL path] stringByExpandingTildeInPath])
|
||||||
|
return [[NSFileManager defaultManager] fileExistsAtPath:path];
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AVFMediaRecorderControlIOS::AVFMediaRecorderControlIOS(AVFCameraService *service, QObject *parent)
|
||||||
|
: QMediaRecorderControl(parent)
|
||||||
|
, m_service(service)
|
||||||
|
, m_state(QMediaRecorder::StoppedState)
|
||||||
|
, m_lastStatus(QMediaRecorder::UnloadedStatus)
|
||||||
|
{
|
||||||
|
Q_ASSERT(service);
|
||||||
|
|
||||||
|
m_writerQueue.reset(dispatch_queue_create("asset-writer-queue", DISPATCH_QUEUE_SERIAL));
|
||||||
|
if (!m_writerQueue) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to create an asset writer's queue";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_writer.reset([[QT_MANGLE_NAMESPACE(AVFMediaAssetWriter) alloc] initWithQueue:m_writerQueue
|
||||||
|
delegate:this delegateQueue:dispatch_get_main_queue()]);
|
||||||
|
if (!m_writer) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "failed to create an asset writer";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVFCameraControl *cameraControl = m_service->cameraControl();
|
||||||
|
if (!cameraControl) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "camera control is nil";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(cameraControl, SIGNAL(captureModeChanged(QCamera::CaptureModes)),
|
||||||
|
SLOT(captureModeChanged(QCamera::CaptureModes)));
|
||||||
|
connect(cameraControl, SIGNAL(statusChanged(QCamera::Status)),
|
||||||
|
SLOT(cameraStatusChanged(QCamera::Status)));
|
||||||
|
}
|
||||||
|
|
||||||
|
AVFMediaRecorderControlIOS::~AVFMediaRecorderControlIOS()
|
||||||
|
{
|
||||||
|
[m_writer abort];
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl AVFMediaRecorderControlIOS::outputLocation() const
|
||||||
|
{
|
||||||
|
return m_outputLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AVFMediaRecorderControlIOS::setOutputLocation(const QUrl &location)
|
||||||
|
{
|
||||||
|
m_outputLocation = location;
|
||||||
|
return location.scheme() == QLatin1String("file") || location.scheme().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMediaRecorder::State AVFMediaRecorderControlIOS::state() const
|
||||||
|
{
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMediaRecorder::Status AVFMediaRecorderControlIOS::status() const
|
||||||
|
{
|
||||||
|
return m_lastStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 AVFMediaRecorderControlIOS::duration() const
|
||||||
|
{
|
||||||
|
return m_writer.data()->m_durationInMs.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AVFMediaRecorderControlIOS::isMuted() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal AVFMediaRecorderControlIOS::volume() const
|
||||||
|
{
|
||||||
|
return 1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::applySettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::setState(QMediaRecorder::State state)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_service->session()
|
||||||
|
&& m_service->session()->captureSession());
|
||||||
|
|
||||||
|
if (!m_writer) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "Invalid recorder";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == m_state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case QMediaRecorder::RecordingState:
|
||||||
|
{
|
||||||
|
AVFCameraControl *cameraControl = m_service->cameraControl();
|
||||||
|
Q_ASSERT(cameraControl);
|
||||||
|
|
||||||
|
if (!(cameraControl->captureMode() & QCamera::CaptureVideo)) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "wrong capture mode, CaptureVideo expected";
|
||||||
|
Q_EMIT error(QMediaRecorder::ResourceError, tr("Failed to start recording"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cameraControl->status() != QCamera::ActiveStatus) {
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "can not start record while camera is not active";
|
||||||
|
Q_EMIT error(QMediaRecorder::ResourceError, tr("Failed to start recording"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString path(m_outputLocation.scheme() == QLatin1String("file") ?
|
||||||
|
m_outputLocation.path() : m_outputLocation.toString());
|
||||||
|
const QUrl fileURL(QUrl::fromLocalFile(m_storageLocation.generateFileName(path, QCamera::CaptureVideo,
|
||||||
|
QLatin1String("clip_"), QLatin1String("mp4"))));
|
||||||
|
|
||||||
|
NSURL *nsFileURL = fileURL.toNSURL();
|
||||||
|
if (!nsFileURL) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "invalid output URL:" << fileURL;
|
||||||
|
Q_EMIT error(QMediaRecorder::ResourceError, tr("Invalid output file URL"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!qt_is_writable_file_URL(nsFileURL)) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "invalid output URL:" << fileURL
|
||||||
|
<< "(the location is not writable)";
|
||||||
|
Q_EMIT error(QMediaRecorder::ResourceError, tr("Non-writeable file location"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (qt_file_exists(nsFileURL)) {
|
||||||
|
// We test for/handle this error here since AWAssetWriter will raise an
|
||||||
|
// Objective-C exception, which is not good at all.
|
||||||
|
qWarning() << Q_FUNC_INFO << "invalid output URL:" << fileURL
|
||||||
|
<< "(file already exists)";
|
||||||
|
Q_EMIT error(QMediaRecorder::ResourceError, tr("File already exists"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVCaptureSession *session = m_service->session()->captureSession();
|
||||||
|
// We stop session now so that no more frames for renderer's queue
|
||||||
|
// generated, will restart in assetWriterStarted.
|
||||||
|
[session stopRunning];
|
||||||
|
|
||||||
|
if ([m_writer setupWithFileURL:nsFileURL cameraService:m_service]) {
|
||||||
|
m_state = QMediaRecorder::RecordingState;
|
||||||
|
m_lastStatus = QMediaRecorder::StartingStatus;
|
||||||
|
|
||||||
|
Q_EMIT actualLocationChanged(fileURL);
|
||||||
|
Q_EMIT stateChanged(m_state);
|
||||||
|
Q_EMIT statusChanged(m_lastStatus);
|
||||||
|
|
||||||
|
dispatch_async(m_writerQueue, ^{
|
||||||
|
[m_writer start];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
[session startRunning];
|
||||||
|
Q_EMIT error(QMediaRecorder::FormatError, tr("Failed to start recording"));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case QMediaRecorder::PausedState:
|
||||||
|
{
|
||||||
|
Q_EMIT error(QMediaRecorder::FormatError, tr("Recording pause not supported"));
|
||||||
|
return;
|
||||||
|
} break;
|
||||||
|
case QMediaRecorder::StoppedState:
|
||||||
|
{
|
||||||
|
// Do not check the camera status, we can stop if we started.
|
||||||
|
stopWriter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::setMuted(bool muted)
|
||||||
|
{
|
||||||
|
Q_UNUSED(muted)
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "not implemented";
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::setVolume(qreal volume)
|
||||||
|
{
|
||||||
|
Q_UNUSED(volume);
|
||||||
|
qDebugCamera() << Q_FUNC_INFO << "not implemented";
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::assetWriterStarted()
|
||||||
|
{
|
||||||
|
m_lastStatus = QMediaRecorder::RecordingStatus;
|
||||||
|
Q_EMIT statusChanged(QMediaRecorder::RecordingStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::assetWriterFailedToStart()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::assetWriterFailedToStop()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::assetWriterFinished()
|
||||||
|
{
|
||||||
|
AVFCameraControl *cameraControl = m_service->cameraControl();
|
||||||
|
Q_ASSERT(cameraControl);
|
||||||
|
|
||||||
|
const QMediaRecorder::Status lastStatus = m_lastStatus;
|
||||||
|
|
||||||
|
if (cameraControl->captureMode() & QCamera::CaptureVideo)
|
||||||
|
m_lastStatus = QMediaRecorder::LoadedStatus;
|
||||||
|
else
|
||||||
|
m_lastStatus = QMediaRecorder::UnloadedStatus;
|
||||||
|
|
||||||
|
m_service->videoOutput()->resetCaptureDelegate();
|
||||||
|
[m_service->session()->captureSession() startRunning];
|
||||||
|
|
||||||
|
if (m_lastStatus != lastStatus)
|
||||||
|
Q_EMIT statusChanged(m_lastStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::captureModeChanged(QCamera::CaptureModes newMode)
|
||||||
|
{
|
||||||
|
AVFCameraControl *cameraControl = m_service->cameraControl();
|
||||||
|
Q_ASSERT(cameraControl);
|
||||||
|
|
||||||
|
const QMediaRecorder::Status lastStatus = m_lastStatus;
|
||||||
|
|
||||||
|
if (newMode & QCamera::CaptureVideo) {
|
||||||
|
if (cameraControl->status() == QCamera::ActiveStatus)
|
||||||
|
m_lastStatus = QMediaRecorder::LoadedStatus;
|
||||||
|
} else {
|
||||||
|
if (m_lastStatus == QMediaRecorder::RecordingStatus)
|
||||||
|
return stopWriter();
|
||||||
|
else
|
||||||
|
m_lastStatus = QMediaRecorder::UnloadedStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_lastStatus != lastStatus)
|
||||||
|
Q_EMIT statusChanged(m_lastStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::cameraStatusChanged(QCamera::Status newStatus)
|
||||||
|
{
|
||||||
|
AVFCameraControl *cameraControl = m_service->cameraControl();
|
||||||
|
Q_ASSERT(cameraControl);
|
||||||
|
|
||||||
|
const QMediaRecorder::Status lastStatus = m_lastStatus;
|
||||||
|
const bool isCapture = cameraControl->captureMode() & QCamera::CaptureVideo;
|
||||||
|
if (newStatus == QCamera::StartingStatus) {
|
||||||
|
if (isCapture && m_lastStatus == QMediaRecorder::UnloadedStatus)
|
||||||
|
m_lastStatus = QMediaRecorder::LoadingStatus;
|
||||||
|
} else if (newStatus == QCamera::ActiveStatus) {
|
||||||
|
if (isCapture && m_lastStatus == QMediaRecorder::LoadingStatus)
|
||||||
|
m_lastStatus = QMediaRecorder::LoadedStatus;
|
||||||
|
} else {
|
||||||
|
if (m_lastStatus == QMediaRecorder::RecordingStatus)
|
||||||
|
return stopWriter();
|
||||||
|
if (newStatus == QCamera::UnloadedStatus)
|
||||||
|
m_lastStatus = QMediaRecorder::UnloadedStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastStatus != m_lastStatus)
|
||||||
|
Q_EMIT statusChanged(m_lastStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVFMediaRecorderControlIOS::stopWriter()
|
||||||
|
{
|
||||||
|
if (m_lastStatus == QMediaRecorder::RecordingStatus) {
|
||||||
|
m_state = QMediaRecorder::StoppedState;
|
||||||
|
m_lastStatus = QMediaRecorder::FinalizingStatus;
|
||||||
|
|
||||||
|
Q_EMIT stateChanged(m_state);
|
||||||
|
Q_EMIT statusChanged(m_lastStatus);
|
||||||
|
|
||||||
|
dispatch_async(m_writerQueue, ^{
|
||||||
|
[m_writer stop];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_avfmediarecordercontrol_ios.cpp"
|
||||||
@@ -27,7 +27,6 @@ HEADERS += \
|
|||||||
avfcameracontrol.h \
|
avfcameracontrol.h \
|
||||||
avfcamerametadatacontrol.h \
|
avfcamerametadatacontrol.h \
|
||||||
avfimagecapturecontrol.h \
|
avfimagecapturecontrol.h \
|
||||||
avfmediarecordercontrol.h \
|
|
||||||
avfcameraservice.h \
|
avfcameraservice.h \
|
||||||
avfcamerasession.h \
|
avfcamerasession.h \
|
||||||
avfstoragelocation.h \
|
avfstoragelocation.h \
|
||||||
@@ -49,7 +48,6 @@ OBJECTIVE_SOURCES += \
|
|||||||
avfcameracontrol.mm \
|
avfcameracontrol.mm \
|
||||||
avfcamerametadatacontrol.mm \
|
avfcamerametadatacontrol.mm \
|
||||||
avfimagecapturecontrol.mm \
|
avfimagecapturecontrol.mm \
|
||||||
avfmediarecordercontrol.mm \
|
|
||||||
avfcameraservice.mm \
|
avfcameraservice.mm \
|
||||||
avfcamerasession.mm \
|
avfcamerasession.mm \
|
||||||
avfstoragelocation.mm \
|
avfstoragelocation.mm \
|
||||||
@@ -66,9 +64,20 @@ OBJECTIVE_SOURCES += \
|
|||||||
avfimageencodercontrol.mm \
|
avfimageencodercontrol.mm \
|
||||||
avfcameraflashcontrol.mm
|
avfcameraflashcontrol.mm
|
||||||
|
|
||||||
ios {
|
osx {
|
||||||
|
|
||||||
HEADERS += avfcamerazoomcontrol.h
|
HEADERS += avfmediarecordercontrol.h
|
||||||
OBJECTIVE_SOURCES += avfcamerazoomcontrol.mm
|
OBJECTIVE_SOURCES += avfmediarecordercontrol.mm
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ios {
|
||||||
|
|
||||||
|
HEADERS += avfcamerazoomcontrol.h \
|
||||||
|
avfmediaassetwriter.h \
|
||||||
|
avfmediarecordercontrol_ios.h
|
||||||
|
OBJECTIVE_SOURCES += avfcamerazoomcontrol.mm \
|
||||||
|
avfmediaassetwriter.mm \
|
||||||
|
avfmediarecordercontrol_ios.mm
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -728,7 +728,7 @@ void AVFMediaPlayerSession::setVolume(int volume)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[player setVolume:m_volume / 100.0f];
|
[player setVolume:volume / 100.0f];
|
||||||
m_volume = volume;
|
m_volume = volume;
|
||||||
|
|
||||||
Q_EMIT volumeChanged(m_volume);
|
Q_EMIT volumeChanged(m_volume);
|
||||||
@@ -752,7 +752,7 @@ void AVFMediaPlayerSession::setMuted(bool muted)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[player setMuted:m_muted];
|
[player setMuted:muted];
|
||||||
m_muted = muted;
|
m_muted = muted;
|
||||||
|
|
||||||
Q_EMIT mutedChanged(muted);
|
Q_EMIT mutedChanged(muted);
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ QSGVivanteVideoMaterial::QSGVivanteVideoMaterial() :
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
setFlag(Blending, false);
|
setFlag(Blending, false);
|
||||||
|
|
||||||
|
mShader = new QSGVivanteVideoMaterialShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGVivanteVideoMaterial::~QSGVivanteVideoMaterial()
|
QSGVivanteVideoMaterial::~QSGVivanteVideoMaterial()
|
||||||
@@ -73,7 +75,7 @@ QSGMaterialType *QSGVivanteVideoMaterial::type() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QSGMaterialShader *QSGVivanteVideoMaterial::createShader() const {
|
QSGMaterialShader *QSGVivanteVideoMaterial::createShader() const {
|
||||||
return new QSGVivanteVideoMaterialShader;
|
return mShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QSGVivanteVideoMaterial::compare(const QSGMaterial *other) const {
|
int QSGVivanteVideoMaterial::compare(const QSGMaterial *other) const {
|
||||||
@@ -175,18 +177,49 @@ GLuint QSGVivanteVideoMaterial::vivanteMapping(QVideoFrame vF)
|
|||||||
glGenTextures(1, &tmpTexId);
|
glGenTextures(1, &tmpTexId);
|
||||||
mBitsToTextureMap.insert(vF.bits(), tmpTexId);
|
mBitsToTextureMap.insert(vF.bits(), tmpTexId);
|
||||||
|
|
||||||
|
// Determine the full width & height. Full means: actual width/height plus extra padding pixels.
|
||||||
|
// The full width can be deduced from the bytesPerLine value. The full height is calculated
|
||||||
|
// by calculating the distance between the start of the first and second planes, and dividing
|
||||||
|
// it by the stride (= the bytesPerLine). If there is only one plane, we don't worry about
|
||||||
|
// extra padding rows, since there are no adjacent extra planes.
|
||||||
|
// XXX: This assumes the distance between bits(1) and bits(0) is exactly the size of the first
|
||||||
|
// plane (the Y plane in the case of YUV data). A better way would be to have a dedicated
|
||||||
|
// planeSize() or planeOffset() getter.
|
||||||
|
// Also, this assumes that planes are tightly packed, that is, there is no space between them.
|
||||||
|
// It is okay to assume this here though, because the Vivante direct textures also assume that.
|
||||||
|
// In other words, if the planes aren't tightly packed, then the direct textures won't be able
|
||||||
|
// to render the frame correctly anyway.
|
||||||
|
int fullWidth = vF.bytesPerLine() / QSGVivanteVideoNode::getBytesForPixelFormat(vF.pixelFormat());
|
||||||
|
int fullHeight = (vF.planeCount() > 1) ? ((vF.bits(1) - vF.bits(0)) / vF.bytesPerLine()) : vF.height();
|
||||||
|
|
||||||
|
// The uscale is the ratio of actual width to the full width (same for vscale and height).
|
||||||
|
// Since the vivante direct textures do not offer a way to explicitly specify the amount of padding
|
||||||
|
// columns and rows, we use a trick. We show the full frame - including the padding pixels - in the
|
||||||
|
// texture, but render only a subset of that texture. This subset goes from (0,0) to (uScale, vScale).
|
||||||
|
// In the shader, the texture coordinates (which go from (0.0, 0.0) to (1.0, 1.0)) are multiplied by
|
||||||
|
// the u/v scale values. Since 1.0 * x = x, this effectively limits the texture coordinates from
|
||||||
|
// (0.0, 0.0) - (1.0, 1.0) to (0.0, 0.0) - (uScale, vScale).
|
||||||
|
float uScale = float(vF.width()) / float(fullWidth);
|
||||||
|
float vScale = float(vF.height()) / float(fullHeight);
|
||||||
|
mShader->setUVScale(uScale, vScale);
|
||||||
|
|
||||||
const uchar *constBits = vF.bits();
|
const uchar *constBits = vF.bits();
|
||||||
void *bits = (void*)constBits;
|
void *bits = (void*)constBits;
|
||||||
|
|
||||||
#ifdef QT_VIVANTE_VIDEO_DEBUG
|
#ifdef QT_VIVANTE_VIDEO_DEBUG
|
||||||
qDebug() << Q_FUNC_INFO << "new texture, texId: " << tmpTexId << "; constBits: " << constBits;
|
qDebug() << Q_FUNC_INFO
|
||||||
|
<< "new texture, texId: " << tmpTexId
|
||||||
|
<< "; constBits: " << constBits
|
||||||
|
<< "; actual/full width: " << vF.width() << "/" << fullWidth
|
||||||
|
<< "; actual/full height: " << vF.height() << "/" << fullHeight
|
||||||
|
<< "; UV scale: U " << uScale << " V " << vScale;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GLuint physical = ~0U;
|
GLuint physical = ~0U;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tmpTexId);
|
glBindTexture(GL_TEXTURE_2D, tmpTexId);
|
||||||
glTexDirectVIVMap_LOCAL(GL_TEXTURE_2D,
|
glTexDirectVIVMap_LOCAL(GL_TEXTURE_2D,
|
||||||
vF.width(), vF.height(),
|
fullWidth, fullHeight,
|
||||||
QSGVivanteVideoNode::getVideoFormat2GLFormatMap().value(vF.pixelFormat()),
|
QSGVivanteVideoNode::getVideoFormat2GLFormatMap().value(vF.pixelFormat()),
|
||||||
&bits, &physical);
|
&bits, &physical);
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,8 @@
|
|||||||
|
|
||||||
#include <private/qsgvideonode_p.h>
|
#include <private/qsgvideonode_p.h>
|
||||||
|
|
||||||
|
class QSGVivanteVideoMaterialShader;
|
||||||
|
|
||||||
class QSGVivanteVideoMaterial : public QSGMaterial
|
class QSGVivanteVideoMaterial : public QSGMaterial
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -78,6 +80,8 @@ private:
|
|||||||
|
|
||||||
GLuint mTexDirectTexture;
|
GLuint mTexDirectTexture;
|
||||||
GLvoid *mTexDirectPlanes[3];
|
GLvoid *mTexDirectPlanes[3];
|
||||||
|
|
||||||
|
QSGVivanteVideoMaterialShader *mShader;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QSGVIDEOMATERIAL_VIVMAP_H
|
#endif // QSGVIDEOMATERIAL_VIVMAP_H
|
||||||
|
|||||||
@@ -35,6 +35,13 @@
|
|||||||
#include "qsgvivantevideonode.h"
|
#include "qsgvivantevideonode.h"
|
||||||
#include "qsgvivantevideomaterial.h"
|
#include "qsgvivantevideomaterial.h"
|
||||||
|
|
||||||
|
QSGVivanteVideoMaterialShader::QSGVivanteVideoMaterialShader() :
|
||||||
|
mUScale(1),
|
||||||
|
mVScale(1),
|
||||||
|
mNewUVScale(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void QSGVivanteVideoMaterialShader::updateState(const RenderState &state,
|
void QSGVivanteVideoMaterialShader::updateState(const RenderState &state,
|
||||||
QSGMaterial *newMaterial,
|
QSGMaterial *newMaterial,
|
||||||
QSGMaterial *oldMaterial)
|
QSGMaterial *oldMaterial)
|
||||||
@@ -48,6 +55,10 @@ void QSGVivanteVideoMaterialShader::updateState(const RenderState &state,
|
|||||||
mat->setOpacity(state.opacity());
|
mat->setOpacity(state.opacity());
|
||||||
program()->setUniformValue(mIdOpacity, state.opacity());
|
program()->setUniformValue(mIdOpacity, state.opacity());
|
||||||
}
|
}
|
||||||
|
if (mNewUVScale) {
|
||||||
|
program()->setUniformValue(mIdUVScale, mUScale, mVScale);
|
||||||
|
mNewUVScale = false;
|
||||||
|
}
|
||||||
if (state.isMatrixDirty())
|
if (state.isMatrixDirty())
|
||||||
program()->setUniformValue(mIdMatrix, state.combinedMatrix());
|
program()->setUniformValue(mIdMatrix, state.combinedMatrix());
|
||||||
}
|
}
|
||||||
@@ -61,6 +72,13 @@ const char * const *QSGVivanteVideoMaterialShader::attributeNames() const {
|
|||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QSGVivanteVideoMaterialShader::setUVScale(float uScale, float vScale)
|
||||||
|
{
|
||||||
|
mUScale = uScale;
|
||||||
|
mVScale = vScale;
|
||||||
|
mNewUVScale = true;
|
||||||
|
}
|
||||||
|
|
||||||
const char *QSGVivanteVideoMaterialShader::vertexShader() const {
|
const char *QSGVivanteVideoMaterialShader::vertexShader() const {
|
||||||
static const char *shader =
|
static const char *shader =
|
||||||
"uniform highp mat4 qt_Matrix; \n"
|
"uniform highp mat4 qt_Matrix; \n"
|
||||||
@@ -78,12 +96,13 @@ const char *QSGVivanteVideoMaterialShader::fragmentShader() const {
|
|||||||
static const char *shader =
|
static const char *shader =
|
||||||
"uniform sampler2D texture;"
|
"uniform sampler2D texture;"
|
||||||
"uniform lowp float opacity;"
|
"uniform lowp float opacity;"
|
||||||
|
"uniform highp vec2 uvScale;"
|
||||||
""
|
""
|
||||||
"varying highp vec2 qt_TexCoord;"
|
"varying highp vec2 qt_TexCoord;"
|
||||||
""
|
""
|
||||||
"void main()"
|
"void main()"
|
||||||
"{"
|
"{"
|
||||||
" gl_FragColor = vec4(texture2D( texture, qt_TexCoord ).rgb, 1.0) * opacity;\n"
|
" gl_FragColor = vec4(texture2D( texture, qt_TexCoord * uvScale ).rgb, 1.0) * opacity;\n"
|
||||||
"}";
|
"}";
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
@@ -93,4 +112,5 @@ void QSGVivanteVideoMaterialShader::initialize() {
|
|||||||
mIdMatrix = program()->uniformLocation("qt_Matrix");
|
mIdMatrix = program()->uniformLocation("qt_Matrix");
|
||||||
mIdTexture = program()->uniformLocation("texture");
|
mIdTexture = program()->uniformLocation("texture");
|
||||||
mIdOpacity = program()->uniformLocation("opacity");
|
mIdOpacity = program()->uniformLocation("opacity");
|
||||||
|
mIdUVScale = program()->uniformLocation("uvScale");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,13 @@
|
|||||||
class QSGVivanteVideoMaterialShader : public QSGMaterialShader
|
class QSGVivanteVideoMaterialShader : public QSGMaterialShader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
QSGVivanteVideoMaterialShader();
|
||||||
|
|
||||||
void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
|
void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
|
||||||
virtual char const *const *attributeNames() const;
|
virtual char const *const *attributeNames() const;
|
||||||
|
|
||||||
|
void setUVScale(float uScale, float vScale);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const char *vertexShader() const;
|
virtual const char *vertexShader() const;
|
||||||
virtual const char *fragmentShader() const;
|
virtual const char *fragmentShader() const;
|
||||||
@@ -51,6 +55,11 @@ private:
|
|||||||
int mIdMatrix;
|
int mIdMatrix;
|
||||||
int mIdTexture;
|
int mIdTexture;
|
||||||
int mIdOpacity;
|
int mIdOpacity;
|
||||||
|
int mIdUVScale;
|
||||||
|
|
||||||
|
float mUScale;
|
||||||
|
float mVScale;
|
||||||
|
bool mNewUVScale;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QSGVIDEOMATERIALSHADER_VIVANTE_H
|
#endif // QSGVIDEOMATERIALSHADER_VIVANTE_H
|
||||||
|
|||||||
@@ -78,4 +78,23 @@ const QMap<QVideoFrame::PixelFormat, GLenum>& QSGVivanteVideoNode::getVideoForma
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int QSGVivanteVideoNode::getBytesForPixelFormat(QVideoFrame::PixelFormat pixelformat)
|
||||||
|
{
|
||||||
|
switch (pixelformat) {
|
||||||
|
case QVideoFrame::Format_YUV420P: return 1;
|
||||||
|
case QVideoFrame::Format_YV12: return 1;
|
||||||
|
case QVideoFrame::Format_NV12: return 1;
|
||||||
|
case QVideoFrame::Format_NV21: return 1;
|
||||||
|
case QVideoFrame::Format_UYVY: return 2;
|
||||||
|
case QVideoFrame::Format_YUYV: return 2;
|
||||||
|
case QVideoFrame::Format_RGB32: return 4;
|
||||||
|
case QVideoFrame::Format_ARGB32: return 4;
|
||||||
|
case QVideoFrame::Format_BGR32: return 4;
|
||||||
|
case QVideoFrame::Format_BGRA32: return 4;
|
||||||
|
case QVideoFrame::Format_RGB565: return 2;
|
||||||
|
default: return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public:
|
|||||||
void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags);
|
void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags);
|
||||||
|
|
||||||
static const QMap<QVideoFrame::PixelFormat, GLenum>& getVideoFormat2GLFormatMap();
|
static const QMap<QVideoFrame::PixelFormat, GLenum>& getVideoFormat2GLFormatMap();
|
||||||
|
static int getBytesForPixelFormat(QVideoFrame::PixelFormat pixelformat);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVideoSurfaceFormat mFormat;
|
QVideoSurfaceFormat mFormat;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**
|
**
|
||||||
** This file is part of the Qt Toolkit.
|
** This file is part of the Qt Toolkit.
|
||||||
**
|
**
|
||||||
** $QT_BEGIN_LICENSE:LGPL21$
|
** $QT_BEGIN_LICENSE:LGPL3$
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
** accordance with the commercial license agreement provided with the
|
** accordance with the commercial license agreement provided with the
|
||||||
@@ -16,16 +16,19 @@
|
|||||||
**
|
**
|
||||||
** GNU Lesser General Public License Usage
|
** GNU Lesser General Public License Usage
|
||||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
** General Public License version 2.1 or version 3 as published by the Free
|
** General Public License version 3 as published by the Free Software
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
** packaging of this file. Please review the following information to
|
||||||
** following information to ensure the GNU Lesser General Public License
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
**
|
||||||
** As a special exception, The Qt Company gives you certain additional
|
** GNU General Public License Usage
|
||||||
** rights. These rights are described in The Qt Company LGPL Exception
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
** General Public License version 2.0 or later as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||||
|
** the packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 2.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||||
**
|
**
|
||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -389,7 +389,8 @@ void MFAudioDecoderControl::handleSampleAdded()
|
|||||||
s->Release();
|
s->Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_cachedAudioBuffer = QAudioBuffer(abuf, m_audioFormat, qint64(sampleStartTime / 10000));
|
// WMF uses 100-nanosecond units, QAudioDecoder uses milliseconds, QAudioBuffer uses microseconds...
|
||||||
|
m_cachedAudioBuffer = QAudioBuffer(abuf, m_audioFormat, qint64(sampleStartTime / 10));
|
||||||
m_bufferReady = true;
|
m_bufferReady = true;
|
||||||
emit positionChanged(m_position);
|
emit positionChanged(m_position);
|
||||||
emit bufferAvailableChanged(m_bufferReady);
|
emit bufferAvailableChanged(m_bufferReady);
|
||||||
|
|||||||
@@ -41,6 +41,10 @@
|
|||||||
#include <private/qmediapluginloader_p.h>
|
#include <private/qmediapluginloader_p.h>
|
||||||
#include <QtCore/qloggingcategory.h>
|
#include <QtCore/qloggingcategory.h>
|
||||||
|
|
||||||
|
static void initResource() {
|
||||||
|
Q_INIT_RESOURCE(qtmultimediaquicktools);
|
||||||
|
}
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(qLcVideo, "qt.multimedia.video")
|
Q_LOGGING_CATEGORY(qLcVideo, "qt.multimedia.video")
|
||||||
@@ -130,6 +134,7 @@ QDeclarativeVideoOutput::QDeclarativeVideoOutput(QQuickItem *parent) :
|
|||||||
m_autoOrientation(false),
|
m_autoOrientation(false),
|
||||||
m_screenOrientationHandler(0)
|
m_screenOrientationHandler(0)
|
||||||
{
|
{
|
||||||
|
initResource();
|
||||||
setFlag(ItemHasContents, true);
|
setFlag(ItemHasContents, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -318,7 +318,8 @@ void QSGVideoMaterial_YUV::bind()
|
|||||||
|
|
||||||
m_frame = QVideoFrame();
|
m_frame = QVideoFrame();
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < m_planeCount; ++i) {
|
// Go backwards to finish with GL_TEXTURE0
|
||||||
|
for (int i = m_planeCount - 1; i >= 0; --i) {
|
||||||
functions->glActiveTexture(GL_TEXTURE0 + i);
|
functions->glActiveTexture(GL_TEXTURE0 + i);
|
||||||
functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[i]);
|
functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ QT += multimedia testlib
|
|||||||
QT -= gui
|
QT -= gui
|
||||||
|
|
||||||
TARGET = tst_qaudiobuffer
|
TARGET = tst_qaudiobuffer
|
||||||
CONFIG += console
|
CONFIG += testcase
|
||||||
CONFIG -= app_bundle
|
CONFIG -= app_bundle
|
||||||
|
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
|||||||
Reference in New Issue
Block a user