Android multimedia plug-in.

Adds MediaPlayer support for Android.

Change-Id: I4c7b1e19927b2e50b227f3a3b3f7ca2e99397618
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
This commit is contained in:
Christian Strømme
2013-01-14 14:23:38 +01:00
committed by The Qt Project
parent 68a38b151e
commit 909a09069f
30 changed files with 3443 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
TEMPLATE = subdirs
SUBDIRS += mediaplayer \
jar

View File

@@ -0,0 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.qtproject.qt5.android.multimedia"
android:versionCode="1"
android:versionName="1.0" >
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
</manifest>

View File

@@ -0,0 +1,11 @@
load(qt_build_paths)
CONFIG += java
TARGET = QtMultimedia
DESTDIR = $$MODULE_BASE_OUTDIR/jar
API_VERSION = android-11
JAVACLASSPATH += $$PWD/src
JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java \
$$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTexture.java \
$$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java

View File

@@ -0,0 +1,445 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtMultimedia module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
package org.qtproject.qt5.android.multimedia;
import java.io.IOException;
import java.lang.String;
// API is level is < 9 unless marked otherwise.
import android.app.Activity;
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.util.Log;
public class QtAndroidMediaPlayer extends MediaPlayer
{
// Native callback functions for MediaPlayer
native public void onErrorNative(int what, int extra, long id);
native public void onBufferingUpdateNative(int percent, long id);
native public void onInfoNative(int what, int extra, long id);
native public void onMediaPlayerInfoNative(int what, int extra, long id);
native public void onVideoSizeChangedNative(int width, int height, long id);
private Uri mUri = null;
private final long mID;
private boolean mMuted = false;
private boolean mPreparing = false;
private boolean mInitialized = false;
private int mVolume = 100;
private static final String TAG = "Qt MediaPlayer";
private static Context mApplicationContext = null;
final int MEDIA_PLAYER_INVALID_STATE = 1;
final int MEDIA_PLAYER_PREPARING = 2;
final int MEDIA_PLAYER_READY = 3;
final int MEDIA_PLAYER_DURATION = 4;
final int MEDIA_PLAYER_PROGRESS = 5;
final int MEDIA_PLAYER_FINISHED = 6;
// Activity set by Qt on load.
static public void setActivity(final Activity activity)
{
try {
mApplicationContext = activity.getApplicationContext();
} catch(final Exception e) {
Log.d(TAG, e.getMessage());
}
}
private class ProgressWatcher implements Runnable
{
@Override
public void run()
{
final int duratation = getDuration();
int currentPosition = getCurrentPosition();
try {
while (duratation >= currentPosition && isPlaying()) {
onMediaPlayerInfoNative(MEDIA_PLAYER_PROGRESS, currentPosition, mID);
Thread.sleep(1000);
currentPosition = getCurrentPosition();
}
} catch (final InterruptedException e) {
Log.d(TAG, e.getMessage());
return;
}
}
}
/**
* MediaPlayer OnErrorListener
*/
private class MediaPlayerErrorListener
implements MediaPlayer.OnErrorListener
{
@Override
public boolean onError(final MediaPlayer mp,
final int what,
final int extra)
{
reset();
onErrorNative(what, extra, mID);
return true;
}
}
/**
* MediaPlayer OnBufferingListener
*/
private class MediaPlayerBufferingListener
implements MediaPlayer.OnBufferingUpdateListener
{
private int mBufferPercent = -1;
@Override
public void onBufferingUpdate(final android.media.MediaPlayer mp,
final int percent)
{
// Avoid updates when percent is unchanged.
// E.g., we keep getting updates when percent == 100
if (mBufferPercent == percent)
return;
onBufferingUpdateNative((mBufferPercent = percent), mID);
}
}
/**
* MediaPlayer OnCompletionListener
*/
private class MediaPlayerCompletionListener
implements MediaPlayer.OnCompletionListener
{
@Override
public void onCompletion(final MediaPlayer mp)
{
onMediaPlayerInfoNative(MEDIA_PLAYER_FINISHED, 0, mID);
reset();
}
}
/**
* MediaPlayer OnInfoListener
*/
private class MediaPlayerInfoListener
implements MediaPlayer.OnInfoListener
{
@Override
public boolean onInfo(final MediaPlayer mp,
final int what,
final int extra)
{
onInfoNative(what, extra, mID);
return true;
}
}
/**
* MediaPlayer OnPreparedListener
*/
private class MediaPlayerPreparedListener
implements MediaPlayer.OnPreparedListener
{
@Override
public void onPrepared(final MediaPlayer mp)
{
onMediaPlayerInfoNative(MEDIA_PLAYER_DURATION, getDuration(), mID);
onMediaPlayerInfoNative(MEDIA_PLAYER_READY, 0, mID);
mPreparing = false;
}
}
/**
* MediaPlayer OnSeekCompleteListener
*/
private class MediaPlayerSeekCompleteListener
implements MediaPlayer.OnSeekCompleteListener
{
@Override
public void onSeekComplete(final MediaPlayer mp)
{
onMediaPlayerInfoNative(MEDIA_PLAYER_PROGRESS, getCurrentPosition(), mID);
}
}
/**
* MediaPlayer OnVideoSizeChangedListener
*/
private class MediaPlayerVideoSizeChangedListener
implements MediaPlayer.OnVideoSizeChangedListener
{
@Override
public void onVideoSizeChanged(final MediaPlayer mp,
final int width,
final int height)
{
onVideoSizeChangedNative(width, height, mID);
}
}
public QtAndroidMediaPlayer(final long id)
{
super();
mID = id;
setOnBufferingUpdateListener(new MediaPlayerBufferingListener());
setOnCompletionListener(new MediaPlayerCompletionListener());
setOnInfoListener(new MediaPlayerInfoListener());
setOnSeekCompleteListener(new MediaPlayerSeekCompleteListener());
setOnVideoSizeChangedListener(new MediaPlayerVideoSizeChangedListener());
setOnErrorListener(new MediaPlayerErrorListener());
}
@Override
public void start()
{
if (!mInitialized) {
onMediaPlayerInfoNative(MEDIA_PLAYER_INVALID_STATE, 0, mID);
return;
}
if (mApplicationContext == null)
return;
if (mPreparing)
return;
if (isPlaying())
return;
try {
super.start();
Thread progressThread = new Thread(new ProgressWatcher());
progressThread.start();
} catch (final IllegalStateException e) {
reset();
Log.d(TAG, e.getMessage());
}
}
@Override
public void pause()
{
if (!isPlaying())
return;
try {
super.pause();
} catch (final IllegalStateException e) {
reset();
Log.d(TAG, e.getMessage());
}
}
@Override
public void stop()
{
if (!mInitialized)
return;
try {
super.stop();
} catch (final IllegalStateException e) {
Log.d(TAG, e.getMessage());
} finally {
reset();
}
}
@Override
public void seekTo(final int msec)
{
if (!mInitialized)
return;
try {
super.seekTo(msec);
onMediaPlayerInfoNative(MEDIA_PLAYER_PROGRESS, msec, mID);
} catch (final IllegalStateException e) {
Log.d(TAG, e.getMessage());
}
}
@Override
public boolean isPlaying()
{
boolean playing = false;
if (!mInitialized)
return playing;
try {
playing = super.isPlaying();
} catch (final IllegalStateException e) {
Log.d(TAG, e.getMessage());
}
return playing;
}
public void setMediaPath(final String path)
{
if (mInitialized)
reset();
try {
mPreparing = true;
onMediaPlayerInfoNative(MEDIA_PLAYER_PREPARING, 0, mID);
mUri = Uri.parse(path);
setDataSource(mApplicationContext, mUri);
mInitialized = true;
setOnPreparedListener(new MediaPlayerPreparedListener());
prepareAsync();
} catch (final IOException e) {
mPreparing = false;
onErrorNative(MEDIA_ERROR_UNKNOWN,
/* MEDIA_ERROR_UNSUPPORTED= */ -1010,
mID);
} catch (final IllegalArgumentException e) {
Log.d(TAG, e.getMessage());
} catch (final SecurityException e) {
Log.d(TAG, e.getMessage());
} catch (final IllegalStateException e) {
Log.d(TAG, e.getMessage());
} catch (final NullPointerException e) {
Log.d(TAG, e.getMessage());
}
}
@Override
public int getCurrentPosition()
{
int currentPosition = 0;
if (!mInitialized)
return currentPosition;
try {
currentPosition = super.getCurrentPosition();
} catch (final IllegalStateException e) {
Log.d(TAG, e.getMessage());
}
return currentPosition;
}
@Override
public int getDuration()
{
int duration = 0;
if (!mInitialized)
return duration;
try {
duration = super.getDuration();
} catch (final IllegalStateException e) {
Log.d(TAG, e.getMessage());
}
return duration;
}
private float adjustVolume(final int volume)
{
if (volume < 1)
return 0.0f;
if (volume > 98)
return 1.0f;
return (float) (1-(Math.log(100-volume)/Math.log(100)));
}
public void setVolume(int volume)
{
if (volume < 0)
volume = 0;
if (volume > 100)
volume = 100;
float newVolume = adjustVolume(volume);
try {
super.setVolume(newVolume, newVolume);
if (!mMuted)
mVolume = volume;
} catch (final IllegalStateException e) {
Log.d(TAG, e.getMessage());
}
}
public int getVolume()
{
return mVolume;
}
public void mute(final boolean mute)
{
mMuted = mute;
setVolume(mute ? 0 : mVolume);
}
public boolean isMuted()
{
return mMuted;
}
@Override
public void reset()
{
mInitialized = false;
super.reset();
}
}

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtMultimedia module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
package org.qtproject.qt5.android.multimedia;
import android.graphics.SurfaceTexture;
public class QtSurfaceTexture implements SurfaceTexture.OnFrameAvailableListener
{
public SurfaceTexture surfaceTexture;
private int texID;
public QtSurfaceTexture(int texName)
{
texID = texName;
surfaceTexture = new SurfaceTexture(texName);
surfaceTexture.setOnFrameAvailableListener(this);
}
public void getTransformMatrix(float[] mtx)
{
surfaceTexture.getTransformMatrix(mtx);
}
public void updateTexImage()
{
surfaceTexture.updateTexImage();
}
public void onFrameAvailable(SurfaceTexture surfaceTexture)
{
notifyFrameAvailable(texID);
}
private static native void notifyFrameAvailable(int id);
}

