[*] 复用

This commit is contained in:
acgist
2023-04-16 12:15:30 +08:00
parent 288447c4dc
commit a08462a3f2
6 changed files with 180 additions and 213 deletions

View File

@@ -9,7 +9,6 @@ import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
@@ -187,9 +186,9 @@ public class MainActivity extends AppCompatActivity implements Serializable {
private void record(View view) {
final MediaManager mediaManager = MediaManager.getInstance();
if (mediaManager.isRecording()) {
mediaManager.stopRecordVideoCapture();
mediaManager.stopRecord();
} else {
mediaManager.startRecordVideoCapture();
mediaManager.startRecord();
}
}

View File

@@ -8,7 +8,6 @@ import android.media.projection.MediaProjection;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
import com.acgist.taoyao.media.client.PhotographClient;
import com.acgist.taoyao.media.client.RecordClient;
@@ -24,6 +23,7 @@ import org.webrtc.AudioTrack;
import org.webrtc.Camera2Enumerator;
import org.webrtc.CameraEnumerator;
import org.webrtc.CameraVideoCapturer;
import org.webrtc.CapturerObserver;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
@@ -37,6 +37,7 @@ import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoDecoderFactory;
import org.webrtc.VideoEncoderFactory;
import org.webrtc.VideoFrame;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;
import org.webrtc.audio.JavaAudioDeviceModule;
@@ -46,8 +47,6 @@ import java.util.Arrays;
/**
* 媒体来源管理器
*
* 注意:镜头选择可以使用代码实现,如果可以经理直接进行物理旋转。
*
* @author acgist
*
* TODO动态码率BITRATE_MODE_VBR、BITRATE_MODE
@@ -64,10 +63,6 @@ public final class MediaManager {
* 当前终端数量
*/
private volatile int clientCount;
/**
* 当前媒体共享数量
*/
private volatile int shareClientCount;
/**
* 视频路径
*/
@@ -121,13 +116,13 @@ public final class MediaManager {
*/
private MediaProperties mediaProperties;
/**
* 频配置
*/
private MediaAudioProperties mediaAudioProperties;
/**
* 视频配置
* 当前共享视频配置
*/
private MediaVideoProperties mediaVideoProperties;
/**
* 当前共享音频配置
*/
private MediaAudioProperties mediaAudioProperties;
/**
* WebRTC配置
*/
@@ -152,34 +147,30 @@ public final class MediaManager {
* 音频来源
*/
private AudioSource audioSource;
/**
* 视频Track
*/
private VideoTrack videoTrack;
/**
* 视频来源
*/
private VideoSource videoSource;
/**
* 视频捕获
*/
private VideoCapturer videoCapturer;
/**
* 主码流视频Track
*/
private VideoTrack mainVideoTrack;
/**
* 主码流视频来源
*/
private VideoSource mainVideoSource;
/**
* 次码流视频Track
*/
private VideoTrack shareVideoTrack;
/**
* 次码流视频来源
*/
private VideoSource shareVideoSource;
/**
* 录制终端
*/
private RecordClient recordClient;
/**
* 录制视频Track
*/
private VideoTrack recordVideoTrack;
/**
* 录制视频来源
*/
private VideoSource recordVideoSource;
/**
* 录制视频捕获
*/
private VideoCapturer recordVideoCapturer;
/**
* 拍照终端
*/
@@ -223,7 +214,6 @@ public final class MediaManager {
private MediaManager() {
this.clientCount = 0;
this.shareClientCount = 0;
}
/**
@@ -284,9 +274,11 @@ public final class MediaManager {
}
}
if (this.clientCount <= 0) {
Log.i(MediaManager.class.getSimpleName(), "加载PeerConnectionFactory");
this.initPeerConnectionFactory();
this.initMedia(videoSourceType);
this.nativeInit();
this.initMedia(videoSourceType);
this.startVideoCapture();
}
this.clientCount++;
}
@@ -296,7 +288,6 @@ public final class MediaManager {
/**
* 关闭一个终端
* 最后一个终端关闭时,释放所有资源。
* 注意:所有本地媒体关闭调用,不要直接关闭本地媒体流。
*
* @return 剩余终端数量
*/
@@ -304,7 +295,12 @@ public final class MediaManager {
synchronized (this) {
this.clientCount--;
if (this.clientCount <= 0) {
this.close();
Log.i(MediaManager.class.getSimpleName(), "释放PeerConnectionFactory");
this.closeAudio();
this.closeMainVideo();
this.closeShareVideo();
this.closeMedia();
this.stopVideoCapture();
this.nativeStop();
this.stopPeerConnectionFactory();
}
@@ -380,7 +376,7 @@ public final class MediaManager {
// .setUseLowLatency()
.setSamplesReadyCallback(audioSamples -> {
if(this.recordClient != null) {
this.recordClient.putAudio(audioSamples);
this.recordClient.onWebRtcAudioRecordSamplesReady(audioSamples);
}
})
.setAudioTrackStateCallback(new JavaAudioDeviceModule.AudioTrackStateCallback() {
@@ -468,10 +464,8 @@ public final class MediaManager {
for (String name : names) {
if (this.videoSourceType == VideoSourceType.FRONT && cameraEnumerator.isFrontFacing(name)) {
this.videoCapturer = cameraEnumerator.createCapturer(name, new MediaCameraEventsHandler());
this.recordVideoCapturer = cameraEnumerator.createCapturer(name, new MediaCameraEventsHandler());
} else if (this.videoSourceType == VideoSourceType.BACK && cameraEnumerator.isBackFacing(name)) {
this.videoCapturer = cameraEnumerator.createCapturer(name, new MediaCameraEventsHandler());
this.recordVideoCapturer = cameraEnumerator.createCapturer(name, new MediaCameraEventsHandler());
} else {
// 忽略其他摄像头
}
@@ -492,7 +486,6 @@ public final class MediaManager {
*/
public void initScreen(Intent intent) {
this.videoCapturer = new ScreenCapturerAndroid(intent, new ScreenCallback());
this.recordVideoCapturer = new ScreenCapturerAndroid(intent, new ScreenCallback());
this.initVideoTrack();
}
@@ -504,33 +497,23 @@ public final class MediaManager {
this.surfaceTextureHelper = SurfaceTextureHelper.create("MediaVideoThread", this.shareEglContext);
// this.surfaceTextureHelper.setTextureSize();
// this.surfaceTextureHelper.setFrameRotation();
// 次码流
this.videoSource = this.peerConnectionFactory.createVideoSource(this.videoCapturer.isScreencast());
this.videoCapturer.initialize(this.surfaceTextureHelper, this.context, this.videoSource.getCapturerObserver());
this.videoTrack = this.peerConnectionFactory.createVideoTrack("TaoyaoV0", this.videoSource);
this.videoTrack.setEnabled(true);
this.mediaStream.addTrack(this.videoTrack);
Log.i(MediaManager.class.getSimpleName(), "加载视频(次码流):" + this.videoTrack.id());
// 主码流
this.recordVideoSource = this.peerConnectionFactory.createVideoSource(this.recordVideoCapturer.isScreencast());
this.recordVideoCapturer.initialize(this.surfaceTextureHelper, this.context, this.recordVideoSource.getCapturerObserver());
this.recordVideoTrack = this.peerConnectionFactory.createVideoTrack("TaoyaoV1", this.recordVideoSource);
this.recordVideoTrack.addSink(videoFrame -> {
// 录制
if (this.recordClient != null) {
videoFrame.retain();
this.recordClient.putVideo(videoFrame);
}
// 拍照
if (this.photographClient != null) {
videoFrame.retain();
this.photographClient.photograph(videoFrame);
}
});
this.recordVideoTrack.setEnabled(true);
Log.i(MediaManager.class.getSimpleName(), "加载视频(主码流):" + this.recordVideoTrack.id());
// 视频处理
// this.videoSource.setVideoProcessor();
this.mainVideoSource = this.peerConnectionFactory.createVideoSource(this.videoCapturer.isScreencast());
this.mainVideoTrack = this.peerConnectionFactory.createVideoTrack("TaoyaoV0", this.mainVideoSource);
this.mainVideoTrack.setEnabled(true);
Log.i(MediaManager.class.getSimpleName(), "加载视频(主码流):" + this.mainVideoTrack.id());
// 次码流
this.shareVideoSource = this.peerConnectionFactory.createVideoSource(this.videoCapturer.isScreencast());
this.shareVideoSource.adaptOutputFormat(this.mediaVideoProperties.getWidth(), this.mediaVideoProperties.getHeight(), this.mediaVideoProperties.getFrameRate());
this.shareVideoTrack = this.peerConnectionFactory.createVideoTrack("TaoyaoV1", this.shareVideoSource);
this.shareVideoTrack.setEnabled(true);
Log.i(MediaManager.class.getSimpleName(), "加载视频(次码流):" + this.shareVideoTrack.id());
// 共享次码流
this.mediaStream.addTrack(this.shareVideoTrack);
// 视频捕获
this.videoCapturer.initialize(this.surfaceTextureHelper, this.context, new VideoCapturerObserver());
// 次码流视频处理
// this.shareVideoSource.setVideoProcessor();
}
/**
@@ -542,8 +525,8 @@ public final class MediaManager {
*/
public void updateMediaConfig(MediaProperties mediaProperties, MediaAudioProperties mediaAudioProperties, MediaVideoProperties mediaVideoProperties) {
this.mediaProperties = mediaProperties;
this.updateAudioConfig(mediaAudioProperties);
this.updateVideoConfig(mediaVideoProperties);
this.updateAudioConfig(this.mediaProperties.getAudio());
this.updateVideoConfig(this.mediaProperties.getVideo());
synchronized (this) {
this.notifyAll();
}
@@ -555,10 +538,10 @@ public final class MediaManager {
public void updateVideoConfig(MediaVideoProperties mediaVideoProperties) {
this.mediaVideoProperties = mediaVideoProperties;
if(this.videoCapturer != null) {
this.stopCapture("次码流", this.videoCapturer);
this.videoCapturer.startCapture(this.mediaVideoProperties.getWidth(), this.mediaVideoProperties.getHeight(), this.mediaVideoProperties.getFrameRate());
if(this.shareVideoSource == null) {
return;
}
this.shareVideoSource.adaptOutputFormat(this.mediaVideoProperties.getWidth(), this.mediaVideoProperties.getHeight(), this.mediaVideoProperties.getFrameRate());
}
public void updateWebrtcConfig(WebrtcProperties webrtcProperties) {
@@ -597,33 +580,22 @@ public final class MediaManager {
return this.mediaStream;
}
public void startVideoCapture() {
synchronized (this) {
if(this.videoCapturer == null) {
return;
}
if(this.shareClientCount > 0) {
this.shareClientCount++;
return;
} else {
this.shareClientCount++;
this.videoCapturer.startCapture(this.mediaVideoProperties.getWidth(), this.mediaVideoProperties.getHeight(), this.mediaVideoProperties.getFrameRate());
}
private void startVideoCapture() {
if(this.videoCapturer == null) {
return;
}
final MediaVideoProperties mediaVideoProperties = this.mediaProperties.getVideos().get(this.videoQuantity);
this.videoCapturer.startCapture(mediaVideoProperties.getWidth(), mediaVideoProperties.getHeight(), mediaVideoProperties.getFrameRate());
}
public void stopVideoCapture() {
synchronized (this) {
if(this.videoCapturer == null) {
return;
}
if(this.shareClientCount <= 0) {
return;
}
this.shareClientCount--;
if(this.shareClientCount <= 0) {
this.stopCapture("次码流", this.videoCapturer);
}
private void stopVideoCapture() {
if(this.videoCapturer == null) {
return;
}
try {
videoCapturer.stopCapture();
} catch (InterruptedException e) {
Log.e(MediaManager.class.getSimpleName(), "关闭视频捕获异常", e);
}
}
@@ -634,21 +606,18 @@ public final class MediaManager {
final PhotographClient photographClient = new PhotographClient(this.imageQuantity, this.imagePath);
if(this.clientCount <= 0) {
filepath = photographClient.photograph(mediaVideoProperties.getWidth(), mediaVideoProperties.getHeight(), VideoSourceType.BACK, this.context);
} else if(this.recordClient != null) {
this.photographClient = photographClient;
filepath = this.photographClient.waitForPhotograph();
} else {
this.photographClient = photographClient;
this.recordVideoCapturer.startCapture(mediaVideoProperties.getWidth(), mediaVideoProperties.getHeight(), PhotographClient.CAPTURER_SIZE);
this.mainVideoTrack.addSink(this.photographClient);
filepath = this.photographClient.waitForPhotograph();
this.stopCapture("主码流", this.recordVideoCapturer);
this.mainVideoTrack.removeSink(this.photographClient);
}
this.photographClient = null;
return filepath;
}
}
public RecordClient startRecordVideoCapture() {
public RecordClient startRecord() {
synchronized (this) {
if(this.recordClient != null) {
return this.recordClient;
@@ -657,38 +626,28 @@ public final class MediaManager {
final MediaVideoProperties mediaVideoProperties = this.mediaProperties.getVideos().get(this.videoQuantity);
this.recordClient = new RecordClient(
mediaAudioProperties.getBitrate(), mediaAudioProperties.getSampleRate(), this.channelCount,
mediaVideoProperties.getBitrate(), mediaVideoProperties.getFrameRate(), this.iFrameInterval, mediaVideoProperties.getWidth(), mediaVideoProperties.getHeight(),
mediaVideoProperties.getBitrate(), mediaVideoProperties.getFrameRate(), this.iFrameInterval,
mediaVideoProperties.getWidth(), mediaVideoProperties.getHeight(),
this.videoPath, this.taoyao, this.mainHandler
);
this.recordClient.start();
this.recordVideoCapturer.startCapture(mediaVideoProperties.getWidth(), mediaVideoProperties.getHeight(), mediaVideoProperties.getFrameRate());
this.mainVideoTrack.addSink(this.recordClient);
return this.recordClient;
}
}
public void stopRecordVideoCapture() {
public void stopRecord() {
synchronized (this) {
if(this.recordClient == null) {
return;
} else {
this.mainVideoTrack.removeSink(this.recordClient);
this.recordClient.close();
this.recordClient = null;
this.stopCapture("主码流", this.recordVideoCapturer);
}
}
}
private void stopCapture(String name, VideoCapturer videoCapturer) {
if(this.videoCapturer == null) {
return;
}
try {
videoCapturer.stopCapture();
} catch (InterruptedException e) {
Log.e(MediaManager.class.getSimpleName(), "关闭视频捕获异常:" + name, e);
}
}
/**
* @param flag Config.WHAT_*
* @param videoTrack 视频媒体流Track
@@ -736,33 +695,25 @@ public final class MediaManager {
/**
* 关闭视频
*/
private void closeVideo() {
private void closeShareVideo() {
// if(this.videoTrack != null) {
// this.videoTrack.dispose();
// this.videoTrack = null;
// }
if(this.videoSource != null) {
this.videoSource.dispose();
this.videoSource = null;
}
if (this.videoCapturer != null) {
this.videoCapturer.dispose();
this.videoCapturer = null;
if(this.shareVideoSource != null) {
this.shareVideoSource.dispose();
this.shareVideoSource = null;
}
}
private void closeRecord() {
if(this.recordVideoTrack != null) {
this.recordVideoTrack.dispose();
this.recordVideoTrack = null;
private void closeMainVideo() {
if(this.mainVideoTrack != null) {
this.mainVideoTrack.dispose();
this.mainVideoTrack = null;
}
if(this.recordVideoSource != null) {
this.recordVideoSource.dispose();
this.recordVideoSource = null;
}
if(this.recordVideoCapturer != null) {
this.recordVideoCapturer.dispose();
this.recordVideoCapturer = null;
if(this.mainVideoSource != null) {
this.mainVideoSource.dispose();
this.mainVideoSource = null;
}
}
@@ -776,6 +727,10 @@ public final class MediaManager {
this.mediaStream.dispose();
this.mediaStream = null;
}
if (this.videoCapturer != null) {
this.videoCapturer.dispose();
this.videoCapturer = null;
}
if(this.surfaceTextureHelper != null) {
this.surfaceTextureHelper.dispose();
this.surfaceTextureHelper = null;
@@ -786,14 +741,34 @@ public final class MediaManager {
}
}
/**
* 释放资源
*/
private void close() {
this.closeAudio();
this.closeVideo();
this.closeRecord();
this.closeMedia();
private class VideoCapturerObserver implements CapturerObserver {
private CapturerObserver mainObserver;
private CapturerObserver shareObserver;
public VideoCapturerObserver() {
this.mainObserver = MediaManager.this.mainVideoSource.getCapturerObserver();
this.shareObserver = MediaManager.this.shareVideoSource.getCapturerObserver();
}
@Override
public void onCapturerStarted(boolean status) {
this.mainObserver.onCapturerStarted(status);
this.shareObserver.onCapturerStarted(status);
}
@Override
public void onCapturerStopped() {
this.mainObserver.onCapturerStopped();
this.shareObserver.onCapturerStopped();
}
@Override
public void onFrameCaptured(VideoFrame videoFrame) {
this.mainObserver.onFrameCaptured(videoFrame);
this.shareObserver.onFrameCaptured(videoFrame);
}
}
/**

View File

@@ -23,9 +23,11 @@ import android.util.Log;
import android.view.Surface;
import com.acgist.taoyao.boot.utils.DateUtils;
import com.acgist.taoyao.media.MediaManager;
import com.acgist.taoyao.media.VideoSourceType;
import org.webrtc.VideoFrame;
import org.webrtc.VideoSink;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -42,7 +44,7 @@ import java.util.List;
*
* @author acgist
*/
public class PhotographClient {
public class PhotographClient implements VideoSink {
public static final int CAPTURER_SIZE = 1;
@@ -65,6 +67,12 @@ public class PhotographClient {
Log.i(RecordClient.class.getSimpleName(), "拍摄照片文件:" + this.filepath);
}
@Override
public void onFrame(VideoFrame videoFrame) {
videoFrame.retain();
this.photograph(videoFrame);
}
public String photograph(VideoFrame videoFrame) {
if(this.wait) {
this.wait = false;

View File

@@ -8,6 +8,7 @@ import android.media.MediaMuxer;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.provider.MediaStore;
import android.util.Log;
import com.acgist.taoyao.boot.utils.DateUtils;
@@ -117,14 +118,6 @@ public class RecordClient extends Client implements VideoSink, JavaAudioDeviceMo
* 媒体合成器
*/
private MediaMuxer mediaMuxer;
/**
* 音频队列
*/
private final BlockingQueue<JavaAudioDeviceModule.AudioSamples> audioSamplesQueue;
/**
* 视频队列
*/
private final BlockingQueue<VideoFrame> videoFrameQueue;
public RecordClient(
int audioBitRate, int sampleRate, int channelCount,
@@ -142,8 +135,6 @@ public class RecordClient extends Client implements VideoSink, JavaAudioDeviceMo
this.height = height;
this.filename = DateUtils.format(LocalDateTime.now(), DateUtils.DateTimeStyle.YYYYMMDDHH24MMSS) + ".mp4";
this.filepath = Paths.get(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath(), path, this.filename).toString();
this.audioSamplesQueue = new LinkedBlockingQueue<>();
this.videoFrameQueue = new LinkedBlockingQueue<>();
}
public void start() {
@@ -201,26 +192,6 @@ public class RecordClient extends Client implements VideoSink, JavaAudioDeviceMo
JavaAudioDeviceModule.AudioSamples audioSamples = null;
final MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
while (!this.close) {
try {
audioSamples = this.audioSamplesQueue.poll(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Log.e(RecordClient.class.getSimpleName(), "录制线程等待异常", e);
}
if(audioSamples == null) {
continue;
}
int index = this.audioCodec.dequeueInputBuffer(WAIT_TIME_US);
if (index >= 0) {
final byte[] data = audioSamples.getData();
final ByteBuffer buffer = this.audioCodec.getInputBuffer(index);
buffer.put(data);
this.audioCodec.queueInputBuffer(index, 0, data.length, this.audioPts, 0);
// 1000000 microseconds / 48000 hz / 2 bytes
this.audioPts += data.length * (1_000_000 / audioSamples.getSampleRate() / 2);
} else {
// WARN
}
audioSamples = null;
outputIndex = this.audioCodec.dequeueOutputBuffer(bufferInfo, WAIT_TIME_US);
if (outputIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
// } else if (outputIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
@@ -281,21 +252,6 @@ public class RecordClient extends Client implements VideoSink, JavaAudioDeviceMo
}
}
/**
* @param audioSamples PCM数据
*/
public void putAudio(JavaAudioDeviceModule.AudioSamples audioSamples) {
if(this.close || !this.audioActive) {
return;
}
Log.i(RecordClient.class.getSimpleName(), "音频信息:" + audioSamples.getAudioFormat());
try {
this.audioSamplesQueue.put(audioSamples);
} catch (InterruptedException e) {
Log.e(RecordClient.class.getSimpleName(), "录制线程等待异常", e);
}
}
/**
* @param videoType 视频格式
*/
@@ -330,7 +286,7 @@ public class RecordClient extends Client implements VideoSink, JavaAudioDeviceMo
final MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
while (!this.close) {
try {
videoFrame = this.videoFrameQueue.poll(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
videoFrame = this.vq.poll(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Log.e(RecordClient.class.getSimpleName(), "录制线程等待异常", e);
}
@@ -408,18 +364,6 @@ public class RecordClient extends Client implements VideoSink, JavaAudioDeviceMo
}
}
public void putVideo(VideoFrame videoFrame) {
if (this.close || !this.videoActive) {
return;
}
Log.i(RecordClient.class.getSimpleName(), "视频信息:" + videoFrame.getRotatedWidth() + " - " + videoFrame.getRotatedHeight());
try {
this.videoFrameQueue.put(videoFrame);
} catch (InterruptedException e) {
Log.e(RecordClient.class.getSimpleName(), "录制线程等待异常", e);
}
}
private void initMediaMuxer() {
try {
this.mediaMuxer = new MediaMuxer(
@@ -465,12 +409,57 @@ public class RecordClient extends Client implements VideoSink, JavaAudioDeviceMo
return this.filepath;
}
@Override
public void onFrame(VideoFrame videoFrame) {
}
/**
* @param audioSamples PCM数据
*/
@Override
public void onWebRtcAudioRecordSamplesReady(JavaAudioDeviceModule.AudioSamples audioSamples) {
if(this.close || !this.audioActive) {
return;
}
Log.i(RecordClient.class.getSimpleName(), "音频信息:" + audioSamples.getAudioFormat());
int index = this.audioCodec.dequeueInputBuffer(WAIT_TIME_US);
if (index >= 0) {
final byte[] data = audioSamples.getData();
final ByteBuffer buffer = this.audioCodec.getInputBuffer(index);
buffer.put(data);
this.audioCodec.queueInputBuffer(index, 0, data.length, this.audioPts, 0);
// 1000000 microseconds / 48000 hz / 2 bytes
this.audioPts += data.length * (1_000_000 / audioSamples.getSampleRate() / 2);
} else {
// WARN
}
audioSamples = null;
}
@Override
public void onFrame(VideoFrame videoFrame) {
videoFrame.retain();
if (this.close || !this.videoActive) {
videoFrame.release();
return;
}
Log.i(RecordClient.class.getSimpleName(), "视频信息:" + videoFrame.getRotatedWidth() + " - " + videoFrame.getRotatedHeight());
try {
vq.put(videoFrame);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// final int videoFrameSize = videoFrame.getRotatedWidth() * videoFrame.getRotatedHeight() * 3 / 2;
// final int index = this.videoCodec.dequeueInputBuffer(WAIT_TIME_US);
// if(index < 0) {
// videoFrame.retain();
// return;
// }
// final VideoFrame.I420Buffer i420 = videoFrame.getBuffer().toI420();
// final ByteBuffer inputByteBuffer = this.videoCodec.getInputBuffer(index);
// YuvHelper.I420ToNV12(i420.getDataY(), i420.getStrideY(), i420.getDataU(), i420.getStrideU(), i420.getDataV(), i420.getStrideV(), inputByteBuffer, i420.getWidth(), i420.getHeight());
// i420.release();
// videoFrame.release();
// this.videoCodec.queueInputBuffer(index, 0, videoFrameSize, videoFrame.getTimestampNs(), 0);
// videoFrame = null;
}
private BlockingQueue<VideoFrame> vq = new LinkedBlockingQueue<>();
}

View File

@@ -109,7 +109,6 @@ public class Room extends CloseableClient implements RouterCallback {
}
super.init();
this.peerConnectionFactory = this.mediaManager.newClient(VideoSourceType.BACK);
this.mediaManager.startVideoCapture();
this.localClient = new LocalClient(this.name, this.clientId, this.taoyao, this.mainHandler);
this.localClient.setMediaStream(this.mediaManager.getMediaStream());
// STUN | TURN
@@ -222,7 +221,6 @@ public class Room extends CloseableClient implements RouterCallback {
this.remoteClients.values().forEach(v -> this.closeRemoteClient(v.clientId));
this.remoteClients.clear();
this.localClient.close();
this.mediaManager.stopVideoCapture();
this.mediaManager.closeClient();
}
}

View File

@@ -102,7 +102,6 @@ public class SessionClient extends Client {
}
super.init();
this.peerConnectionFactory = this.mediaManager.newClient(VideoSourceType.BACK);
this.mediaManager.startVideoCapture();
// STUN | TURN
final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
// TODO读取配置
@@ -281,7 +280,6 @@ public class SessionClient extends Client {
}
super.close();
this.remoteMediaStream.dispose();
this.mediaManager.stopVideoCapture();
this.mediaManager.closeClient();
}
}