From 864ab3a39a8ce5155bf975e9ddd58fd20cd9f87f Mon Sep 17 00:00:00 2001 From: Dmytro Poplavskiy Date: Fri, 13 Jul 2012 11:12:06 +1000 Subject: [PATCH] Camerabin camera service: configure default video settings encodebin doesn't like the encoding profile with ANY container caps, if container and codecs are not specified try to find a commonly used supported combination Change-Id: Icbde042bd17d9682112fb8bbb8f0d506f6ddebe1 Reviewed-by: Michael Goddard --- .../gstreamer/camerabin/camerabinaudioencoder.cpp | 19 +++++++--- .../gstreamer/camerabin/camerabinaudioencoder.h | 3 +- .../gstreamer/camerabin/camerabincontainer.cpp | 22 +++++++++-- .../gstreamer/camerabin/camerabincontainer.h | 7 +++- .../gstreamer/camerabin/camerabinrecorder.cpp | 44 +++++++++++++++++++++- .../gstreamer/camerabin/camerabinsession.cpp | 12 ++++-- .../gstreamer/camerabin/camerabinvideoencoder.cpp | 19 +++++++--- .../gstreamer/camerabin/camerabinvideoencoder.h | 5 ++- .../qcamerabackend/tst_qcamerabackend.cpp | 4 +- 9 files changed, 108 insertions(+), 27 deletions(-) diff --git a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp index bfd22a3..ebbadd1 100644 --- a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp @@ -81,24 +81,31 @@ QAudioEncoderSettings CameraBinAudioEncoder::audioSettings() const void CameraBinAudioEncoder::setAudioSettings(const QAudioEncoderSettings &settings) { - m_userSettings = settings; - m_audioSettings = settings; - emit settingsChanged(); + if (m_audioSettings != settings) { + m_audioSettings = settings; + m_actualAudioSettings = settings; + emit settingsChanged(); + } +} + +QAudioEncoderSettings CameraBinAudioEncoder::actualAudioSettings() const +{ + return m_actualAudioSettings; } void CameraBinAudioEncoder::setActualAudioSettings(const QAudioEncoderSettings &settings) { - m_audioSettings = settings; + m_actualAudioSettings = settings; } void CameraBinAudioEncoder::resetActualSettings() { - m_audioSettings = m_userSettings; + m_actualAudioSettings = m_audioSettings; } GstEncodingProfile *CameraBinAudioEncoder::createProfile() { - QString codec = m_audioSettings.codec(); + QString codec = m_actualAudioSettings.codec(); GstCaps *caps; if (codec.isEmpty()) diff --git a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h index b3157d7..bbc4ab2 100644 --- a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h +++ b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h @@ -80,6 +80,7 @@ public: QAudioEncoderSettings audioSettings() const; void setAudioSettings(const QAudioEncoderSettings&); + QAudioEncoderSettings actualAudioSettings() const; void setActualAudioSettings(const QAudioEncoderSettings&); void resetActualSettings(); @@ -91,8 +92,8 @@ Q_SIGNALS: private: QGstCodecsInfo m_codecs; + QAudioEncoderSettings m_actualAudioSettings; QAudioEncoderSettings m_audioSettings; - QAudioEncoderSettings m_userSettings; }; QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabincontainer.cpp b/src/plugins/gstreamer/camerabin/camerabincontainer.cpp index c24e20a..7b9a138 100644 --- a/src/plugins/gstreamer/camerabin/camerabincontainer.cpp +++ b/src/plugins/gstreamer/camerabin/camerabincontainer.cpp @@ -79,24 +79,40 @@ void CameraBinContainer::setContainerFormat(const QString &format) { if (m_format != format) { m_format = format; + m_actualFormat = format; emit settingsChanged(); } } +QString CameraBinContainer::actualContainerFormat() const +{ + return m_actualFormat; +} + +void CameraBinContainer::setActualContainerFormat(const QString &containerFormat) +{ + m_actualFormat = containerFormat; +} + +void CameraBinContainer::resetActualContainerFormat() +{ + m_actualFormat = m_format; +} + GstEncodingContainerProfile *CameraBinContainer::createProfile() { GstCaps *caps; - if (m_format.isEmpty()) { + if (m_actualFormat.isEmpty()) { caps = gst_caps_new_any(); } else { - QString format = m_format; + QString format = m_actualFormat; QStringList supportedFormats = m_supportedContainers.supportedCodecs(); //if format is not in the list of supported gstreamer mime types, //try to find the mime type with matching extension if (!supportedFormats.contains(format)) { - QString extension = suggestedFileExtension(m_format); + QString extension = suggestedFileExtension(m_actualFormat); foreach (const QString &formatCandidate, supportedFormats) { if (suggestedFileExtension(formatCandidate) == extension) { format = formatCandidate; diff --git a/src/plugins/gstreamer/camerabin/camerabincontainer.h b/src/plugins/gstreamer/camerabin/camerabincontainer.h index 7830516..c9dcd94 100644 --- a/src/plugins/gstreamer/camerabin/camerabincontainer.h +++ b/src/plugins/gstreamer/camerabin/camerabincontainer.h @@ -68,6 +68,10 @@ public: virtual QString containerFormat() const; virtual void setContainerFormat(const QString &format); + QString actualContainerFormat() const; + void setActualContainerFormat(const QString &containerFormat); + void resetActualContainerFormat(); + QString suggestedFileExtension(const QString &containerFormat) const; GstEncodingContainerProfile *createProfile(); @@ -76,7 +80,8 @@ Q_SIGNALS: void settingsChanged(); private: - QString m_format; // backend selected format, using m_userFormat + QString m_format; + QString m_actualFormat; QMap m_fileExtensions; QGstCodecsInfo m_supportedContainers; diff --git a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp index 8e75e71..90cf3ce 100644 --- a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp @@ -130,7 +130,49 @@ qint64 CameraBinRecorder::duration() const void CameraBinRecorder::applySettings() { - //settings are applied during camera startup + CameraBinContainer *containerControl = m_session->mediaContainerControl(); + CameraBinAudioEncoder *audioEncoderControl = m_session->audioEncodeControl(); + CameraBinVideoEncoder *videoEncoderControl = m_session->videoEncodeControl(); + + containerControl->resetActualContainerFormat(); + audioEncoderControl->resetActualSettings(); + videoEncoderControl->resetActualSettings(); + + //encodebin doesn't like the encoding profile with ANY caps, + //if container and codecs are not specified, + //try to find a commonly used supported combination + if (containerControl->containerFormat().isEmpty() && + audioEncoderControl->audioSettings().codec().isEmpty() && + videoEncoderControl->videoSettings().codec().isEmpty()) { + + QList candidates; + candidates.append(QStringList() << "video/x-matroska" << "video/x-h264" << "audio/mpeg, mpegversion=(int)4"); + candidates.append(QStringList() << "video/webm" << "video/x-vp8" << "audio/x-vorbis"); + candidates.append(QStringList() << "application/ogg" << "video/x-theora" << "audio/x-vorbis"); + candidates.append(QStringList() << "video/quicktime" << "video/x-h264" << "audio/mpeg, mpegversion=(int)4"); + candidates.append(QStringList() << "video/quicktime" << "video/x-h264" << "audio/mpeg"); + candidates.append(QStringList() << "video/x-msvideo" << "video/x-divx" << "audio/mpeg"); + + foreach (const QStringList &candidate, candidates) { + if (containerControl->supportedContainers().contains(candidate[0]) && + videoEncoderControl->supportedVideoCodecs().contains(candidate[1]) && + audioEncoderControl->supportedAudioCodecs().contains(candidate[2])) { + containerControl->setActualContainerFormat(candidate[0]); + + QVideoEncoderSettings videoSettings = videoEncoderControl->videoSettings(); + videoSettings.setCodec(candidate[1]); + if (videoSettings.resolution().isEmpty()) + videoSettings.setResolution(640, 480); + videoEncoderControl->setActualVideoSettings(videoSettings); + + QAudioEncoderSettings audioSettings = audioEncoderControl->audioSettings(); + audioSettings.setCodec(candidate[2]); + audioEncoderControl->setActualAudioSettings(audioSettings); + + break; + } + } + } } GstEncodingContainerProfile *CameraBinRecorder::videoProfile() diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index 2c26427..c5c4a50 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -338,7 +338,7 @@ void CameraBinSession::setupCaptureResolution() } if (m_captureMode == QCamera::CaptureVideo) { - QSize resolution = m_videoEncodeControl->videoSettings().resolution(); + QSize resolution = m_videoEncodeControl->actualVideoSettings().resolution(); //qreal framerate = m_videoEncodeControl->videoSettings().frameRate(); if (resolution.isEmpty()) { @@ -644,12 +644,16 @@ void CameraBinSession::setState(QCamera::State newState) GstState pending = GST_STATE_NULL; gst_element_get_state(m_camerabin, &binState, &pending, 0); - setupCaptureResolution(); - if (captureMode() == QCamera::CaptureVideo) + if (captureMode() == QCamera::CaptureVideo) { + m_recorderControl->applySettings(); + g_object_set (G_OBJECT(m_camerabin), "video-profile", m_recorderControl->videoProfile(), NULL); + } + + setupCaptureResolution(); gst_element_set_state(m_camerabin, GST_STATE_PLAYING); } @@ -947,7 +951,7 @@ void CameraBinSession::recordVideo() m_recordingActive = true; m_actualSink = m_sink; if (m_actualSink.isEmpty()) { - QString ext = m_mediaContainerControl->suggestedFileExtension(m_mediaContainerControl->containerFormat()); + QString ext = m_mediaContainerControl->suggestedFileExtension(m_mediaContainerControl->actualContainerFormat()); m_actualSink = QUrl::fromLocalFile(generateFileName("clip_", defaultDir(QCamera::CaptureVideo), ext)); } else if (!m_actualSink.isLocalFile()) { m_actualSink = QUrl::fromLocalFile(m_actualSink.toEncoded()); diff --git a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp index 085b9a1..e756030 100644 --- a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp @@ -103,19 +103,26 @@ QVideoEncoderSettings CameraBinVideoEncoder::videoSettings() const void CameraBinVideoEncoder::setVideoSettings(const QVideoEncoderSettings &settings) { - m_videoSettings = settings; - m_userSettings = settings; - emit settingsChanged(); + if (m_videoSettings != settings) { + m_actualVideoSettings = settings; + m_videoSettings = settings; + emit settingsChanged(); + } +} + +QVideoEncoderSettings CameraBinVideoEncoder::actualVideoSettings() const +{ + return m_actualVideoSettings; } void CameraBinVideoEncoder::setActualVideoSettings(const QVideoEncoderSettings &settings) { - m_videoSettings = settings; + m_actualVideoSettings = settings; } void CameraBinVideoEncoder::resetActualSettings() { - m_videoSettings = m_userSettings; + m_actualVideoSettings = m_videoSettings; } @@ -152,7 +159,7 @@ QPair CameraBinVideoEncoder::rateAsRational(qreal frameRate) const GstEncodingProfile *CameraBinVideoEncoder::createProfile() { - QString codec = m_videoSettings.codec(); + QString codec = m_actualVideoSettings.codec(); GstCaps *caps; if (codec.isEmpty()) diff --git a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h index 9a9dae1..5ab1ae0 100644 --- a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h +++ b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h @@ -78,6 +78,7 @@ public: QVideoEncoderSettings videoSettings() const; void setVideoSettings(const QVideoEncoderSettings &settings); + QVideoEncoderSettings actualVideoSettings() const; void setActualVideoSettings(const QVideoEncoderSettings&); void resetActualSettings(); @@ -91,8 +92,8 @@ private: QGstCodecsInfo m_codecs; - QVideoEncoderSettings m_videoSettings; // backend selected settings, using m_userSettings - QVideoEncoderSettings m_userSettings; + QVideoEncoderSettings m_actualVideoSettings; + QVideoEncoderSettings m_videoSettings; }; QT_END_NAMESPACE diff --git a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp index 830d03d..f46ba9b 100644 --- a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp +++ b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp @@ -602,11 +602,9 @@ void tst_QCameraBackend::testVideoRecording() camera->setCaptureMode(QCamera::CaptureVideo); QVideoEncoderSettings videoSettings; - videoSettings.setResolution(640, 480); + videoSettings.setResolution(320, 240); recorder.setVideoSettings(videoSettings); - recorder.setContainerFormat("ogg"); - QCOMPARE(recorder.status(), QMediaRecorder::UnloadedStatus); camera->start(); -- 2.7.4