View File

@@ -0,0 +1,114 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtMultimedia module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
package org.qtproject.qt5.android.multimedia;
import android.view.SurfaceHolder;
import android.view.Surface;
import android.graphics.Rect;
import android.graphics.Canvas;
public class QtSurfaceTextureHolder implements SurfaceHolder
{
private Surface surfaceTexture;
public QtSurfaceTextureHolder(Surface surface)
{
surfaceTexture = surface;
}
public void addCallback(SurfaceHolder.Callback callback)
{
}
public Surface getSurface()
{
return surfaceTexture;
}
public Rect getSurfaceFrame()
{
return new Rect();
}
public boolean isCreating()
{
return false;
}
public Canvas lockCanvas(Rect dirty)
{
return new Canvas();
}
public Canvas lockCanvas()
{
return new Canvas();
}
public void removeCallback(SurfaceHolder.Callback callback)
{
}
public void setFixedSize(int width, int height)
{
}
public void setFormat(int format)
{
}
public void setKeepScreenOn(boolean screenOn)
{
}
public void setSizeFromLayout()
{
}
public void setType(int type)
{
}
public void unlockCanvasAndPost(Canvas canvas)
{
}
}

View File

@@ -0,0 +1,3 @@
{
"Keys": ["org.qt-project.qt.mediaplayer"]
}

View File

@@ -0,0 +1,24 @@
TARGET = androidmediaplayer
QT += multimedia-private gui-private platformsupport-private network
PLUGIN_TYPE = mediaservice
PLUGIN_CLASS_NAME = QAndroidMediaPlayerServicePlugin
load(qt_plugin)
HEADERS += \
qandroidmediaplayercontrol.h \
qandroidmediaservice.h \
qandroidmetadatareadercontrol.h \
qandroidmediaserviceplugin.h \
qandroidvideorendercontrol.h \
qandroidvideooutput.h
SOURCES += \
qandroidmediaplayercontrol.cpp \
qandroidmediaservice.cpp \
qandroidmetadatareadercontrol.cpp \
qandroidmediaserviceplugin.cpp \
qandroidvideorendercontrol.cpp
OTHER_FILES += mediaplayer.json
include (../wrappers/wrappers.pri)

View File

