1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // This file contains JNI for the video engine interfaces. 12 // The native functions are found using jni's auto discovery. 13 14 #include "webrtc/examples/android/media_demo/jni/video_engine_jni.h" 15 16 #include <map> 17 #include <string> 18 19 #include "webrtc/common_types.h" 20 #include "webrtc/examples/android/media_demo/jni/jni_helpers.h" 21 #include "webrtc/examples/android/media_demo/jni/media_codec_video_decoder.h" 22 #include "webrtc/examples/android/media_demo/jni/voice_engine_jni.h" 23 #include "webrtc/modules/utility/interface/helpers_android.h" 24 #include "webrtc/test/channel_transport/include/channel_transport.h" 25 #include "webrtc/video_engine/include/vie_base.h" 26 #include "webrtc/video_engine/include/vie_capture.h" 27 #include "webrtc/video_engine/include/vie_codec.h" 28 #include "webrtc/video_engine/include/vie_external_codec.h" 29 #include "webrtc/video_engine/include/vie_network.h" 30 #include "webrtc/video_engine/include/vie_render.h" 31 #include "webrtc/video_engine/include/vie_rtp_rtcp.h" 32 33 // Macro for native functions that can be found by way of jni-auto discovery. 34 // Note extern "C" is needed for "discovery" of native methods to work. 35 #define JOWW(rettype, name) \ 36 extern "C" rettype JNIEXPORT JNICALL Java_org_webrtc_webrtcdemo_##name 37 38 namespace { 39 40 static JavaVM* g_vm = NULL; 41 static ClassReferenceHolder* g_class_reference_holder = NULL; 42 43 jclass GetClass(const char* name) { 44 CHECK(g_class_reference_holder, "Class reference holder NULL"); 45 return g_class_reference_holder->GetClass(name); 46 } 47 48 // C(++) description of a camera. This class is created by Java native calls 49 // and associated with the CameraDesc Java class. The Java class is used in the 50 // Java code but it is just a thin wrapper of the C(++) class that contain the 51 // actual information. The information is stored in C(++) as it is used to 52 // call video engine APIs. 53 struct CameraDesc { 54 // The name and id corresponds to ViECapture's |device_nameUTF8| and 55 // |unique_idUTF8|. 56 char name[64]; 57 char unique_id[64]; 58 }; 59 60 // C++ callback class that can be used to register for callbacks from the 61 // video engine. It further propagates the callbacks to 62 // VideoDecodeEncodeObserver.java interface. The memory associated with this 63 // class is managed globally by the VideoEngineData class when registering and 64 // unregistering VideoDecodeEncodeObserver.java to receive callbacks. 65 class VideoDecodeEncodeObserver : public webrtc::ViEDecoderObserver, 66 public webrtc::ViEEncoderObserver { 67 public: 68 explicit VideoDecodeEncodeObserver(jobject j_observer) 69 : j_observer_(j_observer) { 70 webrtc::AttachThreadScoped ats(g_vm); 71 JNIEnv* jni = ats.env(); 72 jclass j_observer_class = jni->GetObjectClass(j_observer_); 73 incoming_rate_ = 74 GetMethodID(jni, j_observer_class, "incomingRate", "(III)V"); 75 incoming_codec_changed_ = 76 GetMethodID(jni, j_observer_class, "incomingCodecChanged", 77 "(ILorg/webrtc/webrtcdemo/VideoCodecInst;)V"); 78 request_new_keyframe_ = 79 GetMethodID(jni, j_observer_class, "requestNewKeyFrame", "(I)V"); 80 outgoing_rate_ = 81 GetMethodID(jni, j_observer_class, "outgoingRate", "(III)V"); 82 j_observer_ = jni->NewGlobalRef(j_observer_); 83 } 84 85 ~VideoDecodeEncodeObserver() { 86 webrtc::AttachThreadScoped ats(g_vm); 87 JNIEnv* jni = ats.env(); 88 jni->DeleteGlobalRef(j_observer_); 89 } 90 91 virtual void IncomingRate(const int video_channel, 92 const unsigned int framerate, 93 const unsigned int bitrate) { 94 webrtc::AttachThreadScoped ats(g_vm); 95 JNIEnv* jni = ats.env(); 96 jni->CallVoidMethod(j_observer_, incoming_rate_, video_channel, 97 static_cast<int>(framerate), static_cast<int>(bitrate)); 98 } 99 100 virtual void DecoderTiming(int decode_ms, int max_decode_ms, 101 int current_delay_ms, int target_delay_ms, 102 int jitter_buffer_ms, int min_playout_delay_ms, 103 int render_delay_ms) { 104 // TODO(fischman): consider plumbing this through to Java. 105 } 106 107 virtual void IncomingCodecChanged(const int video_channel, 108 const webrtc::VideoCodec& video_codec) { 109 webrtc::AttachThreadScoped ats(g_vm); 110 JNIEnv* jni = ats.env(); 111 webrtc::VideoCodec* codec = new webrtc::VideoCodec(video_codec); 112 jclass j_codec_class = 113 GetClass("org/webrtc/webrtcdemo/VideoCodecInst"); 114 jmethodID j_codec_ctor = GetMethodID(jni, j_codec_class, "<init>", "(J)V"); 115 jobject j_codec = 116 jni->NewObject(j_codec_class, j_codec_ctor, jlongFromPointer(codec)); 117 CHECK_EXCEPTION(jni, "error during NewObject"); 118 jni->CallVoidMethod(j_observer_, incoming_codec_changed_, video_channel, 119 j_codec); 120 } 121 122 virtual void RequestNewKeyFrame(const int video_channel) { 123 webrtc::AttachThreadScoped ats(g_vm); 124 JNIEnv* jni = ats.env(); 125 jni->CallVoidMethod(j_observer_, request_new_keyframe_, video_channel); 126 } 127 128 virtual void OutgoingRate(const int video_channel, 129 const unsigned int framerate, 130 const unsigned int bitrate) { 131 webrtc::AttachThreadScoped ats(g_vm); 132 JNIEnv* jni = ats.env(); 133 jni->CallVoidMethod(j_observer_, outgoing_rate_, video_channel, 134 static_cast<int>(framerate), static_cast<int>(bitrate)); 135 } 136 137 virtual void SuspendChange(int video_channel, bool is_suspended) {} 138 139 private: 140 jobject j_observer_; 141 jmethodID incoming_rate_; 142 jmethodID incoming_codec_changed_; 143 jmethodID request_new_keyframe_; 144 jmethodID outgoing_rate_; 145 }; 146 147 template<typename T> 148 void ReleaseSubApi(T instance) { 149 CHECK(instance->Release() == 0, "failed to release instance") 150 } 151 152 class VideoEngineData { 153 public: 154 VideoEngineData() 155 : vie(webrtc::VideoEngine::Create()), 156 base(webrtc::ViEBase::GetInterface(vie)), 157 codec(webrtc::ViECodec::GetInterface(vie)), 158 network(webrtc::ViENetwork::GetInterface(vie)), 159 rtp(webrtc::ViERTP_RTCP::GetInterface(vie)), 160 render(webrtc::ViERender::GetInterface(vie)), 161 capture(webrtc::ViECapture::GetInterface(vie)), 162 externalCodec(webrtc::ViEExternalCodec::GetInterface(vie)) { 163 CHECK(vie != NULL, "Video engine instance failed to be created"); 164 CHECK(base != NULL, "Failed to acquire base interface"); 165 CHECK(codec != NULL, "Failed to acquire codec interface"); 166 CHECK(network != NULL, "Failed to acquire network interface"); 167 CHECK(rtp != NULL, "Failed to acquire rtp interface"); 168 CHECK(render != NULL, "Failed to acquire render interface"); 169 CHECK(capture != NULL, "Failed to acquire capture interface"); 170 CHECK(externalCodec != NULL, "Failed to acquire externalCodec interface"); 171 } 172 173 ~VideoEngineData() { 174 CHECK(channel_transports_.empty(), 175 "ViE transports must be deleted before terminating"); 176 CHECK(observers_.empty(), 177 "ViE observers must be deleted before terminating"); 178 CHECK(external_decoders_.empty(), 179 "ViE external decoders must be deleted before terminating"); 180 ReleaseSubApi(externalCodec); 181 ReleaseSubApi(capture); 182 ReleaseSubApi(render); 183 ReleaseSubApi(rtp); 184 ReleaseSubApi(network); 185 ReleaseSubApi(codec); 186 ReleaseSubApi(base); 187 webrtc::VideoEngine* vie_pointer = vie; 188 CHECK(webrtc::VideoEngine::Delete(vie_pointer), "ViE failed to be deleted"); 189 } 190 191 int CreateChannel() { 192 int channel; 193 CHECK(base->CreateChannel(channel) == 0, "Failed to create channel"); 194 CreateTransport(channel); 195 return channel; 196 } 197 198 int DeleteChannel(int channel) { 199 if (base->DeleteChannel(channel) != 0) { 200 return -1; 201 } 202 DeleteTransport(channel); 203 return 0; 204 } 205 206 webrtc::test::VideoChannelTransport* GetTransport(int channel) { 207 ChannelTransports::iterator found = channel_transports_.find(channel); 208 if (found == channel_transports_.end()) { 209 return NULL; 210 } 211 return found->second; 212 } 213 214 int RegisterObserver(int channel, jobject j_observer) { 215 CHECK(observers_.find(channel) == observers_.end(), 216 "Observer already created for channel, inconsistent state"); 217 observers_[channel] = new VideoDecodeEncodeObserver(j_observer); 218 int ret_val = codec->RegisterDecoderObserver(channel, *observers_[channel]); 219 ret_val |= codec->RegisterEncoderObserver(channel, *observers_[channel]); 220 return ret_val; 221 } 222 223 int DeregisterObserver(int channel) { 224 Observers::iterator found = observers_.find(channel); 225 if (observers_.find(channel) == observers_.end()) { 226 return -1; 227 } 228 int ret_val = codec->DeregisterDecoderObserver(channel); 229 ret_val |= codec->DeregisterEncoderObserver(channel); 230 delete found->second; 231 observers_.erase(found); 232 return ret_val; 233 } 234 235 int RegisterExternalReceiveCodec(jint channel, jint pl_type, jobject decoder, 236 bool internal_source) { 237 CHECK(external_decoders_.find(channel) == external_decoders_.end(), 238 "External decoder already created for channel, inconsistent state"); 239 external_decoders_[channel] = 240 new webrtc::MediaCodecVideoDecoder(g_vm, decoder); 241 return externalCodec->RegisterExternalReceiveCodec( 242 channel, pl_type, external_decoders_[channel], internal_source); 243 } 244 245 int DeRegisterExternalReceiveCodec(jint channel, jint pl_type) { 246 ExternalDecoders::iterator found = external_decoders_.find(channel); 247 CHECK(found != external_decoders_.end(), 248 "ViE channel missing external decoder, inconsistent state"); 249 CHECK(externalCodec->DeRegisterExternalReceiveCodec(channel, pl_type) == 0, 250 "Failed to register external receive decoder"); 251 delete found->second; 252 external_decoders_.erase(found); 253 return 0; 254 } 255 256 webrtc::VideoEngine* const vie; 257 webrtc::ViEBase* const base; 258 webrtc::ViECodec* const codec; 259 webrtc::ViENetwork* const network; 260 webrtc::ViERTP_RTCP* const rtp; 261 webrtc::ViERender* const render; 262 webrtc::ViECapture* const capture; 263 webrtc::ViEExternalCodec* const externalCodec; 264 265 private: 266 // Video engine no longer provides a socket implementation. There is, 267 // however, a socket implementation in webrtc::test. 268 typedef std::map<int, webrtc::test::VideoChannelTransport*> 269 ChannelTransports; 270 typedef std::map<int, VideoDecodeEncodeObserver*> Observers; 271 typedef std::map<int, webrtc::MediaCodecVideoDecoder*> ExternalDecoders; 272 273 void CreateTransport(int channel) { 274 CHECK(GetTransport(channel) == NULL, 275 "Transport already created for ViE channel, inconsistent state"); 276 channel_transports_[channel] = 277 new webrtc::test::VideoChannelTransport(network, channel); 278 } 279 void DeleteTransport(int channel) { 280 CHECK(GetTransport(channel) != NULL, 281 "ViE channel missing transport, inconsistent state"); 282 delete channel_transports_[channel]; 283 channel_transports_.erase(channel); 284 } 285 286 ChannelTransports channel_transports_; 287 Observers observers_; 288 ExternalDecoders external_decoders_; 289 }; 290 291 webrtc::VideoCodec* GetCodecInst(JNIEnv* jni, jobject j_codec) { 292 jclass j_codec_class = jni->GetObjectClass(j_codec); 293 jfieldID native_codec_id = 294 jni->GetFieldID(j_codec_class, "nativeCodecInst", "J"); 295 jlong j_p = jni->GetLongField(j_codec, native_codec_id); 296 return reinterpret_cast<webrtc::VideoCodec*>(j_p); 297 } 298 299 CameraDesc* GetCameraDesc(JNIEnv* jni, jobject j_camera) { 300 jclass j_camera_class = jni->GetObjectClass(j_camera); 301 jfieldID native_camera_id = 302 jni->GetFieldID(j_camera_class, "nativeCameraDesc", "J"); 303 jlong j_p = jni->GetLongField(j_camera, native_camera_id); 304 return reinterpret_cast<CameraDesc*>(j_p); 305 } 306 307 VideoEngineData* GetVideoEngineData(JNIEnv* jni, jobject j_vie) { 308 jclass j_vie_class = jni->GetObjectClass(j_vie); 309 jfieldID native_vie_id = 310 jni->GetFieldID(j_vie_class, "nativeVideoEngine", "J"); 311 jlong j_p = jni->GetLongField(j_vie, native_vie_id); 312 return reinterpret_cast<VideoEngineData*>(j_p); 313 } 314 315 } // namespace 316 317 namespace webrtc_examples { 318 319 static const char* g_classes[] = { 320 "org/webrtc/webrtcdemo/CameraDesc", 321 "org/webrtc/webrtcdemo/RtcpStatistics", 322 "org/webrtc/webrtcdemo/VideoCodecInst", 323 "org/webrtc/webrtcdemo/VideoDecodeEncodeObserver", 324 "org/webrtc/webrtcdemo/MediaCodecVideoDecoder"}; 325 326 void SetVieDeviceObjects(JavaVM* vm) { 327 CHECK(vm, "Trying to register NULL vm"); 328 CHECK(!g_vm, "Trying to re-register vm"); 329 g_vm = vm; 330 webrtc::AttachThreadScoped ats(g_vm); 331 JNIEnv* jni = ats.env(); 332 g_class_reference_holder = new ClassReferenceHolder( 333 jni, g_classes, ARRAYSIZE(g_classes)); 334 } 335 336 void ClearVieDeviceObjects() { 337 CHECK(g_vm, "Clearing vm without it being set"); 338 { 339 webrtc::AttachThreadScoped ats(g_vm); 340 g_class_reference_holder->FreeReferences(ats.env()); 341 } 342 g_vm = NULL; 343 delete g_class_reference_holder; 344 g_class_reference_holder = NULL; 345 } 346 347 } // namespace webrtc_examples 348 349 JOWW(jlong, VideoEngine_create)(JNIEnv* jni, jclass) { 350 VideoEngineData* vie_data = new VideoEngineData(); 351 return jlongFromPointer(vie_data); 352 } 353 354 JOWW(jint, VideoEngine_init)(JNIEnv* jni, jobject j_vie) { 355 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 356 return vie_data->base->Init(); 357 } 358 359 JOWW(jint, VideoEngine_setVoiceEngine)(JNIEnv* jni, jobject j_vie, 360 jobject j_voe) { 361 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 362 webrtc::VoiceEngine* voe = GetVoiceEngine(jni, j_voe); 363 return vie_data->base->SetVoiceEngine(voe); 364 } 365 366 JOWW(void, VideoEngine_dispose)(JNIEnv* jni, jobject j_vie) { 367 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 368 delete vie_data; 369 } 370 371 JOWW(jint, VideoEngine_startSend)(JNIEnv* jni, jobject j_vie, jint channel) { 372 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 373 return vie_data->base->StartSend(channel); 374 } 375 376 JOWW(jint, VideoEngine_stopRender)(JNIEnv* jni, jobject j_vie, jint channel) { 377 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 378 return vie_data->render->StopRender(channel); 379 } 380 381 JOWW(jint, VideoEngine_stopSend)(JNIEnv* jni, jobject j_vie, jint channel) { 382 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 383 return vie_data->base->StopSend(channel); 384 } 385 386 JOWW(jint, VideoEngine_startReceive)(JNIEnv* jni, jobject j_vie, jint channel) { 387 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 388 return vie_data->base->StartReceive(channel); 389 } 390 391 JOWW(jint, VideoEngine_stopReceive)(JNIEnv* jni, jobject j_vie, jint channel) { 392 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 393 return vie_data->base->StopReceive(channel); 394 } 395 396 JOWW(jint, VideoEngine_createChannel)(JNIEnv* jni, jobject j_vie) { 397 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 398 return vie_data->CreateChannel(); 399 } 400 401 JOWW(jint, VideoEngine_deleteChannel)(JNIEnv* jni, jobject j_vie, 402 jint channel) { 403 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 404 return vie_data->DeleteChannel(channel); 405 } 406 407 JOWW(jint, 408 VideoEngine_connectAudioChannel(JNIEnv* jni, jobject j_vie, 409 jint video_channel, jint audio_channel)) { 410 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 411 return vie_data->base->ConnectAudioChannel(video_channel, audio_channel); 412 } 413 414 JOWW(jint, VideoEngine_setLocalReceiver)(JNIEnv* jni, jobject j_vie, 415 jint channel, jint port) { 416 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 417 return vie_data->GetTransport(channel)->SetLocalReceiver(port); 418 } 419 420 JOWW(jint, VideoEngine_setSendDestination)(JNIEnv* jni, jobject j_vie, 421 jint channel, jint port, 422 jstring j_addr) { 423 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 424 std::string addr = JavaToStdString(jni, j_addr); 425 webrtc::test::VideoChannelTransport* transport = 426 vie_data->GetTransport(channel); 427 return transport->SetSendDestination(addr.c_str(), port); 428 } 429 430 JOWW(jint, VideoEngine_setReceiveCodec)(JNIEnv* jni, jobject j_vie, 431 jint channel, jobject j_codec) { 432 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 433 webrtc::VideoCodec* codec = GetCodecInst(jni, j_codec); 434 return vie_data->codec->SetReceiveCodec(channel, *codec); 435 } 436 437 JOWW(jint, VideoEngine_setSendCodec)(JNIEnv* jni, jobject j_vie, jint channel, 438 jobject j_codec) { 439 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 440 webrtc::VideoCodec* codec = GetCodecInst(jni, j_codec); 441 return vie_data->codec->SetSendCodec(channel, *codec); 442 } 443 444 JOWW(jint, VideoEngine_numberOfCodecs)(JNIEnv* jni, jobject j_vie) { 445 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 446 return vie_data->codec->NumberOfCodecs(); 447 } 448 449 JOWW(jobject, VideoEngine_getCodec)(JNIEnv* jni, jobject j_vie, jint index) { 450 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 451 webrtc::VideoCodec* codec = new webrtc::VideoCodec(); 452 CHECK(vie_data->codec->GetCodec(index, *codec) == 0, 453 "getCodec must be called with valid index"); 454 jclass j_codec_class = GetClass("org/webrtc/webrtcdemo/VideoCodecInst"); 455 jmethodID j_codec_ctor = GetMethodID(jni, j_codec_class, "<init>", "(J)V"); 456 jobject j_codec = 457 jni->NewObject(j_codec_class, j_codec_ctor, jlongFromPointer(codec)); 458 CHECK_EXCEPTION(jni, "error during NewObject"); 459 return j_codec; 460 } 461 462 JOWW(jint, VideoEngine_addRenderer)(JNIEnv* jni, jobject j_vie, jint channel, 463 jobject gl_surface, jint z_order, 464 jfloat left, jfloat top, jfloat right, 465 jfloat bottom) { 466 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 467 return vie_data->render->AddRenderer(channel, gl_surface, z_order, left, top, 468 right, bottom); 469 } 470 471 JOWW(jint, VideoEngine_removeRenderer)(JNIEnv* jni, jobject j_vie, 472 jint channel) { 473 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 474 return vie_data->render->RemoveRenderer(channel); 475 } 476 477 JOWW(jint, VideoEngine_registerExternalReceiveCodec)(JNIEnv* jni, jobject j_vie, 478 jint channel, jint pl_type, 479 jobject decoder, 480 bool internal_source) { 481 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 482 return vie_data->RegisterExternalReceiveCodec(channel, pl_type, decoder, 483 true); 484 } 485 486 JOWW(jint, 487 VideoEngine_deRegisterExternalReceiveCodec)(JNIEnv* jni, jobject j_vie, 488 jint channel, jint pl_type) { 489 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 490 return vie_data->DeRegisterExternalReceiveCodec(channel, pl_type); 491 } 492 493 JOWW(jint, VideoEngine_startRender)(JNIEnv* jni, jobject j_vie, jint channel) { 494 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 495 return vie_data->render->StartRender(channel); 496 } 497 498 JOWW(jint, VideoEngine_numberOfCaptureDevices)(JNIEnv* jni, jobject j_vie) { 499 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 500 return vie_data->capture->NumberOfCaptureDevices(); 501 } 502 503 JOWW(jobject, 504 VideoEngine_getCaptureDevice(JNIEnv* jni, jobject j_vie, jint index)) { 505 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 506 CameraDesc* camera_info = new CameraDesc(); 507 if (vie_data->capture->GetCaptureDevice( 508 index, camera_info->name, sizeof(camera_info->name), 509 camera_info->unique_id, sizeof(camera_info->unique_id)) != 0) { 510 delete camera_info; 511 return NULL; 512 } 513 jclass j_camera_class = GetClass("org/webrtc/webrtcdemo/CameraDesc"); 514 jmethodID j_camera_ctor = GetMethodID(jni, j_camera_class, "<init>", "(J)V"); 515 jobject j_camera = jni->NewObject(j_camera_class, j_camera_ctor, 516 jlongFromPointer(camera_info)); 517 CHECK_EXCEPTION(jni, "error during NewObject"); 518 return j_camera; 519 } 520 521 JOWW(jint, VideoEngine_allocateCaptureDevice)(JNIEnv* jni, jobject j_vie, 522 jobject j_camera) { 523 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 524 CameraDesc* camera_info = GetCameraDesc(jni, j_camera); 525 jint capture_id; 526 if (vie_data->capture->AllocateCaptureDevice(camera_info->unique_id, 527 sizeof(camera_info->unique_id), 528 capture_id) != 0) { 529 return -1; 530 } 531 return capture_id; 532 } 533 534 JOWW(jint, VideoEngine_connectCaptureDevice)(JNIEnv* jni, jobject j_vie, 535 jint camera_num, jint channel) { 536 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 537 return vie_data->capture->ConnectCaptureDevice(camera_num, channel); 538 } 539 540 JOWW(jint, VideoEngine_startCapture)(JNIEnv* jni, jobject j_vie, 541 jint camera_num) { 542 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 543 return vie_data->capture->StartCapture(camera_num); 544 } 545 546 JOWW(jint, VideoEngine_stopCapture)(JNIEnv* jni, jobject j_vie, 547 jint camera_id) { 548 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 549 return vie_data->capture->StopCapture(camera_id); 550 } 551 552 JOWW(jint, VideoEngine_releaseCaptureDevice)(JNIEnv* jni, jobject j_vie, 553 jint camera_id) { 554 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 555 return vie_data->capture->ReleaseCaptureDevice(camera_id); 556 } 557 558 JOWW(jint, VideoEngine_getOrientation)(JNIEnv* jni, jobject j_vie, 559 jobject j_camera) { 560 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 561 CameraDesc* camera_info = GetCameraDesc(jni, j_camera); 562 webrtc::RotateCapturedFrame orientation; 563 if (vie_data->capture->GetOrientation(camera_info->unique_id, orientation) != 564 0) { 565 return -1; 566 } 567 return static_cast<jint>(orientation); 568 } 569 570 JOWW(jint, VideoEngine_setRotateCapturedFrames)(JNIEnv* jni, jobject j_vie, 571 jint capture_id, jint degrees) { 572 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 573 return vie_data->capture->SetRotateCapturedFrames( 574 capture_id, static_cast<webrtc::RotateCapturedFrame>(degrees)); 575 } 576 577 JOWW(jint, VideoEngine_setNackStatus)(JNIEnv* jni, jobject j_vie, jint channel, 578 jboolean enable) { 579 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 580 return vie_data->rtp->SetNACKStatus(channel, enable); 581 } 582 583 JOWW(jint, VideoEngine_setKeyFrameRequestMethod)(JNIEnv* jni, jobject j_vie, 584 jint channel, 585 jint request_method) { 586 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 587 return vie_data->rtp->SetKeyFrameRequestMethod( 588 channel, static_cast<webrtc::ViEKeyFrameRequestMethod>(request_method)); 589 } 590 591 JOWW(jobject, VideoEngine_getReceivedRtcpStatistics)(JNIEnv* jni, jobject j_vie, 592 jint channel) { 593 unsigned short fraction_lost; // NOLINT 594 unsigned int cumulative_lost; // NOLINT 595 unsigned int extended_max; // NOLINT 596 unsigned int jitter; // NOLINT 597 int rtt_ms; 598 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 599 if (vie_data->rtp->GetReceivedRTCPStatistics(channel, fraction_lost, 600 cumulative_lost, extended_max, 601 jitter, rtt_ms) != 0) { 602 return NULL; 603 } 604 jclass j_rtcp_statistics_class = 605 GetClass("org/webrtc/webrtcdemo/RtcpStatistics"); 606 jmethodID j_rtcp_statistics_ctor = 607 GetMethodID(jni, j_rtcp_statistics_class, "<init>", "(IIIII)V"); 608 jobject j_rtcp_statistics = 609 jni->NewObject(j_rtcp_statistics_class, j_rtcp_statistics_ctor, 610 fraction_lost, cumulative_lost, extended_max, jitter, 611 rtt_ms); 612 CHECK_EXCEPTION(jni, "error during NewObject"); 613 return j_rtcp_statistics; 614 } 615 616 JOWW(jint, VideoEngine_registerObserver)(JNIEnv* jni, jobject j_vie, 617 jint channel, jobject callback) { 618 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 619 return vie_data->RegisterObserver(channel, callback); 620 } 621 622 JOWW(jint, VideoEngine_deregisterObserver)(JNIEnv* jni, jobject j_vie, 623 jint channel) { 624 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 625 return vie_data->DeregisterObserver(channel); 626 } 627 628 JOWW(jint, VideoEngine_setTraceFile)(JNIEnv* jni, jobject, jstring j_filename, 629 jboolean file_counter) { 630 std::string filename = JavaToStdString(jni, j_filename); 631 return webrtc::VideoEngine::SetTraceFile(filename.c_str(), file_counter); 632 } 633 634 JOWW(jint, VideoEngine_nativeSetTraceFilter)(JNIEnv* jni, jobject, 635 jint filter) { 636 return webrtc::VideoEngine::SetTraceFilter(filter); 637 } 638 639 JOWW(jint, VideoEngine_startRtpDump)(JNIEnv* jni, jobject j_vie, jint channel, 640 jstring j_filename, jint direction) { 641 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 642 std::string filename = JavaToStdString(jni, j_filename); 643 return vie_data->rtp->StartRTPDump( 644 channel, filename.c_str(), static_cast<webrtc::RTPDirections>(direction)); 645 } 646 647 JOWW(jint, VideoEngine_stopRtpDump)(JNIEnv* jni, jobject j_vie, jint channel, 648 jint direction) { 649 VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie); 650 return vie_data->rtp->StopRTPDump( 651 channel, static_cast<webrtc::RTPDirections>(direction)); 652 } 653 654 JOWW(void, VideoCodecInst_dispose)(JNIEnv* jni, jobject j_codec) { 655 delete GetCodecInst(jni, j_codec); 656 } 657 658 JOWW(jint, VideoCodecInst_plType)(JNIEnv* jni, jobject j_codec) { 659 return GetCodecInst(jni, j_codec)->plType; 660 } 661 662 JOWW(jstring, VideoCodecInst_name)(JNIEnv* jni, jobject j_codec) { 663 return jni->NewStringUTF(GetCodecInst(jni, j_codec)->plName); 664 } 665 666 JOWW(jint, VideoCodecInst_width)(JNIEnv* jni, jobject j_codec) { 667 return GetCodecInst(jni, j_codec)->width; 668 } 669 670 JOWW(void, VideoCodecInst_setWidth)(JNIEnv* jni, jobject j_codec, jint width) { 671 GetCodecInst(jni, j_codec)->width = width; 672 } 673 674 JOWW(jint, VideoCodecInst_height)(JNIEnv* jni, jobject j_codec) { 675 return GetCodecInst(jni, j_codec)->height; 676 } 677 678 JOWW(void, VideoCodecInst_setHeight)(JNIEnv* jni, jobject j_codec, 679 jint height) { 680 GetCodecInst(jni, j_codec)->height = height; 681 } 682 683 JOWW(jint, VideoCodecInst_startBitRate)(JNIEnv* jni, jobject j_codec) { 684 return GetCodecInst(jni, j_codec)->startBitrate; 685 } 686 687 JOWW(void, VideoCodecInst_setStartBitRate)(JNIEnv* jni, jobject j_codec, 688 jint bitrate) { 689 GetCodecInst(jni, j_codec)->startBitrate = bitrate; 690 } 691 692 JOWW(jint, VideoCodecInst_maxBitRate)(JNIEnv* jni, jobject j_codec) { 693 return GetCodecInst(jni, j_codec)->maxBitrate; 694 } 695 696 JOWW(void, VideoCodecInst_setMaxBitRate)(JNIEnv* jni, jobject j_codec, 697 jint bitrate) { 698 GetCodecInst(jni, j_codec)->maxBitrate = bitrate; 699 } 700 701 JOWW(jint, VideoCodecInst_maxFrameRate)(JNIEnv* jni, jobject j_codec) { 702 return GetCodecInst(jni, j_codec)->maxFramerate; 703 } 704 705 JOWW(void, VideoCodecInst_setMaxFrameRate)(JNIEnv* jni, jobject j_codec, 706 jint framerate) { 707 GetCodecInst(jni, j_codec)->maxFramerate = framerate; 708 } 709 710 JOWW(void, CameraDesc_dispose)(JNIEnv* jni, jobject j_camera) { 711 delete GetCameraDesc(jni, j_camera); 712 } 713