Skip to content

Commit 9270323

Browse files
Merge pull request #505 from TakayukiHoshi1984/modify_livestreaming_screen
ScreenCastを配信する機能の追加
2 parents f203a00 + 4334b08 commit 9270323

2 files changed

Lines changed: 239 additions & 21 deletions

File tree

dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/profile/HostLiveStreamingProfile.java

Lines changed: 81 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package org.deviceconnect.android.deviceplugin.host.profile;
22

3-
import android.content.Context;
43
import android.content.Intent;
5-
import android.hardware.camera2.CameraCharacteristics;
6-
import android.hardware.camera2.CameraManager;
74
import android.os.Bundle;
85
import android.util.Log;
96

@@ -24,7 +21,6 @@
2421
import org.deviceconnect.android.profile.api.PutApi;
2522
import org.deviceconnect.message.DConnectMessage;
2623

27-
import java.util.List;
2824

2925
public class HostLiveStreamingProfile extends DConnectProfile implements LiveStreamingClient.EventListener {
3026

@@ -50,6 +46,7 @@ public class HostLiveStreamingProfile extends DConnectProfile implements LiveStr
5046
private static final String VIDEO_URI_CAMERA_BACK = "camera-back";
5147
private static final String VIDEO_URI_CAMERA_0 = "camera_0";
5248
private static final String VIDEO_URI_CAMERA_1 = "camera_1";
49+
private static final String VIDEO_URI_SCREEN = "screen";
5350
private static final String AUDIO_URI_TRUE = "true";
5451
private static final String AUDIO_URI_FALSE = "false";
5552
private static final int CAMERA_TYPE_FRONT = 0;
@@ -112,6 +109,7 @@ public boolean onRequest(final Intent request, final Intent response) {
112109
case VIDEO_URI_CAMERA_BACK:
113110
case VIDEO_URI_CAMERA_0:
114111
case VIDEO_URI_CAMERA_1:
112+
case VIDEO_URI_SCREEN:
115113
break;
116114
default:
117115
MessageUtils.setInvalidRequestParameterError(response, "video parameter illegal");
@@ -121,7 +119,6 @@ public boolean onRequest(final Intent request, final Intent response) {
121119
if (DEBUG) {
122120
Log.d(TAG, "mVideoURI : " + mVideoURI);
123121
}
124-
125122
//映像リソースURIからレコーダーを取得する
126123
try {
127124
mHostDeviceLiveStreamRecorder = getHostDeviceLiveStreamRecorder();
@@ -136,6 +133,7 @@ public boolean onRequest(final Intent request, final Intent response) {
136133
MessageUtils.setUnknownError(response, ex.getMessage());
137134
return true;
138135
}
136+
139137
((HostMediaRecorder) mHostDeviceLiveStreamRecorder).requestPermission(new HostMediaRecorder.PermissionCallback() {
140138
@Override
141139
public void onAllowed() {
@@ -420,6 +418,54 @@ public boolean onRequest(final Intent request, final Intent response) {
420418
});
421419
}
422420

421+
private void startLiveStreaming(Intent request, Intent response, Bundle extras, String broadcastURI, LiveStreamingClient.EventListener eventListener) {
422+
//クライアントの生成
423+
mHostDeviceLiveStreamRecorder.createLiveStreamingClient(broadcastURI, eventListener);
424+
425+
//映像無し以外の場合はエンコーダーとパラメーターをセット
426+
if (!mVideoURI.equals("false")) {
427+
Integer width = parseInteger(request, PARAM_KEY_WIDTH);
428+
Integer height = parseInteger(request, PARAM_KEY_HEIGHT);
429+
Integer bitrate = parseInteger(request, PARAM_KEY_BITRATE);
430+
Integer frameRate = parseInteger(request, PARAM_KEY_FRAME_RATE);
431+
if (DEBUG) {
432+
Log.d(TAG, "width : " + width);
433+
Log.d(TAG, "height : " + height);
434+
Log.d(TAG, "bitrate : " + bitrate);
435+
Log.d(TAG, "frameRate : " + frameRate);
436+
}
437+
mHostDeviceLiveStreamRecorder.setVideoEncoder(width, height, bitrate, frameRate);
438+
}
439+
440+
//音声リソースURIの取得
441+
mAudioURI = (String) extras.get(PARAM_KEY_AUDIO);
442+
if (mAudioURI == null) {
443+
mAudioURI = "false";
444+
} else {
445+
switch (mAudioURI) {
446+
case AUDIO_URI_TRUE:
447+
case AUDIO_URI_FALSE:
448+
break;
449+
default:
450+
MessageUtils.setInvalidRequestParameterError(response, "audio parameter illegal");
451+
return;
452+
}
453+
}
454+
if (DEBUG) {
455+
Log.d(TAG, "audioUri : " + mAudioURI);
456+
}
457+
458+
//音声無し以外の場合はエンコーダーをセット
459+
if (!mAudioURI.equals("false")) {
460+
mHostDeviceLiveStreamRecorder.setAudioEncoder();
461+
}
462+
463+
//ストリーミング開始
464+
mHostDeviceLiveStreamRecorder.startLiveStreaming();
465+
466+
setResult(response, DConnectMessage.RESULT_OK);
467+
}
468+
423469
private HostDeviceLiveStreamRecorder getHostDeviceLiveStreamRecorder() {
424470
if (DEBUG) {
425471
Log.d(TAG, "getHostDeviceLiveStreamRecorder()");
@@ -429,35 +475,50 @@ private HostDeviceLiveStreamRecorder getHostDeviceLiveStreamRecorder() {
429475
case VIDEO_URI_TRUE:
430476
case VIDEO_URI_FALSE: {
431477
HostMediaRecorder hostMediaRecorder = mHostMediaRecorderManager.getRecorder(null);
432-
if (mHostMediaRecorderManager.usingStreamingRecorder()) {
433-
throw new RuntimeException("Another target in using.");
434-
}
478+
if (hostMediaRecorder != null) {
479+
if (mHostMediaRecorderManager.usingStreamingRecorder()) {
480+
throw new RuntimeException("Another target in using.");
481+
}
435482

436-
if (hostMediaRecorder instanceof HostDeviceLiveStreamRecorder) {
437-
return (HostDeviceLiveStreamRecorder) hostMediaRecorder;
483+
if (hostMediaRecorder instanceof HostDeviceLiveStreamRecorder) {
484+
return (HostDeviceLiveStreamRecorder) hostMediaRecorder;
485+
}
438486
}
439487
break;
440488
}
441489
case VIDEO_URI_CAMERA_FRONT:
442490
case VIDEO_URI_CAMERA_1: {
443491
HostMediaRecorder hostMediaRecorder = mHostMediaRecorderManager.getRecorder(VIDEO_URI_CAMERA_1);
444-
if (mHostMediaRecorderManager.usingStreamingRecorder()) {
445-
throw new RuntimeException("Another target in using.");
446-
}
447-
if (hostMediaRecorder instanceof HostDeviceLiveStreamRecorder) {
448-
return (HostDeviceLiveStreamRecorder) hostMediaRecorder;
492+
if (hostMediaRecorder != null) {
493+
if (mHostMediaRecorderManager.usingStreamingRecorder()) {
494+
throw new RuntimeException("Another target in using.");
495+
}
496+
if (hostMediaRecorder instanceof HostDeviceLiveStreamRecorder) {
497+
return (HostDeviceLiveStreamRecorder) hostMediaRecorder;
498+
}
449499
}
450500
break;
451501
}
452502
case VIDEO_URI_CAMERA_BACK:
453503
case VIDEO_URI_CAMERA_0: {
454504
HostMediaRecorder hostMediaRecorder = mHostMediaRecorderManager.getRecorder(VIDEO_URI_CAMERA_0);
455-
if (mHostMediaRecorderManager.usingPreviewOrStreamingRecorder(hostMediaRecorder.getId())) {
456-
throw new RuntimeException("Another target in using.");
457-
}
505+
if (hostMediaRecorder != null) {
506+
if (mHostMediaRecorderManager.usingPreviewOrStreamingRecorder(hostMediaRecorder.getId())) {
507+
throw new RuntimeException("Another target in using.");
508+
}
458509

459-
if (hostMediaRecorder instanceof HostDeviceLiveStreamRecorder) {
460-
return (HostDeviceLiveStreamRecorder) hostMediaRecorder;
510+
if (hostMediaRecorder instanceof HostDeviceLiveStreamRecorder) {
511+
return (HostDeviceLiveStreamRecorder) hostMediaRecorder;
512+
}
513+
}
514+
break;
515+
}
516+
case VIDEO_URI_SCREEN: {
517+
HostMediaRecorder hostMediaRecorder = mHostMediaRecorderManager.getRecorder(VIDEO_URI_SCREEN);
518+
if (hostMediaRecorder != null) {
519+
if (hostMediaRecorder instanceof HostDeviceLiveStreamRecorder) {
520+
return (HostDeviceLiveStreamRecorder) hostMediaRecorder;
521+
}
461522
}
462523
break;
463524
}

dConnectDevicePlugin/dConnectDeviceHost/app/src/main/java/org/deviceconnect/android/deviceplugin/host/recorder/screen/ScreenCastRecorder.java

Lines changed: 158 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.content.Context;
1111
import android.graphics.Bitmap;
1212
import android.graphics.PixelFormat;
13+
import android.media.AudioFormat;
1314
import android.media.ImageReader;
1415
import android.net.Uri;
1516
import android.os.Build;
@@ -19,13 +20,19 @@
1920
import android.util.Log;
2021

2122
import org.deviceconnect.android.deviceplugin.host.BuildConfig;
23+
import org.deviceconnect.android.deviceplugin.host.recorder.HostDeviceLiveStreamRecorder;
2224
import org.deviceconnect.android.deviceplugin.host.recorder.HostDevicePhotoRecorder;
2325
import org.deviceconnect.android.deviceplugin.host.recorder.HostDeviceStreamRecorder;
2426
import org.deviceconnect.android.deviceplugin.host.recorder.HostMediaRecorder;
2527
import org.deviceconnect.android.deviceplugin.host.recorder.PreviewServer;
2628
import org.deviceconnect.android.deviceplugin.host.recorder.PreviewServerProvider;
29+
import org.deviceconnect.android.deviceplugin.host.recorder.camera.CameraVideoEncoder;
30+
import org.deviceconnect.android.deviceplugin.host.recorder.util.LiveStreamingClient;
2731
import org.deviceconnect.android.deviceplugin.host.recorder.util.MediaSharing;
2832
import org.deviceconnect.android.deviceplugin.host.recorder.util.RecorderSetting;
33+
import org.deviceconnect.android.libmedia.streaming.audio.AudioEncoder;
34+
import org.deviceconnect.android.libmedia.streaming.audio.AudioQuality;
35+
import org.deviceconnect.android.libmedia.streaming.audio.MicAACLATMEncoder;
2936
import org.deviceconnect.android.provider.FileManager;
3037

3138
import java.io.ByteArrayOutputStream;
@@ -49,7 +56,7 @@
4956
* @author NTT DOCOMO, INC.
5057
*/
5158
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
52-
public class ScreenCastRecorder implements HostMediaRecorder, HostDevicePhotoRecorder, HostDeviceStreamRecorder {
59+
public class ScreenCastRecorder implements HostMediaRecorder, HostDevicePhotoRecorder, HostDeviceStreamRecorder, HostDeviceLiveStreamRecorder {
5360

5461
private static final boolean DEBUG = BuildConfig.DEBUG;
5562

@@ -88,6 +95,7 @@ public class ScreenCastRecorder implements HostMediaRecorder, HostDevicePhotoRec
8895

8996
private ScreenCastPreviewServerProvider mScreenCastPreviewServerProvider;
9097
private Context mContext;
98+
private LiveStreamingClient mLiveStreamingClient;
9199

92100
public ScreenCastRecorder(final Context context,
93101
final FileManager fileMgr) {
@@ -465,4 +473,153 @@ private void registerPhoto(final File photoFile) {
465473
}
466474
}
467475
}
476+
477+
@Override
478+
public void createLiveStreamingClient(String broadcastURI, LiveStreamingClient.EventListener eventListener) {
479+
mLiveStreamingClient = new LiveStreamingClient(broadcastURI, eventListener);
480+
}
481+
482+
@Override
483+
public void setVideoEncoder(Integer width, Integer height, Integer bitrate, Integer frameRate) {
484+
if (DEBUG) {
485+
Log.d(TAG, "setVideoEncoder()");
486+
Log.d(TAG, "width : " + width);
487+
Log.d(TAG, "height : " + height);
488+
Log.d(TAG, "bitrate : " + bitrate);
489+
Log.d(TAG, "framerate : " + frameRate);
490+
Log.d(TAG, "mLiveStreamingClient : " + mLiveStreamingClient);
491+
}
492+
if (mLiveStreamingClient != null) {
493+
ScreenCastVideoEncoder encoder = new ScreenCastVideoEncoder(mScreenCastMgr);
494+
// widthかheightがnullの場合は、PreviewSizeの最小値を設定する
495+
if (width == null || height == null) {
496+
PictureSize pSize = mSupportedPreviewSizes.get(0);
497+
width = pSize.getWidth();
498+
height = pSize.getHeight();
499+
for (int i = 1; i < mSupportedPreviewSizes.size(); i++) {
500+
if (pSize.getWidth() < mSupportedPreviewSizes.get(i).getWidth()) {
501+
width = mSupportedPreviewSizes.get(i).getWidth();
502+
height = mSupportedPreviewSizes.get(i).getHeight();
503+
}
504+
}
505+
}
506+
mLiveStreamingClient.setVideoEncoder(encoder, width, height, bitrate, frameRate);
507+
}
508+
}
509+
510+
@Override
511+
public void setAudioEncoder() {
512+
if (DEBUG) {
513+
Log.d(TAG, "setAudioEncoder()");
514+
Log.d(TAG, "mLiveStreamingClient : " + mLiveStreamingClient);
515+
}
516+
if (mLiveStreamingClient != null) {
517+
AudioEncoder audioEncoder = new MicAACLATMEncoder();
518+
AudioQuality audioQuality = audioEncoder.getAudioQuality();
519+
audioQuality.setChannel(AudioFormat.CHANNEL_IN_MONO);
520+
audioQuality.setSamplingRate(44100);
521+
mLiveStreamingClient.setAudioEncoder(audioEncoder);
522+
}
523+
}
524+
525+
@Override
526+
public void startLiveStreaming() {
527+
if (DEBUG) {
528+
Log.d(TAG, "liveStreamingStart()");
529+
Log.d(TAG, "mLiveStreamingClient : " + mLiveStreamingClient);
530+
}
531+
if (mLiveStreamingClient != null) {
532+
mLiveStreamingClient.start();
533+
}
534+
}
535+
536+
@Override
537+
public void stopLiveStreaming() {
538+
if (DEBUG) {
539+
Log.d(TAG, "liveStreamingStop()");
540+
Log.d(TAG, "mLiveStreamingClient : " + mLiveStreamingClient);
541+
}
542+
if (mLiveStreamingClient != null) {
543+
mLiveStreamingClient.stop();
544+
}
545+
}
546+
547+
@Override
548+
public boolean isStreaming() {
549+
if (mLiveStreamingClient != null) {
550+
return mLiveStreamingClient.isStreaming();
551+
}
552+
return false;
553+
}
554+
555+
@Override
556+
public void setMute(boolean mute) {
557+
if (mLiveStreamingClient != null) {
558+
mLiveStreamingClient.setMute(mute);
559+
}
560+
}
561+
562+
@Override
563+
public boolean isMute() {
564+
if (mLiveStreamingClient != null) {
565+
return mLiveStreamingClient.isMute();
566+
}
567+
return false;
568+
}
569+
570+
@Override
571+
public boolean isError() {
572+
if (mLiveStreamingClient != null) {
573+
return mLiveStreamingClient.isError();
574+
}
575+
return false;
576+
}
577+
578+
@Override
579+
public int getVideoWidth() {
580+
if (mLiveStreamingClient != null) {
581+
return mLiveStreamingClient.getVideoWidth();
582+
}
583+
return 0;
584+
}
585+
586+
@Override
587+
public int getVideoHeight() {
588+
if (mLiveStreamingClient != null) {
589+
return mLiveStreamingClient.getVideoHeight();
590+
}
591+
return 0;
592+
}
593+
594+
@Override
595+
public int getBitrate() {
596+
if (mLiveStreamingClient != null) {
597+
return mLiveStreamingClient.getBitrate();
598+
}
599+
return 0;
600+
}
601+
602+
@Override
603+
public int getFrameRate() {
604+
if (mLiveStreamingClient != null) {
605+
return mLiveStreamingClient.getFrameRate();
606+
}
607+
return 0;
608+
}
609+
610+
@Override
611+
public String getLiveStreamingMimeType() {
612+
if (mLiveStreamingClient != null) {
613+
return mLiveStreamingClient.getMimeType();
614+
}
615+
return MIME_TYPE_JPEG;
616+
}
617+
618+
@Override
619+
public String getBroadcastURI() {
620+
if (mLiveStreamingClient != null) {
621+
return mLiveStreamingClient.getBroadcastURI();
622+
}
623+
return null;
624+
}
468625
}

0 commit comments

Comments
 (0)