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 <michael.goddard@nokia.com>
This commit is contained in:
committed by
Qt by Nokia
parent
b6a8c713bc
commit
864ab3a39a
@@ -81,24 +81,31 @@ QAudioEncoderSettings CameraBinAudioEncoder::audioSettings() const
|
|||||||
|
|
||||||
void CameraBinAudioEncoder::setAudioSettings(const QAudioEncoderSettings &settings)
|
void CameraBinAudioEncoder::setAudioSettings(const QAudioEncoderSettings &settings)
|
||||||
{
|
{
|
||||||
m_userSettings = settings;
|
if (m_audioSettings != settings) {
|
||||||
m_audioSettings = settings;
|
m_audioSettings = settings;
|
||||||
emit settingsChanged();
|
m_actualAudioSettings = settings;
|
||||||
|
emit settingsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QAudioEncoderSettings CameraBinAudioEncoder::actualAudioSettings() const
|
||||||
|
{
|
||||||
|
return m_actualAudioSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraBinAudioEncoder::setActualAudioSettings(const QAudioEncoderSettings &settings)
|
void CameraBinAudioEncoder::setActualAudioSettings(const QAudioEncoderSettings &settings)
|
||||||
{
|
{
|
||||||
m_audioSettings = settings;
|
m_actualAudioSettings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraBinAudioEncoder::resetActualSettings()
|
void CameraBinAudioEncoder::resetActualSettings()
|
||||||
{
|
{
|
||||||
m_audioSettings = m_userSettings;
|
m_actualAudioSettings = m_audioSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
GstEncodingProfile *CameraBinAudioEncoder::createProfile()
|
GstEncodingProfile *CameraBinAudioEncoder::createProfile()
|
||||||
{
|
{
|
||||||
QString codec = m_audioSettings.codec();
|
QString codec = m_actualAudioSettings.codec();
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
|
||||||
if (codec.isEmpty())
|
if (codec.isEmpty())
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ public:
|
|||||||
QAudioEncoderSettings audioSettings() const;
|
QAudioEncoderSettings audioSettings() const;
|
||||||
void setAudioSettings(const QAudioEncoderSettings&);
|
void setAudioSettings(const QAudioEncoderSettings&);
|
||||||
|
|
||||||
|
QAudioEncoderSettings actualAudioSettings() const;
|
||||||
void setActualAudioSettings(const QAudioEncoderSettings&);
|
void setActualAudioSettings(const QAudioEncoderSettings&);
|
||||||
void resetActualSettings();
|
void resetActualSettings();
|
||||||
|
|
||||||
@@ -91,8 +92,8 @@ Q_SIGNALS:
|
|||||||
private:
|
private:
|
||||||
QGstCodecsInfo m_codecs;
|
QGstCodecsInfo m_codecs;
|
||||||
|
|
||||||
|
QAudioEncoderSettings m_actualAudioSettings;
|
||||||
QAudioEncoderSettings m_audioSettings;
|
QAudioEncoderSettings m_audioSettings;
|
||||||
QAudioEncoderSettings m_userSettings;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -79,24 +79,40 @@ void CameraBinContainer::setContainerFormat(const QString &format)
|
|||||||
{
|
{
|
||||||
if (m_format != format) {
|
if (m_format != format) {
|
||||||
m_format = format;
|
m_format = format;
|
||||||
|
m_actualFormat = format;
|
||||||
emit settingsChanged();
|
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()
|
GstEncodingContainerProfile *CameraBinContainer::createProfile()
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
|
||||||
if (m_format.isEmpty()) {
|
if (m_actualFormat.isEmpty()) {
|
||||||
caps = gst_caps_new_any();
|
caps = gst_caps_new_any();
|
||||||
} else {
|
} else {
|
||||||
QString format = m_format;
|
QString format = m_actualFormat;
|
||||||
QStringList supportedFormats = m_supportedContainers.supportedCodecs();
|
QStringList supportedFormats = m_supportedContainers.supportedCodecs();
|
||||||
|
|
||||||
//if format is not in the list of supported gstreamer mime types,
|
//if format is not in the list of supported gstreamer mime types,
|
||||||
//try to find the mime type with matching extension
|
//try to find the mime type with matching extension
|
||||||
if (!supportedFormats.contains(format)) {
|
if (!supportedFormats.contains(format)) {
|
||||||
QString extension = suggestedFileExtension(m_format);
|
QString extension = suggestedFileExtension(m_actualFormat);
|
||||||
foreach (const QString &formatCandidate, supportedFormats) {
|
foreach (const QString &formatCandidate, supportedFormats) {
|
||||||
if (suggestedFileExtension(formatCandidate) == extension) {
|
if (suggestedFileExtension(formatCandidate) == extension) {
|
||||||
format = formatCandidate;
|
format = formatCandidate;
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ public:
|
|||||||
virtual QString containerFormat() const;
|
virtual QString containerFormat() const;
|
||||||
virtual void setContainerFormat(const QString &format);
|
virtual void setContainerFormat(const QString &format);
|
||||||
|
|
||||||
|
QString actualContainerFormat() const;
|
||||||
|
void setActualContainerFormat(const QString &containerFormat);
|
||||||
|
void resetActualContainerFormat();
|
||||||
|
|
||||||
QString suggestedFileExtension(const QString &containerFormat) const;
|
QString suggestedFileExtension(const QString &containerFormat) const;
|
||||||
|
|
||||||
GstEncodingContainerProfile *createProfile();
|
GstEncodingContainerProfile *createProfile();
|
||||||
@@ -76,7 +80,8 @@ Q_SIGNALS:
|
|||||||
void settingsChanged();
|
void settingsChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_format; // backend selected format, using m_userFormat
|
QString m_format;
|
||||||
|
QString m_actualFormat;
|
||||||
QMap<QString, QString> m_fileExtensions;
|
QMap<QString, QString> m_fileExtensions;
|
||||||
|
|
||||||
QGstCodecsInfo m_supportedContainers;
|
QGstCodecsInfo m_supportedContainers;
|
||||||
|
|||||||
@@ -130,7 +130,49 @@ qint64 CameraBinRecorder::duration() const
|
|||||||
|
|
||||||
void CameraBinRecorder::applySettings()
|
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<QStringList> 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()
|
GstEncodingContainerProfile *CameraBinRecorder::videoProfile()
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ void CameraBinSession::setupCaptureResolution()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_captureMode == QCamera::CaptureVideo) {
|
if (m_captureMode == QCamera::CaptureVideo) {
|
||||||
QSize resolution = m_videoEncodeControl->videoSettings().resolution();
|
QSize resolution = m_videoEncodeControl->actualVideoSettings().resolution();
|
||||||
//qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
|
//qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
|
||||||
|
|
||||||
if (resolution.isEmpty()) {
|
if (resolution.isEmpty()) {
|
||||||
@@ -644,12 +644,16 @@ void CameraBinSession::setState(QCamera::State newState)
|
|||||||
GstState pending = GST_STATE_NULL;
|
GstState pending = GST_STATE_NULL;
|
||||||
gst_element_get_state(m_camerabin, &binState, &pending, 0);
|
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),
|
g_object_set (G_OBJECT(m_camerabin),
|
||||||
"video-profile",
|
"video-profile",
|
||||||
m_recorderControl->videoProfile(),
|
m_recorderControl->videoProfile(),
|
||||||
NULL);
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupCaptureResolution();
|
||||||
|
|
||||||
gst_element_set_state(m_camerabin, GST_STATE_PLAYING);
|
gst_element_set_state(m_camerabin, GST_STATE_PLAYING);
|
||||||
}
|
}
|
||||||
@@ -947,7 +951,7 @@ void CameraBinSession::recordVideo()
|
|||||||
m_recordingActive = true;
|
m_recordingActive = true;
|
||||||
m_actualSink = m_sink;
|
m_actualSink = m_sink;
|
||||||
if (m_actualSink.isEmpty()) {
|
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));
|
m_actualSink = QUrl::fromLocalFile(generateFileName("clip_", defaultDir(QCamera::CaptureVideo), ext));
|
||||||
} else if (!m_actualSink.isLocalFile()) {
|
} else if (!m_actualSink.isLocalFile()) {
|
||||||
m_actualSink = QUrl::fromLocalFile(m_actualSink.toEncoded());
|
m_actualSink = QUrl::fromLocalFile(m_actualSink.toEncoded());
|
||||||
|
|||||||
@@ -103,19 +103,26 @@ QVideoEncoderSettings CameraBinVideoEncoder::videoSettings() const
|
|||||||
|
|
||||||
void CameraBinVideoEncoder::setVideoSettings(const QVideoEncoderSettings &settings)
|
void CameraBinVideoEncoder::setVideoSettings(const QVideoEncoderSettings &settings)
|
||||||
{
|
{
|
||||||
m_videoSettings = settings;
|
if (m_videoSettings != settings) {
|
||||||
m_userSettings = settings;
|
m_actualVideoSettings = settings;
|
||||||
emit settingsChanged();
|
m_videoSettings = settings;
|
||||||
|
emit settingsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVideoEncoderSettings CameraBinVideoEncoder::actualVideoSettings() const
|
||||||
|
{
|
||||||
|
return m_actualVideoSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraBinVideoEncoder::setActualVideoSettings(const QVideoEncoderSettings &settings)
|
void CameraBinVideoEncoder::setActualVideoSettings(const QVideoEncoderSettings &settings)
|
||||||
{
|
{
|
||||||
m_videoSettings = settings;
|
m_actualVideoSettings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraBinVideoEncoder::resetActualSettings()
|
void CameraBinVideoEncoder::resetActualSettings()
|
||||||
{
|
{
|
||||||
m_videoSettings = m_userSettings;
|
m_actualVideoSettings = m_videoSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -152,7 +159,7 @@ QPair<int,int> CameraBinVideoEncoder::rateAsRational(qreal frameRate) const
|
|||||||
|
|
||||||
GstEncodingProfile *CameraBinVideoEncoder::createProfile()
|
GstEncodingProfile *CameraBinVideoEncoder::createProfile()
|
||||||
{
|
{
|
||||||
QString codec = m_videoSettings.codec();
|
QString codec = m_actualVideoSettings.codec();
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
|
||||||
if (codec.isEmpty())
|
if (codec.isEmpty())
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public:
|
|||||||
QVideoEncoderSettings videoSettings() const;
|
QVideoEncoderSettings videoSettings() const;
|
||||||
void setVideoSettings(const QVideoEncoderSettings &settings);
|
void setVideoSettings(const QVideoEncoderSettings &settings);
|
||||||
|
|
||||||
|
QVideoEncoderSettings actualVideoSettings() const;
|
||||||
void setActualVideoSettings(const QVideoEncoderSettings&);
|
void setActualVideoSettings(const QVideoEncoderSettings&);
|
||||||
void resetActualSettings();
|
void resetActualSettings();
|
||||||
|
|
||||||
@@ -91,8 +92,8 @@ private:
|
|||||||
|
|
||||||
QGstCodecsInfo m_codecs;
|
QGstCodecsInfo m_codecs;
|
||||||
|
|
||||||
QVideoEncoderSettings m_videoSettings; // backend selected settings, using m_userSettings
|
QVideoEncoderSettings m_actualVideoSettings;
|
||||||
QVideoEncoderSettings m_userSettings;
|
QVideoEncoderSettings m_videoSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -602,11 +602,9 @@ void tst_QCameraBackend::testVideoRecording()
|
|||||||
camera->setCaptureMode(QCamera::CaptureVideo);
|
camera->setCaptureMode(QCamera::CaptureVideo);
|
||||||
|
|
||||||
QVideoEncoderSettings videoSettings;
|
QVideoEncoderSettings videoSettings;
|
||||||
videoSettings.setResolution(640, 480);
|
videoSettings.setResolution(320, 240);
|
||||||
recorder.setVideoSettings(videoSettings);
|
recorder.setVideoSettings(videoSettings);
|
||||||
|
|
||||||
recorder.setContainerFormat("ogg");
|
|
||||||
|
|
||||||
QCOMPARE(recorder.status(), QMediaRecorder::UnloadedStatus);
|
QCOMPARE(recorder.status(), QMediaRecorder::UnloadedStatus);
|
||||||
|
|
||||||
camera->start();
|
camera->start();
|
||||||
|
|||||||
Reference in New Issue
Block a user