From 6468334eb922af18f02ea196d2ac0aff00c71a74 Mon Sep 17 00:00:00 2001 From: Lev Zelenskiy Date: Thu, 16 Feb 2012 16:54:46 +1000 Subject: [PATCH] GStreamer backend for audio decoder service. Includes basic integration test. Change-Id: I4c6d1dbefa1f27e107b3556a3d4da58811eeb122 Reviewed-by: Michael Goddard --- src/gsttools/qgstutils.cpp | 64 +++++- src/multimedia/gsttools_headers/qgstutils_p.h | 2 + .../audiodecoder/qgstreameraudiodecodercontrol.cpp | 1 + .../audiodecoder/qgstreameraudiodecodersession.cpp | 239 +++++++++++++++------ .../audiodecoder/qgstreameraudiodecodersession.h | 15 +- .../qaudiodecoderbackend/qaudiodecoderbackend.pro | 15 ++ .../qaudiodecoderbackend/testdata/test.wav | Bin 0 -> 88232 bytes .../tst_qaudiodecoderbackend.cpp | 151 +++++++++++++ 8 files changed, 413 insertions(+), 74 deletions(-) create mode 100644 tests/auto/integration/qaudiodecoderbackend/qaudiodecoderbackend.pro create mode 100644 tests/auto/integration/qaudiodecoderbackend/testdata/test.wav create mode 100644 tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp index 5c12763..03c31fb 100644 --- a/src/gsttools/qgstutils.cpp +++ b/src/gsttools/qgstutils.cpp @@ -168,7 +168,7 @@ QSize QGstUtils::capsCorrectedResolution(const GstCaps *caps) } /*! - *Returns audio format for caps. + Returns audio format for caps. If caps doesn't have a valid audio format, an empty QAudioFormat is returned. */ @@ -251,4 +251,66 @@ QAudioFormat QGstUtils::audioFormatForCaps(const GstCaps *caps) return format; } + +/*! + Returns audio format for a buffer. + If the buffer doesn't have a valid audio format, an empty QAudioFormat is returned. +*/ + +QAudioFormat QGstUtils::audioFormatForBuffer(GstBuffer *buffer) +{ + GstCaps* caps = gst_buffer_get_caps(buffer); + if (!caps) + return QAudioFormat(); + + QAudioFormat format = QGstUtils::audioFormatForCaps(caps); + gst_caps_unref(caps); + return format; +} + + +/*! + Builds GstCaps for an audio format. + Returns 0 if the audio format is not valid. + Caller must unref GstCaps. +*/ + +GstCaps *QGstUtils::capsForAudioFormat(QAudioFormat format) +{ + GstStructure *structure = 0; + + if (format.isValid()) { + if (format.sampleType() == QAudioFormat::SignedInt || format.sampleType() == QAudioFormat::UnSignedInt) { + structure = gst_structure_new("audio/x-raw-int", NULL); + } else if (format.sampleType() == QAudioFormat::Float) { + structure = gst_structure_new("audio/x-raw-float", NULL); + } + } + + GstCaps *caps = 0; + + if (structure) { + gst_structure_set(structure, "rate", G_TYPE_INT, format.sampleRate(), NULL); + gst_structure_set(structure, "channels", G_TYPE_INT, format.channelCount(), NULL); + gst_structure_set(structure, "width", G_TYPE_INT, format.sampleSize(), NULL); + gst_structure_set(structure, "depth", G_TYPE_INT, format.sampleSize(), NULL); + + if (format.byteOrder() == QAudioFormat::LittleEndian) + gst_structure_set(structure, "endianness", G_TYPE_INT, 1234, NULL); + else if (format.byteOrder() == QAudioFormat::BigEndian) + gst_structure_set(structure, "endianness", G_TYPE_INT, 4321, NULL); + + if (format.sampleType() == QAudioFormat::SignedInt) + gst_structure_set(structure, "signed", G_TYPE_BOOLEAN, TRUE, NULL); + else if (format.sampleType() == QAudioFormat::UnSignedInt) + gst_structure_set(structure, "signed", G_TYPE_BOOLEAN, FALSE, NULL); + + caps = gst_caps_new_empty(); + Q_ASSERT(caps); + gst_caps_append_structure(caps, structure); + } + + return caps; +} + QT_END_NAMESPACE diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h index e9220d7..45bf76e 100644 --- a/src/multimedia/gsttools_headers/qgstutils_p.h +++ b/src/multimedia/gsttools_headers/qgstutils_p.h @@ -69,6 +69,8 @@ namespace QGstUtils { QSize capsResolution(const GstCaps *caps); QSize capsCorrectedResolution(const GstCaps *caps); QAudioFormat audioFormatForCaps(const GstCaps *caps); + QAudioFormat audioFormatForBuffer(GstBuffer *buffer); + GstCaps *capsForAudioFormat(QAudioFormat format); } QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.cpp index db1b716..4668a39 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.cpp +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.cpp @@ -62,6 +62,7 @@ QGstreamerAudioDecoderControl::QGstreamerAudioDecoderControl(QGstreamerAudioDeco connect(m_session, SIGNAL(bufferReady()), this, SIGNAL(bufferReady())); connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString))); connect(m_session, SIGNAL(formatChanged(QAudioFormat)), this, SIGNAL(formatChanged(QAudioFormat))); + connect(m_session, SIGNAL(sourceChanged()), this, SIGNAL(sourceChanged())); connect(m_session, SIGNAL(stateChanged(QAudioDecoder::State)), this, SIGNAL(stateChanged(QAudioDecoder::State))); } diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp index 4afee23..88f3a0e 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp @@ -54,9 +54,24 @@ #include #include #include +#include + +#define MAX_BUFFERS_IN_QUEUE 5 QT_BEGIN_NAMESPACE +typedef enum { + GST_PLAY_FLAG_VIDEO = 0x00000001, + GST_PLAY_FLAG_AUDIO = 0x00000002, + GST_PLAY_FLAG_TEXT = 0x00000004, + GST_PLAY_FLAG_VIS = 0x00000008, + GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010, + GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020, + GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040, + GST_PLAY_FLAG_DOWNLOAD = 0x00000080, + GST_PLAY_FLAG_BUFFERING = 0x000000100 +} GstPlayFlags; + QGstreamerAudioDecoderSession::QGstreamerAudioDecoderSession(QObject *parent) : QObject(parent), m_state(QAudioDecoder::StoppedState), @@ -64,28 +79,67 @@ QGstreamerAudioDecoderSession::QGstreamerAudioDecoderSession(QObject *parent) m_busHelper(0), m_bus(0), m_playbin(0), + m_appSink(0), #if defined(HAVE_GST_APPSRC) m_appSrc(0), #endif - mDevice(0) + mDevice(0), + m_buffersAvailable(0) { // Default format mFormat.setChannels(2); mFormat.setSampleSize(16); mFormat.setFrequency(48000); - mFormat.setCodec("audio/x-raw"); + mFormat.setCodec("audio/pcm"); mFormat.setSampleType(QAudioFormat::UnSignedInt); // Create pipeline here -#if 0 + m_playbin = gst_element_factory_make("playbin2", NULL); + if (m_playbin != 0) { + + int flags = 0; + g_object_get(G_OBJECT(m_playbin), "flags", &flags, NULL); + // make sure not to use GST_PLAY_FLAG_NATIVE_AUDIO, it prevents audio format conversion + flags &= ~(GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_TEXT | GST_PLAY_FLAG_VIS | GST_PLAY_FLAG_NATIVE_AUDIO); + flags |= GST_PLAY_FLAG_AUDIO; + g_object_set(G_OBJECT(m_playbin), "flags", flags, NULL); + + m_appSink = (GstAppSink*)gst_element_factory_make("appsink", NULL); + gst_object_ref(GST_OBJECT(m_appSink)); + + GstAppSinkCallbacks callbacks; + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.new_buffer = &new_buffer; + gst_app_sink_set_callbacks(m_appSink, &callbacks, this, NULL); + gst_app_sink_set_max_buffers(m_appSink, MAX_BUFFERS_IN_QUEUE); + gst_base_sink_set_sync(GST_BASE_SINK(m_appSink), FALSE); + + GstElement *audioConvert = gst_element_factory_make("audioconvert", NULL); + + GstElement *bin = gst_bin_new("audio-output-bin"); + gst_bin_add(GST_BIN(bin), audioConvert); + gst_bin_add(GST_BIN(bin), GST_ELEMENT(m_appSink)); + gst_element_link(audioConvert, GST_ELEMENT(m_appSink)); + + // add ghostpad + GstPad *pad = gst_element_get_static_pad(audioConvert, "sink"); + Q_ASSERT(pad); + gst_element_add_pad(GST_ELEMENT(bin), gst_ghost_pad_new("sink", pad)); + gst_object_unref(GST_OBJECT(pad)); + // Sort out messages m_bus = gst_element_get_bus(m_playbin); m_busHelper = new QGstreamerBusHelper(m_bus, this); m_busHelper->installMessageFilter(this); + + g_object_set(G_OBJECT(m_playbin), "audio-sink", bin, NULL); + + // Set volume to 100% + gdouble volume = 1.0; + g_object_set(G_OBJECT(m_playbin), "volume", volume, NULL); } -#endif } QGstreamerAudioDecoderSession::~QGstreamerAudioDecoderSession() @@ -96,6 +150,7 @@ QGstreamerAudioDecoderSession::~QGstreamerAudioDecoderSession() delete m_busHelper; gst_object_unref(GST_OBJECT(m_bus)); gst_object_unref(GST_OBJECT(m_playbin)); + gst_object_unref(GST_OBJECT(m_appSink)); } } @@ -116,66 +171,6 @@ void QGstreamerAudioDecoderSession::configureAppSrcElement(GObject* object, GObj } #endif -#if 0 -void QGstreamerAudioDecoderSession::loadFromStream(const QNetworkRequest &request, QIODevice *appSrcStream) -{ -#if defined(HAVE_GST_APPSRC) -#ifdef DEBUG_PLAYBIN - qDebug() << Q_FUNC_INFO; -#endif - m_request = request; - m_duration = -1; - m_lastPosition = 0; - m_haveQueueElement = false; - - if (m_appSrc) - m_appSrc->deleteLater(); - m_appSrc = new QGstAppSrc(this); - m_appSrc->setStream(appSrcStream); - - if (m_playbin) { - m_tags.clear(); - emit tagsChanged(); - - g_signal_connect(G_OBJECT(m_playbin), "deep-notify::source", (GCallback) &QGstreamerAudioDecoderSession::configureAppSrcElement, (gpointer)this); - g_object_set(G_OBJECT(m_playbin), "uri", "appsrc://", NULL); - - if (!m_streamTypes.isEmpty()) { - m_streamProperties.clear(); - m_streamTypes.clear(); - - emit streamsChanged(); - } - } -#endif -} - -void QGstreamerAudioDecoderSession::loadFromUri(const QNetworkRequest &request) -{ -#ifdef DEBUG_PLAYBIN - qDebug() << Q_FUNC_INFO << request.url(); -#endif - m_request = request; - m_duration = -1; - m_lastPosition = 0; - m_haveQueueElement = false; - - if (m_playbin) { - m_tags.clear(); - emit tagsChanged(); - - g_object_set(G_OBJECT(m_playbin), "uri", m_request.url().toEncoded().constData(), NULL); - - if (!m_streamTypes.isEmpty()) { - m_streamProperties.clear(); - m_streamTypes.clear(); - - emit streamsChanged(); - } - } -} -#endif - bool QGstreamerAudioDecoderSession::processBusMessage(const QGstreamerMessage &message) { GstMessage* gm = message.rawMessage(); @@ -320,7 +315,10 @@ void QGstreamerAudioDecoderSession::setSourceFilename(const QString &fileName) { stop(); mDevice = 0; + bool isSignalRequired = (mSource != fileName); mSource = fileName; + if (isSignalRequired) + emit sourceChanged(); } QIODevice *QGstreamerAudioDecoderSession::sourceDevice() const @@ -332,17 +330,71 @@ void QGstreamerAudioDecoderSession::setSourceDevice(QIODevice *device) { stop(); mSource.clear(); + bool isSignalRequired = (mDevice != device); mDevice = device; + if (isSignalRequired) + emit sourceChanged(); } void QGstreamerAudioDecoderSession::start() { - // TODO + if (!m_playbin) { + processInvalidMedia(QAudioDecoder::ResourceError, "Playbin element is not valid"); + return; + } + + if (!mSource.isEmpty()) { + g_object_set(G_OBJECT(m_playbin), "uri", QUrl::fromLocalFile(mSource).toEncoded().constData(), NULL); + } else if (mDevice) { + // make sure we can read from device + if (!mDevice->isOpen() || !mDevice->isReadable()) { + processInvalidMedia(QAudioDecoder::AccessDeniedError, "Unable to read from specified device"); + return; + } + + if (m_appSrc) + m_appSrc->deleteLater(); + m_appSrc = new QGstAppSrc(this); + m_appSrc->setStream(mDevice); + + g_signal_connect(G_OBJECT(m_playbin), "deep-notify::source", (GCallback) &QGstreamerAudioDecoderSession::configureAppSrcElement, (gpointer)this); + g_object_set(G_OBJECT(m_playbin), "uri", "appsrc://", NULL); + } else { + return; + } + + // Set audio format + if (m_appSink) { + GstCaps *caps = QGstUtils::capsForAudioFormat(mFormat); + gst_app_sink_set_caps(m_appSink, caps); // appsink unrefs caps + } + + m_pendingState = QAudioDecoder::DecodingState; + if (gst_element_set_state(m_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + qWarning() << "GStreamer; Unable to start decoding process"; + m_pendingState = m_state = QAudioDecoder::StoppedState; + + emit stateChanged(m_state); + } } void QGstreamerAudioDecoderSession::stop() { - // TODO + if (m_playbin) { + gst_element_set_state(m_playbin, GST_STATE_NULL); + + QAudioDecoder::State oldState = m_state; + m_pendingState = m_state = QAudioDecoder::StoppedState; + + // GStreamer thread is stopped. Can safely access m_buffersAvailable + if (m_buffersAvailable != 0) { + m_buffersAvailable = 0; + emit bufferAvailableChanged(false); + } + + if (oldState != m_state) + emit stateChanged(m_state); + } } QAudioFormat QGstreamerAudioDecoderSession::audioFormat() const @@ -360,15 +412,43 @@ void QGstreamerAudioDecoderSession::setAudioFormat(const QAudioFormat &format) QAudioBuffer QGstreamerAudioDecoderSession::read(bool *ok) { - // TODO + QAudioBuffer audioBuffer; + + int buffersAvailable; + { + QMutexLocker locker(&m_buffersMutex); + buffersAvailable = m_buffersAvailable; + + // need to decrement before pulling a buffer + // to make sure assert in QGstreamerAudioDecoderSession::new_buffer works + m_buffersAvailable--; + } + + + if (buffersAvailable) { + if (buffersAvailable == 1) + emit bufferAvailableChanged(false); + + GstBuffer *buffer = gst_app_sink_pull_buffer(m_appSink); + + QAudioFormat format = QGstUtils::audioFormatForBuffer(buffer); + if (format.isValid()) { + // XXX At the moment we have to copy data from GstBuffer into QAudioBuffer. + // We could improve performance by implementing QAbstractAudioBuffer for GstBuffer. + audioBuffer = QAudioBuffer(QByteArray((const char*)buffer->data, buffer->size), format); + } + gst_buffer_unref(buffer); + } + if (ok) - *ok = false; - return QAudioBuffer(); + *ok = audioBuffer.isValid(); + return audioBuffer; } bool QGstreamerAudioDecoderSession::bufferAvailable() const { - return false; + QMutexLocker locker(&m_buffersMutex); + return m_buffersAvailable; } void QGstreamerAudioDecoderSession::processInvalidMedia(QAudioDecoder::Error errorCode, const QString& errorString) @@ -377,4 +457,23 @@ void QGstreamerAudioDecoderSession::processInvalidMedia(QAudioDecoder::Error err emit error(int(errorCode), errorString); } +GstFlowReturn QGstreamerAudioDecoderSession::new_buffer(GstAppSink *, gpointer user_data) +{ + // "Note that the preroll buffer will also be returned as the first buffer when calling gst_app_sink_pull_buffer()." + QGstreamerAudioDecoderSession *session = reinterpret_cast(user_data); + + int buffersAvailable; + { + QMutexLocker locker(&session->m_buffersMutex); + buffersAvailable = session->m_buffersAvailable; + session->m_buffersAvailable++; + Q_ASSERT(session->m_buffersAvailable <= MAX_BUFFERS_IN_QUEUE); + } + + if (!buffersAvailable) + QMetaObject::invokeMethod(session, "bufferAvailableChanged", Qt::QueuedConnection, Q_ARG(bool, true)); + QMetaObject::invokeMethod(session, "bufferReady", Qt::QueuedConnection); + return GST_FLOW_OK; +} + QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h index b6ac751..df8c8e8 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h @@ -43,6 +43,7 @@ #define QGSTREAMERPLAYERSESSION_H #include +#include #include "qgstreameraudiodecodercontrol.h" #include #include @@ -52,6 +53,7 @@ #endif #include +#include QT_BEGIN_NAMESPACE @@ -95,9 +97,12 @@ public: QAudioBuffer read(bool *ok); bool bufferAvailable() const; + static GstFlowReturn new_buffer(GstAppSink *sink, gpointer user_data); + signals: void stateChanged(QAudioDecoder::State newState); void formatChanged(const QAudioFormat &format); + void sourceChanged(); void error(int error, const QString &errorString); @@ -110,9 +115,10 @@ private: QAudioDecoder::State m_state; QAudioDecoder::State m_pendingState; - QGstreamerBusHelper* m_busHelper; - GstBus* m_bus; - GstElement* m_playbin; + QGstreamerBusHelper *m_busHelper; + GstBus *m_bus; + GstElement *m_playbin; + GstAppSink *m_appSink; #if defined(HAVE_GST_APPSRC) QGstAppSrc *m_appSrc; @@ -121,6 +127,9 @@ private: QString mSource; QIODevice *mDevice; // QWeakPointer perhaps QAudioFormat mFormat; + + mutable QMutex m_buffersMutex; + int m_buffersAvailable; }; QT_END_NAMESPACE diff --git a/tests/auto/integration/qaudiodecoderbackend/qaudiodecoderbackend.pro b/tests/auto/integration/qaudiodecoderbackend/qaudiodecoderbackend.pro new file mode 100644 index 0000000..7548b89 --- /dev/null +++ b/tests/auto/integration/qaudiodecoderbackend/qaudiodecoderbackend.pro @@ -0,0 +1,15 @@ +TARGET = tst_qaudiodecoderbackend + +QT += multimedia multimedia-private testlib +CONFIG += no_private_qt_headers_warning + +# This is more of a system test +# CONFIG += testcase + +INCLUDEPATH += \ + ../../../../src/multimedia/audio + +DEFINES += TESTDATA_DIR=\\\"$$PWD/\\\" + +SOURCES += \ + tst_qaudiodecoderbackend.cpp diff --git a/tests/auto/integration/qaudiodecoderbackend/testdata/test.wav b/tests/auto/integration/qaudiodecoderbackend/testdata/test.wav new file mode 100644 index 0000000000000000000000000000000000000000..4dd022661df1b2ac5243b1ed5f92fcd47c3e5991 GIT binary patch literal 88232 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 +#include +#include "qaudiodecoder_p.h" + +#define TEST_FILE_NAME "testdata/test.wav" + +QT_USE_NAMESPACE + +/* + This is the backend conformance test. + + Since it relies on platform media framework and sound hardware + it may be less stable. +*/ + +class tst_QAudioDecoderBackend : public QObject +{ + Q_OBJECT +public slots: + void init(); + void cleanup(); + void initTestCase(); + +private slots: + void decoderTest(); +}; + +void tst_QAudioDecoderBackend::init() +{ +} + +void tst_QAudioDecoderBackend::initTestCase() +{ +} + +void tst_QAudioDecoderBackend::cleanup() +{ +} + +void tst_QAudioDecoderBackend::decoderTest() +{ + QAudioDecoder d; + QVERIFY(d.state() == QAudioDecoder::StoppedState); + QVERIFY(d.bufferAvailable() == false); + QCOMPARE(d.sourceFilename(), QString("")); + + // Test local file + QFileInfo fileInfo(QFINDTESTDATA(TEST_FILE_NAME)); + d.setSourceFilename(fileInfo.absoluteFilePath()); + QVERIFY(d.state() == QAudioDecoder::StoppedState); + QVERIFY(!d.bufferAvailable()); + QCOMPARE(d.sourceFilename(), fileInfo.absoluteFilePath()); + + QSignalSpy readySpy(&d, SIGNAL(bufferReady())); + QSignalSpy bufferChangedSpy(&d, SIGNAL(bufferAvailableChanged(bool))); + QSignalSpy errorSpy(&d, SIGNAL(error(QAudioDecoder::Error))); + QSignalSpy stateSpy(&d, SIGNAL(stateChanged(QAudioDecoder::State))); + + d.start(); + QTRY_VERIFY(!stateSpy.isEmpty()); + QTRY_VERIFY(!readySpy.isEmpty()); + QTRY_VERIFY(!bufferChangedSpy.isEmpty()); + QVERIFY(d.bufferAvailable()); + + bool ok; + QAudioBuffer buffer = d.read(&ok); + QVERIFY(ok); + QVERIFY(buffer.isValid()); + QCOMPARE(buffer.format(), d.audioFormat()); + + QVERIFY(errorSpy.isEmpty()); + + d.stop(); + QTRY_COMPARE(d.state(), QAudioDecoder::StoppedState); + QVERIFY(!d.bufferAvailable()); + readySpy.clear(); + bufferChangedSpy.clear(); + stateSpy.clear(); + + // Test source device + QFile file(fileInfo.absoluteFilePath()); + QVERIFY(file.open(QIODevice::ReadOnly)); + d.setSourceDevice(&file); + + // change output audio format + QAudioFormat format; + format.setChannels(1); + format.setSampleSize(8); + format.setFrequency(8000); + format.setCodec("audio/pcm"); + format.setSampleType(QAudioFormat::SignedInt); + d.setAudioFormat(format); + + d.start(); + QTRY_VERIFY(!stateSpy.isEmpty()); + QTRY_VERIFY(!readySpy.isEmpty()); + QTRY_VERIFY(!bufferChangedSpy.isEmpty()); + QVERIFY(d.bufferAvailable()); + + buffer = d.read(&ok); + QVERIFY(ok); + QVERIFY(buffer.isValid()); + QCOMPARE(buffer.format(), d.audioFormat()); + + QVERIFY(errorSpy.isEmpty()); +} + +QTEST_MAIN(tst_QAudioDecoderBackend) + +#include "tst_qaudiodecoderbackend.moc" -- 2.7.4