@@ -0,0 +1,496 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qandroidmediaplayercontrol.h"
#include "jmediaplayer.h"
#include "qandroidvideooutput.h"
QT_BEGIN_NAMESPACE
QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
: QMediaPlayerControl(parent),
mMediaPlayer(new JMediaPlayer),
mCurrentState(QMediaPlayer::StoppedState),
mCurrentMediaStatus(QMediaPlayer::NoMedia),
mMediaStream(0),
mVideoOutput(0),
mSeekable(true),
mBufferPercent(-1),
mAudioAvailable(false),
mVideoAvailable(false),
mBuffering(false),
mMediaPlayerReady(false),
mPendingPosition(-1)
{
connect(mMediaPlayer, SIGNAL(bufferingUpdate(qint32)),
this, SLOT(onBufferChanged(qint32)));
connect(mMediaPlayer, SIGNAL(info(qint32, qint32)),
this, SLOT(onInfo(qint32, qint32)));
connect(mMediaPlayer, SIGNAL(error(qint32, qint32)),
this, SLOT(onError(qint32, qint32)));
connect(mMediaPlayer, SIGNAL(mediaPlayerInfo(qint32, qint32)),
this, SLOT(onMediaPlayerInfo(qint32, qint32)));
connect(mMediaPlayer, SIGNAL(videoSizeChanged(qint32,qint32)),
this, SLOT(onVideoSizeChanged(qint32,qint32)));
}
QAndroidMediaPlayerControl::~QAndroidMediaPlayerControl()
{
delete mMediaPlayer;
}
QMediaPlayer::State QAndroidMediaPlayerControl::state() const
{
return mCurrentState;
}
QMediaPlayer::MediaStatus QAndroidMediaPlayerControl::mediaStatus() const
{
return mCurrentMediaStatus;
}
qint64 QAndroidMediaPlayerControl::duration() const
{
return (mCurrentMediaStatus == QMediaPlayer::InvalidMedia
|| mCurrentMediaStatus == QMediaPlayer::NoMedia) ? 0
: mMediaPlayer->getDuration();
}
qint64 QAndroidMediaPlayerControl::position() const
{
if (!mMediaPlayerReady)
return mPendingPosition < 0 ? 0 : mPendingPosition;
return mMediaPlayer->getCurrentPosition();
}
void QAndroidMediaPlayerControl::setPosition(qint64 position)
{
if (!mSeekable)
return;
const int seekPosition = (position > INT_MAX) ? INT_MAX : position;
if (!mMediaPlayerReady) {
mPendingPosition = seekPosition;
Q_EMIT positionChanged(seekPosition);
return;
}
mMediaPlayer->seekTo(seekPosition);
mPendingPosition = -1;
}
int QAndroidMediaPlayerControl::volume() const
{
return mMediaPlayer->volume();
}
void QAndroidMediaPlayerControl::setVolume(int volume)
{
mMediaPlayer->setVolume(volume);
Q_EMIT volumeChanged(volume);
}
bool QAndroidMediaPlayerControl::isMuted() const
{
return mMediaPlayer->isMuted();
}
void QAndroidMediaPlayerControl::setMuted(bool muted)
{
mMediaPlayer->setMuted(muted);
Q_EMIT mutedChanged(muted);
}
int QAndroidMediaPlayerControl::bufferStatus() const
{
return mBufferPercent;
}
bool QAndroidMediaPlayerControl::isAudioAvailable() const
{
return mAudioAvailable;
}
bool QAndroidMediaPlayerControl::isVideoAvailable() const
{
return mVideoAvailable;
}
bool QAndroidMediaPlayerControl::isSeekable() const
{
return mSeekable;
}
QMediaTimeRange QAndroidMediaPlayerControl::availablePlaybackRanges() const
{
return mAvailablePlaybackRange;
}
void QAndroidMediaPlayerControl::updateAvailablePlaybackRanges()
{
if (mBuffering) {
const qint64 pos = position();
const qint64 end = (duration() / 100) * mBufferPercent;
mAvailablePlaybackRange.addInterval(pos, end);
} else if (mSeekable) {
mAvailablePlaybackRange = QMediaTimeRange(0, duration());
} else {
mAvailablePlaybackRange = QMediaTimeRange();
}
Q_EMIT availablePlaybackRangesChanged(mAvailablePlaybackRange);
}
qreal QAndroidMediaPlayerControl::playbackRate() const
{
return 1.0f;
}
void QAndroidMediaPlayerControl::setPlaybackRate(qreal rate)
{
Q_UNUSED(rate);
}
QMediaContent QAndroidMediaPlayerControl::media() const
{
return mMediaContent;
}
const QIODevice *QAndroidMediaPlayerControl::mediaStream() const
{
return mMediaStream;
}
void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
QIODevice *stream)
{
mMediaContent = mediaContent;
mMediaStream = stream;
const QString uri = mediaContent.canonicalUrl().toString();
if (!uri.isEmpty())
mMediaPlayer->setDataSource(uri);
else
setMediaStatus(QMediaPlayer::NoMedia);
Q_EMIT mediaChanged(mMediaContent);
resetBufferingProgress();
// reset some properties
setAudioAvailable(false);
setVideoAvailable(false);
setSeekable(true);
}
void QAndroidMediaPlayerControl::setVideoOutput(QAndroidVideoOutput *videoOutput)
{
if (mVideoOutput)
mVideoOutput->stop();
mVideoOutput = videoOutput;
}
void QAndroidMediaPlayerControl::play()
{
if (!mMediaPlayerReady) {
mPendingState = QMediaPlayer::PlayingState;
if (mCurrentState == QMediaPlayer::StoppedState
&& !mMediaContent.isNull()
&& mCurrentMediaStatus != QMediaPlayer::LoadingMedia) {
setMedia(mMediaContent, 0);
}
return;
}
mMediaPlayer->play();
setState(QMediaPlayer::PlayingState);
}
void QAndroidMediaPlayerControl::pause()
{
if (!mMediaPlayerReady) {
mPendingState = QMediaPlayer::PausedState;
return;
}
mMediaPlayer->pause();
setState(QMediaPlayer::PausedState);
}
void QAndroidMediaPlayerControl::stop()
{
mMediaPlayer->stop();
setState(QMediaPlayer::StoppedState);
}
void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra)
{
Q_UNUSED(extra);
switch (what) {
case JMediaPlayer::MEDIA_INFO_UNKNOWN:
break;
case JMediaPlayer::MEDIA_INFO_VIDEO_TRACK_LAGGING:
// IGNORE
break;
case JMediaPlayer::MEDIA_INFO_VIDEO_RENDERING_START:
break;
case JMediaPlayer::MEDIA_INFO_BUFFERING_START:
mPendingState = mCurrentState;
setState(QMediaPlayer::PausedState);
setMediaStatus(QMediaPlayer::StalledMedia);
break;
case JMediaPlayer::MEDIA_INFO_BUFFERING_END:
setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia : QMediaPlayer::BufferingMedia);
flushPendingStates();
break;
case JMediaPlayer::MEDIA_INFO_BAD_INTERLEAVING:
break;
case JMediaPlayer::MEDIA_INFO_NOT_SEEKABLE:
setSeekable(false);
break;
case JMediaPlayer::MEDIA_INFO_METADATA_UPDATE:
Q_EMIT metaDataUpdated();
break;
}
}
void QAndroidMediaPlayerControl::onMediaPlayerInfo(qint32 what, qint32 extra)
{
switch (what) {
case JMediaPlayer::MEDIA_PLAYER_INVALID_STATE:
setError(what, QStringLiteral("Error: Invalid state"));
break;
case JMediaPlayer::MEDIA_PLAYER_PREPARING:
setMediaStatus(QMediaPlayer::LoadingMedia);
setState(QMediaPlayer::StoppedState);
break;
case JMediaPlayer::MEDIA_PLAYER_READY:
if (mBuffering) {
setMediaStatus(mBufferPercent == 100 ? QMediaPlayer::BufferedMedia
: QMediaPlayer::BufferingMedia);
} else {
setMediaStatus(QMediaPlayer::LoadedMedia);
mBufferPercent = 100;
Q_EMIT bufferStatusChanged(mBufferPercent);
updateAvailablePlaybackRanges();
}
setAudioAvailable(true);
mMediaPlayerReady = true;
flushPendingStates();
break;
case JMediaPlayer::MEDIA_PLAYER_DURATION:
Q_EMIT durationChanged(extra);
break;
case JMediaPlayer::MEDIA_PLAYER_PROGRESS:
Q_EMIT positionChanged(extra);
break;
case JMediaPlayer::MEDIA_PLAYER_FINISHED:
setState(QMediaPlayer::StoppedState);
setMediaStatus(QMediaPlayer::EndOfMedia);
break;
}
}
void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra)
{
QString errorString;
QMediaPlayer::Error error = QMediaPlayer::ResourceError;
switch (what) {
case JMediaPlayer::MEDIA_ERROR_UNKNOWN:
errorString = QLatin1String("Error:");
break;
case JMediaPlayer::MEDIA_ERROR_SERVER_DIED:
errorString = QLatin1String("Error: Server died");
error = QMediaPlayer::ServiceMissingError;
break;
}
switch (extra) {
case JMediaPlayer::MEDIA_ERROR_IO: // Network OR file error
errorString += QLatin1String(" (I/O operation failed)");
error = QMediaPlayer::NetworkError;
setMediaStatus(QMediaPlayer::InvalidMedia);
break;
case JMediaPlayer::MEDIA_ERROR_MALFORMED:
errorString += QLatin1String(" (Malformed bitstream)");
error = QMediaPlayer::FormatError;
setMediaStatus(QMediaPlayer::InvalidMedia);
break;
case JMediaPlayer::MEDIA_ERROR_UNSUPPORTED:
errorString += QLatin1String(" (Unsupported media)");
error = QMediaPlayer::FormatError;
setMediaStatus(QMediaPlayer::InvalidMedia);
break;
case JMediaPlayer::MEDIA_ERROR_TIMED_OUT:
errorString += QLatin1String(" (Timed out)");
break;
case JMediaPlayer::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
errorString += QLatin1String(" (Unable to start progressive playback')");
error = QMediaPlayer::FormatError;
setMediaStatus(QMediaPlayer::InvalidMedia);
break;
}
setError(error, errorString);
}
void QAndroidMediaPlayerControl::onBufferChanged(qint32 percent)
{
mBuffering = true;
mBufferPercent = percent;
Q_EMIT bufferStatusChanged(mBufferPercent);
updateAvailablePlaybackRanges();
if (mBufferPercent == 100)
setMediaStatus(QMediaPlayer::BufferedMedia);
}
void QAndroidMediaPlayerControl::onVideoSizeChanged(qint32 width, qint32 height)
{
if (width == 0 || height == 0)
return;
setVideoAvailable(true);
if (mVideoOutput) {
if (!mMediaPlayer->display())
mMediaPlayer->setDisplay(mVideoOutput->surfaceHolder());
if (mMediaPlayer->display())
mVideoOutput->setVideoSize(QSize(width, height));
}
}
void QAndroidMediaPlayerControl::setState(QMediaPlayer::State state)
{
if (mCurrentState == state)
return;
if (state == QMediaPlayer::StoppedState) {
if (mVideoOutput)
mVideoOutput->stop();
resetBufferingProgress();
mMediaPlayerReady = false;
mPendingPosition = -1;
Q_EMIT positionChanged(0);
}
mCurrentState = state;
Q_EMIT stateChanged(mCurrentState);
}
void QAndroidMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status)
{
if (mCurrentMediaStatus == status)
return;
if (status == QMediaPlayer::NoMedia || status == QMediaPlayer::InvalidMedia)
Q_EMIT durationChanged(0);
mCurrentMediaStatus = status;
Q_EMIT mediaStatusChanged(mCurrentMediaStatus);
}
void QAndroidMediaPlayerControl::setError(int error,
const QString &errorString)
{
setState(QMediaPlayer::StoppedState);
Q_EMIT QMediaPlayerControl::error(error, errorString);
}
void QAndroidMediaPlayerControl::setSeekable(bool seekable)
{
if (mSeekable == seekable)
return;
mSeekable = seekable;
Q_EMIT seekableChanged(mSeekable);
}
void QAndroidMediaPlayerControl::setAudioAvailable(bool available)
{
if (mAudioAvailable == available)
return;
mAudioAvailable = available;
Q_EMIT audioAvailableChanged(mAudioAvailable);
}
void QAndroidMediaPlayerControl::setVideoAvailable(bool available)
{
if (mVideoAvailable == available)
return;
mVideoAvailable = available;
Q_EMIT videoAvailableChanged(mVideoAvailable);
}
void QAndroidMediaPlayerControl::resetBufferingProgress()
{
mBuffering = false;
mBufferPercent = 0;
mAvailablePlaybackRange = QMediaTimeRange();
Q_EMIT bufferStatusChanged(mBufferPercent);
}
void QAndroidMediaPlayerControl::flushPendingStates()
{
switch (mPendingState) {
case QMediaPlayer::PlayingState:
if (mPendingPosition > -1)
setPosition(mPendingPosition);
play();
break;
case QMediaPlayer::PausedState:
pause();
break;
case QMediaPlayer::StoppedState:
stop();
break;
}
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,127 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QANDROIDMEDIAPLAYERCONTROL_H
#define QANDROIDMEDIAPLAYERCONTROL_H
#include <qglobal.h>
#include <QMediaPlayerControl>
QT_BEGIN_NAMESPACE
class JMediaPlayer;
class QAndroidVideoOutput;
class QAndroidMediaPlayerControl : public QMediaPlayerControl
{
Q_OBJECT
public:
explicit QAndroidMediaPlayerControl(QObject *parent = 0);
~QAndroidMediaPlayerControl() Q_DECL_OVERRIDE;
QMediaPlayer::State state() const Q_DECL_OVERRIDE;
QMediaPlayer::MediaStatus mediaStatus() const Q_DECL_OVERRIDE;
qint64 duration() const Q_DECL_OVERRIDE;
qint64 position() const Q_DECL_OVERRIDE;
int volume() const Q_DECL_OVERRIDE;
bool isMuted() const Q_DECL_OVERRIDE;
int bufferStatus() const Q_DECL_OVERRIDE;
bool isAudioAvailable() const Q_DECL_OVERRIDE;
bool isVideoAvailable() const Q_DECL_OVERRIDE;
bool isSeekable() const Q_DECL_OVERRIDE;
QMediaTimeRange availablePlaybackRanges() const Q_DECL_OVERRIDE;
qreal playbackRate() const Q_DECL_OVERRIDE;
void setPlaybackRate(qreal rate) Q_DECL_OVERRIDE;
QMediaContent media() const Q_DECL_OVERRIDE;
const QIODevice *mediaStream() const Q_DECL_OVERRIDE;
void setMedia(const QMediaContent &mediaContent, QIODevice *stream) Q_DECL_OVERRIDE;
void setVideoOutput(QAndroidVideoOutput *videoOutput);
Q_SIGNALS:
void metaDataUpdated();
public Q_SLOTS:
void setPosition(qint64 position) Q_DECL_OVERRIDE;
void play() Q_DECL_OVERRIDE;
void pause() Q_DECL_OVERRIDE;
void stop() Q_DECL_OVERRIDE;
void setVolume(int volume) Q_DECL_OVERRIDE;
void setMuted(bool muted) Q_DECL_OVERRIDE;
private Q_SLOTS:
void onError(qint32 what, qint32 extra);
void onInfo(qint32 what, qint32 extra);
void onMediaPlayerInfo(qint32 what, qint32 extra);
void onBufferChanged(qint32 percent);
void onVideoSizeChanged(qint32 width, qint32 height);
private:
JMediaPlayer *mMediaPlayer;
QMediaPlayer::State mCurrentState;
QMediaPlayer::MediaStatus mCurrentMediaStatus;
QMediaContent mMediaContent;
QIODevice *mMediaStream;
QAndroidVideoOutput *mVideoOutput;
bool mSeekable;
int mBufferPercent;
bool mAudioAvailable;
bool mVideoAvailable;
bool mBuffering;
QMediaTimeRange mAvailablePlaybackRange;
bool mMediaPlayerReady;
QMediaPlayer::State mPendingState;
qint64 mPendingPosition;
void setState(QMediaPlayer::State state);
void setMediaStatus(QMediaPlayer::MediaStatus status);
void setError(int error, const QString &errorString);
void setSeekable(bool seekable);
void setAudioAvailable(bool available);
void setVideoAvailable(bool available);
void updateAvailablePlaybackRanges();
void resetBufferingProgress();
void flushPendingStates();
};
QT_END_NAMESPACE
#endif // QANDROIDMEDIAPLAYERCONTROL_H

View File

@@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qandroidmediaservice.h"
#include "qandroidmediaplayercontrol.h"
#include "qandroidmetadatareadercontrol.h"
#include "qandroidvideorendercontrol.h"
QT_BEGIN_NAMESPACE
QAndroidMediaService::QAndroidMediaService(QObject *parent)
: QMediaService(parent)
, mVideoRendererControl(0)
{
mMediaControl = new QAndroidMediaPlayerControl;
mMetadataControl = new QAndroidMetaDataReaderControl;
connect(mMediaControl, SIGNAL(mediaChanged(QMediaContent)),
mMetadataControl, SLOT(onMediaChanged(QMediaContent)));
connect(mMediaControl, SIGNAL(metaDataUpdated()),
mMetadataControl, SLOT(onUpdateMetaData()));
}
QAndroidMediaService::~QAndroidMediaService()
{
delete mMediaControl;
delete mMetadataControl;
delete mVideoRendererControl;
}
QMediaControl *QAndroidMediaService::requestControl(const char *name)
{
if (qstrcmp(name, QMediaPlayerControl_iid) == 0)
return mMediaControl;
if (qstrcmp(name, QMetaDataReaderControl_iid) == 0)
return mMetadataControl;
if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
if (!mVideoRendererControl) {
mVideoRendererControl = new QAndroidVideoRendererControl;
mMediaControl->setVideoOutput(mVideoRendererControl);
return mVideoRendererControl;
}
}
return 0;
}
void QAndroidMediaService::releaseControl(QMediaControl *control)
{
if (control == mVideoRendererControl) {
mMediaControl->setVideoOutput(0);
delete mVideoRendererControl;
mVideoRendererControl = 0;
}
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,71 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QANDROIDMEDIASERVICE_H
#define QANDROIDMEDIASERVICE_H
#include <QMediaService>
QT_BEGIN_NAMESPACE
class QAndroidMediaPlayerControl;
class QAndroidMetaDataReaderControl;
class QAndroidVideoRendererControl;
class QAndroidMediaService : public QMediaService
{
Q_OBJECT
public:
explicit QAndroidMediaService(QObject *parent = 0);
~QAndroidMediaService() Q_DECL_OVERRIDE;
QMediaControl* requestControl(const char *name) Q_DECL_OVERRIDE;
void releaseControl(QMediaControl *control) Q_DECL_OVERRIDE;
private:
QAndroidMediaPlayerControl *mMediaControl;
QAndroidMetaDataReaderControl *mMetadataControl;
QAndroidVideoRendererControl *mVideoRendererControl;
};
QT_END_NAMESPACE
#endif // QANDROIDMEDIASERVICE_H

View File

@@ -0,0 +1,107 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qandroidmediaserviceplugin.h"
#include "qandroidmediaservice.h"
#include "jmediaplayer.h"
#include "jsurfacetexture.h"
#include "jsurfacetextureholder.h"
#include <qdebug.h>
QT_BEGIN_NAMESPACE
QAndroidMediaServicePlugin::QAndroidMediaServicePlugin()
{
}
QAndroidMediaServicePlugin::~QAndroidMediaServicePlugin()
{
}
QMediaService *QAndroidMediaServicePlugin::create(const QString &key)
{
if (key == QStringLiteral(Q_MEDIASERVICE_MEDIAPLAYER))
return new QAndroidMediaService;
qWarning() << "Android service plugin: unsupported key:" << key;
return 0;
}
void QAndroidMediaServicePlugin::release(QMediaService *service)
{
delete service;
}
QMediaServiceProviderHint::Features QAndroidMediaServicePlugin::supportedFeatures(const QByteArray &service) const
{
if (service == Q_MEDIASERVICE_MEDIAPLAYER)
return QMediaServiceProviderHint::VideoSurface;
return QMediaServiceProviderHint::Features();
}
Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/)
{
typedef union {
JNIEnv *nativeEnvironment;
void *venv;
} UnionJNIEnvToVoid;
UnionJNIEnvToVoid uenv;
uenv.venv = NULL;
if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK)
return JNI_ERR;
JNIEnv *jniEnv = uenv.nativeEnvironment;
if (!JMediaPlayer::initJNI(jniEnv) ||
!JSurfaceTexture::initJNI(jniEnv) ||
!JSurfaceTextureHolder::initJNI(jniEnv)) {
return JNI_ERR;
}
return JNI_VERSION_1_4;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QANDROIDMEDIASERVICEPLUGIN_H
#define QANDROIDMEDIASERVICEPLUGIN_H
#include <QMediaServiceProviderPlugin>
QT_BEGIN_NAMESPACE
class QMediaService;
class QAndroidMediaService;
class QAndroidMediaServicePlugin
: public QMediaServiceProviderPlugin
, public QMediaServiceFeaturesInterface
{
Q_OBJECT
Q_INTERFACES(QMediaServiceFeaturesInterface)
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0"
FILE "mediaplayer.json")
public:
QAndroidMediaServicePlugin();
~QAndroidMediaServicePlugin();
QMediaService* create(QString const& key) Q_DECL_OVERRIDE;
void release(QMediaService *service) Q_DECL_OVERRIDE;
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
#endif // QANDROIDMEDIASERVICEPLUGIN_H

