Skip to content

Commit eec4cfd

Browse files
committed
Add VideoCapture to capture frames without a running track
1 parent 0bee0f0 commit eec4cfd

File tree

5 files changed

+418
-0
lines changed

5 files changed

+418
-0
lines changed

webrtc-jni/src/main/cpp/include/JNI_VideoCapture.h

+69
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2021 Alex Andres
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_H_
18+
#define JNI_WEBRTC_MEDIA_VIDEO_CAPTURE_H_
19+
20+
#include "media/video/VideoDevice.h"
21+
22+
#include "api/create_peerconnection_factory.h"
23+
#include "api/video/video_sink_interface.h"
24+
#include "media/base/video_adapter.h"
25+
#include "modules/video_capture/video_capture.h"
26+
#include "modules/video_capture/video_capture_defines.h"
27+
28+
namespace jni
29+
{
30+
class VideoCapture
31+
{
32+
public:
33+
VideoCapture();
34+
~VideoCapture();
35+
36+
void setDevice(const avdev::DevicePtr & device);
37+
void setVideoCaptureCapability(const webrtc::VideoCaptureCapability & capability);
38+
void setVideoSink(std::unique_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink);
39+
void start();
40+
void stop();
41+
void destroy();
42+
43+
private:
44+
avdev::DevicePtr device;
45+
webrtc::VideoCaptureCapability capability;
46+
std::unique_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink;
47+
48+
rtc::scoped_refptr<webrtc::VideoCaptureModule> captureModule;
49+
};
50+
}
51+
52+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright 2021 Alex Andres
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "JNI_VideoCapture.h"
18+
#include "api/VideoTrackSink.h"
19+
#include "media/video/VideoCapture.h"
20+
#include "media/video/VideoDevice.h"
21+
#include "JavaRef.h"
22+
#include "JavaObject.h"
23+
#include "JavaString.h"
24+
#include "JavaUtils.h"
25+
26+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoCaptureDevice
27+
(JNIEnv * env, jobject caller, jobject device)
28+
{
29+
if (!device) {
30+
env->Throw(jni::JavaNullPointerException(env, "VideoDevice is null"));
31+
return;
32+
}
33+
34+
jni::VideoCapture * videoSource = GetHandle<jni::VideoCapture>(env, caller);
35+
CHECK_HANDLE(videoSource);
36+
37+
const auto javaClass = jni::JavaClasses::get<jni::VideoDevice::JavaVideoDeviceClass>(env);
38+
const auto dev = jni::VideoDevice::toNativeVideoDevice(env, jni::JavaLocalRef<jobject>(env, device));
39+
40+
videoSource->setDevice(std::make_shared<jni::avdev::VideoDevice>(dev.getName(), dev.getDescriptor()));
41+
}
42+
43+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoCaptureCapability
44+
(JNIEnv * env, jobject caller, jobject jcapability)
45+
{
46+
jni::VideoCapture * videoSource = GetHandle<jni::VideoCapture>(env, caller);
47+
CHECK_HANDLE(videoSource);
48+
49+
if (!jcapability) {
50+
env->Throw(jni::JavaNullPointerException(env, "VideoCaptureCapability is null"));
51+
return;
52+
}
53+
54+
jint width = env->GetIntField(jcapability, GetFieldID(env, jcapability, "width", "I"));
55+
jint height = env->GetIntField(jcapability, GetFieldID(env, jcapability, "height", "I"));
56+
jint frameRate = env->GetIntField(jcapability, GetFieldID(env, jcapability, "frameRate", "I"));
57+
58+
webrtc::VideoCaptureCapability capability;
59+
capability.width = static_cast<int32_t>(width);
60+
capability.height = static_cast<int32_t>(height);
61+
capability.maxFPS = static_cast<int32_t>(frameRate);
62+
63+
videoSource->setVideoCaptureCapability(capability);
64+
}
65+
66+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_setVideoSink
67+
(JNIEnv * env, jobject caller, jobject jsink)
68+
{
69+
if (jsink == nullptr) {
70+
env->Throw(jni::JavaNullPointerException(env, "VideoTrackSink must not be null"));
71+
return;
72+
}
73+
74+
jni::VideoCapture * videoSource = GetHandle<jni::VideoCapture>(env, caller);
75+
CHECK_HANDLE(videoSource);
76+
77+
videoSource->setVideoSink(std::make_unique<jni::VideoTrackSink>(env, jni::JavaGlobalRef<jobject>(env, jsink)));
78+
}
79+
80+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_start
81+
(JNIEnv * env, jobject caller)
82+
{
83+
jni::VideoCapture * videoSource = GetHandle<jni::VideoCapture>(env, caller);
84+
CHECK_HANDLE(videoSource);
85+
86+
try {
87+
videoSource->start();
88+
}
89+
catch (...) {
90+
ThrowCxxJavaException(env);
91+
}
92+
}
93+
94+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_stop
95+
(JNIEnv * env, jobject caller)
96+
{
97+
jni::VideoCapture * videoSource = GetHandle<jni::VideoCapture>(env, caller);
98+
CHECK_HANDLE(videoSource);
99+
100+
try {
101+
videoSource->stop();
102+
}
103+
catch (...) {
104+
ThrowCxxJavaException(env);
105+
}
106+
}
107+
108+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_dispose
109+
(JNIEnv * env, jobject caller)
110+
{
111+
jni::VideoCapture * videoSource = GetHandle<jni::VideoCapture>(env, caller);
112+
CHECK_HANDLE(videoSource);
113+
114+
SetHandle<std::nullptr_t>(env, caller, nullptr);
115+
116+
videoSource = nullptr;
117+
}
118+
119+
JNIEXPORT void JNICALL Java_dev_onvoid_webrtc_media_video_VideoCapture_initialize
120+
(JNIEnv * env, jobject caller)
121+
{
122+
SetHandle(env, caller, new jni::VideoCapture());
123+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Copyright 2021 Alex Andres
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "media/video/VideoCapture.h"
18+
#include "Exception.h"
19+
20+
#include "api/video/i420_buffer.h"
21+
#include "modules/video_capture/video_capture_factory.h"
22+
23+
namespace jni
24+
{
25+
VideoCapture::VideoCapture() :
26+
captureModule(nullptr)
27+
{
28+
capability.width = static_cast<int32_t>(1280);
29+
capability.height = static_cast<int32_t>(720);
30+
capability.maxFPS = static_cast<int32_t>(30);
31+
}
32+
33+
VideoCapture::~VideoCapture()
34+
{
35+
destroy();
36+
}
37+
38+
void VideoCapture::setDevice(const avdev::DevicePtr & device)
39+
{
40+
this->device = device;
41+
}
42+
43+
void VideoCapture::setVideoCaptureCapability(const webrtc::VideoCaptureCapability & capability)
44+
{
45+
this->capability = capability;
46+
}
47+
48+
void VideoCapture::setVideoSink(std::unique_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink)
49+
{
50+
this->sink = std::move(sink);
51+
}
52+
53+
void VideoCapture::start()
54+
{
55+
if (!device) {
56+
throw new Exception("Video device must be set");
57+
}
58+
59+
std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> info(webrtc::VideoCaptureFactory::CreateDeviceInfo());
60+
61+
if (!info) {
62+
throw new Exception("Create video DeviceInfo failed");
63+
}
64+
65+
uint32_t num = info->NumberOfDevices();
66+
67+
if (num < 1) {
68+
throw new Exception("No video capture devices available");
69+
}
70+
71+
std::string devUid;
72+
const uint32_t size = webrtc::kVideoCaptureDeviceNameLength;
73+
74+
for (uint32_t i = 0; i < num; ++i) {
75+
char name[size] = { 0 };
76+
char guid[size] = { 0 };
77+
78+
int32_t ret = info->GetDeviceName(i, name, size, guid, size);
79+
80+
if (ret != 0) {
81+
RTC_LOG(WARNING) << "Get video capture device name failed";
82+
continue;
83+
}
84+
85+
if (device->getName().compare(name) == 0) {
86+
devUid = guid;
87+
break;
88+
}
89+
}
90+
91+
if (devUid.empty()) {
92+
throw new Exception("Device %s not found", device->getName().c_str());
93+
}
94+
95+
captureModule = webrtc::VideoCaptureFactory::Create(devUid.c_str());
96+
97+
if (!captureModule) {
98+
throw new Exception("Create VideoCaptureModule for UID %s failed", devUid.c_str());
99+
}
100+
101+
captureModule->RegisterCaptureDataCallback(std::move(sink).release());
102+
103+
capability.videoType = webrtc::VideoType::kI420;
104+
105+
if (captureModule->StartCapture(capability) != 0) {
106+
destroy();
107+
108+
throw new Exception("Start video capture for UID %s failed", devUid.c_str());
109+
}
110+
111+
if (!captureModule || !captureModule->CaptureStarted()) {
112+
throw new Exception("Start video capture failed");
113+
}
114+
}
115+
116+
void VideoCapture::stop()
117+
{
118+
destroy();
119+
}
120+
121+
void VideoCapture::destroy()
122+
{
123+
if (!captureModule) {
124+
return;
125+
}
126+
if (captureModule->CaptureStarted()) {
127+
captureModule->StopCapture();
128+
}
129+
130+
captureModule->DeRegisterCaptureDataCallback();
131+
captureModule = nullptr;
132+
}
133+
}

0 commit comments

Comments
 (0)