Merge remote-tracking branch 'origin/5.4' into dev
Change-Id: Id87e56ccfc9f33f98c3d06991f6fe9c14d38fbac
This commit is contained in:
BIN
examples/multimediawidgets/player/doc/images/mediaplayerex.jpg
Normal file
BIN
examples/multimediawidgets/player/doc/images/mediaplayerex.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@@ -31,6 +31,8 @@
|
||||
\ingroup multimedia_examples
|
||||
\brief Playing audio and video.
|
||||
|
||||
\image mediaplayerex.jpg
|
||||
|
||||
\e{Media Player} demonstrates a simple multimedia player that can play
|
||||
audio and or video files using various codecs.
|
||||
|
||||
|
||||
@@ -430,13 +430,15 @@ QVector<QGstUtils::CameraInfo> QGstUtils::enumerateCameras(GstElementFactory *fa
|
||||
QStringLiteral("primary"),
|
||||
QGstreamerVideoInputDeviceControl::primaryCamera(),
|
||||
0,
|
||||
QCamera::BackFace
|
||||
QCamera::BackFace,
|
||||
QByteArray()
|
||||
};
|
||||
const CameraInfo secondary = {
|
||||
QStringLiteral("secondary"),
|
||||
QGstreamerVideoInputDeviceControl::secondaryCamera(),
|
||||
0,
|
||||
QCamera::FrontFace
|
||||
QCamera::FrontFace,
|
||||
QByteArray()
|
||||
};
|
||||
|
||||
devices.append(primary);
|
||||
@@ -498,14 +500,17 @@ QVector<QGstUtils::CameraInfo> QGstUtils::enumerateCameras(GstElementFactory *fa
|
||||
|
||||
if (isCamera) {
|
||||
// find out its driver "name"
|
||||
QByteArray driver;
|
||||
QString name;
|
||||
struct v4l2_capability vcap;
|
||||
memset(&vcap, 0, sizeof(struct v4l2_capability));
|
||||
|
||||
if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0)
|
||||
if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0) {
|
||||
name = entryInfo.fileName();
|
||||
else
|
||||
} else {
|
||||
driver = QByteArray((const char*)vcap.driver);
|
||||
name = QString::fromUtf8((const char*)vcap.card);
|
||||
}
|
||||
//qDebug() << "found camera: " << name;
|
||||
|
||||
|
||||
@@ -513,7 +518,8 @@ QVector<QGstUtils::CameraInfo> QGstUtils::enumerateCameras(GstElementFactory *fa
|
||||
entryInfo.absoluteFilePath(),
|
||||
name,
|
||||
0,
|
||||
QCamera::UnspecifiedPosition
|
||||
QCamera::UnspecifiedPosition,
|
||||
driver
|
||||
};
|
||||
devices.append(device);
|
||||
}
|
||||
@@ -561,6 +567,15 @@ int QGstUtils::cameraOrientation(const QString &device, GstElementFactory * fact
|
||||
return 0;
|
||||
}
|
||||
|
||||
QByteArray QGstUtils::cameraDriver(const QString &device, GstElementFactory *factory)
|
||||
{
|
||||
foreach (const CameraInfo &camera, enumerateCameras(factory)) {
|
||||
if (camera.name == device)
|
||||
return camera.driver;
|
||||
}
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
|
||||
void qt_gst_object_ref_sink(gpointer object)
|
||||
{
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace QGstUtils {
|
||||
QString description;
|
||||
int orientation;
|
||||
QCamera::Position position;
|
||||
QByteArray driver;
|
||||
};
|
||||
|
||||
QMap<QByteArray, QVariant> gstTagListToMap(const GstTagList *list);
|
||||
@@ -84,6 +85,7 @@ namespace QGstUtils {
|
||||
QString cameraDescription(const QString &device, GstElementFactory * factory = 0);
|
||||
QCamera::Position cameraPosition(const QString &device, GstElementFactory * factory = 0);
|
||||
int cameraOrientation(const QString &device, GstElementFactory * factory = 0);
|
||||
QByteArray cameraDriver(const QString &device, GstElementFactory * factory = 0);
|
||||
}
|
||||
|
||||
void qt_gst_object_ref_sink(gpointer object);
|
||||
|
||||
@@ -412,9 +412,41 @@ GstElement *CameraBinSession::buildCameraSource()
|
||||
if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSrc), "video-source")) {
|
||||
GstElement *src = 0;
|
||||
|
||||
if (m_videoInputFactory)
|
||||
/* QT_GSTREAMER_CAMERABIN_VIDEOSRC can be used to set the video source element.
|
||||
|
||||
--- Usage
|
||||
|
||||
QT_GSTREAMER_CAMERABIN_VIDEOSRC=[drivername=elementname[,drivername2=elementname2 ...],][elementname]
|
||||
|
||||
--- Examples
|
||||
|
||||
Always use 'somevideosrc':
|
||||
QT_GSTREAMER_CAMERABIN_VIDEOSRC="somevideosrc"
|
||||
|
||||
Use 'somevideosrc' when the device driver is 'somedriver', otherwise use default:
|
||||
QT_GSTREAMER_CAMERABIN_VIDEOSRC="somedriver=somevideosrc"
|
||||
|
||||
Use 'somevideosrc' when the device driver is 'somedriver', otherwise use 'somevideosrc2'
|
||||
QT_GSTREAMER_CAMERABIN_VIDEOSRC="somedriver=somevideosrc,somevideosrc2"
|
||||
*/
|
||||
const QByteArray envVideoSource = qgetenv("QT_GSTREAMER_CAMERABIN_VIDEOSRC");
|
||||
if (!envVideoSource.isEmpty()) {
|
||||
QList<QByteArray> sources = envVideoSource.split(',');
|
||||
foreach (const QByteArray &source, sources) {
|
||||
QList<QByteArray> keyValue = source.split('=');
|
||||
if (keyValue.count() == 1) {
|
||||
src = gst_element_factory_make(keyValue.at(0), "camera_source");
|
||||
break;
|
||||
} else if (keyValue.at(0) == QGstUtils::cameraDriver(m_inputDevice, m_sourceFactory)) {
|
||||
src = gst_element_factory_make(keyValue.at(1), "camera_source");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (m_videoInputFactory) {
|
||||
src = m_videoInputFactory->buildElement();
|
||||
else
|
||||
}
|
||||
|
||||
if (!src)
|
||||
src = gst_element_factory_make("v4l2src", "camera_source");
|
||||
|
||||
if (src) {
|
||||
|
||||
@@ -70,7 +70,6 @@ QOpenSLESAudioInput::QOpenSLESAudioInput(const QByteArray &device)
|
||||
, m_errorState(QAudio::NoError)
|
||||
, m_deviceState(QAudio::StoppedState)
|
||||
, m_lastNotifyTime(0)
|
||||
, m_volume(1)
|
||||
, m_bufferSize(0)
|
||||
, m_periodSize(0)
|
||||
, m_intervalTime(1000)
|
||||
@@ -480,12 +479,12 @@ qint64 QOpenSLESAudioInput::elapsedUSecs() const
|
||||
void QOpenSLESAudioInput::setVolume(qreal vol)
|
||||
{
|
||||
// Volume interface is not available for the recorder on Android
|
||||
m_volume = vol;
|
||||
Q_UNUSED(vol);
|
||||
}
|
||||
|
||||
qreal QOpenSLESAudioInput::volume() const
|
||||
{
|
||||
return m_volume;
|
||||
return qreal(1.0);
|
||||
}
|
||||
|
||||
void QOpenSLESAudioInput::reset()
|
||||
|
||||
@@ -113,7 +113,6 @@ private:
|
||||
QAudio::State m_deviceState;
|
||||
QTime m_clockStamp;
|
||||
qint64 m_lastNotifyTime;
|
||||
qreal m_volume;
|
||||
int m_bufferSize;
|
||||
int m_periodSize;
|
||||
int m_intervalTime;
|
||||
|
||||
@@ -157,7 +157,7 @@ int QOpenSLESAudioOutput::bytesFree() const
|
||||
if (m_state != QAudio::ActiveState && m_state != QAudio::IdleState)
|
||||
return 0;
|
||||
|
||||
return m_availableBuffers.load() ? m_bufferSize : 0;
|
||||
return m_availableBuffers.loadAcquire() ? m_bufferSize : 0;
|
||||
}
|
||||
|
||||
int QOpenSLESAudioOutput::periodSize() const
|
||||
@@ -343,6 +343,11 @@ void QOpenSLESAudioOutput::onEOSEvent()
|
||||
setError(QAudio::UnderrunError);
|
||||
}
|
||||
|
||||
void QOpenSLESAudioOutput::onBytesProcessed(qint64 bytes)
|
||||
{
|
||||
m_processedBytes += bytes;
|
||||
}
|
||||
|
||||
void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
|
||||
{
|
||||
Q_UNUSED(count);
|
||||
@@ -351,11 +356,13 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
|
||||
if (m_state == QAudio::StoppedState)
|
||||
return;
|
||||
|
||||
if (!m_pullMode) {
|
||||
m_availableBuffers.fetchAndAddRelaxed(1);
|
||||
if (!m_pullMode) { // We're in push mode.
|
||||
// Signal that there is a new open slot in the buffer and return
|
||||
m_availableBuffers.fetchAndAddRelease(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// We're in pull mode.
|
||||
const int index = m_nextBuffer * m_bufferSize;
|
||||
const qint64 readSize = m_audioSource->read(m_buffers + index, m_bufferSize);
|
||||
|
||||
@@ -370,8 +377,8 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
|
||||
return;
|
||||
}
|
||||
|
||||
m_processedBytes += readSize;
|
||||
m_nextBuffer = (m_nextBuffer + 1) % BUFFER_COUNT;
|
||||
QMetaObject::invokeMethod(this, "onBytesProcessed", Qt::QueuedConnection, Q_ARG(qint64, readSize));
|
||||
}
|
||||
|
||||
void QOpenSLESAudioOutput::playCallback(SLPlayItf player, void *ctx, SLuint32 event)
|
||||
@@ -570,7 +577,7 @@ void QOpenSLESAudioOutput::destroyPlayer()
|
||||
m_buffers = Q_NULLPTR;
|
||||
m_processedBytes = 0;
|
||||
m_nextBuffer = 0;
|
||||
m_availableBuffers = BUFFER_COUNT;
|
||||
m_availableBuffers.storeRelease(BUFFER_COUNT);
|
||||
m_playItf = Q_NULLPTR;
|
||||
m_volumeItf = Q_NULLPTR;
|
||||
m_bufferQueueItf = Q_NULLPTR;
|
||||
@@ -599,20 +606,32 @@ void QOpenSLESAudioOutput::startPlayer()
|
||||
|
||||
qint64 QOpenSLESAudioOutput::writeData(const char *data, qint64 len)
|
||||
{
|
||||
if (!len || !m_availableBuffers.load())
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (len > m_bufferSize)
|
||||
len = m_bufferSize;
|
||||
|
||||
// Acquire one slot in the buffer
|
||||
const int before = m_availableBuffers.fetchAndAddAcquire(-1);
|
||||
|
||||
// If there where no vacant slots, then we just overdrew the buffer account...
|
||||
if (before < 1) {
|
||||
m_availableBuffers.fetchAndAddRelease(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int index = m_nextBuffer * m_bufferSize;
|
||||
::memcpy(m_buffers + index, data, len);
|
||||
const SLuint32 res = (*m_bufferQueueItf)->Enqueue(m_bufferQueueItf,
|
||||
m_buffers + index,
|
||||
len);
|
||||
|
||||
if (res == SL_RESULT_BUFFER_INSUFFICIENT)
|
||||
// If we where unable to enqueue a new buffer, give back the acquired slot.
|
||||
if (res == SL_RESULT_BUFFER_INSUFFICIENT) {
|
||||
m_availableBuffers.fetchAndAddRelease(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (res != SL_RESULT_SUCCESS) {
|
||||
setError(QAudio::FatalError);
|
||||
@@ -621,7 +640,6 @@ qint64 QOpenSLESAudioOutput::writeData(const char *data, qint64 len)
|
||||
}
|
||||
|
||||
m_processedBytes += len;
|
||||
m_availableBuffers.fetchAndAddRelaxed(-1);
|
||||
setState(QAudio::ActiveState);
|
||||
setError(QAudio::NoError);
|
||||
m_nextBuffer = (m_nextBuffer + 1) % BUFFER_COUNT;
|
||||
|
||||
@@ -79,6 +79,7 @@ private:
|
||||
friend class SLIODevicePrivate;
|
||||
|
||||
Q_INVOKABLE void onEOSEvent();
|
||||
Q_INVOKABLE void onBytesProcessed(qint64 bytes);
|
||||
void bufferAvailable(quint32 count, quint32 playIndex);
|
||||
|
||||
static void playCallback(SLPlayItf playItf, void *ctx, SLuint32 event);
|
||||
|
||||
@@ -184,8 +184,12 @@ D3DPresentEngine::~D3DPresentEngine()
|
||||
m_egl->destroySurface(m_eglDisplay, m_eglSurface);
|
||||
m_eglSurface = NULL;
|
||||
}
|
||||
if (m_glTexture)
|
||||
QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_glTexture);
|
||||
if (m_glTexture) {
|
||||
if (QOpenGLContext *current = QOpenGLContext::currentContext())
|
||||
current->functions()->glDeleteTextures(1, &m_glTexture);
|
||||
else
|
||||
qWarning() << "D3DPresentEngine: Cannot obtain GL context, unable to delete textures";
|
||||
}
|
||||
|
||||
delete m_glContext;
|
||||
delete m_offscreenSurface;
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
MFPlayerControl::MFPlayerControl(MFPlayerSession *session)
|
||||
: QMediaPlayerControl(session)
|
||||
, m_state(QMediaPlayer::StoppedState)
|
||||
, m_stateDirty(false)
|
||||
, m_videoAvailable(false)
|
||||
, m_audioAvailable(false)
|
||||
, m_duration(-1)
|
||||
|
||||
@@ -227,8 +227,12 @@ QSGVideoMaterial_YUV420::QSGVideoMaterial_YUV420(const QVideoSurfaceFormat &form
|
||||
|
||||
QSGVideoMaterial_YUV420::~QSGVideoMaterial_YUV420()
|
||||
{
|
||||
if (!m_textureSize.isEmpty())
|
||||
QOpenGLContext::currentContext()->functions()->glDeleteTextures(Num_Texture_IDs, m_textureIds);
|
||||
if (!m_textureSize.isEmpty()) {
|
||||
if (QOpenGLContext *current = QOpenGLContext::currentContext())
|
||||
current->functions()->glDeleteTextures(Num_Texture_IDs, m_textureIds);
|
||||
else
|
||||
qWarning() << "QSGVideoMaterial_YUV420: Cannot obtain GL context, unable to delete textures";
|
||||
}
|
||||
}
|
||||
|
||||
void QSGVideoMaterial_YUV420::bind()
|
||||
|
||||
Reference in New Issue
Block a user