View File

@@ -0,0 +1,221 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qandroidmetadatareadercontrol.h"
#include "jmediametadataretriever.h"
#include <qsize.h>
#include <QDate>
QT_BEGIN_NAMESPACE
// Genre name ordered by ID
// see: http://id3.org/id3v2.3.0#Appendix_A_-_Genre_List_from_ID3v1
static const char* qt_ID3GenreNames[] =
{
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz",
"Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno",
"Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno",
"Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
"Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul", "Punk",
"Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
"Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
"Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American",
"Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal",
"Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
"Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", "Revival", "Celtic",
"Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock",
"Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour",
"Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
"Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad",
"Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella",
"Euro-House", "Dance Hall"
};
QAndroidMetaDataReaderControl::QAndroidMetaDataReaderControl(QObject *parent)
: QMetaDataReaderControl(parent)
, m_available(false)
, m_retriever(0)
{
m_retriever = new JMediaMetadataRetriever;
if (!m_retriever->isValid()) {
delete m_retriever;
m_retriever = 0;
}
}
QAndroidMetaDataReaderControl::~QAndroidMetaDataReaderControl()
{
if (m_retriever) {
m_retriever->release();
delete m_retriever;
}
}
bool QAndroidMetaDataReaderControl::isMetaDataAvailable() const
{
return m_available;
}
QVariant QAndroidMetaDataReaderControl::metaData(const QString &key) const
{
return m_metadata.value(key);
}
QStringList QAndroidMetaDataReaderControl::availableMetaData() const
{
return m_metadata.keys();
}
void QAndroidMetaDataReaderControl::onMediaChanged(const QMediaContent &media)
{
if (!m_retriever)
return;
m_mediaContent = media;
updateData();
}
void QAndroidMetaDataReaderControl::onUpdateMetaData()
{
if (!m_retriever || m_mediaContent.isNull())
return;
updateData();
}
void QAndroidMetaDataReaderControl::updateData()
{
m_metadata.clear();
if (!m_mediaContent.isNull()) {
if (m_retriever->setDataSource(m_mediaContent.canonicalUrl())) {
QString mimeType = m_retriever->extractMetadata(JMediaMetadataRetriever::MimeType);
if (!mimeType.isNull())
m_metadata.insert(QMediaMetaData::MediaType, mimeType);
bool isVideo = !m_retriever->extractMetadata(JMediaMetadataRetriever::HasVideo).isNull()
|| mimeType.startsWith(QStringLiteral("video"));
QString string = m_retriever->extractMetadata(JMediaMetadataRetriever::Album);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::AlbumTitle, string);
string = m_retriever->extractMetadata(JMediaMetadataRetriever::AlbumArtist);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::AlbumArtist, string);
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Artist);
if (!string.isNull()) {
m_metadata.insert(isVideo ? QMediaMetaData::LeadPerformer
: QMediaMetaData::ContributingArtist,
string.split('/', QString::SkipEmptyParts));
}
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Author);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::Author, string.split('/', QString::SkipEmptyParts));
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Bitrate);
if (!string.isNull()) {
m_metadata.insert(isVideo ? QMediaMetaData::VideoBitRate
: QMediaMetaData::AudioBitRate,
string.toInt());
}
string = m_retriever->extractMetadata(JMediaMetadataRetriever::CDTrackNumber);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::TrackNumber, string.toInt());
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Composer);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::Composer, string.split('/', QString::SkipEmptyParts));
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Date);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::Date, QDateTime::fromString(string, QStringLiteral("yyyyMMddTHHmmss.zzzZ")).date());
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Duration);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::Duration, string.toLongLong());
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Genre);
if (!string.isNull()) {
// The genre can be returned as an ID3v2 id, get the name for it in that case
if (string.startsWith('(') && string.endsWith(')')) {
bool ok = false;
int genreId = string.mid(1, string.length() - 2).toInt(&ok);
if (ok && genreId >= 0 && genreId <= 125)
string = QLatin1String(qt_ID3GenreNames[genreId]);
}
m_metadata.insert(QMediaMetaData::Genre, string);
}
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Title);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::Title, string);
string = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoHeight);
if (!string.isNull()) {
int height = string.toInt();
int width = m_retriever->extractMetadata(JMediaMetadataRetriever::VideoWidth).toInt();
m_metadata.insert(QMediaMetaData::Resolution, QSize(width, height));
}
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Writer);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::Writer, string.split('/', QString::SkipEmptyParts));
string = m_retriever->extractMetadata(JMediaMetadataRetriever::Year);
if (!string.isNull())
m_metadata.insert(QMediaMetaData::Year, string.toInt());
}
}
bool oldAvailable = m_available;
m_available = !m_metadata.isEmpty();
if (m_available != oldAvailable)
Q_EMIT metaDataAvailableChanged(m_available);
Q_EMIT metaDataChanged();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QANDROIDMETADATAREADERCONTROL_H
#define QANDROIDMETADATAREADERCONTROL_H
#include <QMetaDataReaderControl>
#include <qmediacontent.h>
QT_BEGIN_NAMESPACE
class JMediaMetadataRetriever;
class QAndroidMetaDataReaderControl : public QMetaDataReaderControl
{
Q_OBJECT
public:
explicit QAndroidMetaDataReaderControl(QObject *parent = 0);
~QAndroidMetaDataReaderControl() Q_DECL_OVERRIDE;
bool isMetaDataAvailable() const Q_DECL_OVERRIDE;
QVariant metaData(const QString &key) const Q_DECL_OVERRIDE;
QStringList availableMetaData() const Q_DECL_OVERRIDE;
public Q_SLOTS:
void onMediaChanged(const QMediaContent &media);
void onUpdateMetaData();
private:
void updateData();
QMediaContent m_mediaContent;
bool m_available;
QVariantMap m_metadata;
JMediaMetadataRetriever *m_retriever;
};
QT_END_NAMESPACE
#endif // QANDROIDMETADATAREADERCONTROL_H

