broadcasters) {
if (mOnEventListener != null) {
- mOnEventListener.onBroadcasterStarted(broadcaster);
+ mOnEventListener.onBroadcasterStarted(broadcasters);
}
}
- protected void postOnBroadcasterStopped(Broadcaster broadcaster) {
+ protected void postOnBroadcasterStopped() {
if (mOnEventListener != null) {
- mOnEventListener.onBroadcasterStopped(broadcaster);
+ mOnEventListener.onBroadcasterStopped();
}
}
- protected void postOnBroadcasterError(Broadcaster broadcaster, Exception e) {
+ protected void postOnBroadcasterError(LiveStreaming broadcaster, Exception e) {
if (mOnEventListener != null) {
mOnEventListener.onBroadcasterError(broadcaster, e);
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractPreviewServer.java
index e89537d3d1..d76ae3ab25 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractPreviewServer.java
@@ -1,284 +1,27 @@
package org.deviceconnect.android.deviceplugin.host.recorder;
import android.content.Context;
-import android.graphics.Rect;
-import android.media.AudioAttributes;
-import android.media.AudioFormat;
-import android.media.AudioPlaybackCaptureConfiguration;
-import android.media.projection.MediaProjection;
-import android.os.Build;
-import android.util.Size;
import org.deviceconnect.android.deviceplugin.host.BuildConfig;
-import org.deviceconnect.android.deviceplugin.host.recorder.util.MediaProjectionProvider;
-import org.deviceconnect.android.libmedia.streaming.audio.AudioQuality;
-import org.deviceconnect.android.libmedia.streaming.audio.MicAudioQuality;
-import org.deviceconnect.android.libmedia.streaming.audio.filter.HighPassFilter;
-import org.deviceconnect.android.libmedia.streaming.audio.filter.LowPassFilter;
-import org.deviceconnect.android.libmedia.streaming.gles.EGLSurfaceDrawingThread;
-import org.deviceconnect.android.libmedia.streaming.video.VideoQuality;
-
-import javax.net.ssl.SSLContext;
/**
* プレビュー配信サーバ.
*/
-public abstract class AbstractPreviewServer implements PreviewServer {
+public abstract class AbstractPreviewServer extends AbstractLiveStreaming implements PreviewServer {
protected static final boolean DEBUG = BuildConfig.DEBUG;
protected static final String TAG = "host.dplugin";
- /**
- * コンテキスト.
- */
- private final Context mContext;
-
- /**
- * プレビュー再生を行うレコーダ.
- */
- private final HostMediaRecorder mHostMediaRecorder;
-
- /**
- * プレビュー配信サーバのポート番号.
- */
- private int mPort;
-
- /**
- * ミュート設定.
- */
- private boolean mMute;
-
- /**
- * SSLContext のインスタンス.
- */
- private SSLContext mSSLContext;
-
- /**
- * SSL の使用フラグ.
- */
- private final boolean mUseSSL;
-
- /**
- * コンストラクタ.
- *
- *
- * デフォルトでは、mute は true に設定しています。
- * デフォルトでは、mUseSSL は false に設定します。
- *
- *
- * @param context コンテキスト
- * @param recorder プレビューで表示するレコーダ
- */
- public AbstractPreviewServer(Context context, HostMediaRecorder recorder) {
- this(context, recorder, false);
- }
-
/**
* コンストラクタ.
*
*
- * デフォルトでは、mute は true に設定しています。
+ * デフォルトでは、ミュート設定は true に設定しています。
*
*
- * @param context コンテキスト
* @param recorder プレビューで表示するレコーダ
- * @param useSSL SSL使用フラグ
- */
- public AbstractPreviewServer(Context context, HostMediaRecorder recorder, boolean useSSL) {
- mContext = context;
- mHostMediaRecorder = recorder;
- mUseSSL = useSSL;
- mMute = true;
- }
-
- // Implements PreviewServer methods.
-
- @Override
- public int getPort() {
- return mPort;
- }
-
- @Override
- public void setPort(int port) {
- mPort = port;
- }
-
- @Override
- public void onConfigChange() {
- VideoQuality videoQuality = getVideoQuality();
- if (videoQuality != null) {
- setVideoQuality(videoQuality);
- }
-
- AudioQuality audioQuality = getAudioQuality();
- if (audioQuality != null) {
- setAudioQuality(audioQuality);
-
- HostMediaRecorder.Settings settings = getRecorder().getSettings();
- setMute(settings.isMute());
- }
- }
-
- @Override
- public void setMute(boolean mute) {
- mMute = mute;
- }
-
- @Override
- public boolean isMuted() {
- return mMute;
- }
-
- @Override
- public boolean useSSLContext() {
- return mUseSSL;
- }
-
- @Override
- public void setSSLContext(final SSLContext sslContext) {
- mSSLContext = sslContext;
- }
-
- @Override
- public SSLContext getSSLContext() {
- return mSSLContext;
- }
-
- /**
- * コンテキストを取得します.
- *
- * @return コンテキスト
- */
- public Context getContext() {
- return mContext;
- }
-
- /**
- * プレビューを表示するレコーダー.
- *
- * @return レコーダー
- */
- public HostMediaRecorder getRecorder() {
- return mHostMediaRecorder;
- }
-
- /**
- * 映像の設定を取得します.
- *
- * 映像が使用されていない場合は null を返却すること。
- *
- * @return 映像の設定
+ * @param id 名前
*/
- protected VideoQuality getVideoQuality() {
- return null;
- }
-
- /**
- * 音声の設定を取得します.
- *
- * 音声が使用されていない場合は null を返却すること。
- *
- * @return 音声の設定
- */
- protected AudioQuality getAudioQuality() {
- return null;
- }
-
- /**
- * VideoEncoder の設定に、HostMediaRecorder の設定を反映します.
- *
- * @param videoQuality 設定を行う VideoEncoder の VideoQuality
- */
- public void setVideoQuality(VideoQuality videoQuality) {
- HostMediaRecorder recorder = getRecorder();
- HostMediaRecorder.Settings settings = recorder.getSettings();
-
- Rect rect = settings.getDrawingRange();
- if (rect != null) {
- videoQuality.setVideoWidth(rect.width());
- videoQuality.setVideoHeight(rect.height());
- } else {
- EGLSurfaceDrawingThread d = recorder.getSurfaceDrawingThread();
- Size previewSize = settings.getPreviewSize();
- int w = d.isSwappedDimensions() ? previewSize.getHeight() : previewSize.getWidth();
- int h = d.isSwappedDimensions() ? previewSize.getWidth() : previewSize.getHeight();
- videoQuality.setVideoWidth(w);
- videoQuality.setVideoHeight(h);
- }
- videoQuality.setBitRate(settings.getPreviewBitRate());
- videoQuality.setFrameRate(settings.getPreviewMaxFrameRate());
- videoQuality.setIFrameInterval(settings.getPreviewKeyFrameInterval());
- videoQuality.setUseSoftwareEncoder(settings.isUseSoftwareEncoder());
- videoQuality.setIntraRefresh(settings.getIntraRefresh());
- videoQuality.setProfile(settings.getProfile());
- videoQuality.setLevel(settings.getLevel());
- if (settings.getPreviewBitRateMode() != null) {
- switch (settings.getPreviewBitRateMode()) {
- default:
- case VBR:
- videoQuality.setBitRateMode(VideoQuality.BitRateMode.VBR);
- break;
- case CBR:
- videoQuality.setBitRateMode(VideoQuality.BitRateMode.CBR);
- break;
- case CQ:
- videoQuality.setBitRateMode(VideoQuality.BitRateMode.CQ);
- break;
- }
- } else {
- videoQuality.setBitRateMode(null);
- }
- }
-
- /**
- * AudioEncoder の設定に、HostMediaRecorder の設定を反映します.
- *
- * @param audioQuality 設定を行う AudioEncoder の AudioQuality
- */
- public void setAudioQuality(AudioQuality audioQuality) {
- HostMediaRecorder recorder = getRecorder();
- HostMediaRecorder.Settings settings = recorder.getSettings();
-
- mMute = settings.isMute();
- audioQuality.setChannel(settings.getPreviewChannel() == 1 ?
- AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO);
- audioQuality.setSamplingRate(settings.getPreviewSampleRate());
- audioQuality.setBitRate(settings.getPreviewAudioBitRate());
- audioQuality.setUseAEC(settings.isUseAEC());
-
- if (settings.getAudioFilter() != null) {
- float coeff = settings.getAudioCoefficient();
- switch (settings.getAudioFilter()) {
- case LOW_PASS:
- audioQuality.setFilter(new LowPassFilter(audioQuality, coeff));
- break;
- case HIGH_PASS:
- audioQuality.setFilter(new HighPassFilter(audioQuality, coeff));
- break;
- default:
- audioQuality.setFilter(null);
- break;
- }
- } else {
- audioQuality.setFilter(null);
- }
-
- MicAudioQuality quality = (MicAudioQuality) audioQuality;
- if (settings.getPreviewAudioSource() == HostMediaRecorder.AudioSource.APP) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- // アプリの録音機能
- MediaProjectionProvider provider = recorder.getMediaProjectionProvider();
- if (provider != null && provider.getMediaProjection() != null) {
- MediaProjection mediaProjection = provider.getMediaProjection();
- AudioPlaybackCaptureConfiguration configuration =
- new AudioPlaybackCaptureConfiguration.Builder(mediaProjection)
- .addMatchingUsage(AudioAttributes.USAGE_GAME)
- .addMatchingUsage(AudioAttributes.USAGE_MEDIA)
- .addMatchingUsage(AudioAttributes.USAGE_UNKNOWN)
- .build();
- quality.setCaptureConfig(configuration);
- }
- }
- quality.setSource(MicAudioQuality.Source.APP);
- }
+ public AbstractPreviewServer(HostMediaRecorder recorder, String id) {
+ super(recorder, id);
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractPreviewServerProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractPreviewServerProvider.java
index 8a5681367e..eee047fb67 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractPreviewServerProvider.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractPreviewServerProvider.java
@@ -15,55 +15,26 @@
import android.content.Intent;
import android.os.Build;
-import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import org.deviceconnect.android.deviceplugin.host.R;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
/**
* Host Device Preview Server.
*
* @author NTT DOCOMO, INC.
*/
-public abstract class AbstractPreviewServerProvider implements PreviewServerProvider {
- /**
- * コンテキスト.
- */
- private final Context mContext;
-
- /**
- * プレビュー配信サーバーのリスト.
- */
- private final List mPreviewServers = new ArrayList<>();
-
- /**
- * プレビュー配信を行うレコーダ.
- */
- private final HostMediaRecorder mRecorder;
-
- /**
- * Notification 表示フラグ.
- */
- private boolean mIsRunning;
-
- /**
- * プレビュー配信サーバのイベントを通知するリスナー.
- */
- private OnEventListener mOnEventListener;
+public abstract class AbstractPreviewServerProvider extends AbstractLiveStreamingProvider implements PreviewServerProvider {
/**
* コンストラクタ.
* @param context コンテキスト
*/
public AbstractPreviewServerProvider(final Context context, final HostMediaRecorder recorder) {
- mContext = context;
- mRecorder = recorder;
- mIsRunning = false;
+ super(context, recorder);
}
// PreviewServerProvider
@@ -71,173 +42,35 @@ public AbstractPreviewServerProvider(final Context context, final HostMediaRecor
@Override
public List getSupportedMimeType() {
List mimeType = new ArrayList<>();
- for (PreviewServer server : getServers()) {
+ for (LiveStreaming server : getLiveStreamingList()) {
mimeType.add(server.getMimeType());
}
return mimeType;
}
@Override
- public void addServer(PreviewServer server) {
- mPreviewServers.add(server);
- }
-
- @Override
- public List getServers() {
- return mPreviewServers;
- }
-
- @Override
- public PreviewServer getServerByMimeType(String mimeType) {
- for (PreviewServer server : getServers()) {
- if (server.getMimeType().equalsIgnoreCase(mimeType)) {
- return server;
- }
- }
- return null;
- }
-
- @Override
- public boolean isRunning() {
- return mIsRunning;
- }
-
- @Override
- public List startServers() {
- List results = new ArrayList<>();
-
- CountDownLatch latch = new CountDownLatch(mPreviewServers.size());
- for (PreviewServer server : mPreviewServers) {
- server.startWebServer(new PreviewServer.OnWebServerStartCallback() {
- @Override
- public void onStart(@NonNull String uri) {
- results.add(server);
- latch.countDown();
- }
-
- @Override
- public void onFail() {
- latch.countDown();
- }
- });
- }
-
- try {
- latch.await(5, TimeUnit.SECONDS);
- if (results.size() > 0) {
- mIsRunning = true;
- sendNotification(mRecorder.getId(), mRecorder.getName());
- postPreviewStarted(results);
- }
- } catch (InterruptedException e) {
- // ignore.
- }
- return results;
- }
-
- @Override
- public void stopServers() {
- hideNotification(mRecorder.getId());
-
- for (PreviewServer server : getServers()) {
- server.stopWebServer();
- }
-
- if (mIsRunning) {
- mIsRunning = false;
- postPreviewStopped();
- }
- }
-
- @Override
- public List requestSyncFrame() {
- List result = new ArrayList<>();
- for (PreviewServer server : getServers()) {
- if (server.requestSyncFrame()) {
- result.add(server);
- }
- }
- return result;
- }
-
- @Override
- public void onConfigChange() {
- for (PreviewServer server : getServers()) {
- server.onConfigChange();
- }
- }
-
- @Override
- public void setMute(boolean mute) {
- for (PreviewServer server : getServers()) {
- server.setMute(mute);
- }
- }
-
- @Override
- public void setOnEventListener(OnEventListener listener) {
- mOnEventListener = listener;
- }
-
- protected void postPreviewStarted(List servers) {
- if (mOnEventListener != null) {
- mOnEventListener.onStarted(servers);
- }
- }
-
- protected void postPreviewStopped() {
- if (mOnEventListener != null) {
- mOnEventListener.onStopped();
- }
- }
-
- protected void postPreviewError(PreviewServer server, Exception e) {
- if (mOnEventListener != null) {
- mOnEventListener.onError(server, e);
- }
- }
-
- /**
- * Notification の Id を取得します.
- *
- * @return Notification の Id
- */
- protected int getNotificationId() {
- return 100 + mRecorder.getId().hashCode();
- }
-
- /**
- * プレビュー配信サーバ停止用の Notification を削除します.
- *
- * @param id notification を識別する ID
- */
- private void hideNotification(String id) {
- NotificationManager manager = (NotificationManager) mContext
+ protected void hideNotification(String id) {
+ NotificationManager manager = (NotificationManager) getContext()
.getSystemService(Service.NOTIFICATION_SERVICE);
if (manager != null) {
manager.cancel(id, getNotificationId());
}
}
- /**
- * プレビュー配信サーバ停止用の Notification を送信します.
- *
- * @param id notification を識別する ID
- * @param name 名前
- */
- private void sendNotification(String id, String name) {
+ @Override
+ protected void sendNotification(String id, String name) {
PendingIntent contentIntent = createPendingIntent(id);
Notification notification = createNotification(contentIntent, null, name);
- NotificationManager manager = (NotificationManager) mContext
+ NotificationManager manager = (NotificationManager) getContext()
.getSystemService(Service.NOTIFICATION_SERVICE);
if (manager != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- String channelId = mContext.getResources().getString(R.string.overlay_preview_channel_id);
+ String channelId = getContext().getResources().getString(R.string.overlay_preview_channel_id);
NotificationChannel channel = new NotificationChannel(
channelId,
- mContext.getResources().getString(R.string.host_notification_recorder_preview),
+ getContext().getResources().getString(R.string.host_notification_recorder_preview),
NotificationManager.IMPORTANCE_LOW);
- channel.setDescription(mContext.getResources().getString(R.string.host_notification_recorder_preview_content));
+ channel.setDescription(getContext().getResources().getString(R.string.host_notification_recorder_preview_content));
manager.createNotificationChannel(channel);
notification = createNotification(contentIntent, channelId, name);
}
@@ -245,6 +78,15 @@ private void sendNotification(String id, String name) {
}
}
+ /**
+ * Notification の Id を取得します.
+ *
+ * @return Notification の Id
+ */
+ protected int getNotificationId() {
+ return 100 + getRecorder().getId().hashCode();
+ }
+
/**
* Notificationを作成する.
*
@@ -255,25 +97,25 @@ private void sendNotification(String id, String name) {
*/
protected Notification createNotification(final PendingIntent pendingIntent, final String channelId, String name) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
- NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext.getApplicationContext());
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext().getApplicationContext());
builder.setContentIntent(pendingIntent);
- builder.setTicker(mContext.getString(R.string.host_notification_recorder_preview_ticker));
+ builder.setTicker(getContext().getString(R.string.host_notification_recorder_preview_ticker));
builder.setSmallIcon(R.drawable.dconnect_icon);
- builder.setContentTitle(mContext.getString(R.string.host_notification_recorder_preview, name));
- builder.setContentText(mContext.getString(R.string.host_notification_recorder_preview_content));
+ builder.setContentTitle(getContext().getString(R.string.host_notification_recorder_preview, name));
+ builder.setContentText(getContext().getString(R.string.host_notification_recorder_preview_content));
builder.setWhen(System.currentTimeMillis());
builder.setAutoCancel(true);
builder.setOngoing(true);
return builder.build();
} else {
- Notification.Builder builder = new Notification.Builder(mContext.getApplicationContext());
+ Notification.Builder builder = new Notification.Builder(getContext().getApplicationContext());
builder.setContentIntent(pendingIntent);
- builder.setTicker(mContext.getString(R.string.overlay_preview_ticker));
+ builder.setTicker(getContext().getString(R.string.overlay_preview_ticker));
int iconType = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ?
R.drawable.dconnect_icon : R.drawable.dconnect_icon_lollipop;
builder.setSmallIcon(iconType);
- builder.setContentTitle(mContext.getString(R.string.host_notification_recorder_preview, name));
- builder.setContentText(mContext.getString(R.string.host_notification_recorder_preview_content));
+ builder.setContentTitle(getContext().getString(R.string.host_notification_recorder_preview, name));
+ builder.setContentText(getContext().getString(R.string.host_notification_recorder_preview_content));
builder.setWhen(System.currentTimeMillis());
builder.setAutoCancel(true);
builder.setOngoing(true);
@@ -295,6 +137,6 @@ private PendingIntent createPendingIntent(String id) {
Intent intent = new Intent();
intent.setAction(HostMediaRecorderManager.ACTION_STOP_PREVIEW);
intent.putExtra(HostMediaRecorderManager.KEY_RECORDER_ID, id);
- return PendingIntent.getBroadcast(mContext, getNotificationId(), intent, 0);
+ return PendingIntent.getBroadcast(getContext(), getNotificationId(), intent, 0);
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractRTMPBroadcaster.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractRTMPBroadcaster.java
index b6d23927db..01f813aeeb 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractRTMPBroadcaster.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractRTMPBroadcaster.java
@@ -2,14 +2,10 @@
import org.deviceconnect.android.libmedia.streaming.MediaEncoderException;
import org.deviceconnect.android.libmedia.streaming.audio.AudioEncoder;
-import org.deviceconnect.android.libmedia.streaming.audio.AudioQuality;
-import org.deviceconnect.android.libmedia.streaming.audio.MicAACLATMEncoder;
import org.deviceconnect.android.libmedia.streaming.rtmp.RtmpClient;
import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
-import org.deviceconnect.android.libmedia.streaming.video.VideoQuality;
public abstract class AbstractRTMPBroadcaster extends AbstractBroadcaster {
-
/**
* RTMP 配信クライアント.
*/
@@ -18,36 +14,19 @@ public abstract class AbstractRTMPBroadcaster extends AbstractBroadcaster {
/**
* イベントを通知するためのリスナー.
*/
- private OnEventListener mOnBroadcasterEventListener;
-
- public AbstractRTMPBroadcaster(HostMediaRecorder recorder, String broadcastURI) {
- super(recorder, broadcastURI);
- }
+ private Broadcaster.OnEventListener mOnBroadcasterEventListener;
- /**
- * RTMP で配信するための映像用エンコーダを取得します.
- *
- * @return RTMP で配信するための映像用エンコーダ
- */
- protected VideoEncoder createVideoEncoder() {
- return null;
+ public AbstractRTMPBroadcaster(HostMediaRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
- /**
- * RTMP で配信するための音声用エンコーダを取得します.
- *
- * @return RTMP で配信するための音声用エンコーダ
- */
- protected AudioEncoder createAudioEncoder() {
- HostMediaRecorder.Settings settings = getRecorder().getSettings();
- if (settings.isAudioEnabled()) {
- return new MicAACLATMEncoder();
- }
- return null;
+ @Override
+ public String getMimeType() {
+ return "video/x-rtmp";
}
@Override
- public void setOnEventListener(OnEventListener listener) {
+ public void setOnEventListener(Broadcaster.OnEventListener listener) {
mOnBroadcasterEventListener = listener;
}
@@ -58,6 +37,12 @@ public boolean isRunning() {
@Override
public void start(OnStartCallback callback) {
+ String broadcastURI = getBroadcastURI();
+ if (broadcastURI == null) {
+ callback.onFailed(new RuntimeException("broadcastURI is not set."));
+ return;
+ }
+
VideoEncoder videoEncoder = createVideoEncoder();
if (videoEncoder != null) {
setVideoQuality(videoEncoder.getVideoQuality());
@@ -68,9 +53,9 @@ public void start(OnStartCallback callback) {
setAudioQuality(audioEncoder.getAudioQuality());
}
- HostMediaRecorder.Settings settings = getRecorder().getSettings();
+ HostMediaRecorder.EncoderSettings settings = getEncoderSettings();
- mRtmpClient = new RtmpClient(getBroadcastURI());
+ mRtmpClient = new RtmpClient(broadcastURI);
mRtmpClient.setMaxRetryCount(settings.getRetryCount());
mRtmpClient.setRetryInterval(settings.getRetryInterval());
mRtmpClient.setVideoEncoder(videoEncoder);
@@ -132,44 +117,25 @@ public void stop() {
@Override
public void setMute(boolean mute) {
+ super.setMute(mute);
+
if (mRtmpClient != null) {
mRtmpClient.setMute(mute);
}
}
@Override
- public boolean isMute() {
+ public boolean isMuted() {
return mRtmpClient != null && mRtmpClient.isMute();
}
@Override
- public void onConfigChange() {
- super.onConfigChange();
-
- if (mRtmpClient != null) {
- mRtmpClient.restartVideoEncoder();
- }
- }
-
- @Override
- protected VideoQuality getVideoQuality() {
- if (mRtmpClient != null) {
- VideoEncoder videoEncoder = mRtmpClient.getVideoEncoder();
- if (videoEncoder != null) {
- return videoEncoder.getVideoQuality();
- }
- }
- return null;
+ protected VideoEncoder getVideoEncoder() {
+ return mRtmpClient != null ? mRtmpClient.getVideoEncoder() : null;
}
@Override
- protected AudioQuality getAudioQuality() {
- if (mRtmpClient != null) {
- AudioEncoder audioEncoder = mRtmpClient.getAudioEncoder();
- if (audioEncoder != null) {
- return audioEncoder.getAudioQuality();
- }
- }
- return null;
+ protected AudioEncoder getAudioEncoder() {
+ return mRtmpClient != null ? mRtmpClient.getAudioEncoder() : null;
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractRTSPPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractRTSPPreviewServer.java
index 25c98723aa..bc9c1a9d70 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractRTSPPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractRTSPPreviewServer.java
@@ -1,19 +1,16 @@
package org.deviceconnect.android.deviceplugin.host.recorder;
-import android.content.Context;
import android.util.Log;
import org.deviceconnect.android.libmedia.streaming.audio.AudioEncoder;
-import org.deviceconnect.android.libmedia.streaming.audio.AudioQuality;
import org.deviceconnect.android.libmedia.streaming.rtsp.RtspServer;
import org.deviceconnect.android.libmedia.streaming.rtsp.session.RtspSession;
import org.deviceconnect.android.libmedia.streaming.rtsp.session.audio.AudioStream;
import org.deviceconnect.android.libmedia.streaming.rtsp.session.audio.MicAACLATMStream;
import org.deviceconnect.android.libmedia.streaming.rtsp.session.video.VideoStream;
-import org.deviceconnect.android.libmedia.streaming.video.VideoQuality;
+import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
public abstract class AbstractRTSPPreviewServer extends AbstractPreviewServer {
-
/**
* マイムタイプを定義します.
*/
@@ -29,17 +26,14 @@ public abstract class AbstractRTSPPreviewServer extends AbstractPreviewServer {
*/
private RtspServer mRtspServer;
- public AbstractRTSPPreviewServer(Context context, HostMediaRecorder recorder) {
- this(context, recorder, false);
- }
- public AbstractRTSPPreviewServer(Context context, HostMediaRecorder recorder, boolean useSSL) {
- super(context, recorder, useSSL);
+ public AbstractRTSPPreviewServer(HostMediaRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
@Override
public String getUri() {
- return "rtsp://localhost:" + getPort();
+ return "rtsp://localhost:" + getEncoderSettings().getPort();
}
@Override
@@ -48,57 +42,40 @@ public String getMimeType() {
}
@Override
- public void startWebServer(final OnWebServerStartCallback callback) {
+ public boolean isRunning() {
+ return mRtspServer != null;
+ }
+
+ @Override
+ public void start(final OnStartCallback callback) {
if (mRtspServer == null) {
mRtspServer = new RtspServer();
mRtspServer.setServerName(SERVER_NAME);
- mRtspServer.setServerPort(getPort());
+ mRtspServer.setServerPort(getEncoderSettings().getPort());
mRtspServer.setCallback(mCallback);
try {
mRtspServer.start();
} catch (Exception e) {
- callback.onFail();
+ callback.onFailed(e);
return;
}
}
- callback.onStart(getUri());
+ callback.onSuccess();
}
@Override
- public void stopWebServer() {
+ public void stop() {
if (mRtspServer != null) {
mRtspServer.stop();
mRtspServer = null;
}
}
- @Override
- public boolean requestSyncFrame() {
- RtspServer server = mRtspServer;
- if (server != null) {
- RtspSession session = server.getRtspSession();
- if (session != null) {
- VideoStream videoStream = session.getVideoStream();
- if (videoStream != null) {
- videoStream.getVideoEncoder().requestSyncKeyFrame();
- return true;
- }
- }
- }
- return false;
- }
-
@Override
public long getBPS() {
return mRtspServer != null ? mRtspServer.getBPS() : 0;
}
- @Override
- public void onConfigChange() {
- super.onConfigChange();
- restartVideoStream();
- }
-
@Override
public void setMute(boolean mute) {
super.setMute(mute);
@@ -115,13 +92,13 @@ public void setMute(boolean mute) {
}
@Override
- protected VideoQuality getVideoQuality() {
+ protected VideoEncoder getVideoEncoder() {
if (mRtspServer != null) {
RtspSession session = mRtspServer.getRtspSession();
if (session != null) {
- VideoStream videoStream = session.getVideoStream();
- if (videoStream != null) {
- return videoStream.getVideoEncoder().getVideoQuality();
+ VideoStream stream = session.getVideoStream();
+ if (stream != null) {
+ return stream.getVideoEncoder();
}
}
}
@@ -129,13 +106,13 @@ protected VideoQuality getVideoQuality() {
}
@Override
- protected AudioQuality getAudioQuality() {
+ protected AudioEncoder getAudioEncoder() {
if (mRtspServer != null) {
RtspSession session = mRtspServer.getRtspSession();
if (session != null) {
- AudioStream audioStream = session.getAudioStream();
- if (audioStream != null) {
- return audioStream.getAudioEncoder().getAudioQuality();
+ AudioStream stream = session.getAudioStream();
+ if (stream != null) {
+ return stream.getAudioEncoder();
}
}
}
@@ -183,7 +160,6 @@ protected VideoStream createVideoStream() {
protected AudioStream createAudioStream() {
HostMediaRecorder recorder = getRecorder();
HostMediaRecorder.Settings settings = recorder.getSettings();
-
if (settings.isAudioEnabled()) {
return new MicAACLATMStream(5004);
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractSRTBroadcaster.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractSRTBroadcaster.java
index 66df06d39f..2e9b992e41 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractSRTBroadcaster.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractSRTBroadcaster.java
@@ -2,14 +2,10 @@
import org.deviceconnect.android.libmedia.streaming.MediaEncoderException;
import org.deviceconnect.android.libmedia.streaming.audio.AudioEncoder;
-import org.deviceconnect.android.libmedia.streaming.audio.AudioQuality;
-import org.deviceconnect.android.libmedia.streaming.audio.MicAACLATMEncoder;
import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
-import org.deviceconnect.android.libmedia.streaming.video.VideoQuality;
import org.deviceconnect.android.libsrt.broadcast.SRTClient;
public abstract class AbstractSRTBroadcaster extends AbstractBroadcaster {
-
/**
* RTMP 配信クライアント.
*/
@@ -18,36 +14,19 @@ public abstract class AbstractSRTBroadcaster extends AbstractBroadcaster {
/**
* イベントを通知するためのリスナー.
*/
- private OnEventListener mOnBroadcasterEventListener;
-
- public AbstractSRTBroadcaster(HostMediaRecorder recorder, String broadcastURI) {
- super(recorder, broadcastURI);
- }
+ private Broadcaster.OnEventListener mOnBroadcasterEventListener;
- /**
- * SRT 配信に使用する VideoEncoder のインスタンスを作成します.
- *
- * @return SRT 配信に使用する VideoEncoder
- */
- protected VideoEncoder createVideoEncoder() {
- return null;
+ public AbstractSRTBroadcaster(HostMediaRecorder recorder, String id) {
+ super(recorder, id);
}
- /**
- * SRT 配信に使用する AudioEncoder のインスタンスを作成します.
- *
- * @return SRT 配信に使用する AudioEncoder
- */
- protected AudioEncoder createAudioEncoder() {
- HostMediaRecorder.Settings settings = getRecorder().getSettings();
- if (settings.isAudioEnabled()) {
- return new MicAACLATMEncoder();
- }
- return null;
+ @Override
+ public String getMimeType() {
+ return "video/MP2T";
}
@Override
- public void setOnEventListener(OnEventListener listener) {
+ public void setOnEventListener(Broadcaster.OnEventListener listener) {
mOnBroadcasterEventListener = listener;
}
@@ -58,6 +37,12 @@ public boolean isRunning() {
@Override
public void start(OnStartCallback callback) {
+ String broadcastURI = getBroadcastURI();
+ if (broadcastURI == null) {
+ callback.onFailed(new RuntimeException("broadcastURI is not set."));
+ return;
+ }
+
VideoEncoder videoEncoder = createVideoEncoder();
if (videoEncoder != null) {
setVideoQuality(videoEncoder.getVideoQuality());
@@ -68,7 +53,7 @@ public void start(OnStartCallback callback) {
setAudioQuality(audioEncoder.getAudioQuality());
}
- HostMediaRecorder.Settings settings = getRecorder().getSettings();
+ HostMediaRecorder.EncoderSettings settings = getEncoderSettings();
mSrtClient = new SRTClient(getBroadcastURI());
mSrtClient.setMaxRetryCount(settings.getRetryCount());
@@ -132,44 +117,25 @@ public void stop() {
@Override
public void setMute(boolean mute) {
+ super.setMute(mute);
+
if (mSrtClient != null) {
mSrtClient.setMute(mute);
}
}
@Override
- public boolean isMute() {
+ public boolean isMuted() {
return mSrtClient != null && mSrtClient.isMute();
}
@Override
- public void onConfigChange() {
- super.onConfigChange();
-
- if (mSrtClient != null) {
- mSrtClient.restartVideoEncoder();
- }
- }
-
- @Override
- protected VideoQuality getVideoQuality() {
- if (mSrtClient != null) {
- VideoEncoder videoEncoder = mSrtClient.getVideoEncoder();
- if (videoEncoder != null) {
- return videoEncoder.getVideoQuality();
- }
- }
- return null;
+ protected VideoEncoder getVideoEncoder() {
+ return mSrtClient != null ? mSrtClient.getVideoEncoder() : null;
}
@Override
- protected AudioQuality getAudioQuality() {
- if (mSrtClient != null) {
- AudioEncoder audioEncoder = mSrtClient.getAudioEncoder();
- if (audioEncoder != null) {
- return audioEncoder.getAudioQuality();
- }
- }
- return null;
+ protected AudioEncoder getAudioEncoder() {
+ return mSrtClient != null ? mSrtClient.getAudioEncoder() : null;
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractSRTPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractSRTPreviewServer.java
index 9aeea91a44..ac726f1615 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractSRTPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/AbstractSRTPreviewServer.java
@@ -1,15 +1,11 @@
package org.deviceconnect.android.deviceplugin.host.recorder;
-import android.content.Context;
import android.util.Log;
import org.deviceconnect.android.deviceplugin.host.BuildConfig;
-import org.deviceconnect.android.deviceplugin.host.recorder.util.SRTSettings;
import org.deviceconnect.android.libmedia.streaming.audio.AudioEncoder;
-import org.deviceconnect.android.libmedia.streaming.audio.AudioQuality;
import org.deviceconnect.android.libmedia.streaming.audio.MicAACLATMEncoder;
import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
-import org.deviceconnect.android.libmedia.streaming.video.VideoQuality;
import org.deviceconnect.android.libsrt.server.SRTServer;
import org.deviceconnect.android.libsrt.server.SRTSession;
@@ -22,29 +18,18 @@ public abstract class AbstractSRTPreviewServer extends AbstractPreviewServer {
*/
private static final String MIME_TYPE = "video/MP2T";
- /**
- * SRTの設定.
- */
- private final SRTSettings mSettings;
-
/**
* SRT サーバ.
*/
private SRTServer mSRTServer;
- public AbstractSRTPreviewServer(Context context, HostMediaRecorder recorder) {
- this(context, recorder, false);
- }
-
- public AbstractSRTPreviewServer(Context context, HostMediaRecorder recorder, boolean useSSL) {
- super(context, recorder, useSSL);
- mSettings = new SRTSettings(context);
+ public AbstractSRTPreviewServer(HostMediaRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
-
@Override
public String getUri() {
- return "srt://localhost:" + getPort();
+ return "srt://localhost:" + getEncoderSettings().getPort();
}
@Override
@@ -53,59 +38,43 @@ public String getMimeType() {
}
@Override
- public void startWebServer(final OnWebServerStartCallback callback) {
+ public boolean isRunning() {
+ return mSRTServer != null;
+ }
+
+ @Override
+ public void start(final OnStartCallback callback) {
if (mSRTServer == null) {
try {
- mSRTServer = new SRTServer(getPort());
+ HostMediaRecorder.EncoderSettings settings = getEncoderSettings();
+ mSRTServer = new SRTServer(getEncoderSettings().getPort());
mSRTServer.setStatsInterval(BuildConfig.STATS_INTERVAL);
mSRTServer.setShowStats(DEBUG);
mSRTServer.setCallback(mCallback);
- mSRTServer.setSocketOptions(mSettings.loadSRTSocketOptions());
+ mSRTServer.setSocketOptions(settings.getSRTSocketOptions());
mSRTServer.start();
} catch (Exception e) {
- callback.onFail();
+ callback.onFailed(e);
return;
}
}
- callback.onStart(getUri());
+ callback.onSuccess();
}
@Override
- public void stopWebServer() {
+ public void stop() {
if (mSRTServer != null) {
mSRTServer.stop();
mSRTServer = null;
}
}
- @Override
- public boolean requestSyncFrame() {
- SRTServer server = mSRTServer;
- if (server != null) {
- SRTSession session = server.getSRTSession();
- if (session != null) {
- VideoEncoder videoEncoder = session.getVideoEncoder();
- if (videoEncoder != null) {
- videoEncoder.requestSyncKeyFrame();
- return true;
- }
- }
- }
- return false;
- }
-
@Override
public long getBPS() {
// TODO
return 0;
}
- @Override
- public void onConfigChange() {
- super.onConfigChange();
- restartVideoEncoder();
- }
-
@Override
public void setMute(boolean mute) {
super.setMute(mute);
@@ -122,28 +91,22 @@ public void setMute(boolean mute) {
}
@Override
- protected VideoQuality getVideoQuality() {
+ protected VideoEncoder getVideoEncoder() {
if (mSRTServer != null) {
SRTSession session = mSRTServer.getSRTSession();
if (session != null) {
- VideoEncoder videoEncoder = session.getVideoEncoder();
- if (videoEncoder != null) {
- return videoEncoder.getVideoQuality();
- }
+ return session.getVideoEncoder();
}
}
return null;
}
@Override
- protected AudioQuality getAudioQuality() {
+ protected AudioEncoder getAudioEncoder() {
if (mSRTServer != null) {
SRTSession session = mSRTServer.getSRTSession();
if (session != null) {
- AudioEncoder audioEncoder = session.getAudioEncoder();
- if (audioEncoder != null) {
- return audioEncoder.getAudioQuality();
- }
+ return session.getAudioEncoder();
}
}
return null;
@@ -176,12 +139,26 @@ private void restartAudioEncoder() {
/**
* SRT 用の映像エンコーダを作成します.
*
+ * null を返却した場合には、映像は配信しません。
+ *
+ * このメソッドを実装することでエンコーダを切り替えます。
+ *
* @return SRT 用の映像エンコーダ
*/
protected VideoEncoder createVideoEncoder() {
return null;
}
+ /**
+ * SRT 用の音声エンコーダを作成します.
+ *
+ * null を返却した場合には、音声は配信しません。
+ *
+ * デフォルトで、 aac のエンコーダを作成して返却します。
+ * aac 以外のエンコーダを実装する場合には、このメソッドをオーバーライドします。
+ *
+ * @return SRT 用の音声エンコーダ
+ */
protected AudioEncoder createAudioEncoder() {
HostMediaRecorder recorder = getRecorder();
HostMediaRecorder.Settings settings = recorder.getSettings();
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/Broadcaster.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/Broadcaster.java
index b9a6fdf8ae..08aae3a90d 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/Broadcaster.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/Broadcaster.java
@@ -1,100 +1,10 @@
package org.deviceconnect.android.deviceplugin.host.recorder;
-public interface Broadcaster {
- /**
- * マイムタイプを取得します.
- *
- * @return マイムタイプ
- */
- String getMimeType();
-
+public interface Broadcaster extends LiveStreaming {
/**
* ブロードキャスト先の URI を取得します.
*
* @return ブロードキャスト先の URI
*/
String getBroadcastURI();
-
- /**
- * ブロードキャストのイベントを通知するリスナーを設定します.
- *
- * @param listener リスナー
- */
- void setOnEventListener(OnEventListener listener);
-
- /**
- * ブロードキャスト中か確認します.
- *
- * @return ブロードキャスト中の場合は true、それ以外は false
- */
- boolean isRunning();
-
- /**
- * ブロードキャストを開始します.
- */
- void start(OnStartCallback callback);
-
- /**
- * ブロードキャストを停止します.
- */
- void stop();
-
- /**
- * ミュート設定を行います.
- *
- * @param mute ミュートにする場合にはtrue、それ以外はfalse
- */
- void setMute(boolean mute);
-
- /**
- * ミュート設定を取得します.
- *
- * @return ミュートの場合はtrue、それ以外はfalse
- */
- boolean isMute();
-
- /**
- * 設定が変更されたことを通知します.
- */
- void onConfigChange();
-
- /**
- * ブロードキャストの開始結果を通知するコールバック.
- */
- interface OnStartCallback {
- /**
- * ブロードキャストに成功したことを通知します.
- */
- void onSuccess();
-
- /**
- * ブロードキャストに失敗したことを通知します.
- *
- * @param e 失敗原因の例外
- */
- void onFailed(Exception e);
- }
-
- /**
- * ブロードキャストのイベントを通知するリスナー.
- */
- interface OnEventListener {
-
- /**
- * ブロードキャストが開始されたことを通知します.
- */
- void onStarted();
-
- /**
- * ブロードキャストが停止されたことを通知します.
- */
- void onStopped();
-
- /**
- * ブロードキャストでエラーが発生したことを通知します.
- *
- * @param e エラー原因の例外
- */
- void onError(Exception e);
- }
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/BroadcasterProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/BroadcasterProvider.java
index 675653085e..a409614bdf 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/BroadcasterProvider.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/BroadcasterProvider.java
@@ -1,73 +1,5 @@
package org.deviceconnect.android.deviceplugin.host.recorder;
-public interface BroadcasterProvider {
- /**
- * ブロードキャスターのリストを取得します.
- *
- * @return ブロードキャスターのリスト
- */
- Broadcaster getBroadcaster();
+public interface BroadcasterProvider extends LiveStreamingProvider {
- /**
- * ブロードキャスト中か確認します.
- *
- * @return ブロードキャスト中は true、それ以外は false
- */
- boolean isRunning();
-
- /**
- * ブロードキャスターを開始します.
- *
- * @param broadcastURI 配信先の URI
- */
- Broadcaster startBroadcaster(String broadcastURI);
-
- /**
- * ブロードキャスターを停止します.
- */
- void stopBroadcaster();
-
- /**
- * 設定が変更されたことを通知します.
- */
- void onConfigChange();
-
- /**
- * Recorder をミュート状態にする.
- */
- void setMute(boolean mute);
-
- /**
- * BroadcasterProvider で発生したイベントを通知するリスナーを設定します.
- *
- * @param listener リスナー
- */
- void setOnEventListener(OnEventListener listener);
-
- /**
- * イベントを通知するリスナー.
- */
- interface OnEventListener {
- /**
- * Broadcaster が開始されたことを通知します.
- *
- * @param broadcaster 開始した Broadcaster
- */
- void onStarted(Broadcaster broadcaster);
-
- /**
- * Broadcaster が停止されたことを通知します.
- *
- * @param broadcaster 停止した Broadcaster
- */
- void onStopped(Broadcaster broadcaster);
-
- /**
- * Broadcaster でエラーが発生したことを通知します.
- *
- * @param broadcaster エラーが発生した Broadcaster
- * @param e エラー原因の例外
- */
- void onError(Broadcaster broadcaster, Exception e);
- }
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/CropInterface.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/CropInterface.java
new file mode 100644
index 0000000000..4ca92972d1
--- /dev/null
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/CropInterface.java
@@ -0,0 +1,67 @@
+package org.deviceconnect.android.deviceplugin.host.recorder;
+
+import android.graphics.Rect;
+
+public interface CropInterface {
+
+ /**
+ * PreviewSurfaceView で枠を表示する時に表示する名前を取得します.
+ *
+ * @return 名前
+ */
+ String getName();
+
+ /**
+ * start で指定された矩形から end で指定された矩形に移動します.
+ *
+ * @param start 開始する矩形
+ * @param end 停止する矩形
+ * @param duration 移動する時間(ミリ秒)
+ */
+ void moveCropRect(Rect start, Rect end, int duration);
+
+ /**
+ * クロップ範囲を設定します.
+ *
+ * @param rect クロップする範囲の矩形
+ */
+ void setCropRect(Rect rect);
+
+ /**
+ * クロップ範囲を取得します.
+ *
+ * @return クロップする範囲の矩形
+ */
+ Rect getCropRect();
+
+ /**
+ * イベントリスナーを追加します.
+ *
+ * @param listener 追加するリスナー
+ */
+ void addOnEventListener(OnEventListener listener);
+
+ /**
+ * イベントリスナーを削除します.
+ *
+ * @param listener 削除するリスナー
+ */
+ void removeOnEventListener(OnEventListener listener);
+
+ interface OnEventListener {
+ /**
+ * クロップする矩形が追加されたことを通知します.
+ */
+ void onAdded(CropInterface crop, Rect cropRect);
+
+ /**
+ * クロップする矩形が削除されたことを通知します.
+ */
+ void onRemoved(CropInterface crop);
+
+ /**
+ * クロップする矩形が移動したことを通知します.
+ */
+ void onMoved(CropInterface crop, Rect cropRect);
+ }
+}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/HostMediaRecorder.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/HostMediaRecorder.java
index e537887342..28ccf450da 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/HostMediaRecorder.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/HostMediaRecorder.java
@@ -12,14 +12,19 @@
import android.util.Range;
import android.util.Size;
+import org.deviceconnect.android.deviceplugin.host.R;
import org.deviceconnect.android.deviceplugin.host.recorder.util.CapabilityUtil;
import org.deviceconnect.android.deviceplugin.host.recorder.util.MediaProjectionProvider;
import org.deviceconnect.android.deviceplugin.host.recorder.util.PropertyUtil;
import org.deviceconnect.android.libmedia.streaming.gles.EGLSurfaceDrawingThread;
+import org.deviceconnect.android.libsrt.SRT;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import javax.net.ssl.SSLContext;
@@ -123,7 +128,7 @@ public interface HostMediaRecorder extends HostDevicePhotoRecorder, HostDeviceSt
*
* @return 開始したプレビュー配信サーバのリスト
*/
- List startPreview();
+ List startPreview();
/**
* プレビュー配信サーバを停止します.
@@ -143,7 +148,7 @@ public interface HostMediaRecorder extends HostDevicePhotoRecorder, HostDeviceSt
* @param broadcastURI ブロードキャスト先のURI
* @return ブロードキャストしているクラス
*/
- Broadcaster startBroadcaster(String broadcastURI);
+ List startBroadcaster(String broadcastURI);
/**
* ブロードキャストを停止します.
@@ -183,6 +188,16 @@ public interface HostMediaRecorder extends HostDevicePhotoRecorder, HostDeviceSt
*/
void requestKeyFrame();
+ /**
+ * ビットレートの更新を要求します.
+ */
+ void requestBitRate();
+
+ /**
+ * JPEG 品質の更新を要求します.
+ */
+ void requestJpegQuality();
+
/**
* ミュート設定を行います.
*
@@ -240,10 +255,38 @@ interface PermissionCallback {
void onDisallowed();
}
+ enum MimeType {
+ MJPEG("video/x-mjpeg"),
+ RTSP("video/x-rtp"),
+ SRT("video/MP2T"),
+ RTMP("video/x-rtmp"),
+ UNKNOWN("");
+
+ private final String mValue;
+
+ MimeType(String value) {
+ mValue = value;
+ }
+
+ public String getValue() {
+ return mValue;
+ }
+
+ public static MimeType typeOf(String mimeType) {
+ for (MimeType type : values()) {
+ if (type.mValue.equalsIgnoreCase(mimeType)) {
+ return type;
+ }
+ }
+ return UNKNOWN;
+ }
+ }
+
enum AudioSource {
DEFAULT("default"),
MIC("mic"),
- APP("app");
+ APP("app"),
+ NONE("none");
private final String mSource;
@@ -261,18 +304,18 @@ public static AudioSource typeOf(String source) {
return audioSource;
}
}
- return null;
+ return NONE;
}
}
- enum VideoEncoderName {
+ enum VideoCodec {
H264("h264", "video/avc"),
H265("h265", "video/hevc");
private final String mName;
private final String mMimeType;
- VideoEncoderName(String name, String mimeType) {
+ VideoCodec(String name, String mimeType) {
mName = name;
mMimeType = mimeType;
}
@@ -285,8 +328,8 @@ public String getMimeType() {
return mMimeType;
}
- public static VideoEncoderName nameOf(String name) {
- for (VideoEncoderName encoder : values()) {
+ public static VideoCodec nameOf(String name) {
+ for (VideoCodec encoder : values()) {
if (encoder.getName().equalsIgnoreCase(name)) {
return encoder;
}
@@ -335,6 +378,20 @@ public int getProfile() {
public int getLevel() {
return mLevel;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ProfileLevel that = (ProfileLevel) o;
+ return mProfile == that.mProfile &&
+ mLevel == that.mLevel;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mProfile, mLevel);
+ }
}
enum AudioFilter {
@@ -412,7 +469,7 @@ interface OnEventListener extends HostDeviceStreamRecorder.OnEventListener, Host
*
* @param servers 開始したプレビュー配信サーバ
*/
- void onPreviewStarted(List servers);
+ void onPreviewStarted(List servers);
/**
* プレビュー配信を停止した時に呼び出されます.
@@ -429,16 +486,14 @@ interface OnEventListener extends HostDeviceStreamRecorder.OnEventListener, Host
/**
* ブロードキャストを開始した時に呼び出されます.
*
- * @param broadcaster 開始したブロードキャスト
+ * @param broadcasters 開始したブロードキャスト
*/
- void onBroadcasterStarted(Broadcaster broadcaster);
+ void onBroadcasterStarted(List broadcasters);
/**
* ブロードキャストを停止した時に呼び出されます.
- *
- * @param broadcaster 停止したブロードキャスト
*/
- void onBroadcasterStopped(Broadcaster broadcaster);
+ void onBroadcasterStopped();
/**
* ブロードキャストでエラーが発生したときに呼び出されます.
@@ -446,7 +501,7 @@ interface OnEventListener extends HostDeviceStreamRecorder.OnEventListener, Host
* @param broadcaster エラーが発生した Broadcaster
* @param e エラー原因の例外
*/
- void onBroadcasterError(Broadcaster broadcaster, Exception e);
+ void onBroadcasterError(LiveStreaming broadcaster, Exception e);
/**
* レコーダで発生したエラーを通知します.
@@ -456,68 +511,120 @@ interface OnEventListener extends HostDeviceStreamRecorder.OnEventListener, Host
void onError(Exception e);
}
- /**
- * HostMediaRecorder の設定を保持するクラス.
- */
- abstract class Settings {
- private final PropertyUtil mPref;
+ class EncoderSettings {
+ private static final int DEFAULT_PREVIEW_MAX_FRAME_RATE = 30;
+ private static final int DEFAULT_PREVIEW_BITRATE = 2 * 1024 * 1024;
+ private static final String DEFAULT_PREVIEW_ENCODER = VideoCodec.H264.mName;
+ private static final int DEFAULT_PREVIEW_KEY_FRAME_INTERVAL = 1;
- public Settings(Context context, HostMediaRecorder recorder) {
- mPref = new PropertyUtil(context, recorder.getId().replaceAll("/", "_"));
+ private final PropertyUtil mProperty;
+ private final Context mContext;
+
+ public EncoderSettings(Context context, String name) {
+ mContext = context;
+ mProperty = new PropertyUtil(context, name);
}
/**
- * 初期化されているか確認します.
+ * データを削除します.
+ */
+ public void clear() {
+ mProperty.clear();
+ }
+
+ /**
+ * 名前を取得します.
*
- * @return 初期化されている場合はtrue、それ以外はfalse
+ * @return 名前
*/
- public boolean isInitialized() {
- return mPref.getString("test", null) != null;
+ public String getName() {
+ return mProperty.getString("name", null);
}
/**
- * 初期化完了を書き込みます.
+ * 名前を設定します.
+ *
+ * @param name 名前
*/
- public void finishInitialization() {
- mPref.put("test", "test");
+ public void setName(String name) {
+ mProperty.put("name", name);
}
/**
- * 保存データを初期化します.
+ * マイムタイプを取得します.
+ *
+ * @return マイムタイプ
*/
- public void clear() {
- mPref.clear();
+ public MimeType getMimeType() {
+ return MimeType.typeOf(mProperty.getString("mime_type", null));
}
/**
- * 自動フォーカスモードを取得します.
+ * マイムタイプを設定します.
*
- * 未設定の場合は null を返却します。
+ * @param mimeType マイムタイプ
+ */
+ public void setMimeType(MimeType mimeType) {
+ if (mimeType == null) {
+ throw new IllegalArgumentException("mimeType is null.");
+ }
+ mProperty.put("mime_type", mimeType.getValue());
+ }
+
+ /**
+ * サーバ用のポート番号を取得します.
*
- * @return 自動フォーカスモード
+ * @return サーバ用のポート番号
*/
- public Integer getPreviewAutoFocusMode() {
- return mPref.getInteger("preview_auto_focus", null);
+ public Integer getPort() {
+ return mProperty.getInteger("port", 0);
}
/**
- * 自動フォーカスモードを設定します.
+ * サーバ用のポート番号を設定します.
*
- * mode が設定された場合には、未設定にします。
+ * @param port サーバ用のポート番号
+ */
+ public void setPort(int port) {
+ mProperty.put("port", port);
+ }
+
+ /**
+ * SSL を使用するか確認します.
*
- * サポートされていないモードが設定された場合には例外が発生します。
+ * @return SSL を使用する場合はtrue、それ以外はfalse
+ */
+ public boolean isUseSSL() {
+ return mProperty.getBoolean("use_ssl", false);
+ }
+
+ /**
+ * SSL 使用フラグを設定します.
*
- * @param mode 自動フォーカスモード
+ * @param useSSL SSL 使用フラグ
*/
- public void setPreviewAutoFocusMode(Integer mode) {
- if (mode == null) {
- mPref.remove("preview_auto_focus");
- } else {
- if (!isSupportedAutoFocusMode(mode)) {
- throw new IllegalArgumentException("focus mode is not supported.");
- }
- mPref.put("preview_auto_focus", mode);
- }
+ public void setUseSSL(boolean useSSL) {
+ mProperty.put("use_ssl", useSSL);
+ }
+
+ //// MediaCodec
+
+ /**
+ * プレビューサイズを取得します.
+ *
+ * @return プレビューサイズ
+ */
+ public Size getPreviewSize() {
+ return mProperty.getSize("preview_size_width", "preview_size_height");
+ }
+
+ /**
+ * プレビューサイズを設定します.
+ *
+ * @param previewSize プレビューサイズ
+ */
+ public void setPreviewSize(Size previewSize) {
+ mProperty.put("preview_size_width", "preview_size_height", previewSize);
}
/**
@@ -525,8 +632,8 @@ public void setPreviewAutoFocusMode(Integer mode) {
*
* @return エンコード名
*/
- public VideoEncoderName getPreviewEncoderName() {
- return VideoEncoderName.nameOf(getPreviewEncoder());
+ public VideoCodec getPreviewEncoderName() {
+ return VideoCodec.nameOf(getPreviewEncoder());
}
/**
@@ -537,7 +644,7 @@ public VideoEncoderName getPreviewEncoderName() {
* @return プレビューの配信エンコードの名前
*/
public String getPreviewEncoder() {
- return mPref.getString("preview_encoder", "h264");
+ return mProperty.getString("preview_encoder", DEFAULT_PREVIEW_ENCODER);
}
/**
@@ -547,12 +654,12 @@ public String getPreviewEncoder() {
*/
public void setPreviewEncoder(String encoder) {
if (encoder == null) {
- mPref.remove("preview_encoder");
+ mProperty.remove("preview_encoder");
} else {
if (!isSupportedVideoEncoder(encoder)) {
throw new IllegalArgumentException("encoder is not supported.");
}
- mPref.put("preview_encoder", encoder);
+ mProperty.put("preview_encoder", encoder);
}
}
@@ -564,8 +671,8 @@ public void setPreviewEncoder(String encoder) {
* @return プロファイルとレベル
*/
public ProfileLevel getProfileLevel() {
- Integer profile = mPref.getInteger("preview_profile", null);
- Integer level = mPref.getInteger("preview_level", null);
+ Integer profile = mProperty.getInteger("preview_profile", null);
+ Integer level = mProperty.getInteger("preview_level", null);
if (profile != null && level != null) {
return new ProfileLevel(profile, level);
}
@@ -575,7 +682,7 @@ public ProfileLevel getProfileLevel() {
/**
* プロファイルとレベルを設定します.
*
- * null が設定された場合には、未設定にします。
+ * null が設定された場合には、値を削除して未設定にします。
*
* サポートされていないプロファイルとレベルが設定された場合には例外を発生します。
*
@@ -583,14 +690,14 @@ public ProfileLevel getProfileLevel() {
*/
public void setProfileLevel(ProfileLevel pl) {
if (pl == null) {
- mPref.remove("preview_profile");
- mPref.remove("preview_level");
+ mProperty.remove("preview_profile");
+ mProperty.remove("preview_level");
} else {
if (!isSupportedProfileLevel(pl.getProfile(), pl.getLevel())) {
throw new IllegalArgumentException("profile and level are not supported.");
}
- mPref.put("preview_profile", pl.getProfile());
- mPref.put("preview_level", pl.getLevel());
+ mProperty.put("preview_profile", pl.getProfile());
+ mProperty.put("preview_level", pl.getLevel());
}
}
@@ -600,7 +707,7 @@ public void setProfileLevel(ProfileLevel pl) {
* @return プロファイル
*/
public Integer getProfile() {
- return mPref.getInteger("preview_profile", 0);
+ return mProperty.getInteger("preview_profile", 0);
}
/**
@@ -609,119 +716,169 @@ public Integer getProfile() {
* @return レベル
*/
public Integer getLevel() {
- return mPref.getInteger("preview_level", 0);
+ return mProperty.getInteger("preview_level", 0);
}
/**
- * 写真サイズを取得します.
+ * フレームレートを取得します.
*
- * @return 写真サイズ
+ * @return フレームレート
*/
- public Size getPictureSize() {
- return mPref.getSize("picture_size_width", "picture_size_height");
+ public int getPreviewMaxFrameRate() {
+ return mProperty.getInteger("preview_framerate", DEFAULT_PREVIEW_MAX_FRAME_RATE);
}
/**
- * 写真サイズを設定します.
- *
- * サポートされていない写真サイズの場合は IllegalArgumentException を発生させます。
+ * フレームレートを設定します.
*
- * @param pictureSize 写真サイズ
+ * @param previewMaxFrameRate フレームレート
*/
- public void setPictureSize(Size pictureSize) {
- if (!isSupportedPictureSize(pictureSize)) {
- throw new IllegalArgumentException("pictureSize is not supported.");
+ public void setPreviewMaxFrameRate(Integer previewMaxFrameRate) {
+ if (previewMaxFrameRate <= 0) {
+ throw new IllegalArgumentException("previewMaxFrameRate is zero or negative.");
}
- mPref.put(
- "picture_size_width",
- "picture_size_height",
- pictureSize);
+ mProperty.put("preview_framerate", previewMaxFrameRate);
}
/**
- * プレビューサイズを取得します.
+ * ビットレートを取得します.
*
- * @return プレビューサイズ
+ * @return ビットレート(byte)
*/
- public Size getPreviewSize() {
- return mPref.getSize("preview_size_width", "preview_size_height");
+ public int getPreviewBitRate() {
+ return mProperty.getInteger("preview_bitrate", DEFAULT_PREVIEW_BITRATE);
}
/**
- * プレビューサイズを設定します.
+ * ビットレートを設定します.
*
- * サポートされていないプレビューサイズの場合は IllegalArgumentException を発生させます。
+ * @param previewBitRate ビットレート(byte)
+ */
+ public void setPreviewBitRate(int previewBitRate) {
+ if (previewBitRate <= 0) {
+ throw new IllegalArgumentException("previewBitRate is zero or negative.");
+ }
+ mProperty.put("preview_bitrate", String.valueOf(previewBitRate));
+ }
+
+ /**
+ * ビットレートモードを取得します.
*
- * @param previewSize プレビューサイズ
+ * @return ビットレートモード
*/
- public void setPreviewSize(Size previewSize) {
- if (!isSupportedPreviewSize(previewSize)) {
- throw new IllegalArgumentException("previewSize is not supported.");
+ public BitRateMode getPreviewBitRateMode() {
+ return BitRateMode.nameOf(mProperty.getString("preview_bitrate_mode", null));
+ }
+
+ /**
+ * ビットレートモードを設定します.
+ *
+ * @param mode ビットレートモード
+ */
+ public void setPreviewBitRateMode(BitRateMode mode) {
+ if (mode == null) {
+ mProperty.remove("preview_bitrate_mode");
+ } else {
+ mProperty.put("preview_bitrate_mode", mode.getName());
}
- mPref.put("preview_size_width", "preview_size_height", previewSize);
}
/**
- * フレームレートを取得します.
+ * キーフレームインターバルを取得します.
*
- * @return フレームレート
+ * @return キーフレームを発行する間隔(ミリ秒)
*/
- public int getPreviewMaxFrameRate() {
- return mPref.getInteger("preview_framerate", 30);
+ public int getPreviewKeyFrameInterval() {
+ return mProperty.getInteger("preview_i_frame_interval", DEFAULT_PREVIEW_KEY_FRAME_INTERVAL);
}
/**
- * フレームレートを設定します.
+ * キーフレームインターバルを設定します.
*
- * @param previewMaxFrameRate フレームレート
+ * @param previewKeyFrameInterval キーフレームを発行する間隔(ミリ秒)
*/
- public void setPreviewMaxFrameRate(Integer previewMaxFrameRate) {
- if (previewMaxFrameRate <= 0) {
- throw new IllegalArgumentException("previewMaxFrameRate is zero or negative.");
+ public void setPreviewKeyFrameInterval(int previewKeyFrameInterval) {
+ if (previewKeyFrameInterval < 0) {
+ throw new IllegalArgumentException("previewKeyFrameInterval is negative.");
}
- mPref.put("preview_framerate", previewMaxFrameRate);
+ mProperty.put("preview_i_frame_interval", previewKeyFrameInterval);
}
/**
- * ビットレートを取得します.
+ * ソフトウェアエンコーダを優先的に使用するフラグを確認します.
*
- * @return ビットレート(byte)
+ * @return ソフトウェアエンコーダを優先的に使用する場合は true、それ以外は false
*/
- public int getPreviewBitRate() {
- return mPref.getInteger("preview_bitrate", 2 * 1024 * 1024);
+ public boolean isUseSoftwareEncoder() {
+ return mProperty.getBoolean("preview_use_software_encoder", false);
}
/**
- * ビットレートを設定します.
+ * ソフトウェアエンコーダを優先的に使用するフラグを設定します.
*
- * @param previewBitRate ビットレート(byte)
+ * @param used ソフトウェアエンコーダを優先的に使用する場合は true、それ以外は false
*/
- public void setPreviewBitRate(int previewBitRate) {
- if (previewBitRate <= 0) {
- throw new IllegalArgumentException("previewBitRate is zero or negative.");
+ public void setUseSoftwareEncoder(boolean used) {
+ mProperty.put("preview_use_software_encoder", used);
+ }
+
+ /**
+ * イントラリフレッシュのフレーム数を取得します.
+ *
+ * @return イントラリフレッシュのフレーム数
+ */
+ public Integer getIntraRefresh() {
+ return mProperty.getInteger("preview_intra_refresh", 0);
+ }
+
+ /**
+ * イントラリフレッシュのフレーム数を設定します.
+ *
+ * @param refresh イントラリフレッシュのフレーム数
+ */
+ public void setIntraRefresh(Integer refresh) {
+ if (refresh == null) {
+ mProperty.remove("preview_intra_refresh");
+ } else {
+ mProperty.put("preview_intra_refresh", refresh);
}
- mPref.put("preview_bitrate", String.valueOf(previewBitRate));
}
/**
- * キーフレームインターバルを取得します.
+ * 切り抜き範囲を取得します.
*
- * @return キーフレームを発行する間隔(ミリ秒)
+ * 範囲ば設定されていない場合には、null を返却します.
+ *
+ * @return 切り抜き範囲
*/
- public int getPreviewKeyFrameInterval() {
- return mPref.getInteger("preview_i_frame_interval", 1);
+ public Rect getCropRect() {
+ return mProperty.getRect("preview_clip_left",
+ "preview_clip_top",
+ "preview_clip_right",
+ "preview_clip_bottom");
}
/**
- * キーフレームインターバルを設定します.
+ * 切り抜き範囲を設定します.
*
- * @param previewKeyFrameInterval キーフレームを発行する間隔(ミリ秒)
+ * 引数に null が指定された場合には、切り抜き範囲を削除します。
+ *
+ * @param rect 切り抜き範囲
*/
- public void setPreviewKeyFrameInterval(int previewKeyFrameInterval) {
- if (previewKeyFrameInterval <= 0) {
- throw new IllegalArgumentException("previewKeyFrameInterval is zero or negative.");
+ public void setCropRect(Rect rect) {
+ if (rect == null) {
+ mProperty.remove("preview_clip_left");
+ mProperty.remove("preview_clip_top");
+ mProperty.remove("preview_clip_right");
+ mProperty.remove("preview_clip_bottom");
+ } else {
+ mProperty.put(
+ "preview_clip_left",
+ "preview_clip_top",
+ "preview_clip_right",
+ "preview_clip_bottom",
+ rect);
}
- mPref.put("preview_i_frame_interval", previewKeyFrameInterval);
}
/**
@@ -730,7 +887,7 @@ public void setPreviewKeyFrameInterval(int previewKeyFrameInterval) {
* @return プレビューの品質
*/
public int getPreviewQuality() {
- return mPref.getInteger("preview_jpeg_quality", 80);
+ return mProperty.getInteger("preview_jpeg_quality", 80);
}
/**
@@ -748,86 +905,579 @@ public void setPreviewQuality(int quality) {
if (quality > 100) {
throw new IllegalArgumentException("quality is over 100.");
}
- mPref.put("preview_jpeg_quality", quality);
+ mProperty.put("preview_jpeg_quality", quality);
}
/**
- * ホワイトバランスの設定を取得します.
+ * サポートしているエンコーダの解像度の最大値を取得します.
*
- * @return ホワイトバランス
+ * @return サポートしている解像度の最大値
*/
- public Integer getPreviewWhiteBalance() {
- return mPref.getInteger("preview_white_balance", null);
+ public Size getSupportedPreviewSize() {
+ VideoCodec codec = getPreviewEncoderName();
+ if (codec != null) {
+ return CapabilityUtil.getSupportedMaxSize(codec.getMimeType());
+ }
+ return CapabilityUtil.getSupportedMaxSize(VideoCodec.H264.getMimeType());
}
/**
- * ホワイトバランスを設定します.
+ * サポートしているエンコーダの解像度の最大値を取得します.
*
- * @param whiteBalance ホワイトバランス
+ * @param mimeType マイムタイプ
+ * @return サポートしている解像度の最大値
*/
- public void setPreviewWhiteBalance(Integer whiteBalance) {
- if (whiteBalance == null) {
- mPref.remove("preview_white_balance");
- } else {
- if (!isSupportedWhiteBalanceMode(whiteBalance)) {
- throw new IllegalArgumentException("WhiteBalance is unsupported value.");
- }
- mPref.put("preview_white_balance", whiteBalance);
- }
+ public Size getSupportedPreviewSize(String mimeType) {
+ return CapabilityUtil.getSupportedMaxSize(mimeType);
}
- public Integer getPreviewAutoExposureMode() {
- return mPref.getInteger("preview_auto_exposure_mode", null);
+ /**
+ * 指定されたサイズがサポートされているか確認します.
+ *
+ * @param mimeType マイムタイプ
+ * @param size 解像度
+ * @return サポートされている場合はtrue、それ以外はfalse
+ */
+ public boolean isSupportedPreviewSize(String mimeType, Size size) {
+ Size maxSize = getSupportedPreviewSize(mimeType);
+ return maxSize != null && (size.getWidth() <= maxSize.getWidth() && size.getHeight() <= maxSize.getHeight());
}
- public void setPreviewAutoExposureMode(Integer mode) {
- if (mode == null) {
- mPref.remove("preview_auto_exposure_mode");
- } else {
- if (!isSupportedAutoExposureMode(mode)) {
- throw new IllegalArgumentException("Exposure mode is unsupported value.");
- }
- mPref.put("preview_auto_exposure_mode", mode);
- }
+ /**
+ * 画面に表示するプレビューのリストを取得します.
+ *
+ * @return プレビューリスト
+ */
+ public List getSupportedEncoderSizes() {
+ return new ArrayList<>();
}
/**
- * ソフトウェアエンコーダを優先的に使用するフラグを確認します.
+ * サポートしているエンコーダのリストを取得します.
*
- * @return ソフトウェアエンコーダを優先的に使用する場合は true、それ以外は false
+ * @return サポートしているエンコーダのリスト
*/
- public boolean isUseSoftwareEncoder() {
- return mPref.getBoolean("preview_use_software_encoder", false);
+ public List getSupportedVideoEncoders() {
+ List list = new ArrayList<>();
+ List supported = CapabilityUtil.getSupportedVideoEncoders();
+ for (VideoCodec encoderName : VideoCodec.values()) {
+ if (supported.contains(encoderName.getMimeType())) {
+ list.add(encoderName.getName());
+ }
+ }
+ return list;
}
/**
- * ソフトウェアエンコーダを優先的に使用するフラグを設定します.
+ * サポートしているプロファイル・レベルの一覧を取得します.
*
- * @param used ソフトウェアエンコーダを優先的に使用する場合は true、それ以外は false
+ * @return サポートしているプロファイル・レベルの一覧
*/
- public void setUseSoftwareEncoder(boolean used) {
- mPref.put("preview_use_software_encoder", used);
+ public List getSupportedProfileLevel() {
+ VideoCodec encoderName = getPreviewEncoderName();
+ return CapabilityUtil.getSupportedProfileLevel(encoderName.getMimeType());
+ }
+
+ /**
+ * 指定されたエンコーダがサポートされているか確認します.
+ *
+ * @param encoder エンコーダ名
+ * @return サポートされている場合はtrue、それ以外はfalse
+ */
+ public boolean isSupportedVideoEncoder(String encoder) {
+ List encoderList = getSupportedVideoEncoders();
+ if (encoderList != null) {
+ for (String e : encoderList) {
+ if (e.equalsIgnoreCase(encoder)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 指定されたプロファイルとレベルがサポートされているか確認します.
+ *
+ * @param profile プロファイル
+ * @param level レベル
+ * @return サポートされている場合はtrue、それ以外はfalse
+ */
+ public boolean isSupportedProfileLevel(int profile, int level) {
+ List list = getSupportedProfileLevel();
+ if (list != null) {
+ for (ProfileLevel pl : list) {
+ if (profile == pl.getProfile() && level == pl.getLevel()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * SRT サーバに対して設定するオプションの一覧を作成します.
+ *
+ * @return オプションの一覧
+ */
+ public Map getSRTSocketOptions() {
+ Map options = new HashMap<>();
+ for (SRTOptionItem item : SRT_OPTION_ITEMS) {
+ String key = mContext.getString(item.getPrefKey());
+ String value = mProperty.getString(key, null);
+ if (value == null || "".equals(value)) {
+ continue;
+ }
+
+ try {
+ if (item.getValueClass() == Long.class) {
+ options.put(item.getOptionEnum(), Long.parseLong(value));
+ } else if (item.getValueClass() == Integer.class) {
+ options.put(item.getOptionEnum(), Integer.parseInt(value));
+ } else {
+ options.put(item.getOptionEnum(), value);
+ }
+ } catch (Exception ignored) {}
+ }
+ return options;
+ }
+
+ /**
+ * 設定画面でサポートする SRT オプションの定義.
+ */
+ private static final List SRT_OPTION_ITEMS = Arrays.asList(
+ new SRTOptionItem(SRT.SRTO_PEERLATENCY, Integer.class, R.string.pref_key_settings_srt_peerlatency),
+ new SRTOptionItem(SRT.SRTO_LOSSMAXTTL, Integer.class, R.string.pref_key_settings_srt_lossmaxttl),
+ new SRTOptionItem(SRT.SRTO_INPUTBW, Long.class, R.string.pref_key_settings_srt_inputbw),
+ new SRTOptionItem(SRT.SRTO_OHEADBW, Integer.class, R.string.pref_key_settings_srt_oheadbw),
+ new SRTOptionItem(SRT.SRTO_CONNTIMEO, Integer.class, R.string.pref_key_settings_srt_conntimeo),
+ new SRTOptionItem(SRT.SRTO_PEERIDLETIMEO, Integer.class, R.string.pref_key_settings_srt_peeridletimeo),
+ new SRTOptionItem(SRT.SRTO_PACKETFILTER, String.class, R.string.pref_key_settings_srt_packetfilter));
+
+ /**
+ * SRT オプション設定項目の定義.
+ *
+ * SRT オプションの列挙子 ({@link SRT} で定義されているもの) に対して、値の型とプリファレンスキーを対応づける.
+ */
+ private static class SRTOptionItem {
+ final int mOptionEnum;
+ final Class> mValueClass;
+ final int mPrefKey;
+
+ SRTOptionItem(int optionEnum, Class> valueClass, int prefKey) {
+ mOptionEnum = optionEnum;
+ mValueClass = valueClass;
+ mPrefKey = prefKey;
+ }
+
+ int getOptionEnum() {
+ return mOptionEnum;
+ }
+
+ int getPrefKey() {
+ return mPrefKey;
+ }
+
+ Class> getValueClass() {
+ return mValueClass;
+ }
+ }
+
+ // 配信
+
+ /**
+ * 配信先の URI を取得します.
+ *
+ * 設定されていない場合は null を返却します.
+ *
+ * @return 配信先の URI
+ */
+ public String getBroadcastURI() {
+ return mProperty.getString("broadcast_uri", null);
+ }
+
+ /**
+ * 配信先の URI を設定します.
+ *
+ * @param broadcastURI 配信先の URI
+ */
+ public void setBroadcastURI(String broadcastURI) {
+ mProperty.put("broadcast_uri", broadcastURI);
+ }
+
+ /**
+ * リトライ回数を取得します.
+ *
+ * @return リトライ回数
+ */
+ public int getRetryCount() {
+ return mProperty.getInteger("broadcast_retry_count", 0);
+ }
+
+ /**
+ * リトライ回数を設定します.
+ *
+ * @param count リトライ回数
+ */
+ public void setRetryCount(int count) {
+ if (count < 0) {
+ mProperty.remove("broadcast_retry_count");
+ } else {
+ mProperty.put("broadcast_retry_count", count);
+ }
+ }
+
+ /**
+ * リトライのインターバルを取得します.
+ *
+ * @return リトライのインターバル
+ */
+ public int getRetryInterval() {
+ return mProperty.getInteger("broadcast_retry_interval", 3000);
+ }
+
+ /**
+ * リトライのインターバルを設定します.
+ *
+ * @param interval リトライのインターバル
+ */
+ public void setRetryInterval(int interval) {
+ if (interval < 0) {
+ mProperty.remove("broadcast_retry_interval");
+ } else {
+ mProperty.put("broadcast_retry_interval", interval);
+ }
+ }
+ }
+
+ /**
+ * HostMediaRecorder の設定を保持するクラス.
+ */
+ abstract class Settings {
+ private final PropertyUtil mProperty;
+ private final Context mContext;
+
+ public Settings(Context context, HostMediaRecorder recorder) {
+ mContext = context;
+ mProperty = new PropertyUtil(context, recorder.getId());
+ }
+
+ protected EncoderSettings createEncoderSettings(String encoderId) {
+ return new EncoderSettings(mContext, encoderId);
+ }
+
+ /**
+ * 初期化されているか確認します.
+ *
+ * @return 初期化されている場合はtrue、それ以外はfalse
+ */
+ public boolean isInitialized() {
+ return mProperty.getString("initialization", null) != null;
+ }
+
+ /**
+ * 初期化完了を書き込みます.
+ */
+ public void finishInitialization() {
+ mProperty.put("initialization", "completion");
+ }
+
+ /**
+ * 保存データを初期化します.
+ */
+ public void clear() {
+ for (String encoderId : getEncoderIdList()) {
+ getEncoderSetting(encoderId).clear();
+ }
+ mProperty.clear();
+ }
+
+ /**
+ * 指定された ID に対応するエンコーダの設定を取得します.
+ *
+ * @param encoderId 配信先の設定の ID
+ * @return エンコーダ設定
+ */
+ public EncoderSettings getEncoderSetting(String encoderId) {
+ List encoderSettingList = getEncoderIdList();
+ if (encoderSettingList.contains(encoderId)) {
+ return createEncoderSettings(encoderId);
+ }
+ return null;
+ }
+
+ /**
+ * エンコーダの ID リストを取得します.
+ *
+ * @return エンコーダリスト
+ */
+ public List getEncoderIdList() {
+ return mProperty.getArrayString("encoder_id_list");
+ }
+
+ /**
+ * エンコーダ ID が存在するか確認します.
+ *
+ * @param encoderId エンコーダID
+ * @return 存在する場合はtrue、それ以外はfalse
+ */
+ public boolean existEncoderId(String encoderId) {
+ List encoderIdList = getEncoderIdList();
+ return encoderIdList.contains(encoderId);
+ }
+
+ /**
+ * エンコーダを追加します.
+ *
+ * 既に同じ ID が存在する場合には何も処理を行いません。
+ *
+ * @param encoderId 追加するエンコーダ ID
+ */
+ public void addEncoder(String encoderId) {
+ List encoderList = getEncoderIdList();
+ if (encoderList.contains(encoderId)) {
+ return;
+ }
+ encoderList.add(encoderId);
+ mProperty.put("encoder_id_list", encoderList);
+ }
+
+ /**
+ * エンコーダを削除します.
+ *
+ * @param encoderId 削除するエンコーダ ID
+ */
+ public void removeEncoder(String encoderId) {
+ EncoderSettings encoderSettings = getEncoderSetting(encoderId);
+ if (encoderId != null && encoderSettings != null) {
+ encoderSettings.clear();
+ }
+
+ List encoderList = getEncoderIdList();
+ encoderList.remove(encoderId);
+ mProperty.put("encoder_id_list", encoderList);
+ }
+
+ // カメラ設定
+
+ /**
+ * カメラの向きを取得します.
+ *
+ * @return カメラの向き
+ */
+ public int getOrientation() {
+ return mProperty.getInteger("camera_orientation", -1);
+ }
+
+ /**
+ * カメラの向きを設定します.
+ *
+ * @param orientation カメラの向き
+ */
+ public void setOrientation(int orientation) {
+ mProperty.put("camera_orientation", orientation);
+ }
+
+ /**
+ * 写真サイズを取得します.
+ *
+ * @return 写真サイズ
+ */
+ public Size getPictureSize() {
+ return mProperty.getSize("picture_size_width", "picture_size_height");
+ }
+
+ /**
+ * 写真サイズを設定します.
+ *
+ * サポートされていない写真サイズの場合は IllegalArgumentException を発生させます。
+ *
+ * @param pictureSize 写真サイズ
+ */
+ public void setPictureSize(Size pictureSize) {
+ if (pictureSize == null) {
+ throw new IllegalArgumentException("pictureSize is not set.");
+ }
+ if (!isSupportedPictureSize(pictureSize)) {
+ throw new IllegalArgumentException("pictureSize is not supported.");
+ }
+ mProperty.put("picture_size_width", "picture_size_height", pictureSize);
+ }
+
+ /**
+ * プレビューサイズを取得します.
+ *
+ * @return プレビューサイズ
+ */
+ public Size getPreviewSize() {
+ return mProperty.getSize("preview_size_width", "preview_size_height");
+ }
+
+ /**
+ * プレビューサイズを設定します.
+ *
+ * サポートされていないプレビューサイズの場合は IllegalArgumentException を発生させます。
+ *
+ * @param previewSize プレビューサイズ
+ */
+ public void setPreviewSize(Size previewSize) {
+ if (previewSize == null) {
+ throw new IllegalArgumentException("previewSize is not set.");
+ }
+ if (!isSupportedPreviewSize(previewSize)) {
+ throw new IllegalArgumentException("previewSize is not supported.");
+ }
+ mProperty.put("preview_size_width", "preview_size_height", previewSize);
+ }
+
+ /**
+ * 設定が近い fps を取得します.
+ *
+ * @param frameRate フレームレート
+ * @return fps
+ */
+ public Range getPreviewFpsFromFrameRate(int frameRate) {
+ List> fpsList = getSupportedFps();
+ for (Range fps : fpsList) {
+ if (frameRate == fps.getLower() && frameRate == fps.getUpper()) {
+ return fps;
+ }
+ }
+ Range t = null;
+ int diff = Integer.MAX_VALUE;
+ for (Range fps : fpsList) {
+ if (fps.getLower() < frameRate && frameRate <= fps.getUpper()) {
+ if (t != null) {
+ int a = fps.getUpper() - frameRate;
+ int b = fps.getLower() - frameRate;
+ int l = a * a + b * b;
+ if (l < diff) {
+ diff = l;
+ t = fps;
+ }
+ } else {
+ t = fps;
+ }
+ }
+ }
+ return t;
+ }
+
+ /**
+ * フレームレートを取得します.
+ *
+ * @return フレームレート
+ */
+ public Range getPreviewFps() {
+ Integer lower = mProperty.getInteger("preview_fps_lower", null);
+ Integer upper = mProperty.getInteger("preview_fps_upper", null);
+ if (lower != null && upper != null) {
+ return new Range<>(lower, upper);
+ }
+ return null;
+ }
+
+ /**
+ * フレームレートを設定します.
+ *
+ * サポートされていないフレームレート場合は IllegalArgumentException を発生させます。
+ *
+ * @param fps フレームレート
+ */
+ public void setPreviewFps(Range fps) {
+ if (fps == null) {
+ mProperty.remove("preview_fps_lower");
+ mProperty.remove("preview_fps_upper");
+ } else {
+ if (!isSupportedFps(fps)) {
+ throw new IllegalArgumentException("previewFps is not supported.");
+ }
+ mProperty.put("preview_fps_lower", fps.getLower());
+ mProperty.put("preview_fps_upper", fps.getUpper());
+ }
+ }
+
+ /**
+ * 自動フォーカスモードを取得します.
+ *
+ * 未設定の場合は null を返却します。
+ *
+ * @return 自動フォーカスモード
+ */
+ public Integer getPreviewAutoFocusMode() {
+ return mProperty.getInteger("preview_auto_focus", null);
+ }
+
+ /**
+ * 自動フォーカスモードを設定します.
+ *
+ * mode が設定された場合には、未設定にします。
+ *
+ * サポートされていないモードが設定された場合には例外が発生します。
+ *
+ * @param mode 自動フォーカスモード
+ */
+ public void setPreviewAutoFocusMode(Integer mode) {
+ if (mode == null) {
+ mProperty.remove("preview_auto_focus");
+ } else {
+ if (!isSupportedAutoFocusMode(mode)) {
+ throw new IllegalArgumentException("focus mode is not supported.");
+ }
+ mProperty.put("preview_auto_focus", mode);
+ }
+ }
+
+ /**
+ * ホワイトバランスの設定を取得します.
+ *
+ * @return ホワイトバランス
+ */
+ public Integer getPreviewWhiteBalance() {
+ return mProperty.getInteger("preview_white_balance", null);
+ }
+
+ /**
+ * ホワイトバランスを設定します.
+ *
+ * @param whiteBalance ホワイトバランス
+ */
+ public void setPreviewWhiteBalance(Integer whiteBalance) {
+ if (whiteBalance == null) {
+ mProperty.remove("preview_white_balance");
+ } else {
+ if (!isSupportedWhiteBalanceMode(whiteBalance)) {
+ throw new IllegalArgumentException("WhiteBalance is unsupported value.");
+ }
+ mProperty.put("preview_white_balance", whiteBalance);
+ }
}
/**
- * イントラリフレッシュのフレーム数を取得します.
+ * 自動露出モードを取得します.
*
- * @return イントラリフレッシュのフレーム数
+ * @return 自動露出モード
*/
- public Integer getIntraRefresh() {
- return mPref.getInteger("preview_intra_refresh", 0);
+ public Integer getPreviewAutoExposureMode() {
+ return mProperty.getInteger("preview_auto_exposure_mode", null);
}
/**
- * イントラリフレッシュのフレーム数を設定します.
+ * 自動露出モードを設定します.
*
- * @param refresh イントラリフレッシュのフレーム数
+ * mode に null が指定された場合は設定を削除します。
+ *
+ * @param mode 自動露出モード
*/
- public void setIntraRefresh(Integer refresh) {
- if (refresh == null) {
- mPref.remove("preview_intra_refresh");
+ public void setPreviewAutoExposureMode(Integer mode) {
+ if (mode == null) {
+ mProperty.remove("preview_auto_exposure_mode");
} else {
- mPref.put("preview_intra_refresh", refresh);
+ if (!isSupportedAutoExposureMode(mode)) {
+ throw new IllegalArgumentException("Exposure mode is unsupported value.");
+ }
+ mProperty.put("preview_auto_exposure_mode", mode);
}
}
@@ -837,7 +1487,7 @@ public void setIntraRefresh(Integer refresh) {
* @return 手ぶれ補正モード
*/
public Integer getStabilizationMode() {
- return mPref.getInteger("preview_stabilization_mode", null);
+ return mProperty.getInteger("preview_stabilization_mode", null);
}
/**
@@ -847,12 +1497,12 @@ public Integer getStabilizationMode() {
*/
public void setStabilizationMode(Integer mode) {
if (mode == null) {
- mPref.remove("preview_stabilization_mode");
+ mProperty.remove("preview_stabilization_mode");
} else {
if (!isSupportedStabilization(mode)) {
throw new IllegalArgumentException("Stabilization Mode is unsupported value.");
}
- mPref.put("preview_stabilization_mode", mode);
+ mProperty.put("preview_stabilization_mode", mode);
}
}
@@ -862,7 +1512,7 @@ public void setStabilizationMode(Integer mode) {
* @return 光学手ぶれ補正モード
*/
public Integer getOpticalStabilizationMode() {
- return mPref.getInteger("preview_optical_stabilization_mode", null);
+ return mProperty.getInteger("preview_optical_stabilization_mode", null);
}
/**
@@ -872,12 +1522,12 @@ public Integer getOpticalStabilizationMode() {
*/
public void setOpticalStabilizationMode(Integer mode) {
if (mode == null) {
- mPref.remove("preview_optical_stabilization_mode");
+ mProperty.remove("preview_optical_stabilization_mode");
} else {
if (!isSupportedOpticalStabilization(mode)) {
throw new IllegalArgumentException("Optical Stabilization Mode is unsupported value.");
}
- mPref.put("preview_optical_stabilization_mode", mode);
+ mProperty.put("preview_optical_stabilization_mode", mode);
}
}
@@ -887,7 +1537,7 @@ public void setOpticalStabilizationMode(Integer mode) {
* @return デジタルズーム
*/
public Float getDigitalZoom() {
- return mPref.getFloat("preview_digital_zoom", null);
+ return mProperty.getFloat("preview_digital_zoom", null);
}
/**
@@ -897,17 +1547,24 @@ public Float getDigitalZoom() {
*/
public void setDigitalZoom(Float zoom) {
if (zoom == null) {
- mPref.remove("preview_digital_zoom");
+ mProperty.remove("preview_digital_zoom");
} else {
if (!isSupportedDigitalZoom(zoom)) {
throw new IllegalArgumentException("Digital zoom is unsupported value.");
}
- mPref.put("preview_digital_zoom", zoom);
+ mProperty.put("preview_digital_zoom", zoom);
}
}
+ /**
+ * 焦点距離を取得します.
+ *
+ * 未設定の場合は null を返却します。
+ *
+ * @return 焦点距離
+ */
public Float getFocalLength() {
- Float value = mPref.getFloat("preview_focal_length", null);
+ Float value = mProperty.getFloat("preview_focal_length", null);
if (value == null) {
return null;
}
@@ -920,156 +1577,195 @@ public Float getFocalLength() {
return null;
}
+ /**
+ * 焦点距離を設定します.
+ *
+ * focalLength に null が指定された場合には、設定を削除します。
+ * サポートされていない値が指定された場合には、IllegalArgumentException が発生します。
+ *
+ * @param focalLength 焦点距離
+ */
public void setFocalLength(Float focalLength) {
if (focalLength == null) {
- mPref.remove("preview_focal_length");
+ mProperty.remove("preview_focal_length");
} else {
if (!isSupportedFocalLength(focalLength)) {
throw new IllegalArgumentException("focalLength cannot set.");
}
- mPref.put("preview_focal_length", focalLength);
+ mProperty.put("preview_focal_length", focalLength);
}
}
+ /**
+ * ノイズ低減モードを取得します.
+ *
+ * 未設定の場合は、null を返却します。
+ *
+ * @return ノイズ低減モード
+ */
public Integer getNoiseReduction() {
- return mPref.getInteger("preview_reduction_noise", null);
+ return mProperty.getInteger("preview_reduction_noise", null);
}
+ /**
+ * ノイズ低減モードを設定します.
+ *
+ * mode に null が指定された場合には、設定を削除します。
+ * サポートされていない値が指定された場合には、IllegalArgumentException が発生します。
+ *
+ * @param mode ノイズ低減モード
+ */
public void setNoiseReduction(Integer mode) {
if (mode == null) {
- mPref.remove("preview_reduction_noise");
+ mProperty.remove("preview_reduction_noise");
} else {
if (!isSupportedNoiseReduction(mode)) {
throw new IllegalArgumentException("mode cannot set.");
}
- mPref.put("preview_reduction_noise", mode);
- }
- }
-
- public BitRateMode getPreviewBitRateMode() {
- return BitRateMode.nameOf(mPref.getString("preview_bitrate_mode", null));
- }
-
- public void setPreviewBitRateMode(BitRateMode mode) {
- if (mode == null) {
- mPref.remove("preview_bitrate_mode");
- } else {
- mPref.put("preview_bitrate_mode", mode.getName());
+ mProperty.put("preview_reduction_noise", mode);
}
}
+ /**
+ * 自動露出モードを取得します.
+ *
+ * @return 自動露出モード
+ */
public Integer getAutoExposureMode() {
- return mPref.getInteger("preview_auto_exposure_mode", null);
+ return mProperty.getInteger("preview_auto_exposure_mode", null);
}
+ /**
+ * 自動露出モードを設定します.
+ *
+ * mode に null が指定された場合には設定を削除します。
+ * サポートされていない値が指定された場合には、IllegalArgumentException が発生します。
+ *
+ * @param mode 自動露出モード
+ */
public void setAutoExposureMode(Integer mode) {
if (mode == null) {
- mPref.remove("preview_auto_exposure_mode");
+ mProperty.remove("preview_auto_exposure_mode");
} else {
if (!isSupportedAutoExposureMode(mode)) {
throw new IllegalArgumentException("mode cannot set.");
}
- mPref.put("preview_auto_exposure_mode", mode);
+ mProperty.put("preview_auto_exposure_mode", mode);
}
}
+ /**
+ * 露出時間を取得します.
+ *
+ * @return 露出時間
+ */
public Long getSensorExposureTime() {
- return mPref.getLong("preview_sensor_exposure_time", null);
+ return mProperty.getLong("preview_sensor_exposure_time", null);
}
+ /**
+ * 露出時間を設定します.
+ *
+ * mode に null が指定された場合には設定を削除します。
+ * サポートされていない値が指定された場合には、IllegalArgumentException が発生します。
+ *
+ * @param exposureTime 露出時間
+ */
public void setSensorExposureTime(Long exposureTime) {
if (exposureTime == null) {
- mPref.remove("preview_sensor_exposure_time");
+ mProperty.remove("preview_sensor_exposure_time");
} else {
if (!isSupportedSensorExposureTime(exposureTime)) {
throw new IllegalArgumentException("exposureTime cannot set.");
}
- mPref.put("preview_sensor_exposure_time", exposureTime);
+ mProperty.put("preview_sensor_exposure_time", exposureTime);
}
}
+ /**
+ * ISO 感度を取得します.
+ *
+ * @return ISO 感度
+ */
public Integer getSensorSensitivity() {
- return mPref.getInteger("preview_sensor_sensitivity", null);
+ return mProperty.getInteger("preview_sensor_sensitivity", null);
}
+ /**
+ * ISO 感度を設定します.
+ *
+ * mode に null が指定された場合には設定を削除します。
+ * サポートされていない値が指定された場合には、IllegalArgumentException が発生します。
+ *
+ * @param sensitivity ISO 感度
+ */
public void setSensorSensitivity(Integer sensitivity) {
if (sensitivity == null) {
- mPref.remove("preview_sensor_sensitivity");
+ mProperty.remove("preview_sensor_sensitivity");
} else {
- if (!isSupportedSensorSensorSensitivity(sensitivity)) {
+ if (!isSupportedSensorSensitivity(sensitivity)) {
throw new IllegalArgumentException("sensitivity cannot set.");
}
- mPref.put("preview_sensor_sensitivity", sensitivity);
+ mProperty.put("preview_sensor_sensitivity", sensitivity);
}
}
+ /**
+ * フレーム時間を取得します.
+ *
+ * 未設定の場合は null を返却します。
+ *
+ * @return フレーム時間
+ */
public Long getSensorFrameDuration() {
- return mPref.getLong("preview_sensor_frame_duration", null);
+ return mProperty.getLong("preview_sensor_frame_duration", null);
}
+ /**
+ * フレーム時間を設定します.
+ *
+ * @param frameDuration フレーム時間
+ */
public void setSensorFrameDuration(Long frameDuration) {
if (frameDuration == null) {
- mPref.remove("preview_sensor_frame_duration");
+ mProperty.remove("preview_sensor_frame_duration");
} else {
if (!isSupportedSensorFrameDuration(frameDuration)) {
throw new IllegalArgumentException("frameDuration cannot set.");
}
- mPref.put("preview_sensor_frame_duration", frameDuration);
- }
- }
-
- public Integer getPreviewWhiteBalanceTemperature() {
- return mPref.getInteger("preview_sensor_white_balance_temperature", null);
- }
-
- public void setPreviewWhiteBalanceTemperature(Integer temperature) {
- if (temperature == null) {
- mPref.remove("preview_sensor_white_balance_temperature");
- } else {
- if (!isSupportedWhiteBalanceTemperature(temperature)) {
- throw new IllegalArgumentException("whiteBalanceTemperature cannot set.");
- }
- mPref.put("preview_sensor_white_balance_temperature", temperature);
+ mProperty.put("preview_sensor_frame_duration", frameDuration);
}
}
/**
- * 切り抜き範囲を取得します.
+ * 色温度を取得します.
*
- * 範囲ば設定されていない場合には、null を返却します.
+ * 未設定の場合は null を返却します。
*
- * @return 切り抜き範囲
+ * @return 色温度
*/
- public Rect getDrawingRange() {
- return mPref.getRect("preview_clip_left",
- "preview_clip_top",
- "preview_clip_right",
- "preview_clip_bottom");
+ public Integer getPreviewWhiteBalanceTemperature() {
+ return mProperty.getInteger("preview_sensor_white_balance_temperature", null);
}
/**
- * 切り抜き範囲を設定します.
+ * 色温度を設定します.
*
- * 引数に null が指定された場合には、切り抜き範囲を削除します。
- *
- * @param rect 切り抜き範囲
+ * @param temperature 色温度
*/
- public void setDrawingRange(Rect rect) {
- if (rect == null) {
- mPref.remove("preview_clip_left");
- mPref.remove("preview_clip_top");
- mPref.remove("preview_clip_right");
- mPref.remove("preview_clip_bottom");
+ public void setPreviewWhiteBalanceTemperature(Integer temperature) {
+ if (temperature == null) {
+ mProperty.remove("preview_sensor_white_balance_temperature");
} else {
- mPref.put(
- "preview_clip_left",
- "preview_clip_top",
- "preview_clip_right",
- "preview_clip_bottom",
- rect);
+ if (!isSupportedWhiteBalanceTemperature(temperature)) {
+ throw new IllegalArgumentException("whiteBalanceTemperature cannot set.");
+ }
+ mProperty.put("preview_sensor_white_balance_temperature", temperature);
}
}
+ /// サポートしているデータサイズ
+
/**
* サポートしている写真サイズを取得します.
*
@@ -1180,6 +1876,13 @@ public Long getMaxSensorFrameDuration() {
return null;
}
+ /**
+ * サポートしている色温度の範囲を取得します.
+ *
+ * サポートしていない場合は null を返却します。
+ *
+ * @return 色温度の範囲
+ */
public Range getSupportedWhiteBalanceTemperature() {
return null;
}
@@ -1192,7 +1895,7 @@ public Range getSupportedWhiteBalanceTemperature() {
public List getSupportedVideoEncoders() {
List list = new ArrayList<>();
List supported = CapabilityUtil.getSupportedVideoEncoders();
- for (VideoEncoderName encoderName : VideoEncoderName.values()) {
+ for (VideoCodec encoderName : VideoCodec.values()) {
if (supported.contains(encoderName.getMimeType())) {
list.add(encoderName.getName());
}
@@ -1200,23 +1903,55 @@ public List getSupportedVideoEncoders() {
return list;
}
- public List getSupportedProfileLevel() {
- VideoEncoderName encoderName = getPreviewEncoderName();
+ /**
+ * サポートしているプロファイル・レベルの一覧を取得します.
+ *
+ * @return サポートしているプロファイル・レベルの一覧
+ */
+ public List getSupportedProfileLevel(VideoCodec encoderName) {
return CapabilityUtil.getSupportedProfileLevel(encoderName.getMimeType());
}
+ /**
+ * サポートしている手ぶれ補正のリストを取得します.
+ *
+ * サポートしていない場合は、空のリストを返却します。
+ *
+ * @return サポートしている手ぶれ補正のリスト
+ */
public List getSupportedStabilizationList() {
return new ArrayList<>();
}
+ /**
+ * サポートしている光学手ぶれ補正のリストを取得します.
+ *
+ * サポートしていない場合は、空のリストを返却します。
+ *
+ * @return サポートしている光学手ぶれ補正のリスト
+ */
public List getSupportedOpticalStabilizationList() {
return new ArrayList<>();
}
+ /**
+ * サポートしているノイズ低減モートのリストを取得します.
+ *
+ * サポートしていない場合は、空のリストを返却します。
+ *
+ * @return サポートしているノイズ低減モートのリスト
+ */
public List getSupportedNoiseReductionList() {
return new ArrayList<>();
}
+ /**
+ * サポートしている焦点距離のリストを取得します.
+ *
+ * サポートしていない場合は、空のリストを返却します。
+ *
+ * @return サポートしている焦点距離のリスト
+ */
public List getSupportedFocalLengthList() {
return new ArrayList<>();
}
@@ -1302,6 +2037,12 @@ public boolean isSupportedFps(Range fps) {
return false;
}
+ /**
+ * 指定されたフォーカスモードがサポートされているか確認します.
+ *
+ * @param mode 確認するフォーカスモード
+ * @return サポートされている場合はtrue、それ以外はfalse
+ */
public boolean isSupportedAutoFocusMode(int mode) {
List modeList = getSupportedAutoFocusModeList();
if (modeList != null) {
@@ -1332,6 +2073,12 @@ public boolean isSupportedWhiteBalanceMode(int whiteBalance) {
return false;
}
+ /**
+ * 指定された色温度がサポートされているか確認します.
+ *
+ * @param temperature 色温度
+ * @return サポートされている場合はtrue、それ以外はfalse
+ */
public boolean isSupportedWhiteBalanceTemperature(int temperature) {
Range range = getSupportedWhiteBalanceTemperature();
if (range != null) {
@@ -1340,6 +2087,12 @@ public boolean isSupportedWhiteBalanceTemperature(int temperature) {
return false;
}
+ /**
+ * 指定された自動露出モードがサポートされているか確認します.
+ *
+ * @param mode 自動露出モード
+ * @return サポートされている場合はtrue、それ以外はfalse
+ */
public boolean isSupportedAutoExposureMode(Integer mode) {
List modeList = getSupportedAutoExposureModeList();
if (modeList != null) {
@@ -1352,6 +2105,12 @@ public boolean isSupportedAutoExposureMode(Integer mode) {
return false;
}
+ /**
+ * 指定された露出時間がサポートされているか確認します.
+ *
+ * @param time 露出時間
+ * @return サポートされている場合はtrue、それ以外はfalse
+ */
public boolean isSupportedSensorExposureTime(long time) {
Range range = getSupportedSensorExposureTime();
if (range != null) {
@@ -1360,7 +2119,13 @@ public boolean isSupportedSensorExposureTime(long time) {
return false;
}
- public boolean isSupportedSensorSensorSensitivity(int sensitivity) {
+ /**
+ * 指定された ISO 感度がサポートされているか確認します.
+ *
+ * @param sensitivity ISO 感度
+ * @return サポートされている場合はtrue、それ以外はfalse
+ */
+ public boolean isSupportedSensorSensitivity(int sensitivity) {
Range range = getSupportedSensorSensitivity();
if (range != null) {
return range.getLower() <= sensitivity && sensitivity <= range.getUpper();
@@ -1368,6 +2133,12 @@ public boolean isSupportedSensorSensorSensitivity(int sensitivity) {
return false;
}
+ /**
+ * 指定されたフレーム時間がサポートされているか確認します.
+ *
+ * @param frameDuration フレーム時間
+ * @return サポートされている場合はtrue、それ以外はfalse
+ */
public boolean isSupportedSensorFrameDuration(long frameDuration) {
Long maxFrameDuration = getMaxSensorFrameDuration();
if (maxFrameDuration != null) {
@@ -1397,12 +2168,13 @@ public boolean isSupportedVideoEncoder(String encoder) {
/**
* 指定されたプロファイルとレベルがサポートされているか確認します.
*
+ * @param codec コーデック
* @param profile プロファイル
* @param level レベル
* @return サポートされている場合はtrue、それ以外はfalse
*/
- public boolean isSupportedProfileLevel(int profile, int level) {
- List list = getSupportedProfileLevel();
+ public boolean isSupportedProfileLevel(VideoCodec codec, int profile, int level) {
+ List list = getSupportedProfileLevel(codec);
if (list != null) {
for (ProfileLevel pl : list) {
if (profile == pl.getProfile() && level == pl.getLevel()) {
@@ -1504,7 +2276,7 @@ public boolean isSupportedFocalLength(Float focalLength) {
* @return プレビュー音声が有効の場合はtrue、それ以外はfalse
*/
public boolean isAudioEnabled() {
- return getPreviewAudioSource() != null;
+ return getPreviewAudioSource() != AudioSource.NONE;
}
/**
@@ -1513,7 +2285,7 @@ public boolean isAudioEnabled() {
* @return 音声タイプ
*/
public AudioSource getPreviewAudioSource() {
- return AudioSource.typeOf(mPref.getString("preview_audio_source", "none"));
+ return AudioSource.typeOf(mProperty.getString("preview_audio_source", "none"));
}
/**
@@ -1523,9 +2295,9 @@ public AudioSource getPreviewAudioSource() {
*/
public void setPreviewAudioSource(AudioSource audioSource) {
if (audioSource == null) {
- mPref.put("preview_audio_source", "none");
+ mProperty.put("preview_audio_source", "none");
} else {
- mPref.put("preview_audio_source", audioSource.mSource);
+ mProperty.put("preview_audio_source", audioSource.mSource);
}
}
@@ -1535,7 +2307,7 @@ public void setPreviewAudioSource(AudioSource audioSource) {
* @return プレビュー音声のビットレート
*/
public int getPreviewAudioBitRate() {
- return mPref.getInteger("preview_audio_bitrate", 64 * 1024);
+ return mProperty.getInteger("preview_audio_bitrate", 64 * 1024);
}
/**
@@ -1547,7 +2319,7 @@ public void setPreviewAudioBitRate(int bitRate) {
if (bitRate <= 0) {
throw new IllegalArgumentException("previewAudioBitRate is zero or negative value.");
}
- mPref.put("preview_audio_bitrate", bitRate);
+ mProperty.put("preview_audio_bitrate", bitRate);
}
/**
@@ -1556,7 +2328,7 @@ public void setPreviewAudioBitRate(int bitRate) {
* @return プレビュー音声のサンプルレート
*/
public int getPreviewSampleRate() {
- return mPref.getInteger("preview_audio_sample_rate", 16000);
+ return mProperty.getInteger("preview_audio_sample_rate", 16000);
}
/**
@@ -1566,12 +2338,12 @@ public int getPreviewSampleRate() {
*/
public void setPreviewSampleRate(Integer sampleRate) {
if (sampleRate == null) {
- mPref.remove("preview_audio_sample_rate");
+ mProperty.remove("preview_audio_sample_rate");
} else {
if (!isSupportedSampleRate(sampleRate)) {
throw new IllegalArgumentException("preivewSampleRate is invalid.");
}
- mPref.put("preview_audio_sample_rate", sampleRate);
+ mProperty.put("preview_audio_sample_rate", sampleRate);
}
}
@@ -1581,7 +2353,7 @@ public void setPreviewSampleRate(Integer sampleRate) {
* @return プレビュー音声のチャンネル数
*/
public int getPreviewChannel() {
- return mPref.getInteger("preview_audio_channel", 1);
+ return mProperty.getInteger("preview_audio_channel", 1);
}
/**
@@ -1590,7 +2362,7 @@ public int getPreviewChannel() {
* @param channel プレビュー音声のチャンネル数
*/
public void setPreviewChannel(int channel) {
- mPref.put("preview_audio_channel", channel);
+ mProperty.put("preview_audio_channel", channel);
}
/**
@@ -1599,7 +2371,7 @@ public void setPreviewChannel(int channel) {
* @return プレビュー配信のエコーキャンセラー
*/
public boolean isUseAEC() {
- return mPref.getBoolean("preview_audio_aec", true);
+ return mProperty.getBoolean("preview_audio_aec", true);
}
/**
@@ -1608,7 +2380,7 @@ public boolean isUseAEC() {
* @param used プレビュー配信のエコーキャンセラー
*/
public void setUseAEC(boolean used) {
- mPref.put("preview_audio_aec", used);
+ mProperty.put("preview_audio_aec", used);
}
/**
@@ -1617,7 +2389,7 @@ public void setUseAEC(boolean used) {
* @return ミュートの場合はtrue、それ以外の場合はfalse
*/
public boolean isMute() {
- return mPref.getBoolean("preview_audio_mute", false);
+ return mProperty.getBoolean("preview_audio_mute", false);
}
/**
@@ -1626,27 +2398,27 @@ public boolean isMute() {
* @param mute ミュートにする場合はtrue、それ以外はfalse
*/
public void setMute(boolean mute) {
- mPref.put("preview_audio_mute", mute);
+ mProperty.put("preview_audio_mute", mute);
}
public AudioFilter getAudioFilter() {
- return AudioFilter.nameOf(mPref.getString("preview_audio_filter", "none"));
+ return AudioFilter.nameOf(mProperty.getString("preview_audio_filter", "none"));
}
public void setAudioFilter(AudioFilter filter) {
if (filter == null) {
- mPref.remove("preview_audio_filter");
+ mProperty.remove("preview_audio_filter");
} else {
- mPref.put("preview_audio_filter", filter.mName);
+ mProperty.put("preview_audio_filter", filter.mName);
}
}
public float getAudioCoefficient() {
- return mPref.getInteger("preview_audio_coefficient", 10) / 100.0f;
+ return mProperty.getInteger("preview_audio_coefficient", 10) / 100.0f;
}
public void setAudioCoefficient(float coefficient) {
- mPref.put("preview_audio_coefficient", (int) (coefficient * 100));
+ mProperty.put("preview_audio_coefficient", (int) (coefficient * 100));
}
public boolean isSupportedAudioSource(AudioSource source) {
@@ -1706,145 +2478,5 @@ public boolean isSupportedSampleRate(int sampleRate) {
}
return false;
}
-
- // 配信
-
- /**
- * 配信先の URI を取得します.
- *
- * 設定されていない場合は null を返却します.
- *
- * @return 配信先の URI
- */
- public String getBroadcastURI() {
- return mPref.getString("broadcast_uri", null);
- }
-
- /**
- * 配信先の URI を設定します.
- *
- * @param broadcastURI 配信先の URI
- */
- public void setBroadcastURI(String broadcastURI) {
- mPref.put("broadcast_uri", broadcastURI);
- }
-
- /**
- * リトライ回数を取得します.
- *
- * @return リトライ回数
- */
- public int getRetryCount() {
- return mPref.getInteger("broadcast_retry_count", 0);
- }
-
- /**
- * リトライ回数を設定します.
- *
- * @param count リトライ回数
- */
- public void setRetryCount(int count) {
- if (count < 0) {
- mPref.remove("broadcast_retry_count");
- } else {
- mPref.put("broadcast_retry_count", count);
- }
- }
-
- /**
- * リトライのインターバルを取得します.
- *
- * @return リトライのインターバル
- */
- public int getRetryInterval() {
- return mPref.getInteger("broadcast_retry_interval", 3000);
- }
-
- /**
- * リトライのインターバルを設定します.
- *
- * @param interval リトライのインターバル
- */
- public void setRetryInterval(int interval) {
- if (interval < 0) {
- mPref.remove("broadcast_retry_interval");
- } else {
- mPref.put("broadcast_retry_interval", interval);
- }
- }
-
- // ポート番号
-
- /**
- * Motion JPEG サーバ用のポート番号を取得します.
- *
- * @return Motion JPEG サーバ用のポート番号
- */
- public Integer getMjpegPort() {
- return mPref.getInteger("mjpeg_port", 0);
- }
-
- /**
- * Motion JPEG サーバ用のポート番号を設定します.
- *
- * @param port Motion JPEG サーバ用のポート番号
- */
- public void setMjpegPort(int port) {
- mPref.put("mjpeg_port", port);
- }
-
- /**
- * SSL で暗号化された Motion JPEG サーバ用のポート番号を取得します.
- *
- * @return Motion JPEG サーバ用のポート番号
- */
- public Integer getMjpegSSLPort() {
- return mPref.getInteger("mjpeg_ssl_port", 0);
- }
-
- /**
- * SSL で暗号化された Motion JPEG サーバ用のポート番号を取得します.
- *
- * @param port Motion JPEG サーバ用のポート番号
- */
- public void setMjpegSSLPort(int port) {
- mPref.put("mjpeg_ssl_port", port);
- }
-
- /**
- * RTSP サーバ用のポート番号を取得します.
- *
- * @return RTSP サーバ用のポート番号
- */
- public Integer getRtspPort() {
- return mPref.getInteger("rtsp_port", 0);
- }
-
- /**
- * RTSP サーバ用のポート番号を設定します.
- *
- * @param port RTSP サーバ用のポート番号
- */
- public void setRtspPort(int port) {
- mPref.put("rtsp_port", port);
- }
-
- /**
- * SRT サーバ用のポート番号を取得します.
- *
- * @return SRT サーバ用のポート番号
- */
- public Integer getSrtPort() {
- return mPref.getInteger("srt_port", 0);
- }
-
- /**
- * SRT サーバ用のポート番号を設定します.
- *
- * @param port SRT サーバ用のポート番号
- */
- public void setSrtPort(int port) {
- mPref.put("srt_port", port);
- }
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/HostMediaRecorderManager.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/HostMediaRecorderManager.java
index 5cf671c121..600f27734d 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/HostMediaRecorderManager.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/HostMediaRecorderManager.java
@@ -118,7 +118,7 @@ public HostMediaRecorderManager(final DevicePluginContext pluginContext, final F
mHostDevicePluginContext = pluginContext;
mMediaProjectionProvider = new MediaProjectionProvider(pluginContext.getContext());
mFileManager = fileManager;
- initRecorders();
+ createRecorders();
}
private Context getContext() {
@@ -126,13 +126,13 @@ private Context getContext() {
}
/**
- * レコーダの初期化処理を行います.
+ * 使用するレコーダの一覧を作成します.
*
*
* ここで使用できるレコーダの登録を行います。
*
*/
- private void initRecorders() {
+ private void createRecorders() {
if (checkCameraHardware(getContext())) {
try {
mCameraWrapperManager = new CameraWrapperManager(getContext());
@@ -157,80 +157,6 @@ private void initRecorders() {
// ignore.
}
}
-
- for (HostMediaRecorder recorder : mRecorders) {
- recorder.setOnEventListener(new HostMediaRecorder.OnEventListener() {
- @Override
- public void onMuteChanged(boolean mute) {
- postOnMuteChanged(recorder, mute);
- }
-
- @Override
- public void onConfigChanged() {
- postOnConfigChanged(recorder);
- }
-
- @Override
- public void onPreviewStarted(List servers) {
- postOnPreviewStarted(recorder, servers);
- }
-
- @Override
- public void onPreviewStopped() {
- postOnPreviewStopped(recorder);
- }
-
- @Override
- public void onPreviewError(Exception e) {
- postOnPreviewError(recorder, e);
- }
-
- @Override
- public void onBroadcasterStarted(Broadcaster broadcaster) {
- postOnBroadcasterStarted(recorder, broadcaster);
- }
-
- @Override
- public void onBroadcasterStopped(Broadcaster broadcaster) {
- postOnBroadcasterStopped(recorder, broadcaster);
- }
-
- @Override
- public void onBroadcasterError(Broadcaster broadcaster, Exception e) {
- postOnBroadcasterError(recorder, broadcaster, e);
- }
-
- @Override
- public void onError(Exception e) {
- postOnError(recorder, e);
- }
-
- @Override
- public void onTakePhoto(String uri, String filePath, String mimeType) {
- postOnTakePhoto(recorder, uri, filePath, mimeType);
- }
-
- @Override
- public void onRecordingStarted(String fileName) {
- postOnRecordingStarted(recorder, fileName);
- }
-
- @Override
- public void onRecordingPause() {
- postOnRecordingPause(recorder);
- }
-
- @Override
- public void onRecordingResume() {
- postOnRecordingResume(recorder);
- }
-
- @Override
- public void onRecordingStopped(String fileName) {
- postOnRecordingStopped(recorder, fileName);
- }
- });
- }
}
/**
@@ -270,12 +196,92 @@ private void createCameraRecorders(final CameraWrapperManager cameraMgr, final F
}
}
+ /**
+ * レコーダの初期化処理を行います.
+ *
+ * @param recorder 初期化するレコーダ
+ */
+ private void initRecorder(HostMediaRecorder recorder) {
+ recorder.setOnEventListener(new HostMediaRecorder.OnEventListener() {
+ @Override
+ public void onMuteChanged(boolean mute) {
+ postOnMuteChanged(recorder, mute);
+ }
+
+ @Override
+ public void onConfigChanged() {
+ postOnConfigChanged(recorder);
+ }
+
+ @Override
+ public void onPreviewStarted(List servers) {
+ postOnPreviewStarted(recorder, servers);
+ }
+
+ @Override
+ public void onPreviewStopped() {
+ postOnPreviewStopped(recorder);
+ }
+
+ @Override
+ public void onPreviewError(Exception e) {
+ postOnPreviewError(recorder, e);
+ }
+
+ @Override
+ public void onBroadcasterStarted(List broadcasters) {
+ postOnBroadcasterStarted(recorder, broadcasters);
+ }
+
+ @Override
+ public void onBroadcasterStopped() {
+ postOnBroadcasterStopped(recorder);
+ }
+
+ @Override
+ public void onBroadcasterError(LiveStreaming broadcaster, Exception e) {
+ postOnBroadcasterError(recorder, broadcaster, e);
+ }
+
+ @Override
+ public void onError(Exception e) {
+ postOnError(recorder, e);
+ }
+
+ @Override
+ public void onTakePhoto(String uri, String filePath, String mimeType) {
+ postOnTakePhoto(recorder, uri, filePath, mimeType);
+ }
+
+ @Override
+ public void onRecordingStarted(String fileName) {
+ postOnRecordingStarted(recorder, fileName);
+ }
+
+ @Override
+ public void onRecordingPause() {
+ postOnRecordingPause(recorder);
+ }
+
+ @Override
+ public void onRecordingResume() {
+ postOnRecordingResume(recorder);
+ }
+
+ @Override
+ public void onRecordingStopped(String fileName) {
+ postOnRecordingStopped(recorder, fileName);
+ }
+ });
+ recorder.initialize();
+ }
+
/**
* 初期化処理を行います.
*/
public void initialize() {
for (HostMediaRecorder recorder : getRecorders()) {
- recorder.initialize();
+ initRecorder(recorder);
}
onDisplayRotationChanged(getContext());
@@ -318,14 +324,70 @@ public void destroy() {
mCameraWrapperManager.destroy();
}
+ /**
+ * レコーダが存在するか確認します.
+ *
+ * @param cameraId カメラID
+ * @return 存在する場合は true、それ以外は false
+ */
+ private boolean existRecorder(String cameraId) {
+ for (HostMediaRecorder recorder : mRecorders) {
+ if (recorder instanceof Camera2Recorder) {
+ String id = ((Camera2Recorder) recorder).getCameraWrapper().getId();
+ if (cameraId.equals(id)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * ロストしたカメラを一旦レコーダから削除します.
+ */
+ private void removeLostCamera() {
+ List removeList = new ArrayList<>();
+ for (HostMediaRecorder recorder : mRecorders) {
+ if (recorder instanceof Camera2Recorder) {
+ String cameraId = ((Camera2Recorder) recorder).getCameraWrapper().getId();
+ if (mCameraWrapperManager.getCameraById(cameraId) == null) {
+ removeList.add((Camera2Recorder) recorder);
+ }
+ }
+ }
+
+ for (Camera2Recorder recorder : removeList) {
+ recorder.destroy();
+ mRecorders.remove(recorder);
+ postOnLostRecorder(recorder);
+ }
+ }
+
/**
* 端末が対応しているレコーダを読み込みし直す
*/
public void reloadRecorders() {
- destroy();
- mRecorders.clear();
- initRecorders();
+ try {
+ mCameraWrapperManager.reload();
+
+ removeLostCamera();
+
+ for (CameraWrapper camera : mCameraWrapperManager.getCameraList()) {
+ if (existRecorder(camera.getId())) {
+ continue;
+ }
+
+ Camera2Recorder recorder = new Camera2Recorder(getContext(), camera, mFileManager, mMediaProjectionProvider);
+ initRecorder(recorder);
+ mRecorders.add(recorder);
+
+ postOnFoundRecorder(recorder);
+ }
+ } catch (Exception e) {
+ // ignore.
+ }
}
+
/**
* 指定されたレコーダが使用できるか確認します.
*
@@ -418,6 +480,8 @@ public List getCameraRecorders() {
* @return レコーダ
*/
public HostMediaRecorder getRecorder(final String id) {
+ reloadRecorders();
+
if (mRecorders.size() == 0) {
return null;
}
@@ -592,7 +656,7 @@ private void postOnConfigChanged(HostMediaRecorder recorder) {
}
}
- private void postOnPreviewStarted(HostMediaRecorder recorder, List servers) {
+ private void postOnPreviewStarted(HostMediaRecorder recorder, List servers) {
for (OnEventListener l : mOnEventListeners) {
l.onPreviewStarted(recorder, servers);
}
@@ -610,19 +674,19 @@ private void postOnPreviewError(HostMediaRecorder recorder, Exception e) {
}
}
- private void postOnBroadcasterStarted(HostMediaRecorder recorder, Broadcaster broadcaster) {
+ private void postOnBroadcasterStarted(HostMediaRecorder recorder, List broadcasters) {
for (OnEventListener l : mOnEventListeners) {
- l.onBroadcasterStarted(recorder, broadcaster);
+ l.onBroadcasterStarted(recorder, broadcasters);
}
}
- private void postOnBroadcasterStopped(HostMediaRecorder recorder, Broadcaster broadcaster) {
+ private void postOnBroadcasterStopped(HostMediaRecorder recorder) {
for (OnEventListener l : mOnEventListeners) {
- l.onBroadcasterStopped(recorder, broadcaster);
+ l.onBroadcasterStopped(recorder);
}
}
- private void postOnBroadcasterError(HostMediaRecorder recorder, Broadcaster broadcaster, Exception e) {
+ private void postOnBroadcasterError(HostMediaRecorder recorder, LiveStreaming broadcaster, Exception e) {
for (OnEventListener l : mOnEventListeners) {
l.onBroadcasterError(recorder, broadcaster, e);
}
@@ -658,6 +722,26 @@ private void postOnRecordingStopped(HostMediaRecorder recorder, String fileName)
}
}
+ private void postOnFoundRecorder(HostMediaRecorder recorder) {
+ for (OnEventListener l : mOnEventListeners) {
+ try {
+ l.onFoundRecorder(recorder);
+ } catch (Exception e) {
+ // ignore.
+ }
+ }
+ }
+
+ private void postOnLostRecorder(HostMediaRecorder recorder) {
+ for (OnEventListener l : mOnEventListeners) {
+ try {
+ l.onLostRecorder(recorder);
+ } catch (Exception e) {
+ // ignore.
+ }
+ }
+ }
+
private void postOnError(HostMediaRecorder recorder, Exception e) {
for (OnEventListener l : mOnEventListeners) {
l.onError(recorder, e);
@@ -668,13 +752,13 @@ public interface OnEventListener {
void onMuteChanged(HostMediaRecorder recorder, boolean mute);
void onConfigChanged(HostMediaRecorder recorder);
- void onPreviewStarted(HostMediaRecorder recorder, List servers);
+ void onPreviewStarted(HostMediaRecorder recorder, List servers);
void onPreviewStopped(HostMediaRecorder recorder);
void onPreviewError(HostMediaRecorder recorder, Exception e);
- void onBroadcasterStarted(HostMediaRecorder recorder, Broadcaster broadcaster);
- void onBroadcasterStopped(HostMediaRecorder recorder, Broadcaster broadcaster);
- void onBroadcasterError(HostMediaRecorder recorder, Broadcaster broadcaster, Exception e);
+ void onBroadcasterStarted(HostMediaRecorder recorder, List broadcasters);
+ void onBroadcasterStopped(HostMediaRecorder recorder);
+ void onBroadcasterError(HostMediaRecorder recorder, LiveStreaming broadcaster, Exception e);
void onTakePhoto(HostMediaRecorder recorder, String uri, String filePath, String mimeType);
@@ -683,6 +767,9 @@ public interface OnEventListener {
void onRecordingResume(HostMediaRecorder recorder);
void onRecordingStopped(HostMediaRecorder recorder, String fileName);
+ void onFoundRecorder(HostMediaRecorder recorder);
+ void onLostRecorder(HostMediaRecorder recorder);
+
void onError(HostMediaRecorder recorder, Exception e);
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/LiveStreaming.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/LiveStreaming.java
new file mode 100644
index 0000000000..858dbd5d92
--- /dev/null
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/LiveStreaming.java
@@ -0,0 +1,162 @@
+package org.deviceconnect.android.deviceplugin.host.recorder;
+
+import javax.net.ssl.SSLContext;
+
+public interface LiveStreaming {
+ /**
+ * サーバのIDします.
+ *
+ * @return サーバID
+ */
+ String getId();
+
+ /**
+ * サーバが配信するプレビューのマイムタイプを取得します.
+ *
+ * @return マイムタイプ
+ */
+ String getMimeType();
+
+ /**
+ * サーバへの URL を取得します.
+ *
+ * @return サーバへの URL
+ */
+ String getUri();
+
+ /**
+ * 起動中か確認します.
+ *
+ * @return 起動中の場合は true、それ以外は false
+ */
+ boolean isRunning();
+
+ /**
+ * サーバを開始します.
+ *
+ * @param callback 開始結果を通知するコールバック
+ */
+ void start(OnStartCallback callback);
+
+ /**
+ * サーバを停止します.
+ */
+ void stop();
+
+ /**
+ * 設定が変更されたことを通知します.
+ */
+ void onConfigChange();
+
+ /**
+ * Recorder をミュート状態にする.
+ */
+ void setMute(boolean mute);
+
+ /**
+ * Recorder のミュート状態を返す.
+ * @return mute状態
+ */
+ boolean isMuted();
+
+ /**
+ * 映像のエンコーダーに対して sync frame の即時生成を要求する.
+ *
+ * @return 即時生成を受け付けた場合はtrue, そうでない場合はfalse
+ */
+ boolean requestSyncFrame();
+
+ /**
+ * 映像のエンコーダーにビットレートの更新を要求する.
+ *
+ * @return 更新を受け付けた場合はtrue, そうでない場合はfalse
+ */
+ boolean requestBitRate();
+
+ /**
+ * JPEG 品質の更新を要求する.
+ *
+ * @return 更新を受け付けた場合はtrue, そうでない場合はfalse
+ */
+ boolean requestJpegQuality();
+
+ /**
+ * プレビューサーバから配信したデータの BPS を取得します.
+ *
+ * @return プレビューサーバから配信したデータの BPS
+ */
+ long getBPS();
+
+ /**
+ * サーバを解放します.
+ */
+ void release();
+
+ /**
+ * イベントを通知するリスナーを設定します.
+ *
+ * @param listener リスナー
+ */
+ void setOnEventListener(OnEventListener listener);
+
+ /**
+ * SSLContext を使用するかどうかのフラグを返す.
+ *
+ * @return SSLContext を使用する場合はtrue, そうでない場合はfalse
+ */
+ boolean useSSLContext();
+
+ /**
+ * SSL コンテキストの設定を行います.
+ *
+ * @param sslContext SSL コンテキスト
+ */
+ void setSSLContext(SSLContext sslContext);
+
+ /**
+ * SSL コンテキストを取得します.
+ *
+ * @return SSL コンテキスト
+ */
+ SSLContext getSSLContext();
+
+ /**
+ * 起動結果を通知するコールバック.
+ */
+ interface OnStartCallback {
+ /**
+ * 起動成功したことを通知します.
+ */
+ void onSuccess();
+
+ /**
+ * 起動失敗したことを通知します.
+ *
+ * @param e 失敗原因の例外
+ */
+ void onFailed(Exception e);
+ }
+
+ /**
+ * イベントを通知するリスナー.
+ */
+ interface OnEventListener {
+
+ /**
+ * 開始されたことを通知します.
+ */
+ void onStarted();
+
+ /**
+ * 停止されたことを通知します.
+ */
+ void onStopped();
+
+ /**
+ * エラーが発生したことを通知します.
+ *
+ * @param e エラー原因の例外
+ */
+ void onError(Exception e);
+ }
+}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/LiveStreamingProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/LiveStreamingProvider.java
new file mode 100644
index 0000000000..55f2bc5c3b
--- /dev/null
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/LiveStreamingProvider.java
@@ -0,0 +1,124 @@
+package org.deviceconnect.android.deviceplugin.host.recorder;
+
+import java.util.List;
+
+public interface LiveStreamingProvider {
+ /**
+ * 配信用のサーバを作成します.
+ *
+ * @param encoderId サーバの識別子
+ * @param encoderSettings エンコード設定
+ * @return サーバ
+ */
+ LiveStreaming createLiveStreaming(String encoderId, HostMediaRecorder.EncoderSettings encoderSettings);
+
+ /**
+ * 追加します.
+ *
+ * @param liveStreaming 追加するプレビュー配信サーバ
+ */
+ void addLiveStreaming(LiveStreaming liveStreaming);
+
+ /**
+ * 削除します.
+ *
+ * @param encoderId サーバの識別子
+ */
+ void removeLiveStreaming(String encoderId);
+
+ /**
+ * サポートしているプレビュー配信用サーバのリストを取得します.
+ * @return プレビュー配信用サーバのリスト
+ */
+ List getLiveStreamingList();
+
+ /**
+ * プレビューで配信するマイムタイプを取得します.
+ *
+ * @return プレビューで配信するマイムタイプ
+ */
+ List getSupportedMimeType();
+
+ /**
+ * プレビューサーバが動作している確認します.
+ *
+ * @return 動作中の場合は true、それ以外は false
+ */
+ boolean isRunning();
+
+ /**
+ * 全てのプレビュー配信サーバを開始します.
+ *
+ * レスポンスのリストが空の場合には、全てのプレビュー配信サーバの起動に失敗しています。
+ *
+ * @return 起動に成功したプレビュー配信サーバのリスト
+ */
+ List start();
+
+ /**
+ * 全てのプレビュー配信サーバを停止します.
+ */
+ void stop();
+
+ /**
+ * 映像のエンコーダーに対して sync frame の即時生成を要求する.
+ */
+ void requestSyncFrame();
+
+ /**
+ * 映像のエンコーダーに対してビットレートの更新を要求する。
+ */
+ void requestBitRate();
+
+ /**
+ * 映像のエンコーダーに対して JPEG の品質の更新を要求する。
+ */
+ void requestJpegQuality();
+
+ /**
+ * 設定が変更されたことを通知します.
+ */
+ void onConfigChange();
+
+ /**
+ * Recorder をミュート状態にする.
+ */
+ void setMute(boolean mute);
+
+ /**
+ * イベントを通知するリスナーを設定します.
+ *
+ * @param listener リスナー
+ */
+ void setOnEventListener(OnEventListener listener);
+
+ /**
+ * 配信用のサーバを開放します.
+ */
+ void release();
+
+ /**
+ * プレビュー配信サーバのイベントを通知するリスナー.
+ */
+ interface OnEventListener {
+ /**
+ * プレビュー配信サーバを開始したことを通知します.
+ *
+ * @param servers 開始したサーバのリスト
+ */
+ void onStarted(List servers);
+
+ /**
+ * プレビュー配信サーバを停止したことを通知します.
+ */
+ void onStopped();
+
+ /**
+ * プレビュー配信サーバでエラーが発生したことを通知します.
+ *
+ * @param server エラーが発生したサーバ
+ * @param e エラー原因の例外
+ */
+ void onError(LiveStreaming server, Exception e);
+ }
+}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/PreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/PreviewServer.java
index 7dc5f8289d..8daa347c4a 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/PreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/PreviewServer.java
@@ -6,117 +6,9 @@
*/
package org.deviceconnect.android.deviceplugin.host.recorder;
-import javax.net.ssl.SSLContext;
-
/**
* プレビュー配信用サーバを定義するインターフェース.
*/
-public interface PreviewServer {
- /**
- * サーバが配信するプレビューのマイムタイプを取得します.
- *
- * @return マイムタイプ
- */
- String getMimeType();
-
- /**
- * サーバへの URL を取得します.
- *
- * @return サーバへの URL
- */
- String getUri();
-
- /**
- * プレビュー配信サーバのポート番号を取得します.
- *
- * @return ポート番号
- */
- int getPort();
-
- /**
- * プレビュー配信サーバのポート番号を設定します.
- *
- * @param port ポート番号
- */
- void setPort(int port);
-
- /**
- * サーバを開始します.
- *
- * @param callback 開始結果を通知するコールバック
- */
- void startWebServer(OnWebServerStartCallback callback);
-
- /**
- * サーバを停止します.
- */
- void stopWebServer();
-
- /**
- * 設定が変更されたことを通知します.
- */
- void onConfigChange();
-
- /**
- * Recorder をミュート状態にする.
- */
- void setMute(boolean mute);
-
- /**
- * Recorder のミュート状態を返す.
- * @return mute状態
- */
- boolean isMuted();
-
- /**
- * 映像のエンコーダーに対して sync frame の即時生成を要求する.
- *
- * @return 即時生成を受け付けた場合はtrue, そうでない場合はfalse
- */
- boolean requestSyncFrame();
-
- /**
- * SSLContext を使用するかどうかのフラグを返す.
- *
- * @return SSLContext を使用する場合はtrue, そうでない場合はfalse
- */
- boolean useSSLContext();
-
- /**
- * SSL コンテキストの設定を行います.
- *
- * @param sslContext SSL コンテキスト
- */
- void setSSLContext(SSLContext sslContext);
-
- /**
- * SSL コンテキストを取得します.
- *
- * @return SSL コンテキスト
- */
- SSLContext getSSLContext();
-
- /**
- * プレビューサーバから配信したデータの BPS を取得します.
- *
- * @return プレビューサーバから配信したデータの BPS
- */
- long getBPS();
-
- /**
- * Callback interface used to receive the result of starting a web server.
- */
- interface OnWebServerStartCallback {
- /**
- * Called when a web server successfully started.
- *
- * @param uri An ever-updating, static image URI.
- */
- void onStart(String uri);
+public interface PreviewServer extends LiveStreaming {
- /**
- * Called when a web server failed to start.
- */
- void onFail();
- }
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/PreviewServerProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/PreviewServerProvider.java
index c8d63fdeae..a37d3133df 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/PreviewServerProvider.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/PreviewServerProvider.java
@@ -6,108 +6,6 @@
*/
package org.deviceconnect.android.deviceplugin.host.recorder;
-import java.util.List;
+public interface PreviewServerProvider extends LiveStreamingProvider {
-public interface PreviewServerProvider {
- /**
- * プレビューで配信するマイムタイプを取得します.
- *
- * @return プレビューで配信するマイムタイプ
- */
- List getSupportedMimeType();
-
- /**
- * サポートしているプレビュー配信サーバを追加します.
- *
- * @param server 追加するプレビュー配信サーバ
- */
- void addServer(PreviewServer server);
-
- /**
- * サポートしているプレビュー配信用サーバのリストを取得します.
- * @return プレビュー配信用サーバのリスト
- */
- List getServers();
-
- /**
- * 指定されたマイムタイプに対応するプレビュー配信サーバを取得します.
- *
- *
- * マイムタイプに対応したプレビュー配信サーバが存在しない場合は null を返却します。
- *
- *
- * @param mimeType マイムタイプ
- * @return プレビュー配信サーバ
- */
- PreviewServer getServerByMimeType(String mimeType);
-
- /**
- * プレビューサーバが動作している確認します.
- *
- * @return 動作中の場合は true、それ以外は false
- */
- boolean isRunning();
-
- /**
- * 全てのプレビュー配信サーバを開始します.
- *
- * レスポンスのリストが空の場合には、全てのプレビュー配信サーバの起動に失敗しています。
- *
- * @return 起動に成功したプレビュー配信サーバのリスト
- */
- List startServers();
-
- /**
- * 全てのプレビュー配信サーバを停止します.
- */
- void stopServers();
-
- /**
- * 全てのサーバの映像のエンコーダーに対して sync frame の即時生成を要求する.
- *
- * @return 実際に即時生成を受け付けたサーバのリスト
- */
- List requestSyncFrame();
-
- /**
- * 設定が変更されたことを通知します.
- */
- void onConfigChange();
-
- /**
- * Recorder をミュート状態にする.
- */
- void setMute(boolean mute);
-
- /**
- * イベントを通知するリスナーを設定します.
- *
- * @param listener リスナー
- */
- void setOnEventListener(OnEventListener listener);
-
- /**
- * プレビュー配信サーバのイベントを通知するリスナー.
- */
- interface OnEventListener {
- /**
- * プレビュー配信サーバを開始したことを通知します.
- *
- * @param servers 開始したサーバのリスト
- */
- void onStarted(List servers);
-
- /**
- * プレビュー配信サーバを停止したことを通知します.
- */
- void onStopped();
-
- /**
- * プレビュー配信サーバでエラーが発生したことを通知します.
- *
- * @param server エラーが発生したサーバ
- * @param e エラー原因の例外
- */
- void onError(PreviewServer server, Exception e);
- }
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioBroadcasterProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioBroadcasterProvider.java
index 488d9ab72a..7655c04596 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioBroadcasterProvider.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioBroadcasterProvider.java
@@ -3,25 +3,20 @@
import android.content.Context;
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractBroadcastProvider;
-import org.deviceconnect.android.deviceplugin.host.recorder.Broadcaster;
+import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
+import org.deviceconnect.android.deviceplugin.host.recorder.LiveStreaming;
public class AudioBroadcasterProvider extends AbstractBroadcastProvider {
- private final HostAudioRecorder mRecorder;
-
public AudioBroadcasterProvider(Context context, HostAudioRecorder recorder) {
super(context, recorder);
- mRecorder = recorder;
}
@Override
- public Broadcaster createBroadcaster(String broadcastURI) {
- if (broadcastURI.startsWith("srt://")) {
- return new AudioSRTBroadcaster(mRecorder, broadcastURI);
- } else if (broadcastURI.startsWith("rtmp://") || broadcastURI.startsWith("rtmps://")) {
- return new AudioRTMPBroadcaster(mRecorder, broadcastURI);
- } else {
- return null;
+ public LiveStreaming createLiveStreaming(String encoderId, HostMediaRecorder.EncoderSettings encoderSettings) {
+ if (encoderSettings.getMimeType() == HostMediaRecorder.MimeType.RTMP) {
+ return new AudioRTMPBroadcaster((HostAudioRecorder) getRecorder(), encoderId);
}
+ return null;
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioConst.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioConst.java
deleted file mode 100755
index b703559e5e..0000000000
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioConst.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- AudioConst.java
- Copyright (c) 2014 NTT DOCOMO,INC.
- Released under the MIT license
- http://opensource.org/licenses/mit-license.php
- */
-
-package org.deviceconnect.android.deviceplugin.host.recorder.audio;
-
-/**
- * 音声録音Broadcastで使用する定数を定義.
- *
- * [音声録音開始リクエストBroadcast]
- * ・ホストデバイスプラグインのHostMediaStreamingRecordingProfileから送信される。
- * ・action: SEND_HOSTDP_TO_AUDIO
- * ・putExtra(EXTRA_NAME, EXTRA_NAME_AUDIO_RECORD_START);
- *
- * [音声録音停止リクエストBroadcast]
- * ・ホストデバイスプラグインのHostMediaStreamingRecordingProfileへレスポンスを返す。
- * ・action: SEND_CAMERA_TO_AUDIO
- * ・putExtra(EXTRA_NAME, EXTRA_NAME_AUDIO_RECORD_STOP);
- *
- * [音声録音一時停止リクエストBroadcast]
- * ・ホストデバイスプラグインのHostMediaStreamingRecordingProfileへレスポンスを返す。
- * ・action: SEND_CAMERA_TO_AUDIO
- * ・putExtra(EXTRA_NAME, EXTRA_NAME_AUDIO_RECORD_PAUSE);
- *
- * @author NTT DOCOMO, INC.
- */
-public final class AudioConst {
-
- /**
- * Constructor.
- */
- private AudioConst() {
- // No operation.
- }
-
- /** Audio呼び出しアクション. */
- public static final String SEND_HOSTDP_TO_AUDIO =
- "org.deviceconnect.android.intent.action.SEND_HOSTDP_TO_AUDIO";
-
- /** コマンド名. */
- public static final String EXTRA_NAME = "command";
-
- /** 再生. */
- public static final String EXTRA_NAME_AUDIO_RECORD_START = "start";
-
- /** 停止. */
- public static final String EXTRA_NAME_AUDIO_RECORD_STOP = "stop";
-
- /** 一時停止. */
- public static final String EXTRA_NAME_AUDIO_RECORD_PAUSE = "pause";
-
- /** Resume. */
- public static final String EXTRA_NAME_AUDIO_RECORD_RESUME = "resume";
- /** ServiceのID. */
- public static final String EXTRA_SERVICE_ID = "serviceId";
- /** 使用するレコーダーのID. */
- public static final String EXTRA_RECORDER_ID = "recorderId";
-
- /** ファイル名. */
- public static final String EXTRA_FILE_NAME = "filename";
-
- /** コールバック */
- public static final String EXTRA_CALLBACK = "callback";
-
- /** コールバックのエラーメッセージ。 */
- public static final String EXTRA_CALLBACK_ERROR_MESSAGE = "callback_error_message";
-
- /** フォーマット名. */
- public static final String FORMAT_TYPE = ".aac";
-}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioPreviewServer.java
deleted file mode 100644
index bb0a0dc497..0000000000
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioPreviewServer.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.deviceconnect.android.deviceplugin.host.recorder.audio;
-
-import android.content.Context;
-
-import org.deviceconnect.android.deviceplugin.host.recorder.AbstractPreviewServer;
-import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
-
-public class AudioPreviewServer extends AbstractPreviewServer {
- /**
- * コンストラクタ.
- *
- * @param context コンテキスト
- * @param recorder プレビューで表示するレコーダ
- */
- public AudioPreviewServer(Context context, HostMediaRecorder recorder) {
- super(context, recorder);
- }
-
- @Override
- public String getMimeType() {
- return null;
- }
-
- @Override
- public String getUri() {
- return null;
- }
-
- @Override
- public void startWebServer(OnWebServerStartCallback callback) {
- }
-
- @Override
- public void stopWebServer() {
- }
-
- @Override
- public boolean requestSyncFrame() {
- return false;
- }
-
- @Override
- public long getBPS() {
- return 0;
- }
-}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioPreviewServerProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioPreviewServerProvider.java
index 5c39dc7213..5e373f1fa7 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioPreviewServerProvider.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioPreviewServerProvider.java
@@ -4,6 +4,7 @@
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractPreviewServerProvider;
import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
+import org.deviceconnect.android.deviceplugin.host.recorder.LiveStreaming;
public class AudioPreviewServerProvider extends AbstractPreviewServerProvider {
/**
@@ -14,10 +15,16 @@ public class AudioPreviewServerProvider extends AbstractPreviewServerProvider {
*/
public AudioPreviewServerProvider(Context context, HostMediaRecorder recorder) {
super(context, recorder);
+ }
- HostMediaRecorder.Settings settings = recorder.getSettings();
-
- addServer(new AudioRTSPPreviewServer(context, recorder, settings.getRtspPort()));
- addServer(new AudioSRTPreviewServer(context, recorder, settings.getSrtPort()));
+ @Override
+ public LiveStreaming createLiveStreaming(String encoderId, HostMediaRecorder.EncoderSettings encoderSettings) {
+ switch (encoderSettings.getMimeType()) {
+ case RTSP:
+ return new AudioRTSPPreviewServer(getRecorder(), encoderId);
+ case SRT:
+ return new AudioSRTPreviewServer(getRecorder(), encoderId);
+ }
+ return null;
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioRTMPBroadcaster.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioRTMPBroadcaster.java
index ac0eaf6a0f..ac4525746b 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioRTMPBroadcaster.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioRTMPBroadcaster.java
@@ -4,13 +4,15 @@
import android.graphics.Color;
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractRTMPBroadcaster;
+import org.deviceconnect.android.deviceplugin.host.recorder.Broadcaster;
import org.deviceconnect.android.libmedia.streaming.video.CanvasVideoEncoder;
import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
public class AudioRTMPBroadcaster extends AbstractRTMPBroadcaster {
private final HostAudioRecorder mRecorder;
- public AudioRTMPBroadcaster(HostAudioRecorder recorder, String broadcastURI) {
- super(recorder, broadcastURI);
+
+ public AudioRTMPBroadcaster(HostAudioRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
mRecorder = recorder;
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioRTSPPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioRTSPPreviewServer.java
index 60d3b6880f..2f1b147e8c 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioRTSPPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioRTSPPreviewServer.java
@@ -1,13 +1,10 @@
package org.deviceconnect.android.deviceplugin.host.recorder.audio;
-import android.content.Context;
-
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractRTSPPreviewServer;
import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
public class AudioRTSPPreviewServer extends AbstractRTSPPreviewServer {
- AudioRTSPPreviewServer(Context context, HostMediaRecorder recorder, int port) {
- super(context, recorder);
- setPort(port);
+ AudioRTSPPreviewServer(HostMediaRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioSRTBroadcaster.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioSRTBroadcaster.java
index 35e58e4050..0c994d59fd 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioSRTBroadcaster.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioSRTBroadcaster.java
@@ -3,7 +3,7 @@
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractSRTBroadcaster;
public class AudioSRTBroadcaster extends AbstractSRTBroadcaster {
- public AudioSRTBroadcaster(HostAudioRecorder recorder, String broadcastURI) {
- super(recorder, broadcastURI);
+ public AudioSRTBroadcaster(HostAudioRecorder recorder, String name) {
+ super(recorder, name);
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioSRTPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioSRTPreviewServer.java
index eecc2911ef..94429bf564 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioSRTPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/AudioSRTPreviewServer.java
@@ -1,13 +1,10 @@
package org.deviceconnect.android.deviceplugin.host.recorder.audio;
-import android.content.Context;
-
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractSRTPreviewServer;
import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
public class AudioSRTPreviewServer extends AbstractSRTPreviewServer {
- AudioSRTPreviewServer(final Context context, final HostMediaRecorder recorder, final int port) {
- super(context, recorder);
- setPort(port);
+ AudioSRTPreviewServer(HostMediaRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/HostAudioRecorder.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/HostAudioRecorder.java
index 0127b62c19..660d454cb1 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/HostAudioRecorder.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/audio/HostAudioRecorder.java
@@ -74,18 +74,44 @@ public HostAudioRecorder(final Context context, FileManager fileManager, MediaPr
private void initSettings() {
if (!mSettings.isInitialized()) {
mSettings.setPreviewSize(new Size(320, 240));
- mSettings.setPreviewBitRate(512 * 1024);
- mSettings.setPreviewMaxFrameRate(30);
- mSettings.setPreviewKeyFrameInterval(1);
+ // 音声設定
mSettings.setPreviewAudioSource(AudioSource.DEFAULT);
- mSettings.setPreviewAudioBitRate(64 * 1024);
- mSettings.setPreviewSampleRate(16000);
+ mSettings.setPreviewAudioBitRate(128 * 1024);
+ mSettings.setPreviewSampleRate(48000);
mSettings.setPreviewChannel(1);
mSettings.setUseAEC(true);
- mSettings.setRtspPort(32000);
- mSettings.setSrtPort(33000);
+ // 各サーバ設定
+ mSettings.addEncoder(getId() + "-RTSP");
+ EncoderSettings rtsp = mSettings.getEncoderSetting(getId() + "-RTSP");
+ rtsp.setName("RTSP");
+ rtsp.setMimeType(MimeType.RTSP);
+ rtsp.setPort(32000);
+ rtsp.setPreviewSize(new Size(320, 240));
+ rtsp.setPreviewBitRate(2 * 1024 * 1024);
+ rtsp.setPreviewMaxFrameRate(30);
+ rtsp.setPreviewKeyFrameInterval(5);
+
+ mSettings.addEncoder(getId() + "-SRT");
+ EncoderSettings srt = mSettings.getEncoderSetting(getId() + "-SRT");
+ srt.setName("SRT");
+ srt.setMimeType(MimeType.SRT);
+ srt.setPort(33000);
+ srt.setPreviewSize(new Size(320, 240));
+ srt.setPreviewBitRate(2 * 1024 * 1024);
+ srt.setPreviewMaxFrameRate(30);
+ srt.setPreviewKeyFrameInterval(5);
+
+ mSettings.addEncoder(getId() + "-RTMP");
+ EncoderSettings rtmp = mSettings.getEncoderSetting(getId() + "-RTMP");
+ rtmp.setName("RTMP");
+ rtmp.setMimeType(MimeType.RTMP);
+ rtmp.setPreviewSize(new Size(320, 240));
+ rtmp.setPreviewBitRate(2 * 1024 * 1024);
+ rtmp.setPreviewMaxFrameRate(30);
+ rtmp.setPreviewKeyFrameInterval(5);
+ rtmp.setBroadcastURI("rtmp://localhost:1935");
mSettings.finishInitialization();
}
@@ -238,7 +264,7 @@ public boolean hasVideo() {
// private method.
private String generateAudioFileName() {
- return "android_audio_" + mSimpleDateFormat.format(new Date()) + AudioConst.FORMAT_TYPE;
+ return "android_audio_" + mSimpleDateFormat.format(new Date()) + ".aac";
}
protected MP4Recorder createMP4Recorder() {
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2BroadcasterProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2BroadcasterProvider.java
index 95d167af93..4e31144488 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2BroadcasterProvider.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2BroadcasterProvider.java
@@ -3,27 +3,19 @@
import android.content.Context;
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractBroadcastProvider;
-import org.deviceconnect.android.deviceplugin.host.recorder.Broadcaster;
+import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
+import org.deviceconnect.android.deviceplugin.host.recorder.LiveStreaming;
public class Camera2BroadcasterProvider extends AbstractBroadcastProvider {
- /**
- * カメラを操作するレコーダ.
- */
- private final Camera2Recorder mRecorder;
-
public Camera2BroadcasterProvider(Context context, Camera2Recorder recorder) {
super(context, recorder);
- mRecorder = recorder;
}
@Override
- public Broadcaster createBroadcaster(String broadcastURI) {
- if (broadcastURI.startsWith("srt://")) {
- return new Camera2SRTBroadcaster(mRecorder, broadcastURI);
- } else if (broadcastURI.startsWith("rtmp://") || broadcastURI.startsWith("rtmps://")) {
- return new Camera2RTMPBroadcaster(mRecorder, broadcastURI);
- } else {
- return null;
+ public LiveStreaming createLiveStreaming(String encoderId, HostMediaRecorder.EncoderSettings encoderSettings) {
+ if (encoderSettings.getMimeType() == HostMediaRecorder.MimeType.RTMP) {
+ return new Camera2RTMPBroadcaster((Camera2Recorder) getRecorder(), encoderId);
}
+ return null;
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2MJPEGPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2MJPEGPreviewServer.java
index a124fae9e7..7071a24e74 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2MJPEGPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2MJPEGPreviewServer.java
@@ -6,21 +6,15 @@
*/
package org.deviceconnect.android.deviceplugin.host.recorder.camera;
-import android.content.Context;
-import android.graphics.SurfaceTexture;
-
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractMJPEGPreviewServer;
import org.deviceconnect.android.libmedia.streaming.mjpeg.MJPEGEncoder;
/**
* カメラのプレビューをMJPEG形式で配信するサーバー.
- *
- * {@link SurfaceTexture} をもとに実装.
*/
class Camera2MJPEGPreviewServer extends AbstractMJPEGPreviewServer {
- Camera2MJPEGPreviewServer(Context context, Camera2Recorder recorder, int port, boolean useSSL) {
- super(context, recorder, useSSL);
- setPort(port);
+ Camera2MJPEGPreviewServer(Camera2Recorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
@Override
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2PreviewServerProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2PreviewServerProvider.java
index a54dae45a4..035b108f44 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2PreviewServerProvider.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2PreviewServerProvider.java
@@ -10,6 +10,7 @@
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractPreviewServerProvider;
import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
+import org.deviceconnect.android.deviceplugin.host.recorder.LiveStreaming;
import org.deviceconnect.android.deviceplugin.host.recorder.PreviewServer;
import org.deviceconnect.android.deviceplugin.host.recorder.util.OverlayManager;
@@ -34,20 +35,12 @@ class Camera2PreviewServerProvider extends AbstractPreviewServerProvider {
*/
Camera2PreviewServerProvider(final Context context, final Camera2Recorder recorder) {
super(context, recorder);
-
mOverlayManager = new OverlayManager(context, recorder);
-
- HostMediaRecorder.Settings settings = recorder.getSettings();
-
- addServer(new Camera2MJPEGPreviewServer(context, recorder, settings.getMjpegPort(), false));
- addServer(new Camera2MJPEGPreviewServer(context, recorder, settings.getMjpegSSLPort(), true));
- addServer(new Camera2RTSPPreviewServer(context, recorder, settings.getRtspPort()));
- addServer(new Camera2SRTPreviewServer(context, recorder, settings.getSrtPort()));
}
@Override
- public List startServers() {
- List servers = super.startServers();
+ public List start() {
+ List servers = super.start();
if (!servers.isEmpty()) {
mOverlayManager.registerBroadcastReceiver();
}
@@ -55,9 +48,9 @@ public List startServers() {
}
@Override
- public void stopServers() {
+ public void stop() {
mOverlayManager.destroy();
- super.stopServers();
+ super.stop();
}
@Override
@@ -65,4 +58,17 @@ public void onConfigChange() {
super.onConfigChange();
mOverlayManager.onConfigChange();
}
+
+ @Override
+ public LiveStreaming createLiveStreaming(String encoderId, HostMediaRecorder.EncoderSettings encoderSettings) {
+ switch (encoderSettings.getMimeType()) {
+ case MJPEG:
+ return new Camera2MJPEGPreviewServer((Camera2Recorder) getRecorder(), encoderId);
+ case RTSP:
+ return new Camera2RTSPPreviewServer((Camera2Recorder) getRecorder(), encoderId);
+ case SRT:
+ return new Camera2SRTPreviewServer((Camera2Recorder) getRecorder(), encoderId);
+ }
+ return null;
+ }
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2RTMPBroadcaster.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2RTMPBroadcaster.java
index 96ab040074..7fad036ed1 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2RTMPBroadcaster.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2RTMPBroadcaster.java
@@ -5,8 +5,8 @@
public class Camera2RTMPBroadcaster extends AbstractRTMPBroadcaster {
- public Camera2RTMPBroadcaster(Camera2Recorder recorder, String broadcastURI) {
- super(recorder, broadcastURI);
+ public Camera2RTMPBroadcaster(Camera2Recorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
@Override
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2RTSPPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2RTSPPreviewServer.java
index 5b8f101439..061a512b6a 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2RTSPPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2RTSPPreviewServer.java
@@ -1,27 +1,23 @@
package org.deviceconnect.android.deviceplugin.host.recorder.camera;
-import android.content.Context;
import android.os.Build;
import androidx.annotation.RequiresApi;
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractRTSPPreviewServer;
-import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
import org.deviceconnect.android.libmedia.streaming.rtsp.session.video.VideoStream;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class Camera2RTSPPreviewServer extends AbstractRTSPPreviewServer {
- Camera2RTSPPreviewServer(Context context, Camera2Recorder recorder, int port) {
- super(context, recorder);
- setPort(port);
+ Camera2RTSPPreviewServer(Camera2Recorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
@Override
protected VideoStream createVideoStream() {
Camera2Recorder recorder = (Camera2Recorder) getRecorder();
- HostMediaRecorder.Settings settings = recorder.getSettings();
- switch (settings.getPreviewEncoderName()) {
+ switch (getEncoderSettings().getPreviewEncoderName()) {
case H264:
default:
return new CameraH264VideoStream(recorder, 5006);
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2Recorder.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2Recorder.java
index 4ea30ff09c..db69ceede8 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2Recorder.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2Recorder.java
@@ -39,11 +39,35 @@
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class Camera2Recorder extends AbstractMediaRecorder {
+ protected static final List ENCODE_SIZE_LIST = Arrays.asList(
+ new Size(128, 96),
+ new Size(320, 240),
+ new Size(640, 480),
+ new Size(800, 600),
+ new Size(1024, 768),
+ new Size(1280, 960),
+ new Size(1440, 1080),
+ new Size(1600, 1200),
+ new Size(320, 180),
+ new Size(640, 360),
+ new Size(854, 480),
+ new Size(1280, 720),
+ new Size(1366, 768),
+ new Size(1920, 1080),
+ new Size(2560, 1440),
+ new Size(3840, 2160),
+ new Size(5760, 3240),
+ new Size(7680, 4320)
+ );
+
/**
* カメラターゲットIDの定義.
*/
@@ -150,49 +174,96 @@ public Camera2Recorder(Context context, CameraWrapper camera, FileManager fileMa
mCamera2BroadcasterProvider = new Camera2BroadcasterProvider(context, this);
}
+ /**
+ * サイズの小さい方からソートを行うための比較演算子.
+ */
+ private static final Comparator SIZE_COMPARATOR = (lhs, rhs) -> {
+ // We cast here to ensure the multiplications won't overflow
+ return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
+ (long) rhs.getWidth() * rhs.getHeight());
+ };
+
+ private List getEncoderSizeList() {
+ Size maxSize = CapabilityUtil.getSupportedMaxSize(VideoCodec.H264.getMimeType());
+ List sizes = new ArrayList<>();
+ for (Size size : ENCODE_SIZE_LIST) {
+ if (size.getWidth() <= maxSize.getWidth() && size.getHeight() <= maxSize.getHeight()) {
+ sizes.add(size);
+ }
+ }
+ Collections.sort(sizes, SIZE_COMPARATOR);
+ return sizes;
+ }
+
/**
* レコーダの設定を初期化します.
*/
private void initSupportedSettings() {
CameraWrapper.Options options = mCameraWrapper.getOptions();
- // MediaCodec でエンコードできる最大解像度を取得
- // TODO h264, h265 で最大解像度が違う場合はどうするべきか?
- // TODO ハードウェアエンコーダとソフトウェアエンコーダで最大解像度が違うのはどうするべきか?
- Size maxSize = CapabilityUtil.getSupportedMaxSize("video/avc");
- List supportPreviewSizes = new ArrayList<>();
- for (Size size : options.getSupportedPreviewSizeList()) {
- if (maxSize != null) {
- if (size.getWidth() <= maxSize.getWidth() && size.getHeight() <= maxSize.getHeight()) {
- supportPreviewSizes.add(size);
- }
- }
- }
-
+ List> supportedFpsList = options.getSupportedFpsList();
mSettings.mSupportedPictureSize = new ArrayList<>(options.getSupportedPictureSizeList());
- mSettings.mSupportedPreviewSize = supportPreviewSizes;
+ mSettings.mSupportedPreviewSize = new ArrayList<>(options.getSupportedPreviewSizeList());
+ mSettings.mSupportedEncoderSize = getEncoderSizeList();
if (!mSettings.isInitialized()) {
+ // カメラ設定
mSettings.setPictureSize(options.getDefaultPictureSize());
mSettings.setPreviewSize(options.getDefaultPreviewSize());
- mSettings.setPreviewBitRate(2 * 1024 * 1024);
- mSettings.setPreviewMaxFrameRate(30);
- mSettings.setPreviewKeyFrameInterval(1);
- mSettings.setPreviewQuality(80);
mSettings.setPreviewAutoFocusMode(options.getAutoFocusMode());
mSettings.setPreviewWhiteBalance(options.getAutoWhiteBalanceMode());
mSettings.setPreviewWhiteBalanceTemperature(5600);
+ if (supportedFpsList.size() > 0) {
+ mSettings.setPreviewFps(supportedFpsList.get(supportedFpsList.size() - 1));
+ }
+ mSettings.setOrientation(Surface.ROTATION_90);
+ // 音声設定
mSettings.setPreviewAudioSource(null);
- mSettings.setPreviewAudioBitRate(64 * 1024);
- mSettings.setPreviewSampleRate(16000);
+ mSettings.setPreviewAudioBitRate(128 * 1024);
+ mSettings.setPreviewSampleRate(48000);
mSettings.setPreviewChannel(1);
mSettings.setUseAEC(true);
- mSettings.setMjpegPort(11000 + mFacing.mValue);
- mSettings.setMjpegSSLPort(11100 + mFacing.mValue);
- mSettings.setRtspPort(12000 + mFacing.mValue);
- mSettings.setSrtPort(13000 + mFacing.mValue);
+ // 各サーバ設定
+ mSettings.addEncoder(getId() + "-MJPEG");
+ EncoderSettings mjpeg = mSettings.getEncoderSetting(getId() + "-MJPEG");
+ mjpeg.setName("MJPEG");
+ mjpeg.setMimeType(MimeType.MJPEG);
+ mjpeg.setPort(11000 + mFacing.mValue);
+ mjpeg.setPreviewSize(options.getDefaultPreviewSize());
+ mjpeg.setPreviewQuality(80);
+ mjpeg.setPreviewMaxFrameRate(30);
+
+ mSettings.addEncoder(getId() + "-RTSP");
+ EncoderSettings rtsp = mSettings.getEncoderSetting(getId() + "-RTSP");
+ rtsp.setName("RTSP");
+ rtsp.setMimeType(MimeType.RTSP);
+ rtsp.setPort(12000 + mFacing.mValue);
+ rtsp.setPreviewSize(options.getDefaultPreviewSize());
+ rtsp.setPreviewBitRate(2 * 1024 * 1024);
+ rtsp.setPreviewMaxFrameRate(30);
+ rtsp.setPreviewKeyFrameInterval(5);
+
+ mSettings.addEncoder(getId() + "-SRT");
+ EncoderSettings srt = mSettings.getEncoderSetting(getId() + "-SRT");
+ srt.setName("SRT");
+ srt.setMimeType(MimeType.SRT);
+ srt.setPort(13000 + mFacing.mValue);
+ srt.setPreviewSize(options.getDefaultPreviewSize());
+ srt.setPreviewBitRate(2 * 1024 * 1024);
+ srt.setPreviewMaxFrameRate(30);
+ srt.setPreviewKeyFrameInterval(5);
+
+ mSettings.addEncoder(getId() + "-RTMP");
+ EncoderSettings rtmp = mSettings.getEncoderSetting(getId() + "-RTMP");
+ rtmp.setName("RTMP");
+ rtmp.setMimeType(MimeType.RTMP);
+ rtmp.setPreviewSize(options.getDefaultPreviewSize());
+ rtmp.setPreviewBitRate(2 * 1024 * 1024);
+ rtmp.setPreviewMaxFrameRate(30);
+ rtmp.setPreviewKeyFrameInterval(5);
+ rtmp.setBroadcastURI("rtmp://localhost:1935");
mSettings.finishInitialization();
}
@@ -207,8 +278,8 @@ public CameraWrapper getCameraWrapper() {
@Override
public synchronized void clean() {
super.clean();
- mCamera2BroadcasterProvider.stopBroadcaster();
- mCamera2PreviewServerProvider.stopServers();
+ mCamera2BroadcasterProvider.stop();
+ mCamera2PreviewServerProvider.stop();
mCameraSurfaceDrawingThread.stop(true);
}
@@ -220,7 +291,7 @@ public void destroy() {
@Override
public String getId() {
- return ID_BASE + "_" + mCameraWrapper.getId();
+ return ID_BASE + "_" + mCameraWrapper.getId().replaceAll("/", "_");
}
@Override
@@ -241,6 +312,7 @@ public String getMimeType() {
@Override
public List getSupportedMimeTypes() {
List mimeTypes = mCamera2PreviewServerProvider.getSupportedMimeType();
+ mimeTypes.addAll(mCamera2BroadcasterProvider.getSupportedMimeType());
mimeTypes.add(0, MIME_TYPE_JPEG);
return mimeTypes;
}
@@ -409,8 +481,13 @@ private void takePhotoInternal(final @NonNull OnPhotoEventListener listener) {
return;
}
+ int currentRotation = mCurrentRotation;
+ if (getSettings().getOrientation() != -1) {
+ currentRotation = getSettings().getOrientation();
+ }
+
byte[] jpeg = ImageUtil.convertToJPEG(photo);
- int deviceRotation = ROTATIONS.get(mCurrentRotation);
+ int deviceRotation = ROTATIONS.get(currentRotation);
int cameraRotation = mCameraWrapper.getSensorOrientation();
int degrees = (360 - deviceRotation + cameraRotation) % 360;
if (mFacing == CameraFacing.FRONT) {
@@ -493,14 +570,24 @@ public static CameraFacing detect(CameraWrapper cameraWrapper) {
}
private class CameraSettings extends Settings {
-
private List mSupportedPictureSize = new ArrayList<>();
private List mSupportedPreviewSize = new ArrayList<>();
+ private List mSupportedEncoderSize;
CameraSettings(Context context, HostMediaRecorder recorder) {
super(context, recorder);
}
+ @Override
+ protected EncoderSettings createEncoderSettings(String encoderId) {
+ return new EncoderSettings(getContext(), encoderId) {
+ @Override
+ public List getSupportedEncoderSizes() {
+ return mSupportedEncoderSize;
+ }
+ };
+ }
+
@Override
public List getSupportedPictureSizes() {
return mSupportedPictureSize;
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2SRTBroadcaster.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2SRTBroadcaster.java
index 54e3ea26c2..e71ddbd2c1 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2SRTBroadcaster.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2SRTBroadcaster.java
@@ -1,20 +1,18 @@
package org.deviceconnect.android.deviceplugin.host.recorder.camera;
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractSRTBroadcaster;
-import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
public class Camera2SRTBroadcaster extends AbstractSRTBroadcaster {
- public Camera2SRTBroadcaster(Camera2Recorder recorder, String broadcastURI) {
- super(recorder, broadcastURI);
+ public Camera2SRTBroadcaster(Camera2Recorder recorder, String id) {
+ super(recorder, id);
}
@Override
protected VideoEncoder createVideoEncoder() {
Camera2Recorder recorder = (Camera2Recorder) getRecorder();
- HostMediaRecorder.Settings settings = recorder.getSettings();
- switch (settings.getPreviewEncoderName()) {
+ switch (getEncoderSettings().getPreviewEncoderName()) {
case H264:
default:
return new CameraVideoEncoder(recorder);
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2SRTPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2SRTPreviewServer.java
index 126d6f4037..a7d97a5f40 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2SRTPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/Camera2SRTPreviewServer.java
@@ -1,22 +1,17 @@
package org.deviceconnect.android.deviceplugin.host.recorder.camera;
-import android.content.Context;
-
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractSRTPreviewServer;
-import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
public class Camera2SRTPreviewServer extends AbstractSRTPreviewServer {
- Camera2SRTPreviewServer(final Context context, final Camera2Recorder recorder, final int port) {
- super(context, recorder);
- setPort(port);
+ Camera2SRTPreviewServer(Camera2Recorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
@Override
protected VideoEncoder createVideoEncoder() {
Camera2Recorder recorder = (Camera2Recorder) getRecorder();
- HostMediaRecorder.Settings settings = recorder.getSettings();
- switch (settings.getPreviewEncoderName()) {
+ switch (getEncoderSettings().getPreviewEncoderName()) {
case H264:
default:
return new CameraVideoEncoder(recorder);
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraMJPEGEncoder.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraMJPEGEncoder.java
index 37678b9441..7a7adf0059 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraMJPEGEncoder.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraMJPEGEncoder.java
@@ -3,26 +3,7 @@
import org.deviceconnect.android.libmedia.streaming.mjpeg.SurfaceMJPEGEncoder;
public class CameraMJPEGEncoder extends SurfaceMJPEGEncoder {
-
CameraMJPEGEncoder(Camera2Recorder recorder) {
super(recorder.getSurfaceDrawingThread());
}
-
- // SurfaceMJPEGEncoder
-
- @Override
- protected void prepare() {
- }
-
- @Override
- protected void startRecording() {
- }
-
- @Override
- protected void stopRecording() {
- }
-
- @Override
- protected void release() {
- }
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraSurfaceDrawingThread.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraSurfaceDrawingThread.java
index 6c3e88350f..92d52d0122 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraSurfaceDrawingThread.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraSurfaceDrawingThread.java
@@ -7,6 +7,7 @@
import android.view.WindowManager;
import org.deviceconnect.android.deviceplugin.host.camera.CameraWrapper;
+import org.deviceconnect.android.deviceplugin.host.camera.CameraWrapperException;
import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
import org.deviceconnect.android.libmedia.streaming.gles.EGLSurfaceDrawingThread;
import org.deviceconnect.android.libmedia.streaming.gles.SurfaceTextureManager;
@@ -28,11 +29,15 @@ public CameraSurfaceDrawingThread(Camera2Recorder recorder) {
@Override
public int getDisplayRotation() {
- WindowManager wm = (WindowManager) mRecorder.getContext().getSystemService(Context.WINDOW_SERVICE);
- if (wm == null) {
- throw new RuntimeException("WindowManager is not supported.");
+ int orientation = mRecorder.getSettings().getOrientation();
+ if (orientation == -1) {
+ WindowManager wm = (WindowManager) mRecorder.getContext().getSystemService(Context.WINDOW_SERVICE);
+ if (wm == null) {
+ throw new RuntimeException("WindowManager is not supported.");
+ }
+ return wm.getDefaultDisplay().getRotation();
}
- return wm.getDefaultDisplay().getRotation();
+ return orientation;
}
@Override
@@ -59,69 +64,64 @@ public boolean isSwappedDimensions() {
@Override
protected void onStarted() {
- startCamera(getSurfaceTexture());
+ try {
+ startCamera(getSurfaceTexture());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
@Override
protected void onStopped() {
- stopCamera();
+ try {
+ stopCamera();
+ } catch (Exception e) {
+ // ignore.
+ }
}
@Override
public void start() {
HostMediaRecorder.Settings settings = mRecorder.getSettings();
Size previewSize = settings.getPreviewSize();
- if (previewSize != null) {
- setSize(previewSize.getWidth(), previewSize.getHeight());
- setDrawingRange(settings.getDrawingRange());
- super.start();
- }
+ int w = isSwappedDimensions() ? previewSize.getHeight() : previewSize.getWidth();
+ int h = isSwappedDimensions() ? previewSize.getWidth() : previewSize.getHeight();
+ setSize(w, h);
+ super.start();
}
@Override
protected SurfaceTextureManager createStManager() {
+ HostMediaRecorder.Settings settings = mRecorder.getSettings();
+ Size previewSize = settings.getPreviewSize();
SurfaceTextureManager manager = new SurfaceTextureManager();
SurfaceTexture st = manager.getSurfaceTexture();
- st.setDefaultBufferSize(getWidth(), getHeight());
- if (getDrawingRange() != null) {
- // カメラは描画時に端末の向きによって回転するので、ここでは描画範囲の計算も回転してから行う
- int w = isSwappedDimensions() ? getHeight() : getWidth();
- int h = isSwappedDimensions() ? getWidth() : getHeight();
- manager.setDrawingRange(getDrawingRange(), w, h);
- }
+ st.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
return manager;
}
- private void startCamera(SurfaceTexture surfaceTexture) {
- try {
- HostMediaRecorder.Settings settings = mRecorder.getSettings();
- CameraWrapper cameraWrapper = mRecorder.getCameraWrapper();
- cameraWrapper.getOptions().setPictureSize(settings.getPictureSize());
- cameraWrapper.getOptions().setPreviewSize(settings.getPreviewSize());
- cameraWrapper.getOptions().setFps(settings.getPreviewMaxFrameRate());
- cameraWrapper.getOptions().setAutoFocusMode(settings.getPreviewAutoFocusMode());
- cameraWrapper.getOptions().setAutoWhiteBalanceMode(settings.getPreviewWhiteBalance());
- cameraWrapper.getOptions().setWhiteBalanceTemperature(settings.getPreviewWhiteBalanceTemperature());
- cameraWrapper.getOptions().setAutoExposureMode(settings.getAutoExposureMode());
- cameraWrapper.getOptions().setSensorExposureTime(settings.getSensorExposureTime());
- cameraWrapper.getOptions().setSensorSensitivity(settings.getSensorSensitivity());
- cameraWrapper.getOptions().setSensorFrameDuration(settings.getSensorFrameDuration());
- cameraWrapper.getOptions().setStabilizationMode(settings.getStabilizationMode());
- cameraWrapper.getOptions().setOpticalStabilizationMode(settings.getOpticalStabilizationMode());
- cameraWrapper.getOptions().setDigitalZoom(settings.getDigitalZoom());
- cameraWrapper.getOptions().setNoiseReductionMode(settings.getNoiseReduction());
- cameraWrapper.getOptions().setFocalLength(settings.getFocalLength());
- cameraWrapper.startPreview(new Surface(surfaceTexture));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ private void startCamera(SurfaceTexture surfaceTexture) throws CameraWrapperException {
+ HostMediaRecorder.Settings settings = mRecorder.getSettings();
+ CameraWrapper cameraWrapper = mRecorder.getCameraWrapper();
+ cameraWrapper.getOptions().setPictureSize(settings.getPictureSize());
+ cameraWrapper.getOptions().setPreviewSize(settings.getPreviewSize());
+ cameraWrapper.getOptions().setFps(settings.getPreviewFps());
+ cameraWrapper.getOptions().setAutoFocusMode(settings.getPreviewAutoFocusMode());
+ cameraWrapper.getOptions().setAutoWhiteBalanceMode(settings.getPreviewWhiteBalance());
+ cameraWrapper.getOptions().setWhiteBalanceTemperature(settings.getPreviewWhiteBalanceTemperature());
+ cameraWrapper.getOptions().setAutoExposureMode(settings.getAutoExposureMode());
+ cameraWrapper.getOptions().setSensorExposureTime(settings.getSensorExposureTime());
+ cameraWrapper.getOptions().setSensorSensitivity(settings.getSensorSensitivity());
+ cameraWrapper.getOptions().setSensorFrameDuration(settings.getSensorFrameDuration());
+ cameraWrapper.getOptions().setStabilizationMode(settings.getStabilizationMode());
+ cameraWrapper.getOptions().setOpticalStabilizationMode(settings.getOpticalStabilizationMode());
+ cameraWrapper.getOptions().setDigitalZoom(settings.getDigitalZoom());
+ cameraWrapper.getOptions().setNoiseReductionMode(settings.getNoiseReduction());
+ cameraWrapper.getOptions().setFocalLength(settings.getFocalLength());
+ cameraWrapper.startPreview(new Surface(surfaceTexture));
}
private void stopCamera() {
- try {
- mRecorder.getCameraWrapper().stopPreview();
- } catch (Exception e) {
- // ignore.
- }
+ mRecorder.getCameraWrapper().stopPreview();
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraVideoEncoder.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraVideoEncoder.java
index c39c186efd..cf4ca573d0 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraVideoEncoder.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/camera/CameraVideoEncoder.java
@@ -28,14 +28,4 @@ public CameraVideoEncoder(Camera2Recorder recorder, String mimeType) {
public VideoQuality getVideoQuality() {
return mVideoQuality;
}
-
- // SurfaceVideoEncoder
-
- @Override
- protected void onStartSurfaceDrawing() {
- }
-
- @Override
- protected void onStopSurfaceDrawing() {
- }
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastBroadcasterProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastBroadcasterProvider.java
index 140084d553..fbb047d1dc 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastBroadcasterProvider.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastBroadcasterProvider.java
@@ -3,25 +3,20 @@
import android.content.Context;
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractBroadcastProvider;
-import org.deviceconnect.android.deviceplugin.host.recorder.Broadcaster;
+import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
+import org.deviceconnect.android.deviceplugin.host.recorder.LiveStreaming;
public class ScreenCastBroadcasterProvider extends AbstractBroadcastProvider {
- private final ScreenCastRecorder mRecorder;
-
public ScreenCastBroadcasterProvider(Context context, ScreenCastRecorder recorder) {
super(context, recorder);
- mRecorder = recorder;
}
@Override
- public Broadcaster createBroadcaster(String broadcastURI) {
- if (broadcastURI.startsWith("srt://")) {
- return new ScreenCastSRTBroadcaster(mRecorder, broadcastURI);
- } else if (broadcastURI.startsWith("rtmp://") || broadcastURI.startsWith("rtmps://")) {
- return new ScreenCastRTMPBroadcaster(mRecorder, broadcastURI);
- } else {
- return null;
+ public LiveStreaming createLiveStreaming(String encoderId, HostMediaRecorder.EncoderSettings encoderSettings) {
+ if (encoderSettings.getMimeType() == HostMediaRecorder.MimeType.RTMP) {
+ return new ScreenCastRTMPBroadcaster((ScreenCastRecorder) getRecorder(), encoderId);
}
+ return null;
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastMJPEGEncoder.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastMJPEGEncoder.java
index 964a39c031..8c3e2c59b8 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastMJPEGEncoder.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastMJPEGEncoder.java
@@ -3,24 +3,7 @@
import org.deviceconnect.android.libmedia.streaming.mjpeg.SurfaceMJPEGEncoder;
public class ScreenCastMJPEGEncoder extends SurfaceMJPEGEncoder {
-
ScreenCastMJPEGEncoder(ScreenCastRecorder recorder) {
super(recorder.getSurfaceDrawingThread());
}
-
- @Override
- protected void prepare() {
- }
-
- @Override
- protected void startRecording() {
- }
-
- @Override
- protected void stopRecording() {
- }
-
- @Override
- protected void release() {
- }
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastMJPEGPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastMJPEGPreviewServer.java
index 049af34fb6..547bda2aeb 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastMJPEGPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastMJPEGPreviewServer.java
@@ -9,10 +9,8 @@
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class ScreenCastMJPEGPreviewServer extends AbstractMJPEGPreviewServer {
-
- ScreenCastMJPEGPreviewServer(Context context, ScreenCastRecorder recorder, int port, boolean useSSL) {
- super(context, recorder, useSSL);
- setPort(port);
+ ScreenCastMJPEGPreviewServer(ScreenCastRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
@Override
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastPreviewServerProvider.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastPreviewServerProvider.java
index 30f1143ef4..5bf23c4e11 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastPreviewServerProvider.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastPreviewServerProvider.java
@@ -4,6 +4,9 @@
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractPreviewServerProvider;
import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
+import org.deviceconnect.android.deviceplugin.host.recorder.LiveStreaming;
+
+import java.util.List;
/**
* スクリーンキャストのプレビューを配信するサーバを管理するクラス.
@@ -11,12 +14,18 @@
class ScreenCastPreviewServerProvider extends AbstractPreviewServerProvider {
ScreenCastPreviewServerProvider(Context context, ScreenCastRecorder recorder) {
super(context, recorder);
+ }
- HostMediaRecorder.Settings settings = recorder.getSettings();
-
- addServer(new ScreenCastMJPEGPreviewServer(context, recorder, settings.getMjpegPort(), false));
- addServer(new ScreenCastMJPEGPreviewServer(context, recorder, settings.getMjpegSSLPort(), true));
- addServer(new ScreenCastRTSPPreviewServer(context, recorder, settings.getRtspPort()));
- addServer(new ScreenCastSRTPreviewServer(context, recorder, settings.getSrtPort()));
+ @Override
+ public LiveStreaming createLiveStreaming(String encoderId, HostMediaRecorder.EncoderSettings encoderSettings) {
+ switch (encoderSettings.getMimeType()) {
+ case MJPEG:
+ return new ScreenCastMJPEGPreviewServer((ScreenCastRecorder) getRecorder(), encoderId);
+ case RTSP:
+ return new ScreenCastRTSPPreviewServer((ScreenCastRecorder) getRecorder(), encoderId);
+ case SRT:
+ return new ScreenCastSRTPreviewServer((ScreenCastRecorder) getRecorder(), encoderId);
+ }
+ return null;
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRTMPBroadcaster.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRTMPBroadcaster.java
index 3a7a3b3f27..1386dd0194 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRTMPBroadcaster.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRTMPBroadcaster.java
@@ -4,8 +4,8 @@
import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
public class ScreenCastRTMPBroadcaster extends AbstractRTMPBroadcaster {
- public ScreenCastRTMPBroadcaster(ScreenCastRecorder recorder, String broadcastURI) {
- super(recorder, broadcastURI);
+ public ScreenCastRTMPBroadcaster(ScreenCastRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
@Override
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRTSPPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRTSPPreviewServer.java
index 0645c27c4e..3c9e452853 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRTSPPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRTSPPreviewServer.java
@@ -1,31 +1,27 @@
package org.deviceconnect.android.deviceplugin.host.recorder.screen;
-import android.content.Context;
import android.os.Build;
import androidx.annotation.RequiresApi;
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractRTSPPreviewServer;
-import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
import org.deviceconnect.android.libmedia.streaming.rtsp.session.video.VideoStream;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class ScreenCastRTSPPreviewServer extends AbstractRTSPPreviewServer {
- ScreenCastRTSPPreviewServer(Context context, ScreenCastRecorder recorder, int port) {
- super(context, recorder);
- setPort(port);
+ ScreenCastRTSPPreviewServer(ScreenCastRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
@Override
protected VideoStream createVideoStream() {
ScreenCastRecorder recorder = (ScreenCastRecorder) getRecorder();
- HostMediaRecorder.Settings settings = recorder.getSettings();
- switch (settings.getPreviewEncoderName()) {
+ switch (getEncoderSettings().getPreviewEncoderName()) {
case H264:
default:
- return new ScreenCastH264VideoStream(recorder, 5006);
+ return new ScreenCastH264VideoStream(recorder, 5016);
case H265:
- return new ScreenCastH265VideoStream(recorder, 5006);
+ return new ScreenCastH265VideoStream(recorder, 5016);
}
}
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRecorder.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRecorder.java
index 5230447ff2..d11bb0a370 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRecorder.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRecorder.java
@@ -90,15 +90,22 @@ public ScreenCastRecorder(Context context, FileManager fileMgr, MediaProjectionP
mScreenCastBroadcasterProvider = new ScreenCastBroadcasterProvider(context, this);
}
+ private List getEncoderSizeList(List supportPreviewSizes) {
+ List sizes = new ArrayList<>();
+ Size maxSize = CapabilityUtil.getSupportedMaxSize(VideoCodec.H264.getMimeType());
+ for (Size size : supportPreviewSizes) {
+ if (size.getWidth() <= maxSize.getWidth() && size.getHeight() <= maxSize.getHeight()
+ || size.getWidth() <= maxSize.getHeight() && size.getHeight() <= maxSize.getWidth()) {
+ sizes.add(size);
+ }
+ }
+ return sizes;
+ }
+
/**
* レコーダの設定を初期化します.
*/
private void initSupportedSettings() {
- // MediaCodec でエンコードできる最大解像度を取得
- // TODO h264, h265 で最大解像度が違う場合はどうするべきか?
- // TODO ハードウェアエンコーダとソフトウェアエンコーダで最大解像度が違うのはどうするべきか?
- Size maxSize = CapabilityUtil.getSupportedMaxSize("video/avc");
-
Size originalSize = getDisplaySize();
List supportPictureSizes = new ArrayList<>();
List supportPreviewSizes = new ArrayList<>();
@@ -116,14 +123,11 @@ private void initSupportedSettings() {
Size size = new Size(width, height);
supportPictureSizes.add(size);
- if (maxSize != null) {
- if (size.getWidth() <= maxSize.getWidth() && size.getHeight() <= maxSize.getHeight()) {
- supportPreviewSizes.add(size);
- }
- }
+ supportPreviewSizes.add(size);
}
mSettings.mSupportedPreviewSize = supportPreviewSizes;
mSettings.mSupportedPictureSize = supportPictureSizes;
+ mSettings.mSupportEncoderSizeList = getEncoderSizeList(supportPreviewSizes);
List> supportFps = new ArrayList<>();
supportFps.add(new Range<>(30, 30));
@@ -132,20 +136,55 @@ private void initSupportedSettings() {
if (!mSettings.isInitialized()) {
mSettings.setPreviewSize(mSettings.getSupportedPreviewSizes().get(0));
mSettings.setPictureSize(mSettings.getSupportedPictureSizes().get(0));
- mSettings.setPreviewBitRate(2 * 1024 * 1024);
- mSettings.setPreviewMaxFrameRate(30);
- mSettings.setPreviewKeyFrameInterval(1);
- mSettings.setPreviewQuality(80);
+ mSettings.setOrientation(Surface.ROTATION_90);
- mSettings.setPreviewAudioBitRate(64 * 1024);
- mSettings.setPreviewSampleRate(16000);
+ // 音声設定
+ mSettings.setPreviewAudioSource(null);
+ mSettings.setPreviewAudioBitRate(128 * 1024);
+ mSettings.setPreviewSampleRate(48000);
mSettings.setPreviewChannel(1);
mSettings.setUseAEC(true);
- mSettings.setMjpegPort(21000);
- mSettings.setMjpegSSLPort(21100);
- mSettings.setRtspPort(22000);
- mSettings.setSrtPort(23000);
+ // プレビュー配信サーバ設定
+ mSettings.addEncoder(getId() + "-MJPEG");
+ EncoderSettings mjpeg = mSettings.getEncoderSetting(getId() + "-MJPEG");
+ mjpeg.setName("MJPEG");
+ mjpeg.setMimeType(MimeType.MJPEG);
+ mjpeg.setPort(21000);
+ mjpeg.setPreviewSize(mSettings.getSupportedPreviewSizes().get(0));
+ mjpeg.setPreviewQuality(80);
+ mjpeg.setPreviewMaxFrameRate(30);
+
+ mSettings.addEncoder(getId() + "-RTSP");
+ EncoderSettings rtsp = mSettings.getEncoderSetting(getId() + "-RTSP");
+ rtsp.setName("RTSP");
+ rtsp.setMimeType(MimeType.RTSP);
+ rtsp.setPort(22000);
+ rtsp.setPreviewSize(mSettings.getSupportedPreviewSizes().get(0));
+ rtsp.setPreviewBitRate(2 * 1024 * 1024);
+ rtsp.setPreviewMaxFrameRate(30);
+ rtsp.setPreviewKeyFrameInterval(5);
+
+ mSettings.addEncoder(getId() + "-SRT");
+ EncoderSettings srt = mSettings.getEncoderSetting(getId() + "-SRT");
+ srt.setName("SRT");
+ srt.setMimeType(MimeType.SRT);
+ srt.setPort(23000);
+ srt.setPreviewSize(mSettings.getSupportedPreviewSizes().get(0));
+ srt.setPreviewBitRate(2 * 1024 * 1024);
+ srt.setPreviewMaxFrameRate(30);
+ srt.setPreviewKeyFrameInterval(5);
+
+ // 配信設定
+ mSettings.addEncoder(getId() + "-RTMP");
+ EncoderSettings rtmp = mSettings.getEncoderSetting(getId() + "-RTMP");
+ rtmp.setName("RTMP");
+ rtmp.setMimeType(MimeType.RTMP);
+ rtmp.setPreviewSize(mSettings.getSupportedPreviewSizes().get(0));
+ rtmp.setPreviewBitRate(2 * 1024 * 1024);
+ rtmp.setPreviewMaxFrameRate(30);
+ rtmp.setPreviewKeyFrameInterval(5);
+ rtmp.setBroadcastURI("rtmp://localhost:1935");
mSettings.finishInitialization();
}
@@ -161,52 +200,36 @@ private Size getDisplaySize() {
if (wm == null) {
throw new RuntimeException("WindowManager is not supported.");
}
- DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
- boolean isSwap;
- switch (wm.getDefaultDisplay().getRotation()) {
- case Surface.ROTATION_0:
- case Surface.ROTATION_180:
- isSwap = false;
- break;
- default:
- case Surface.ROTATION_90:
- case Surface.ROTATION_270:
- isSwap = true;
- break;
- }
+
int insetsWidth = 0;
int insetsHeight = 0;
Size displaySize;
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WindowMetrics windowMetrics = wm.getCurrentWindowMetrics();
- final WindowInsets windowInsets = windowMetrics.getWindowInsets();
+ WindowInsets windowInsets = windowMetrics.getWindowInsets();
Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
| WindowInsets.Type.displayCutout());
-
- int width = isSwap ? windowMetrics.getBounds().height() :windowMetrics.getBounds().width();
- int height = isSwap ? windowMetrics.getBounds().width() :windowMetrics.getBounds().height();
+ int width = windowMetrics.getBounds().width();
+ int height = windowMetrics.getBounds().height();
insetsWidth = insets.right + insets.left;
insetsHeight = insets.top + insets.bottom;
-
- // Legacy size that Display#getSize reports
- displaySize = new Size(width - insetsWidth,
- height - insetsHeight);
+ displaySize = new Size(width - insetsWidth, height - insetsHeight);
} else {
- // 画面が回転している場合には、縦横をスワップしておく。
- int width = isSwap ? metrics.heightPixels : metrics.widthPixels;
- int height = isSwap ? metrics.widthPixels : metrics.heightPixels;
- displaySize = new Size(width, height);
+ DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
+ displaySize = new Size(metrics.widthPixels, metrics.heightPixels);
}
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Display.Mode[] modes = wm.getDefaultDisplay().getSupportedModes();
- if(modes.length > 0){
+ if (modes.length > 0){
Display.Mode mode = modes[modes.length - 1];
- int width = isSwap ? mode.getPhysicalHeight() : mode.getPhysicalWidth();
- int height = isSwap ? mode.getPhysicalWidth() : mode.getPhysicalHeight();
- // 4Kサイズの解像度がある場合はそちらを優先する
+ int width = mode.getPhysicalWidth();
+ int height = mode.getPhysicalHeight();
+ // 4K サイズの解像度がある場合はそちらを優先する
displaySize = new Size(width - insetsWidth, height - insetsHeight);
}
}
+
return displaySize;
}
@@ -218,8 +241,8 @@ public EGLSurfaceDrawingThread getSurfaceDrawingThread() {
@Override
public void clean() {
super.clean();
- mScreenCastBroadcasterProvider.stopBroadcaster();
- mScreenCastPreviewServerProvider.stopServers();
+ mScreenCastBroadcasterProvider.stop();
+ mScreenCastPreviewServerProvider.stop();
mScreenCastMgr.clean();
}
@@ -242,6 +265,7 @@ public String getMimeType() {
@Override
public List getSupportedMimeTypes() {
List mimeTypes = mScreenCastPreviewServerProvider.getSupportedMimeType();
+ mimeTypes.addAll(mScreenCastBroadcasterProvider.getSupportedMimeType());
mimeTypes.add(0, MIME_TYPE_JPEG);
return mimeTypes;
}
@@ -379,15 +403,26 @@ private void takePhotoInternal(final @NonNull OnPhotoEventListener listener) {
}
}
- private static class ScreenCastSettings extends Settings {
+ private class ScreenCastSettings extends Settings {
private List mSupportedPictureSize = new ArrayList<>();
private List mSupportedPreviewSize = new ArrayList<>();
private List> mSupportedFps = new ArrayList<>();
+ private List mSupportEncoderSizeList = new ArrayList<>();
ScreenCastSettings(Context context, HostMediaRecorder recorder) {
super(context, recorder);
}
+ @Override
+ protected EncoderSettings createEncoderSettings(String encoderId) {
+ return new EncoderSettings(getContext(), encoderId) {
+ @Override
+ public List getSupportedEncoderSizes() {
+ return mSupportEncoderSizeList;
+ }
+ };
+ }
+
@Override
public List getSupportedPictureSizes() {
return mSupportedPictureSize;
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSRTBroadcaster.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSRTBroadcaster.java
index b7a72b20fa..fdf5e9de1c 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSRTBroadcaster.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSRTBroadcaster.java
@@ -1,20 +1,18 @@
package org.deviceconnect.android.deviceplugin.host.recorder.screen;
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractSRTBroadcaster;
-import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
public class ScreenCastSRTBroadcaster extends AbstractSRTBroadcaster {
- public ScreenCastSRTBroadcaster(ScreenCastRecorder recorder, String broadcastURI) {
- super(recorder, broadcastURI);
+ public ScreenCastSRTBroadcaster(ScreenCastRecorder recorder, String name) {
+ super(recorder, name);
}
@Override
protected VideoEncoder createVideoEncoder() {
ScreenCastRecorder recorder = (ScreenCastRecorder) getRecorder();
- HostMediaRecorder.Settings settings = recorder.getSettings();
- switch (settings.getPreviewEncoderName()) {
+ switch (getEncoderSettings().getPreviewEncoderName()) {
case H264:
default:
return new ScreenCastVideoEncoder(recorder);
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSRTPreviewServer.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSRTPreviewServer.java
index e52cf97800..29400103e7 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSRTPreviewServer.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSRTPreviewServer.java
@@ -6,10 +6,7 @@
*/
package org.deviceconnect.android.deviceplugin.host.recorder.screen;
-import android.content.Context;
-
import org.deviceconnect.android.deviceplugin.host.recorder.AbstractSRTPreviewServer;
-import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
import org.deviceconnect.android.libmedia.streaming.video.VideoEncoder;
/**
@@ -18,16 +15,14 @@
* @author NTT DOCOMO, INC.
*/
class ScreenCastSRTPreviewServer extends AbstractSRTPreviewServer {
- ScreenCastSRTPreviewServer(final Context context, final ScreenCastRecorder recorder, final int port) {
- super(context, recorder);
- setPort(port);
+ ScreenCastSRTPreviewServer(ScreenCastRecorder recorder, String encoderId) {
+ super(recorder, encoderId);
}
@Override
protected VideoEncoder createVideoEncoder() {
ScreenCastRecorder recorder = (ScreenCastRecorder) getRecorder();
- HostMediaRecorder.Settings settings = recorder.getSettings();
- switch (settings.getPreviewEncoderName()) {
+ switch (getEncoderSettings().getPreviewEncoderName()) {
case H264:
default:
return new ScreenCastVideoEncoder(recorder);
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSurfaceDrawingThread.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSurfaceDrawingThread.java
index f47da6287e..1be49f8399 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSurfaceDrawingThread.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastSurfaceDrawingThread.java
@@ -31,7 +31,7 @@ public ScreenCastSurfaceDrawingThread(ScreenCastRecorder recorder) {
// 画面の更新が発生しない場合は、MediaCodec に更新イベントが発生しないので
// ここでは、画面更新のタイムアウトを 0 にして、タイムアウトが発生しないように設定
- setTimeout(0);
+ setRenderingTimeout(0);
}
// EGLSurfaceDrawingThread
@@ -44,7 +44,20 @@ public int getDisplayRotation() {
@Override
public boolean isSwappedDimensions() {
- return mRecorder.getScreenCastMgr().isSwappedDimensions();
+ int orientation = mRecorder.getSettings().getOrientation();
+ if (orientation == -1) {
+ return mRecorder.getScreenCastMgr().isSwappedDimensions();
+ }
+
+ switch (orientation) {
+ case Surface.ROTATION_0:
+ case Surface.ROTATION_180:
+ return false;
+ case Surface.ROTATION_90:
+ case Surface.ROTATION_270:
+ default:
+ return true;
+ }
}
@Override
@@ -61,13 +74,10 @@ protected void onStopped() {
public void start() {
HostMediaRecorder.Settings settings = mRecorder.getSettings();
Size previewSize = settings.getPreviewSize();
- if (previewSize != null) {
- int width = isSwappedDimensions() ? previewSize.getHeight() : previewSize.getWidth();
- int height = isSwappedDimensions() ? previewSize.getWidth() : previewSize.getHeight();
- setSize(width, height);
- setDrawingRange(settings.getDrawingRange());
- super.start();
- }
+ int width = isSwappedDimensions() ? previewSize.getHeight() : previewSize.getWidth();
+ int height = isSwappedDimensions() ? previewSize.getWidth() : previewSize.getHeight();
+ setSize(width, height);
+ super.start();
}
private void startScreenCast(SurfaceTexture surfaceTexture) {
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastVideoEncoder.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastVideoEncoder.java
index a8c6262f41..d5b0e88029 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastVideoEncoder.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastVideoEncoder.java
@@ -25,14 +25,4 @@ public ScreenCastVideoEncoder(ScreenCastRecorder recorder, String mimeType) {
public VideoQuality getVideoQuality() {
return mVideoQuality;
}
-
- // SurfaceVideoEncoder
-
- @Override
- protected void onStartSurfaceDrawing() {
- }
-
- @Override
- protected void onStopSurfaceDrawing() {
- }
}
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/SurfaceScreenCast.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/SurfaceScreenCast.java
index 291c43d3dd..8f1c8c0cb2 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/SurfaceScreenCast.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/SurfaceScreenCast.java
@@ -9,7 +9,7 @@
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class SurfaceScreenCast extends AbstractScreenCast {
- private Surface mOutputSurface;
+ private final Surface mOutputSurface;
SurfaceScreenCast(Context context, MediaProjection mediaProjection,
Surface outputSurface, int width, int height) {
diff --git a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/ui/PreviewSurfaceView.java b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/ui/PreviewSurfaceView.java
index 0d454615dc..a0a51c34a2 100644
--- a/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/ui/PreviewSurfaceView.java
+++ b/dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/ui/PreviewSurfaceView.java
@@ -1,17 +1,39 @@
package org.deviceconnect.android.deviceplugin.host.recorder.ui;
+import android.annotation.SuppressLint;
import android.content.Context;
+import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.Size;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import androidx.constraintlayout.widget.ConstraintLayout;
import org.deviceconnect.android.deviceplugin.host.R;
+import org.deviceconnect.android.deviceplugin.host.recorder.CropInterface;
+
+import java.util.HashMap;
+import java.util.Map;
public class PreviewSurfaceView extends FrameLayout {
+ private int mPreviewWidth;
+ private int mPreviewHeight;
+ private int mSurfaceWidth;
+ private int mSurfaceHeight;
+ private int mDragStartX;
+ private int mDragStartY;
+ private boolean mDragFlag;
+ private boolean mScaleFlag;
+ private ScaleGestureDetector mScaleGestureDetector;
+ private final Map