diff options
6 files changed, 111 insertions, 0 deletions
diff --git a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp index fe8098a02..865a764a8 100644 --- a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp @@ -117,4 +117,28 @@ GstEncodingProfile *CameraBinAudioEncoder::createProfile() return profile; } +void CameraBinAudioEncoder::applySettings(GstElement *encoder) +{ + GObjectClass * const objectClass = G_OBJECT_GET_CLASS(encoder); + const char * const name = gst_plugin_feature_get_name( + GST_PLUGIN_FEATURE(gst_element_get_factory(encoder))); + + const bool isVorbis = qstrcmp(name, "vorbisenc") == 0; + + const int bitRate = m_actualAudioSettings.bitRate(); + if (!isVorbis && bitRate == -1) { + // Bit rate is invalid, don't evaluate the remaining conditions unless the encoder is + // vorbisenc which is known to accept -1 as an unspecified bitrate. + } else if (g_object_class_find_property(objectClass, "bitrate")) { + g_object_set(G_OBJECT(encoder), "bitrate", bitRate, NULL); + } else if (g_object_class_find_property(objectClass, "target-bitrate")) { + g_object_set(G_OBJECT(encoder), "target-bitrate", bitRate, NULL); + } + + if (isVorbis) { + static const double qualities[] = { 0.1, 0.3, 0.5, 0.7, 1.0 }; + g_object_set(G_OBJECT(encoder), "quality", qualities[m_actualAudioSettings.quality()], NULL); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h index 46f812a67..f71436552 100644 --- a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h +++ b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h @@ -78,6 +78,8 @@ public: GstEncodingProfile *createProfile(); + void applySettings(GstElement *element); + Q_SIGNALS: void settingsChanged(); diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index 420ce5853..850f8c16c 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -133,6 +133,7 @@ CameraBinSession::CameraBinSession(GstElementFactory *sourceFactory, QObject *pa m_capsFilter(0), m_fileSink(0), m_audioEncoder(0), + m_videoEncoder(0), m_muxer(0) { if (m_sourceFactory) @@ -140,6 +141,8 @@ CameraBinSession::CameraBinSession(GstElementFactory *sourceFactory, QObject *pa m_camerabin = gst_element_factory_make("camerabin2", "camerabin2"); g_signal_connect(G_OBJECT(m_camerabin), "notify::idle", G_CALLBACK(updateBusyStatus), this); + g_signal_connect(G_OBJECT(m_camerabin), "element-added", G_CALLBACK(elementAdded), this); + g_signal_connect(G_OBJECT(m_camerabin), "element-removed", G_CALLBACK(elementRemoved), this); qt_gst_object_ref_sink(m_camerabin); m_bus = gst_element_get_bus(m_camerabin); @@ -344,6 +347,9 @@ void CameraBinSession::setupCaptureResolution() } else { g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, NULL, NULL); } + + if (m_videoEncoder) + m_videoEncodeControl->applySettings(m_videoEncoder); } void CameraBinSession::setAudioCaptureCaps() @@ -370,6 +376,9 @@ void CameraBinSession::setAudioCaptureCaps() GstCaps *caps = gst_caps_new_full(structure, NULL); g_object_set(G_OBJECT(m_camerabin), AUDIO_CAPTURE_CAPS_PROPERTY, caps, NULL); gst_caps_unref(caps); + + if (m_audioEncoder) + m_audioEncodeControl->applySettings(m_audioEncoder); } GstElement *CameraBinSession::buildCameraSource() @@ -1293,4 +1302,32 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate, return res; } +void CameraBinSession::elementAdded(GstBin *, GstElement *element, CameraBinSession *session) +{ + GstElementFactory *factory = gst_element_get_factory(element); + + if (GST_IS_BIN(element)) { + g_signal_connect(G_OBJECT(element), "element-added", G_CALLBACK(elementAdded), session); + g_signal_connect(G_OBJECT(element), "element-removed", G_CALLBACK(elementRemoved), session); + } else if (!factory) { + // no-op + } else if (gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER)) { + session->m_audioEncoder = element; + + session->m_audioEncodeControl->applySettings(element); + } else if (gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER)) { + session->m_videoEncoder = element; + + session->m_videoEncodeControl->applySettings(element); + } +} + +void CameraBinSession::elementRemoved(GstBin *, GstElement *element, CameraBinSession *session) +{ + if (element == session->m_audioEncoder) + session->m_audioEncoder = 0; + else if (element == session->m_videoEncoder) + session->m_videoEncoder = 0; +} + QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.h b/src/plugins/gstreamer/camerabin/camerabinsession.h index 42ed0e988..7e8a46dee 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.h +++ b/src/plugins/gstreamer/camerabin/camerabinsession.h @@ -190,6 +190,9 @@ private: void setAudioCaptureCaps(); static void updateBusyStatus(GObject *o, GParamSpec *p, gpointer d); + static void elementAdded(GstBin *bin, GstElement *element, CameraBinSession *session); + static void elementRemoved(GstBin *bin, GstElement *element, CameraBinSession *session); + QUrl m_sink; QUrl m_actualSink; bool m_recordingActive; @@ -241,6 +244,7 @@ private: GstElement *m_capsFilter; GstElement *m_fileSink; GstElement *m_audioEncoder; + GstElement *m_videoEncoder; GstElement *m_muxer; public: diff --git a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp index 228054318..554437047 100644 --- a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp @@ -175,4 +175,46 @@ GstEncodingProfile *CameraBinVideoEncoder::createProfile() return (GstEncodingProfile *)profile; } +void CameraBinVideoEncoder::applySettings(GstElement *encoder) +{ + GObjectClass * const objectClass = G_OBJECT_GET_CLASS(encoder); + const char * const name = gst_plugin_feature_get_name( + GST_PLUGIN_FEATURE(gst_element_get_factory(encoder))); + + const int bitRate = m_actualVideoSettings.bitRate(); + if (bitRate == -1) { + // Bit rate is invalid, don't evaluate the remaining conditions. + } else if (g_object_class_find_property(objectClass, "bitrate")) { + g_object_set(G_OBJECT(encoder), "bitrate", bitRate, NULL); + } else if (g_object_class_find_property(objectClass, "target-bitrate")) { + g_object_set(G_OBJECT(encoder), "target-bitrate", bitRate, NULL); + } + + if (qstrcmp(name, "theoraenc") == 0) { + static const int qualities[] = { 8, 16, 32, 45, 60 }; + g_object_set(G_OBJECT(encoder), "quality", qualities[m_actualVideoSettings.quality()], NULL); + } else if (qstrncmp(name, "avenc_", 6) == 0) { + if (g_object_class_find_property(objectClass, "pass")) { + static const int modes[] = { 0, 2, 512, 1024 }; + g_object_set(G_OBJECT(encoder), "pass", modes[m_actualVideoSettings.encodingMode()], NULL); + } + if (g_object_class_find_property(objectClass, "quantizer")) { + static const double qualities[] = { 20, 8.0, 3.0, 2.5, 2.0 }; + g_object_set(G_OBJECT(encoder), "quantizer", qualities[m_actualVideoSettings.quality()], NULL); + } + } else if (qstrncmp(name, "omx", 3) == 0) { + if (!g_object_class_find_property(objectClass, "control-rate")) { + } else switch (m_actualVideoSettings.encodingMode()) { + case QMultimedia::ConstantBitRateEncoding: + g_object_set(G_OBJECT(encoder), "control-rate", 2, NULL); + break; + case QMultimedia::AverageBitRateEncoding: + g_object_set(G_OBJECT(encoder), "control-rate", 1, NULL); + break; + default: + g_object_set(G_OBJECT(encoder), "control-rate", 0, NULL); + } + } +} + QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h index 0838ba651..dabe098ab 100644 --- a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h +++ b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h @@ -76,6 +76,8 @@ public: GstEncodingProfile *createProfile(); + void applySettings(GstElement *encoder); + Q_SIGNALS: void settingsChanged(); |