View File

@@ -0,0 +1,64 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QANDROIDVIDEOOUTPUT_H
#define QANDROIDVIDEOOUTPUT_H
#include <qglobal.h>
#include <qsize.h>
#include <jni.h>
QT_BEGIN_NAMESPACE
class QAndroidVideoOutput
{
public:
QAndroidVideoOutput() { }
virtual ~QAndroidVideoOutput() { }
virtual jobject surfaceHolder() = 0;
virtual void setVideoSize(const QSize &size) = 0;
virtual void stop() = 0;
};
QT_END_NAMESPACE
#endif // QANDROIDVIDEOOUTPUT_H

View File

@@ -0,0 +1,375 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qandroidvideorendercontrol.h"
#include <QtPlatformSupport/private/qjnihelpers_p.h>
#include "jsurfacetextureholder.h"
#include <QAbstractVideoSurface>
#include <QOpenGLContext>
#include <QOffscreenSurface>
#include <QOpenGLFramebufferObject>
#include <QVideoSurfaceFormat>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
QT_BEGIN_NAMESPACE
static const GLfloat g_vertex_data[] = {
-1.f, 1.f,
1.f, 1.f,
1.f, -1.f,
-1.f, -1.f
};
static const GLfloat g_texture_data[] = {
0.f, 0.f,
1.f, 0.f,
1.f, 1.f,
0.f, 1.f
};
class TextureVideoBuffer : public QAbstractVideoBuffer
{
public:
TextureVideoBuffer(GLuint textureId)
: QAbstractVideoBuffer(GLTextureHandle)
, m_textureId(textureId)
{}
virtual ~TextureVideoBuffer() {}
MapMode mapMode() const { return NotMapped; }
uchar *map(MapMode, int*, int*) { return 0; }
void unmap() {}
QVariant handle() const
{
return QVariant::fromValue<unsigned int>(m_textureId);
}
private:
GLuint m_textureId;
};
class ImageVideoBuffer : public QAbstractVideoBuffer
{
public:
ImageVideoBuffer(const QImage &image)
: QAbstractVideoBuffer(NoHandle)
, m_image(image)
, m_mode(NotMapped)
{
}
MapMode mapMode() const { return m_mode; }
uchar *map(MapMode mode, int *, int *)
{
if (mode != NotMapped && m_mode == NotMapped) {
m_mode = mode;
return m_image.bits();
}
return 0;
}
void unmap()
{
m_mode = NotMapped;
}
private:
QImage m_image;
MapMode m_mode;
};
QAndroidVideoRendererControl::QAndroidVideoRendererControl(QObject *parent)
: QVideoRendererControl(parent)
, m_surface(0)
, m_offscreenSurface(0)
, m_glContext(0)
, m_fbo(0)
, m_program(0)
, m_useImage(false)
, m_androidSurface(0)
, m_surfaceTexture(0)
, m_surfaceHolder(0)
, m_externalTex(0)
{
}
QAndroidVideoRendererControl::~QAndroidVideoRendererControl()
{
if (m_glContext)
m_glContext->makeCurrent(m_offscreenSurface);
if (m_surfaceTexture) {
QJNILocalRef<jobject> surfaceTex = m_surfaceTexture->surfaceTexture();
QJNIObject obj(surfaceTex.object());
obj.callMethod<void>("release");
delete m_surfaceTexture;
m_surfaceTexture = 0;
}
if (m_androidSurface) {
m_androidSurface->callMethod<void>("release");
delete m_androidSurface;
m_androidSurface = 0;
}
if (m_surfaceHolder) {
delete m_surfaceHolder;
m_surfaceHolder = 0;
}
if (m_externalTex)
glDeleteTextures(1, &m_externalTex);
delete m_fbo;
delete m_program;
delete m_glContext;
delete m_offscreenSurface;
}
QAbstractVideoSurface *QAndroidVideoRendererControl::surface() const
{
return m_surface;
}
void QAndroidVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
{
if (surface == m_surface)
return;
if (m_surface && m_surface->isActive())
m_surface->stop();
m_surface = surface;
m_useImage = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).contains(QVideoFrame::Format_BGR32);
}
jobject QAndroidVideoRendererControl::surfaceHolder()
{
if (m_surfaceHolder)
return m_surfaceHolder->object();
QOpenGLContext *currContext = QOpenGLContext::currentContext();
// If we don't have a GL context in the current thread, create one and share it
// with the render thread GL context
if (!currContext && !m_glContext) {
m_offscreenSurface = new QOffscreenSurface;
QSurfaceFormat format;
format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
m_offscreenSurface->setFormat(format);
m_offscreenSurface->create();
QOpenGLContext *shareContext = 0;
if (m_surface)
shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>());
m_glContext = new QOpenGLContext;
m_glContext->setFormat(m_offscreenSurface->requestedFormat());
if (shareContext)
m_glContext->setShareContext(shareContext);
if (!m_glContext->create())
return 0;
// if sharing contexts is not supported, fallback to image rendering and send the bits
// to the video surface
if (!m_glContext->shareContext())
m_useImage = true;
}
if (m_glContext)
m_glContext->makeCurrent(m_offscreenSurface);
glGenTextures(1, &m_externalTex);
m_surfaceTexture = new JSurfaceTexture(m_externalTex);
if (m_surfaceTexture->isValid()) {
connect(m_surfaceTexture, SIGNAL(frameAvailable()), this, SLOT(onFrameAvailable()));
QJNILocalRef<jobject> surfaceTex = m_surfaceTexture->surfaceTexture();
m_androidSurface = new QJNIObject("android/view/Surface",
"(Landroid/graphics/SurfaceTexture;)V",
surfaceTex.object());
m_surfaceHolder = new JSurfaceTextureHolder(m_androidSurface->object());
} else {
delete m_surfaceTexture;
m_surfaceTexture = 0;
glDeleteTextures(1, &m_externalTex);
}
if (m_surfaceHolder)
return m_surfaceHolder->object();
return 0;
}
void QAndroidVideoRendererControl::setVideoSize(const QSize &size)
{
if (m_nativeSize == size)
return;
m_nativeSize = size;
delete m_fbo;
m_fbo = 0;
}
void QAndroidVideoRendererControl::stop()
{
if (m_surface && m_surface->isActive())
m_surface->stop();
m_nativeSize = QSize();
}
void QAndroidVideoRendererControl::onFrameAvailable()
{
if (m_glContext)
m_glContext->makeCurrent(m_offscreenSurface);
m_surfaceTexture->updateTexImage();
if (!m_nativeSize.isValid())
return;
renderFrameToFbo();
QAbstractVideoBuffer *buffer = 0;
QVideoFrame frame;
if (m_useImage) {
buffer = new ImageVideoBuffer(m_fbo->toImage().mirrored());
frame = QVideoFrame(buffer, m_nativeSize, QVideoFrame::Format_RGB32);
} else {
buffer = new TextureVideoBuffer(m_fbo->texture());
frame = QVideoFrame(buffer, m_nativeSize, QVideoFrame::Format_BGR32);
}
if (m_surface && frame.isValid()) {
if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat()
|| m_surface->nativeResolution() != frame.size())) {
m_surface->stop();
}
if (!m_surface->isActive()) {
QVideoSurfaceFormat format(frame.size(), frame.pixelFormat(),
m_useImage ? QAbstractVideoBuffer::NoHandle
: QAbstractVideoBuffer::GLTextureHandle);
m_surface->start(format);
}
if (m_surface->isActive())
m_surface->present(frame);
}
}
void QAndroidVideoRendererControl::renderFrameToFbo()
{
createGLResources();
m_fbo->bind();
glViewport(0, 0, m_nativeSize.width(), m_nativeSize.height());
m_program->bind();
m_program->enableAttributeArray(0);
m_program->enableAttributeArray(1);
m_program->setUniformValue("frameTexture", GLuint(0));
m_program->setUniformValue("texMatrix", m_surfaceTexture->getTransformMatrix());
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, g_vertex_data);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, g_texture_data);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
m_program->disableAttributeArray(0);
m_program->disableAttributeArray(1);
m_program->release();
glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
m_fbo->release();
glFinish();
}
void QAndroidVideoRendererControl::createGLResources()
{
if (!m_fbo)
m_fbo = new QOpenGLFramebufferObject(m_nativeSize);
if (!m_program) {
m_program = new QOpenGLShaderProgram;
QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_program);
vertexShader->compileSourceCode("attribute highp vec4 vertexCoordsArray; \n" \
"attribute highp vec2 textureCoordArray; \n" \
"uniform highp mat4 texMatrix; \n" \
"varying highp vec2 textureCoords; \n" \
"void main(void) \n" \
"{ \n" \
" gl_Position = vertexCoordsArray; \n" \
" textureCoords = (texMatrix * vec4(textureCoordArray, 0.0, 1.0)).xy; \n" \
"}\n");
m_program->addShader(vertexShader);
QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_program);
fragmentShader->compileSourceCode("#extension GL_OES_EGL_image_external : require \n" \
"varying highp vec2 textureCoords; \n" \
"uniform samplerExternalOES frameTexture; \n" \
"void main() \n" \
"{ \n" \
" gl_FragColor = texture2D(frameTexture, textureCoords); \n" \
"}\n");
m_program->addShader(fragmentShader);
m_program->bindAttributeLocation("vertexCoordsArray", 0);
m_program->bindAttributeLocation("textureCoordArray", 1);
m_program->link();
}
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,95 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QANDROIDVIDEORENDERCONTROL_H
#define QANDROIDVIDEORENDERCONTROL_H
#include <qvideorenderercontrol.h>
#include "qandroidvideooutput.h"
#include "jsurfacetexture.h"
QT_BEGIN_NAMESPACE
class QOpenGLContext;
class QOffscreenSurface;
class QOpenGLFramebufferObject;
class QOpenGLShaderProgram;
class JSurfaceTextureHolder;
class QAndroidVideoRendererControl : public QVideoRendererControl, public QAndroidVideoOutput
{
Q_OBJECT
public:
explicit QAndroidVideoRendererControl(QObject *parent = 0);
~QAndroidVideoRendererControl() Q_DECL_OVERRIDE;
QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE;
void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE;
jobject surfaceHolder() Q_DECL_OVERRIDE;
void setVideoSize(const QSize &size) Q_DECL_OVERRIDE;
void stop() Q_DECL_OVERRIDE;
private Q_SLOTS:
void onFrameAvailable();
private:
void setupSurface();
void renderFrameToFbo();
void createGLResources();
QAbstractVideoSurface *m_surface;
QOffscreenSurface *m_offscreenSurface;
QOpenGLContext *m_glContext;
QOpenGLFramebufferObject *m_fbo;
QOpenGLShaderProgram *m_program;
bool m_useImage;
QSize m_nativeSize;
QJNIObject *m_androidSurface;
JSurfaceTexture *m_surfaceTexture;
JSurfaceTextureHolder *m_surfaceHolder;
uint m_externalTex;
};
QT_END_NAMESPACE
#endif // QANDROIDVIDEORENDERCONTROL_H

