diff options
Diffstat (limited to 'src/plugins/gstreamer/mediacapture')
8 files changed, 157 insertions, 342 deletions
diff --git a/src/plugins/gstreamer/mediacapture/mediacapturecamera.json b/src/plugins/gstreamer/mediacapture/mediacapturecamera.json index af9f3575f..f5fba17e6 100644 --- a/src/plugins/gstreamer/mediacapture/mediacapturecamera.json +++ b/src/plugins/gstreamer/mediacapture/mediacapturecamera.json @@ -1,4 +1,4 @@ { - "Keys": ["gstreamermediacapture"] + "Keys": ["gstreamermediacapture"], "Services": ["org.qt-project.qt.audiosource", "org.qt-project.qt.camera"] } diff --git a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp index d05df4997..8881445f8 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp @@ -34,6 +34,7 @@ #include "qgstreameraudioencode.h" #include "qgstreamercapturesession.h" #include "qgstreamermediacontainercontrol.h" +#include <private/qgstutils_p.h> #include <QtCore/qdebug.h> @@ -175,7 +176,7 @@ GstElement *QGstreamerAudioEncode::createEncoder() if (m_audioSettings.sampleRate() > 0 || m_audioSettings.channelCount() > 0) { GstCaps *caps = gst_caps_new_empty(); - GstStructure *structure = gst_structure_new("audio/x-raw-int", NULL); + GstStructure *structure = qt_gst_structure_new_empty(QT_GSTREAMER_RAW_AUDIO_MIME); if (m_audioSettings.sampleRate() > 0) gst_structure_set(structure, "rate", G_TYPE_INT, m_audioSettings.sampleRate(), NULL ); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp index 97a165dca..1ab98cd4a 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp @@ -62,27 +62,25 @@ QT_BEGIN_NAMESPACE -QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObject *parent): - QMediaService(parent) -{ - m_captureSession = 0; - m_cameraControl = 0; - m_metaDataControl = 0; - +QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObject *parent) + : QMediaService(parent) + , m_captureSession(0) + , m_cameraControl(0) #if defined(USE_GSTREAMER_CAMERA) - m_videoInput = 0; + , m_videoInput(0) #endif - m_audioInputSelector = 0; - m_videoInputDevice = 0; - - m_videoOutput = 0; - m_videoRenderer = 0; - m_videoWindow = 0; + , m_metaDataControl(0) + , m_audioInputSelector(0) + , m_videoInputDevice(0) + , m_videoOutput(0) + , m_videoRenderer(0) + , m_videoWindow(0) #if defined(HAVE_WIDGETS) - m_videoWidgetControl = 0; + , m_videoWidgetControl(0) #endif - m_imageCaptureControl = 0; - + , m_imageCaptureControl(0) + , m_audioProbeControl(0) +{ if (service == Q_MEDIASERVICE_AUDIOSOURCE) { m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::Audio, this); } @@ -163,12 +161,12 @@ QMediaControl *QGstreamerCaptureService::requestControl(const char *name) return m_imageCaptureControl; if (qstrcmp(name,QMediaAudioProbeControl_iid) == 0) { - if (m_captureSession) { - QGstreamerAudioProbeControl *probe = new QGstreamerAudioProbeControl(this); - m_captureSession->addProbe(probe); - return probe; + if (!m_audioProbeControl) { + m_audioProbeControl = new QGstreamerAudioProbeControl(this); + m_captureSession->addProbe(m_audioProbeControl); } - return 0; + m_audioProbeControl->ref.ref(); + return m_audioProbeControl; } if (!m_videoOutput) { @@ -194,17 +192,15 @@ QMediaControl *QGstreamerCaptureService::requestControl(const char *name) void QGstreamerCaptureService::releaseControl(QMediaControl *control) { - if (control && control == m_videoOutput) { + if (!control) { + return; + } else if (control == m_videoOutput) { m_videoOutput = 0; m_captureSession->setVideoPreview(0); - } - - QGstreamerAudioProbeControl* audioProbe = qobject_cast<QGstreamerAudioProbeControl*>(control); - if (audioProbe) { - if (m_captureSession) - m_captureSession->removeProbe(audioProbe); - delete audioProbe; - return; + } else if (control == m_audioProbeControl && !m_audioProbeControl->ref.deref()) { + m_captureSession->removeProbe(m_audioProbeControl); + delete m_audioProbeControl; + m_audioProbeControl = 0; } } diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h index 7ff8ce253..e0cf4ee42 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h @@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE class QAudioInputSelectorControl; class QVideoDeviceSelectorControl; +class QGstreamerAudioProbeControl; class QGstreamerCaptureSession; class QGstreamerCameraControl; class QGstreamerMessage; @@ -86,6 +87,8 @@ private: QMediaControl *m_videoWidgetControl; #endif QGstreamerImageCaptureControl *m_imageCaptureControl; + + QGstreamerAudioProbeControl *m_audioProbeControl; }; QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp index 0ac34ee72..85ed687d3 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp @@ -110,90 +110,16 @@ QMultimedia::SupportEstimate QGstreamerCaptureServicePlugin::hasSupport(const QS return QGstUtils::hasSupport(mimeType, codecs, m_supportedMimeTypeSet); } + +static bool isEncoderOrMuxer(GstElementFactory *factory) +{ + return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_MUXER) + || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_ENCODER); +} + void QGstreamerCaptureServicePlugin::updateSupportedMimeTypes() const { - //enumerate supported mime types - gst_init(NULL, NULL); - - GList *plugins, *orig_plugins; - orig_plugins = plugins = gst_default_registry_get_plugin_list (); - - while (plugins) { - GList *features, *orig_features; - - GstPlugin *plugin = (GstPlugin *) (plugins->data); - plugins = g_list_next (plugins); - - if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED - continue; - - orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (), - plugin->desc.name); - while (features) { - if (!G_UNLIKELY(features->data == NULL)) { - GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data); - if (GST_IS_ELEMENT_FACTORY (feature)) { - GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature)); - if (factory - && factory->numpadtemplates > 0 - && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 - || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0 - || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) { - const GList *pads = factory->staticpadtemplates; - while (pads) { - GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data); - pads = g_list_next (pads); - if (padtemplate->direction != GST_PAD_SINK) - continue; - if (padtemplate->static_caps.string) { - GstCaps *caps = gst_static_caps_get(&padtemplate->static_caps); - if (!gst_caps_is_any (caps) && ! gst_caps_is_empty (caps)) { - for (guint i = 0; i < gst_caps_get_size(caps); i++) { - GstStructure *structure = gst_caps_get_structure(caps, i); - QString nameLowcase = QString(gst_structure_get_name (structure)).toLower(); - - m_supportedMimeTypeSet.insert(nameLowcase); - if (nameLowcase.contains("mpeg")) { - //Because mpeg version number is only included in the detail - //description, it is necessary to manually extract this information - //in order to match the mime type of mpeg4. - const GValue *value = gst_structure_get_value(structure, "mpegversion"); - if (value) { - gchar *str = gst_value_serialize (value); - QString versions(str); - QStringList elements = versions.split(QRegExp("\\D+"), QString::SkipEmptyParts); - foreach (const QString &e, elements) - m_supportedMimeTypeSet.insert(nameLowcase + e); - g_free (str); - } - } - } - } - gst_caps_unref(caps); - } - } - gst_object_unref (factory); - } - } else if (GST_IS_TYPE_FIND_FACTORY(feature)) { - QString name(gst_plugin_feature_get_name(feature)); - if (name.contains('/')) //filter out any string without '/' which is obviously not a mime type - m_supportedMimeTypeSet.insert(name.toLower()); - } - } - features = g_list_next (features); - } - gst_plugin_feature_list_free (orig_features); - } - gst_plugin_list_free (orig_plugins); - -#if defined QT_SUPPORTEDMIMETYPES_DEBUG - QStringList list = m_supportedMimeTypeSet.toList(); - list.sort(); - if (qgetenv("QT_DEBUG_PLUGINS").toInt() > 0) { - foreach (const QString &type, list) - qDebug() << type; - } -#endif + m_supportedMimeTypeSet = QGstUtils::supportedMimeTypes(isEncoderOrMuxer); } QStringList QGstreamerCaptureServicePlugin::supportedMimeTypes() const 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)); } } diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h index a759f22e5..ad26327e7 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h @@ -41,8 +41,10 @@ #include <QtCore/qurl.h> #include <gst/gst.h> +#include <gst/video/video.h> #include <private/qgstreamerbushelper_p.h> +#include <private/qgstreamerbufferprobe_p.h> QT_BEGIN_NAMESPACE @@ -70,7 +72,10 @@ public: virtual QList<QSize> supportedResolutions(qreal frameRate = -1) const = 0; }; -class QGstreamerCaptureSession : public QObject, public QGstreamerBusMessageFilter +class QGstreamerCaptureSession + : public QObject + , public QGstreamerBusMessageFilter + , private QGstreamerBufferProbe { Q_OBJECT Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged) @@ -131,7 +136,6 @@ public: void addProbe(QGstreamerAudioProbeControl* probe); void removeProbe(QGstreamerAudioProbeControl* probe); - static gboolean padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data); signals: void stateChanged(QGstreamerCaptureSession::State state); @@ -156,6 +160,9 @@ public slots: void setVolume(qreal volume); private: + void probeCaps(GstCaps *caps); + bool probeBuffer(GstBuffer *buffer); + enum PipelineMode { EmptyPipeline, PreviewPipeline, RecordingPipeline, PreviewAndRecordingPipeline }; GstElement *buildEncodeBin(); @@ -180,9 +187,7 @@ private: QGstreamerCaptureSession::CaptureMode m_captureMode; QMap<QByteArray, QVariant> m_metaData; - QList<QGstreamerAudioProbeControl*> m_audioProbes; - QMutex m_audioProbeMutex; - int m_audioBufferProbeId; + QGstreamerAudioProbeControl *m_audioProbe; QGstreamerElementFactory *m_audioInputFactory; QGstreamerElementFactory *m_audioPreviewFactory; @@ -217,6 +222,10 @@ private: GstElement *m_encodeBin; +#if GST_CHECK_VERSION(1,0,0) + GstVideoInfo m_previewInfo; +#endif + public: bool m_passImage; bool m_passPrerollImage; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp index 2f0d0ee76..81b85d7b0 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp @@ -34,7 +34,7 @@ #include "qgstreamervideoencode.h" #include "qgstreamercapturesession.h" #include "qgstreamermediacontainercontrol.h" - +#include <private/qgstutils_p.h> #include <QtCore/qdebug.h> #include <math.h> @@ -147,7 +147,7 @@ GstElement *QGstreamerVideoEncode::createEncoder() GstElement *capsFilter = gst_element_factory_make("capsfilter", "capsfilter-video"); gst_bin_add(encoderBin, capsFilter); - GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", NULL); + GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, NULL); gst_bin_add(encoderBin, colorspace); gst_bin_add(encoderBin, encoderElement); @@ -252,27 +252,22 @@ GstElement *QGstreamerVideoEncode::createEncoder() } if (!m_videoSettings.resolution().isEmpty() || m_videoSettings.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 (!m_videoSettings.resolution().isEmpty()) { - gst_structure_set(structure, "width", G_TYPE_INT, m_videoSettings.resolution().width(), NULL); - gst_structure_set(structure, "height", G_TYPE_INT, m_videoSettings.resolution().height(), NULL); - } - - if (m_videoSettings.frameRate() > 0.001) { - QPair<int,int> rate = rateAsRational(); - - //qDebug() << "frame rate:" << num << denum; - - gst_structure_set(structure, "framerate", GST_TYPE_FRACTION, rate.first, rate.second, NULL); - } + GstCaps *caps = QGstUtils::videoFilterCaps(); + + if (!m_videoSettings.resolution().isEmpty()) { + gst_caps_set_simple( + caps, + "width", G_TYPE_INT, m_videoSettings.resolution().width(), + "height", G_TYPE_INT, m_videoSettings.resolution().height(), + NULL); + } - gst_caps_append_structure(caps,structure); + if (m_videoSettings.frameRate() > 0.001) { + QPair<int,int> rate = rateAsRational(); + gst_caps_set_simple( + caps, + "framerate", GST_TYPE_FRACTION, rate.first, rate.second, + NULL); } //qDebug() << "set video caps filter:" << gst_caps_to_string(caps); |