summaryrefslogtreecommitdiffstats
path: root/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp')
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp285
1 files changed, 85 insertions, 200 deletions
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
index a2bd80de8..af5b339e5 100644
--- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
@@ -45,6 +45,7 @@
#include <gst/gsttagsetter.h>
#include <gst/gstversion.h>
+#include <gst/video/video.h>
#include <QtCore/qdebug.h>
#include <QtCore/qurl.h>
@@ -52,7 +53,6 @@
#include <QCoreApplication>
#include <QtCore/qmetaobject.h>
#include <QtCore/qfile.h>
-
#include <QtGui/qimage.h>
QT_BEGIN_NAMESPACE
@@ -64,7 +64,7 @@ QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::Cap
m_waitingForEos(false),
m_pipelineMode(EmptyPipeline),
m_captureMode(captureMode),
- m_audioBufferProbeId(-1),
+ m_audioProbe(0),
m_audioInputFactory(0),
m_audioPreviewFactory(0),
m_videoInputFactory(0),
@@ -169,7 +169,7 @@ GstElement *QGstreamerCaptureSession::buildEncodeBin()
if (m_captureMode & Video) {
GstElement *videoQueue = gst_element_factory_make("queue", "video-encode-queue");
- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-encoder");
+ GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "videoconvert-encoder");
GstElement *videoscale = gst_element_factory_make("videoscale","videoscale-encoder");
gst_bin_add_many(GST_BIN(encodeBin), videoQueue, colorspace, videoscale, NULL);
@@ -280,7 +280,7 @@ GstElement *QGstreamerCaptureSession::buildVideoPreview()
if (m_viewfinderInterface) {
GstElement *bin = gst_bin_new("video-preview-bin");
- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-preview");
+ GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "videoconvert-preview");
GstElement *capsFilter = gst_element_factory_make("capsfilter", "capsfilter-video-preview");
GstElement *preview = m_viewfinderInterface->videoSink();
@@ -299,36 +299,25 @@ GstElement *QGstreamerCaptureSession::buildVideoPreview()
resolution = m_imageEncodeControl->imageSettings().resolution();
}
- if (!resolution.isEmpty() || frameRate > 0.001) {
- GstCaps *caps = gst_caps_new_empty();
- QStringList structureTypes;
- structureTypes << "video/x-raw-yuv" << "video/x-raw-rgb";
-
- foreach(const QString &structureType, structureTypes) {
- GstStructure *structure = gst_structure_new(structureType.toLatin1().constData(), NULL);
-
- if (!resolution.isEmpty()) {
- gst_structure_set(structure, "width", G_TYPE_INT, resolution.width(), NULL);
- gst_structure_set(structure, "height", G_TYPE_INT, resolution.height(), NULL);
- }
-
- if (frameRate > 0.001) {
- QPair<int,int> rate = m_videoEncodeControl->rateAsRational();
+ GstCaps *caps = QGstUtils::videoFilterCaps();
- //qDebug() << "frame rate:" << num << denum;
+ if (!resolution.isEmpty()) {
+ gst_caps_set_simple(caps, "width", G_TYPE_INT, resolution.width(), NULL);
+ gst_caps_set_simple(caps, "height", G_TYPE_INT, resolution.height(), NULL);
+ }
+ if (frameRate > 0.001) {
+ QPair<int,int> rate = m_videoEncodeControl->rateAsRational();
- gst_structure_set(structure, "framerate", GST_TYPE_FRACTION, rate.first, rate.second, NULL);
- }
+ //qDebug() << "frame rate:" << num << denum;
- gst_caps_append_structure(caps,structure);
- }
+ gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, rate.first, rate.second, NULL);
+ }
- //qDebug() << "set video preview caps filter:" << gst_caps_to_string(caps);
+ //qDebug() << "set video preview caps filter:" << gst_caps_to_string(caps);
- g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
+ g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
- gst_caps_unref(caps);
- }
+ gst_caps_unref(caps);
// add ghostpads
GstPad *pad = gst_element_get_static_pad(colorspace, "sink");
@@ -342,7 +331,7 @@ GstElement *QGstreamerCaptureSession::buildVideoPreview()
previewElement = gst_element_factory_make("fakesink", "video-preview");
#else
GstElement *bin = gst_bin_new("video-preview-bin");
- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-preview");
+ GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "videoconvert-preview");
GstElement *preview = gst_element_factory_make("ximagesink", "video-preview");
gst_bin_add_many(GST_BIN(bin), colorspace, preview, NULL);
gst_element_link(colorspace,preview);
@@ -360,101 +349,49 @@ GstElement *QGstreamerCaptureSession::buildVideoPreview()
return previewElement;
}
-
-static gboolean passImageFilter(GstElement *element,
- GstBuffer *buffer,
- void *appdata)
+void QGstreamerCaptureSession::probeCaps(GstCaps *caps)
{
- Q_UNUSED(element);
- Q_UNUSED(buffer);
-
- QGstreamerCaptureSession *session = (QGstreamerCaptureSession *)appdata;
- if (session->m_passImage || session->m_passPrerollImage) {
- session->m_passImage = false;
-
- if (session->m_passPrerollImage) {
- session->m_passPrerollImage = false;
- return TRUE;
- }
- session->m_passPrerollImage = false;
-
- QImage img;
-
- GstCaps *caps = gst_buffer_get_caps(buffer);
- if (caps) {
- GstStructure *structure = gst_caps_get_structure (caps, 0);
- gint width = 0;
- gint height = 0;
-
- if (structure &&
- gst_structure_get_int(structure, "width", &width) &&
- gst_structure_get_int(structure, "height", &height) &&
- width > 0 && height > 0) {
- if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) {
- guint32 fourcc = 0;
- gst_structure_get_fourcc(structure, "format", &fourcc);
-
- if (fourcc == GST_MAKE_FOURCC('I','4','2','0')) {
- img = QImage(width/2, height/2, QImage::Format_RGB32);
-
- const uchar *data = (const uchar *)buffer->data;
+#if GST_CHECK_VERSION(1,0,0)
+ gst_video_info_from_caps(&m_previewInfo, caps);
+#else
+ Q_UNUSED(caps);
+#endif
+}
- for (int y=0; y<height; y+=2) {
- const uchar *yLine = data + y*width;
- const uchar *uLine = data + width*height + y*width/4;
- const uchar *vLine = data + width*height*5/4 + y*width/4;
+bool QGstreamerCaptureSession::probeBuffer(GstBuffer *buffer)
+{
+ if (m_passPrerollImage) {
+ m_passImage = false;
+ m_passPrerollImage = false;
- for (int x=0; x<width; x+=2) {
- const qreal Y = 1.164*(yLine[x]-16);
- const int U = uLine[x/2]-128;
- const int V = vLine[x/2]-128;
+ return true;
+ } else if (!m_passImage) {
+ return false;
+ }
- int b = qBound(0, int(Y + 2.018*U), 255);
- int g = qBound(0, int(Y - 0.813*V - 0.391*U), 255);
- int r = qBound(0, int(Y + 1.596*V), 255);
+ m_passImage = false;
- img.setPixel(x/2,y/2,qRgb(r,g,b));
- }
- }
- }
+#if GST_CHECK_VERSION(1,0,0)
+ QImage img = QGstUtils::bufferToImage(buffer, m_previewInfo);
+#else
+ QImage img = QGstUtils::bufferToImage(buffer);
+#endif
- } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
- QImage::Format format = QImage::Format_Invalid;
- int bpp = 0;
- gst_structure_get_int(structure, "bpp", &bpp);
-
- if (bpp == 24)
- format = QImage::Format_RGB888;
- else if (bpp == 32)
- format = QImage::Format_RGB32;
-
- if (format != QImage::Format_Invalid) {
- img = QImage((const uchar *)buffer->data,
- width,
- height,
- format);
- img.bits(); //detach
- }
- }
- }
- gst_caps_unref(caps);
- }
+ if (img.isNull())
+ return true;
- static QMetaMethod exposedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageExposed);
- exposedSignal.invoke(session,
- Qt::QueuedConnection,
- Q_ARG(int,session->m_imageRequestId));
+ static QMetaMethod exposedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageExposed);
+ exposedSignal.invoke(this,
+ Qt::QueuedConnection,
+ Q_ARG(int,m_imageRequestId));
- static QMetaMethod capturedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageCaptured);
- capturedSignal.invoke(session,
- Qt::QueuedConnection,
- Q_ARG(int,session->m_imageRequestId),
- Q_ARG(QImage,img));
+ static QMetaMethod capturedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageCaptured);
+ capturedSignal.invoke(this,
+ Qt::QueuedConnection,
+ Q_ARG(int,m_imageRequestId),
+ Q_ARG(QImage,img));
- return TRUE;
- } else {
- return FALSE;
- }
+ return true;
}
static gboolean saveImageFilter(GstElement *element,
@@ -471,7 +408,15 @@ static gboolean saveImageFilter(GstElement *element,
if (!fileName.isEmpty()) {
QFile f(fileName);
if (f.open(QFile::WriteOnly)) {
- f.write((const char *)buffer->data, buffer->size);
+#if GST_CHECK_VERSION(1,0,0)
+ GstMapInfo info;
+ if (gst_buffer_map(buffer, &info, GST_MAP_READ)) {
+ f.write(reinterpret_cast<const char *>(info.data), info.size);
+ gst_buffer_unmap(buffer, &info);
+ }
+#else
+ f.write(reinterpret_cast<const char *>(buffer->data), buffer->size);
+#endif
f.close();
static QMetaMethod savedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageSaved);
@@ -489,18 +434,19 @@ GstElement *QGstreamerCaptureSession::buildImageCapture()
{
GstElement *bin = gst_bin_new("image-capture-bin");
GstElement *queue = gst_element_factory_make("queue", "queue-image-capture");
- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-image-capture");
+ GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "videoconvert-image-capture");
GstElement *encoder = gst_element_factory_make("jpegenc", "image-encoder");
GstElement *sink = gst_element_factory_make("fakesink","sink-image-capture");
GstPad *pad = gst_element_get_static_pad(queue, "src");
Q_ASSERT(pad);
- gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this);
+
+ addProbeToPad(pad, false);
+
gst_object_unref(GST_OBJECT(pad));
g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, NULL);
- g_signal_connect(G_OBJECT(sink), "handoff",
- G_CALLBACK(saveImageFilter), this);
+ g_signal_connect(G_OBJECT(sink), "handoff", G_CALLBACK(saveImageFilter), this);
gst_bin_add_many(GST_BIN(bin), queue, colorspace, encoder, sink, NULL);
gst_element_link_many(queue, colorspace, encoder, sink, NULL);
@@ -715,6 +661,8 @@ void QGstreamerCaptureSession::dumpGraph(const QString &fileName)
_gst_debug_bin_to_dot_file(GST_BIN(m_pipeline),
GstDebugGraphDetails(/*GST_DEBUG_GRAPH_SHOW_ALL |*/ GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES),
fileName.toLatin1());
+#else
+ Q_UNUSED(fileName);
#endif
}
@@ -877,10 +825,8 @@ void QGstreamerCaptureSession::setState(QGstreamerCaptureSession::State newState
qint64 QGstreamerCaptureSession::duration() const
{
- GstFormat format = GST_FORMAT_TIME;
- gint64 duration = 0;
-
- if ( m_encodeBin && gst_element_query_position(m_encodeBin, &format, &duration))
+ gint64 duration = 0;
+ if (m_encodeBin && qt_gst_element_query_position(m_encodeBin, GST_FORMAT_TIME, &duration))
return duration / 1000000;
else
return 0;
@@ -896,50 +842,8 @@ void QGstreamerCaptureSession::setMetaData(const QMap<QByteArray, QVariant> &dat
//qDebug() << "QGstreamerCaptureSession::setMetaData" << data;
m_metaData = data;
- if (m_encodeBin) {
- GstIterator *elements = gst_bin_iterate_all_by_interface(GST_BIN(m_encodeBin), GST_TYPE_TAG_SETTER);
- GstElement *element = 0;
- while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) {
- //qDebug() << "found element with tag setter interface:" << gst_element_get_name(element);
- QMapIterator<QByteArray, QVariant> it(data);
- while (it.hasNext()) {
- it.next();
- const QString tagName = it.key();
- const QVariant tagValue = it.value();
-
-
- switch(tagValue.type()) {
- case QVariant::String:
- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
- GST_TAG_MERGE_REPLACE_ALL,
- tagName.toUtf8().constData(),
- tagValue.toString().toUtf8().constData(),
- NULL);
- break;
- case QVariant::Int:
- case QVariant::LongLong:
- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
- GST_TAG_MERGE_REPLACE_ALL,
- tagName.toUtf8().constData(),
- tagValue.toInt(),
- NULL);
- break;
- case QVariant::Double:
- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
- GST_TAG_MERGE_REPLACE_ALL,
- tagName.toUtf8().constData(),
- tagValue.toDouble(),
- NULL);
- break;
- default:
- break;
- }
-
- }
-
- }
- gst_iterator_free(elements);
- }
+ if (m_encodeBin)
+ QGstUtils::setMetaData(GST_BIN(m_encodeBin), data);
}
bool QGstreamerCaptureSession::processBusMessage(const QGstreamerMessage &message)
@@ -1058,34 +962,16 @@ void QGstreamerCaptureSession::setVolume(qreal volume)
void QGstreamerCaptureSession::addProbe(QGstreamerAudioProbeControl* probe)
{
- QMutexLocker locker(&m_audioProbeMutex);
-
- if (m_audioProbes.contains(probe))
- return;
-
- m_audioProbes.append(probe);
+ Q_ASSERT(!m_audioProbe);
+ m_audioProbe = probe;
+ addAudioBufferProbe();
}
void QGstreamerCaptureSession::removeProbe(QGstreamerAudioProbeControl* probe)
{
- QMutexLocker locker(&m_audioProbeMutex);
- m_audioProbes.removeOne(probe);
-}
-
-gboolean QGstreamerCaptureSession::padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
-{
- Q_UNUSED(pad);
-
- QGstreamerCaptureSession *session = reinterpret_cast<QGstreamerCaptureSession*>(user_data);
- QMutexLocker locker(&session->m_audioProbeMutex);
-
- if (session->m_audioProbes.isEmpty())
- return TRUE;
-
- foreach (QGstreamerAudioProbeControl* probe, session->m_audioProbes)
- probe->bufferProbed(buffer);
-
- return TRUE;
+ Q_ASSERT(m_audioProbe == probe);
+ removeAudioBufferProbe();
+ m_audioProbe = 0;
}
GstPad *QGstreamerCaptureSession::getAudioProbePad()
@@ -1114,26 +1000,25 @@ GstPad *QGstreamerCaptureSession::getAudioProbePad()
void QGstreamerCaptureSession::removeAudioBufferProbe()
{
- if (m_audioBufferProbeId == -1)
+ if (!m_audioProbe)
return;
GstPad *pad = getAudioProbePad();
if (pad) {
- gst_pad_remove_buffer_probe(pad, m_audioBufferProbeId);
- gst_object_unref(G_OBJECT(pad));
+ m_audioProbe->removeProbeFromPad(pad);
+ gst_object_unref(GST_OBJECT(pad));
}
-
- m_audioBufferProbeId = -1;
}
void QGstreamerCaptureSession::addAudioBufferProbe()
{
- Q_ASSERT(m_audioBufferProbeId == -1);
+ if (!m_audioProbe)
+ return;
GstPad *pad = getAudioProbePad();
if (pad) {
- m_audioBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padAudioBufferProbe), this);
- gst_object_unref(G_OBJECT(pad));
+ m_audioProbe->addProbeToPad(pad);
+ gst_object_unref(GST_OBJECT(pad));
}
}