View File

@@ -0,0 +1,126 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "jmediametadataretriever.h"
#include <QtPlatformSupport/private/qjnihelpers_p.h>
#include <qpa/qplatformnativeinterface.h>
#include <qguiapplication.h>
QT_BEGIN_NAMESPACE
static jobject g_activity = 0;
JMediaMetadataRetriever::JMediaMetadataRetriever()
: QJNIObject("android/media/MediaMetadataRetriever")
{
if (!g_activity) {
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
g_activity = static_cast<jobject>(nativeInterface->nativeResourceForIntegration("QtActivity"));
}
}
JMediaMetadataRetriever::~JMediaMetadataRetriever()
{
}
QString JMediaMetadataRetriever::extractMetadata(MetadataKey key)
{
QString value;
QJNILocalRef<jstring> metadata = callObjectMethod<jstring>("extractMetadata",
"(I)Ljava/lang/String;",
jint(key));
if (!metadata.isNull())
value = qt_convertJString(metadata.object());
return value;
}
void JMediaMetadataRetriever::release()
{
callMethod<void>("release");
}
bool JMediaMetadataRetriever::setDataSource(const QUrl &url)
{
QAttachedJNIEnv env;
bool loaded = false;
QJNILocalRef<jstring> string = qt_toJString(url.toString());
QJNILocalRef<jobject> uri = callStaticObjectMethod<jobject>("android/net/Uri",
"parse",
"(Ljava/lang/String;)Landroid/net/Uri;",
string.object());
if (env->ExceptionCheck()) {
env->ExceptionClear();
} else {
callMethod<void>("setDataSource",
"(Landroid/content/Context;Landroid/net/Uri;)V",
g_activity,
uri.object());
if (env->ExceptionCheck())
env->ExceptionClear();
else
loaded = true;
}
return loaded;
}
bool JMediaMetadataRetriever::setDataSource(const QString &path)
{
QAttachedJNIEnv env;
bool loaded = false;
callMethod<void>("setDataSource", "(Ljava/lang/String;)V", qt_toJString(path).object());
if (env->ExceptionCheck())
env->ExceptionClear();
else
loaded = true;
return loaded;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,91 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef JMEDIAMETADATARETRIEVER_H
#define JMEDIAMETADATARETRIEVER_H
#include <QtPlatformSupport/private/qjniobject_p.h>
#include <qurl.h>
QT_BEGIN_NAMESPACE
class JMediaMetadataRetriever : public QJNIObject
{
public:
enum MetadataKey {
Album = 1,
AlbumArtist = 13,
Artist = 2,
Author = 3,
Bitrate = 20,
CDTrackNumber = 0,
Compilation = 15,
Composer = 4,
Date = 5,
DiscNumber = 14,
Duration = 9,
Genre = 6,
HasAudio = 16,
HasVideo = 17,
Location = 23,
MimeType = 12,
NumTracks = 10,
Title = 7,
VideoHeight = 19,
VideoWidth = 18,
VideoRotation = 24,
Writer = 11,
Year = 8
};
JMediaMetadataRetriever();
~JMediaMetadataRetriever();
QString extractMetadata(MetadataKey key);
void release();
bool setDataSource(const QUrl &url);
bool setDataSource(const QString &path);
};
QT_END_NAMESPACE
#endif // JMEDIAMETADATARETRIEVER_H

View File

@@ -0,0 +1,265 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "jmediaplayer.h"
#include <QString>
#include <qpa/qplatformnativeinterface.h>
#include <qguiapplication.h>
#include <QtPlatformSupport/private/qjnihelpers_p.h>
namespace {
jclass mediaPlayerClass = 0;
QMap<jlong, JMediaPlayer *> mplayers;
}
QT_BEGIN_NAMESPACE
bool JMediaPlayer::mActivitySet = false;
JMediaPlayer::JMediaPlayer()
: QObject()
, QJNIObject(mediaPlayerClass, "(J)V", reinterpret_cast<jlong>(this))
, mId(reinterpret_cast<jlong>(this))
, mDisplay(0)
{
mplayers.insert(mId, this);
if (!mActivitySet) {
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
jobject activity = static_cast<jobject>(nativeInterface->nativeResourceForIntegration("QtActivity"));
QJNIObject::callStaticMethod<void>(mediaPlayerClass,
"setActivity",
"(Landroid/app/Activity;)V",
activity);
mActivitySet = true;
}
}
JMediaPlayer::~JMediaPlayer()
{
mplayers.remove(mId);
}
void JMediaPlayer::onError(qint32 what, qint32 extra)
{
Q_EMIT error(what, extra);
}
void JMediaPlayer::onBufferingUpdate(qint32 percent)
{
Q_EMIT bufferingUpdate(percent);
}
void JMediaPlayer::onInfo(qint32 what, qint32 extra)
{
Q_EMIT info(what, extra);
}
void JMediaPlayer::onMediaPlayerInfo(qint32 what, qint32 extra)
{
Q_EMIT mediaPlayerInfo(what, extra);
}
void JMediaPlayer::onVideoSizeChanged(qint32 width, qint32 height)
{
Q_EMIT videoSizeChanged(width, height);
}
int JMediaPlayer::getCurrentPosition()
{
return callMethod<jint>("getCurrentPosition");
}
int JMediaPlayer::getDuration()
{
return callMethod<jint>("getDuration");
}
bool JMediaPlayer::isPlaying()
{
return callMethod<jboolean>("isPlaying");
}
int JMediaPlayer::volume()
{
return callMethod<jint>("getVolume");
}
bool JMediaPlayer::isMuted()
{
return callMethod<jboolean>("isMuted");
}
void JMediaPlayer::play()
{
callMethod<void>("start");
}
void JMediaPlayer::pause()
{
callMethod<void>("pause");
}
void JMediaPlayer::stop()
{
callMethod<void>("stop");
}
void JMediaPlayer::seekTo(qint32 msec)
{
callMethod<void>("seekTo", "(I)V", jint(msec));
}
void JMediaPlayer::setMuted(bool mute)
{
callMethod<void>("mute", "(Z)V", jboolean(mute));
}
void JMediaPlayer::setDataSource(const QString &path)
{
QJNILocalRef<jstring> string = qt_toJString(path);
callMethod<void>("setMediaPath", "(Ljava/lang/String;)V", string.object());
}
void JMediaPlayer::setVolume(int volume)
{
callMethod<void>("setVolume", "(I)V", jint(volume));
}
void JMediaPlayer::setDisplay(jobject surfaceHolder)
{
mDisplay = surfaceHolder;
callMethod<void>("setDisplay", "(Landroid/view/SurfaceHolder;)V", mDisplay);
}
QT_END_NAMESPACE
static void onErrorNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id];
if (!mp)
return;
mp->onError(what, extra);
}
static void onBufferingUpdateNative(JNIEnv *env, jobject thiz, jint percent, jlong id)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id];
if (!mp)
return;
mp->onBufferingUpdate(percent);
}
static void onInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id];
if (!mp)
return;
mp->onInfo(what, extra);
}
static void onMediaPlayerInfoNative(JNIEnv *env, jobject thiz, jint what, jint extra, jlong id)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id];
if (!mp)
return;
mp->onMediaPlayerInfo(what, extra);
}
static void onVideoSizeChangedNative(JNIEnv *env,
jobject thiz,
jint width,
jint height,
jlong id)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
JMediaPlayer *const mp = mplayers[id];
if (!mp)
return;
mp->onVideoSizeChanged(width, height);
}
QT_BEGIN_NAMESPACE
bool JMediaPlayer::initJNI(JNIEnv *env)
{
jclass jClass = env->FindClass("org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer");
if (jClass) {
mediaPlayerClass = static_cast<jclass>(env->NewGlobalRef(jClass));
JNINativeMethod methods[] = {
{"onErrorNative", "(IIJ)V", reinterpret_cast<void *>(onErrorNative)},
{"onBufferingUpdateNative", "(IJ)V", reinterpret_cast<void *>(onBufferingUpdateNative)},
{"onInfoNative", "(IIJ)V", reinterpret_cast<void *>(onInfoNative)},
{"onMediaPlayerInfoNative", "(IIJ)V", reinterpret_cast<void *>(onMediaPlayerInfoNative)},
{"onVideoSizeChangedNative", "(IIJ)V", reinterpret_cast<void *>(onVideoSizeChangedNative)}
};
if (env->RegisterNatives(mediaPlayerClass,
methods,
sizeof(methods) / sizeof(methods[0])) < 0) {
return false;
}
}
return true;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,133 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QANDROIDMEDIAPLAYER_H
#define QANDROIDMEDIAPLAYER_H
#include <QObject>
#include <QtPlatformSupport/private/qjniobject_p.h>
QT_BEGIN_NAMESPACE
class JMediaPlayer : public QObject, public QJNIObject
{
Q_OBJECT
public:
JMediaPlayer();
~JMediaPlayer();
enum MediaError
{
// What
MEDIA_ERROR_UNKNOWN = 1,
MEDIA_ERROR_SERVER_DIED = 100,
// Extra
MEDIA_ERROR_IO = -1004,
MEDIA_ERROR_MALFORMED = -1007,
MEDIA_ERROR_UNSUPPORTED = -1010,
MEDIA_ERROR_TIMED_OUT = -110,
MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200
};
enum MediaInfo
{
MEDIA_INFO_UNKNOWN = 1,
MEDIA_INFO_VIDEO_TRACK_LAGGING = 700,
MEDIA_INFO_VIDEO_RENDERING_START = 3,
MEDIA_INFO_BUFFERING_START = 701,
MEDIA_INFO_BUFFERING_END = 702,
MEDIA_INFO_BAD_INTERLEAVING = 800,
MEDIA_INFO_NOT_SEEKABLE = 801,
MEDIA_INFO_METADATA_UPDATE = 802
};
enum MediaPlayerInfo
{
MEDIA_PLAYER_INVALID_STATE = 1,
MEDIA_PLAYER_PREPARING = 2,
MEDIA_PLAYER_READY = 3,
MEDIA_PLAYER_DURATION = 4,
MEDIA_PLAYER_PROGRESS = 5,
MEDIA_PLAYER_FINISHED = 6
};
int getCurrentPosition();
int getDuration();
bool isPlaying();
int volume();
bool isMuted();
jobject display() { return mDisplay; }
void play();
void pause();
void stop();
void seekTo(qint32 msec);
void setMuted(bool mute);
void setDataSource(const QString &path);
void setVolume(int volume);
void setDisplay(jobject surfaceHolder);
void onError(qint32 what, qint32 extra);
void onBufferingUpdate(qint32 percent);
void onInfo(qint32 what, qint32 extra);
void onMediaPlayerInfo(qint32 what, qint32 extra);
void onVideoSizeChanged(qint32 width, qint32 height);
static bool initJNI(JNIEnv *env);
Q_SIGNALS:
void error(qint32 what, qint32 extra);
void bufferingUpdate(qint32 percent);
void completion();
void info(qint32 what, qint32 extra);
void mediaPlayerInfo(qint32 what, qint32 extra);
void videoSizeChanged(qint32 width, qint32 height);
private:
jlong mId;
jobject mDisplay;
static bool mActivitySet;
};
QT_END_NAMESPACE
#endif // QANDROIDMEDIAPLAYER_H

View File

@@ -0,0 +1,118 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "jsurfacetexture.h"
#include <QtPlatformSupport/private/qjnihelpers_p.h>
QT_BEGIN_NAMESPACE
static jclass g_qtSurfaceTextureClass = 0;
static QHash<int, JSurfaceTexture*> g_objectMap;
// native method for QtSurfaceTexture.java
static void notifyFrameAvailable(JNIEnv* , jobject, int id)
{
JSurfaceTexture *obj = g_objectMap.value(id, 0);
if (obj)
Q_EMIT obj->frameAvailable();
}
JSurfaceTexture::JSurfaceTexture(unsigned int texName)
: QObject()
, QJNIObject(g_qtSurfaceTextureClass, "(I)V", jint(texName))
, m_texID(int(texName))
{
if (m_jobject)
g_objectMap.insert(int(texName), this);
}
JSurfaceTexture::~JSurfaceTexture()
{
if (m_jobject)
g_objectMap.remove(m_texID);
}
QMatrix4x4 JSurfaceTexture::getTransformMatrix()
{
QAttachedJNIEnv env;
QMatrix4x4 matrix;
jfloatArray array = env->NewFloatArray(16);
callMethod<void>("getTransformMatrix", "([F)V", array);
env->GetFloatArrayRegion(array, 0, 16, matrix.data());
env->DeleteLocalRef(array);
return matrix;
}
void JSurfaceTexture::updateTexImage()
{
callMethod<void>("updateTexImage");
}
QJNILocalRef<jobject> JSurfaceTexture::surfaceTexture()
{
return getObjectField<jobject>("surfaceTexture", "Landroid/graphics/SurfaceTexture;");
}
static JNINativeMethod methods[] = {
{"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable}
};
bool JSurfaceTexture::initJNI(JNIEnv *env)
{
jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtSurfaceTexture");
if (env->ExceptionCheck())
env->ExceptionClear();
if (clazz) {
g_qtSurfaceTextureClass = static_cast<jclass>(env->NewGlobalRef(clazz));
if (env->RegisterNatives(g_qtSurfaceTextureClass,
methods,
sizeof(methods) / sizeof(methods[0])) < 0) {
return false;
}
}
return true;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef JSURFACETEXTURE_H
#define JSURFACETEXTURE_H
#include <qobject.h>
#include <QtPlatformSupport/private/qjniobject_p.h>
#include <QMatrix4x4>
QT_BEGIN_NAMESPACE
class JSurfaceTexture : public QObject, public QJNIObject
{
Q_OBJECT
public:
explicit JSurfaceTexture(unsigned int texName);
~JSurfaceTexture();
QMatrix4x4 getTransformMatrix();
void updateTexImage();
QJNILocalRef<jobject> surfaceTexture();
static bool initJNI(JNIEnv *env);
Q_SIGNALS:
void frameAvailable();
private:
int m_texID;
};
QT_END_NAMESPACE
#endif // JSURFACETEXTURE_H

View File

@@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "jsurfacetextureholder.h"
QT_BEGIN_NAMESPACE
static jclass g_qtSurfaceTextureHolderClass = 0;
JSurfaceTextureHolder::JSurfaceTextureHolder(jobject surface)
: QJNIObject(g_qtSurfaceTextureHolderClass, "(Landroid/view/Surface;)V", surface)
{
}
bool JSurfaceTextureHolder::initJNI(JNIEnv *env)
{
jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder");
if (env->ExceptionCheck())
env->ExceptionClear();
if (clazz)
g_qtSurfaceTextureHolderClass = static_cast<jclass>(env->NewGlobalRef(clazz));
return true;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef JSURFACETEXTUREHOLDER_H
#define JSURFACETEXTUREHOLDER_H
#include <QtPlatformSupport/private/qjniobject_p.h>
QT_BEGIN_NAMESPACE
class JSurfaceTextureHolder : public QJNIObject
{
public:
JSurfaceTextureHolder(jobject surface);
static bool initJNI(JNIEnv *env);
};
QT_END_NAMESPACE
#endif // JSURFACETEXTUREHOLDER_H

View File

@@ -0,0 +1,15 @@
QT += platformsupport-private
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/jmediaplayer.h \
$$PWD/jsurfacetexture.h \
$$PWD/jsurfacetextureholder.h \
$$PWD/jmediametadataretriever.h
SOURCES += \
$$PWD/jmediaplayer.cpp \
$$PWD/jsurfacetexture.cpp \
$$PWD/jsurfacetextureholder.cpp \
$$PWD/jmediametadataretriever.cpp