Remove video from WebRTC Android example.
This is in preparation to remove the use of the old Video Api and the use of the old video capture module on Android in particular. R=henrika@webrtc.org, mflodman@webrtc.org, pbos@webrtc.org Review URL: https://webrtc-codereview.appspot.com/44819004 Cr-Commit-Position: refs/heads/master@{#8856}
This commit is contained in:
parent
d4362cd336
commit
855acf72d0
@ -1,4 +1,4 @@
|
||||
This directory contains a sample app for sending and receiving video and audio
|
||||
This directory contains a sample app for sending and receiving audio
|
||||
on Android. It further lets you enable and disable some call quality
|
||||
enhancements such as echo cancellation, noise suppression etc.
|
||||
|
||||
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/examples/android/media_demo/jni/media_codec_video_decoder.h"
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include "webrtc/examples/android/media_demo/jni/jni_helpers.h"
|
||||
#include "webrtc/modules/utility/interface/helpers_android.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
MediaCodecVideoDecoder::MediaCodecVideoDecoder(JavaVM* vm, jobject decoder)
|
||||
: vm_(vm), decoder_(NULL), j_start_(NULL), j_push_buffer_(NULL) {
|
||||
AttachThreadScoped ats(vm_);
|
||||
JNIEnv* jni = ats.env();
|
||||
// Make sure that the decoder is not recycled.
|
||||
decoder_ = jni->NewGlobalRef(decoder);
|
||||
|
||||
// Get all function IDs.
|
||||
jclass decoderClass = jni->GetObjectClass(decoder);
|
||||
j_push_buffer_ =
|
||||
jni->GetMethodID(decoderClass, "pushBuffer", "(Ljava/nio/ByteBuffer;J)V");
|
||||
j_start_ = jni->GetMethodID(decoderClass, "start", "(II)Z");
|
||||
}
|
||||
|
||||
MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {
|
||||
AttachThreadScoped ats(vm_);
|
||||
JNIEnv* jni = ats.env();
|
||||
jni->DeleteGlobalRef(decoder_);
|
||||
}
|
||||
|
||||
int32_t MediaCodecVideoDecoder::InitDecode(const VideoCodec* codecSettings,
|
||||
int32_t numberOfCores) {
|
||||
AttachThreadScoped ats(vm_);
|
||||
JNIEnv* jni = ats.env();
|
||||
if (!jni->CallBooleanMethod(decoder_, j_start_, codecSettings->width,
|
||||
codecSettings->height)) {
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
int32_t MediaCodecVideoDecoder::Decode(
|
||||
const EncodedImage& inputImage, bool missingFrames,
|
||||
const RTPFragmentationHeader* fragmentation,
|
||||
const CodecSpecificInfo* codecSpecificInfo, int64_t renderTimeMs) {
|
||||
|
||||
AttachThreadScoped ats(vm_);
|
||||
JNIEnv* jni = ats.env();
|
||||
jobject byteBuffer =
|
||||
jni->NewDirectByteBuffer(inputImage._buffer, inputImage._length);
|
||||
jni->CallVoidMethod(decoder_, j_push_buffer_, byteBuffer, renderTimeMs);
|
||||
jni->DeleteLocalRef(byteBuffer);
|
||||
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
|
||||
}
|
||||
|
||||
int32_t MediaCodecVideoDecoder::RegisterDecodeCompleteCallback(
|
||||
DecodedImageCallback* callback) {
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
int32_t MediaCodecVideoDecoder::Release() {
|
||||
// TODO(hellner): this maps nicely to MediaCodecVideoDecoder::dispose().
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
int32_t MediaCodecVideoDecoder::Reset() {
|
||||
// TODO(hellner): implement. MediaCodec::stop() followed by
|
||||
// MediaCodec::start()?
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_EXAMPLES_ANDROID_MEDIA_DEMO_JNI_MEDIA_CODEC_VIDEO_DECODER_H_
|
||||
#define WEBRTC_EXAMPLES_ANDROID_MEDIA_DEMO_JNI_MEDIA_CODEC_VIDEO_DECODER_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "webrtc/examples/android/media_demo/jni/jni_helpers.h"
|
||||
#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class MediaCodecVideoDecoder : public VideoDecoder {
|
||||
public:
|
||||
MediaCodecVideoDecoder(JavaVM* vm, jobject decoder);
|
||||
virtual ~MediaCodecVideoDecoder();
|
||||
|
||||
virtual int32_t InitDecode(const VideoCodec* codecSettings,
|
||||
int32_t numberOfCores);
|
||||
|
||||
virtual int32_t Decode(const EncodedImage& inputImage, bool missingFrames,
|
||||
const RTPFragmentationHeader* fragmentation,
|
||||
const CodecSpecificInfo* codecSpecificInfo,
|
||||
int64_t renderTimeMs);
|
||||
|
||||
virtual int32_t RegisterDecodeCompleteCallback(
|
||||
DecodedImageCallback* callback);
|
||||
|
||||
virtual int32_t Release();
|
||||
|
||||
virtual int32_t Reset();
|
||||
|
||||
virtual int32_t SetCodecConfigParameters(const uint8_t* /*buffer*/,
|
||||
int32_t /*size*/) {
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
|
||||
virtual VideoDecoder* Copy() {
|
||||
CHECK(0, "Not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
JavaVM* vm_;
|
||||
// Global reference to a (Java) MediaCodecVideoDecoder object.
|
||||
jobject decoder_;
|
||||
jmethodID j_start_;
|
||||
jmethodID j_push_buffer_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_EXAMPLES_ANDROID_MEDIA_DEMO_JNI_MEDIA_CODEC_VIDEO_DECODER_H_
|
@ -13,10 +13,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/examples/android/media_demo/jni/jni_helpers.h"
|
||||
#include "webrtc/examples/android/media_demo/jni/video_engine_jni.h"
|
||||
#include "webrtc/examples/android/media_demo/jni/voice_engine_jni.h"
|
||||
#include "webrtc/modules/video_capture/video_capture_internal.h"
|
||||
#include "webrtc/modules/video_render/video_render_internal.h"
|
||||
#include "webrtc/voice_engine/include/voe_base.h"
|
||||
|
||||
// Macro for native functions that can be found by way of jni-auto discovery.
|
||||
@ -38,11 +35,6 @@ JOWW(void, NativeWebRtcContextRegistry_register)(
|
||||
jclass,
|
||||
jobject context) {
|
||||
webrtc_examples::SetVoeDeviceObjects(g_vm);
|
||||
webrtc_examples::SetVieDeviceObjects(g_vm);
|
||||
CHECK(webrtc::SetCaptureAndroidVM(g_vm, context) == 0,
|
||||
"Failed to register android objects to video capture");
|
||||
CHECK(webrtc::SetRenderAndroidVM(g_vm) == 0,
|
||||
"Failed to register android objects to video render");
|
||||
CHECK(webrtc::VoiceEngine::SetAndroidObjects(g_vm, context) == 0,
|
||||
"Failed to register android objects to voice engine");
|
||||
}
|
||||
@ -50,12 +42,7 @@ JOWW(void, NativeWebRtcContextRegistry_register)(
|
||||
JOWW(void, NativeWebRtcContextRegistry_unRegister)(
|
||||
JNIEnv* jni,
|
||||
jclass) {
|
||||
CHECK(webrtc::SetCaptureAndroidVM(NULL, NULL) == 0,
|
||||
"Failed to unregister android objects from video capture");
|
||||
CHECK(webrtc::SetRenderAndroidVM(NULL) == 0,
|
||||
"Failed to unregister android objects from video render");
|
||||
CHECK(webrtc::VoiceEngine::SetAndroidObjects(NULL, NULL) == 0,
|
||||
"Failed to unregister android objects from voice engine");
|
||||
webrtc_examples::ClearVieDeviceObjects();
|
||||
webrtc_examples::ClearVoeDeviceObjects();
|
||||
}
|
||||
|
@ -1,727 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// This file contains JNI for the video engine interfaces.
|
||||
// The native functions are found using jni's auto discovery.
|
||||
|
||||
#include "webrtc/examples/android/media_demo/jni/video_engine_jni.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/base/arraysize.h"
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/examples/android/media_demo/jni/jni_helpers.h"
|
||||
#include "webrtc/examples/android/media_demo/jni/media_codec_video_decoder.h"
|
||||
#include "webrtc/examples/android/media_demo/jni/voice_engine_jni.h"
|
||||
#include "webrtc/modules/utility/interface/helpers_android.h"
|
||||
#include "webrtc/test/channel_transport/include/channel_transport.h"
|
||||
#include "webrtc/video_engine/include/vie_base.h"
|
||||
#include "webrtc/video_engine/include/vie_capture.h"
|
||||
#include "webrtc/video_engine/include/vie_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_external_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_network.h"
|
||||
#include "webrtc/video_engine/include/vie_render.h"
|
||||
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
|
||||
|
||||
// Macro for native functions that can be found by way of jni-auto discovery.
|
||||
// Note extern "C" is needed for "discovery" of native methods to work.
|
||||
#define JOWW(rettype, name) \
|
||||
extern "C" rettype JNIEXPORT JNICALL Java_org_webrtc_webrtcdemo_##name
|
||||
|
||||
namespace {
|
||||
|
||||
static JavaVM* g_vm = NULL;
|
||||
static ClassReferenceHolder* g_class_reference_holder = NULL;
|
||||
|
||||
jclass GetClass(const char* name) {
|
||||
CHECK(g_class_reference_holder, "Class reference holder NULL");
|
||||
return g_class_reference_holder->GetClass(name);
|
||||
}
|
||||
|
||||
// C(++) description of a camera. This class is created by Java native calls
|
||||
// and associated with the CameraDesc Java class. The Java class is used in the
|
||||
// Java code but it is just a thin wrapper of the C(++) class that contain the
|
||||
// actual information. The information is stored in C(++) as it is used to
|
||||
// call video engine APIs.
|
||||
struct CameraDesc {
|
||||
// The name and id corresponds to ViECapture's |device_nameUTF8| and
|
||||
// |unique_idUTF8|.
|
||||
char name[64];
|
||||
char unique_id[64];
|
||||
};
|
||||
|
||||
// C++ callback class that can be used to register for callbacks from the
|
||||
// video engine. It further propagates the callbacks to
|
||||
// VideoDecodeEncodeObserver.java interface. The memory associated with this
|
||||
// class is managed globally by the VideoEngineData class when registering and
|
||||
// unregistering VideoDecodeEncodeObserver.java to receive callbacks.
|
||||
class VideoDecodeEncodeObserver : public webrtc::ViEDecoderObserver,
|
||||
public webrtc::ViEEncoderObserver {
|
||||
public:
|
||||
explicit VideoDecodeEncodeObserver(jobject j_observer)
|
||||
: j_observer_(j_observer) {
|
||||
webrtc::AttachThreadScoped ats(g_vm);
|
||||
JNIEnv* jni = ats.env();
|
||||
jclass j_observer_class = jni->GetObjectClass(j_observer_);
|
||||
incoming_rate_ =
|
||||
GetMethodID(jni, j_observer_class, "incomingRate", "(III)V");
|
||||
incoming_codec_changed_ =
|
||||
GetMethodID(jni, j_observer_class, "incomingCodecChanged",
|
||||
"(ILorg/webrtc/webrtcdemo/VideoCodecInst;)V");
|
||||
request_new_keyframe_ =
|
||||
GetMethodID(jni, j_observer_class, "requestNewKeyFrame", "(I)V");
|
||||
outgoing_rate_ =
|
||||
GetMethodID(jni, j_observer_class, "outgoingRate", "(III)V");
|
||||
j_observer_ = jni->NewGlobalRef(j_observer_);
|
||||
}
|
||||
|
||||
~VideoDecodeEncodeObserver() {
|
||||
webrtc::AttachThreadScoped ats(g_vm);
|
||||
JNIEnv* jni = ats.env();
|
||||
jni->DeleteGlobalRef(j_observer_);
|
||||
}
|
||||
|
||||
virtual void IncomingRate(const int video_channel,
|
||||
const unsigned int framerate,
|
||||
const unsigned int bitrate) {
|
||||
webrtc::AttachThreadScoped ats(g_vm);
|
||||
JNIEnv* jni = ats.env();
|
||||
jni->CallVoidMethod(j_observer_, incoming_rate_, video_channel,
|
||||
static_cast<int>(framerate), static_cast<int>(bitrate));
|
||||
}
|
||||
|
||||
virtual void DecoderTiming(int decode_ms, int max_decode_ms,
|
||||
int current_delay_ms, int target_delay_ms,
|
||||
int jitter_buffer_ms, int min_playout_delay_ms,
|
||||
int render_delay_ms) {
|
||||
// TODO(fischman): consider plumbing this through to Java.
|
||||
}
|
||||
|
||||
virtual void IncomingCodecChanged(const int video_channel,
|
||||
const webrtc::VideoCodec& video_codec) {
|
||||
webrtc::AttachThreadScoped ats(g_vm);
|
||||
JNIEnv* jni = ats.env();
|
||||
webrtc::VideoCodec* codec = new webrtc::VideoCodec(video_codec);
|
||||
jclass j_codec_class =
|
||||
GetClass("org/webrtc/webrtcdemo/VideoCodecInst");
|
||||
jmethodID j_codec_ctor = GetMethodID(jni, j_codec_class, "<init>", "(J)V");
|
||||
jobject j_codec =
|
||||
jni->NewObject(j_codec_class, j_codec_ctor, jlongFromPointer(codec));
|
||||
CHECK_JNI_EXCEPTION(jni, "error during NewObject");
|
||||
jni->CallVoidMethod(j_observer_, incoming_codec_changed_, video_channel,
|
||||
j_codec);
|
||||
}
|
||||
|
||||
virtual void RequestNewKeyFrame(const int video_channel) {
|
||||
webrtc::AttachThreadScoped ats(g_vm);
|
||||
JNIEnv* jni = ats.env();
|
||||
jni->CallVoidMethod(j_observer_, request_new_keyframe_, video_channel);
|
||||
}
|
||||
|
||||
virtual void OutgoingRate(const int video_channel,
|
||||
const unsigned int framerate,
|
||||
const unsigned int bitrate) {
|
||||
webrtc::AttachThreadScoped ats(g_vm);
|
||||
JNIEnv* jni = ats.env();
|
||||
jni->CallVoidMethod(j_observer_, outgoing_rate_, video_channel,
|
||||
static_cast<int>(framerate), static_cast<int>(bitrate));
|
||||
}
|
||||
|
||||
virtual void SuspendChange(int video_channel, bool is_suspended) {}
|
||||
|
||||
private:
|
||||
jobject j_observer_;
|
||||
jmethodID incoming_rate_;
|
||||
jmethodID incoming_codec_changed_;
|
||||
jmethodID request_new_keyframe_;
|
||||
jmethodID outgoing_rate_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void ReleaseSubApi(T instance) {
|
||||
CHECK(instance->Release() == 0, "failed to release instance")
|
||||
}
|
||||
|
||||
class VideoEngineData {
|
||||
public:
|
||||
VideoEngineData()
|
||||
: vie(webrtc::VideoEngine::Create()),
|
||||
base(webrtc::ViEBase::GetInterface(vie)),
|
||||
codec(webrtc::ViECodec::GetInterface(vie)),
|
||||
network(webrtc::ViENetwork::GetInterface(vie)),
|
||||
rtp(webrtc::ViERTP_RTCP::GetInterface(vie)),
|
||||
render(webrtc::ViERender::GetInterface(vie)),
|
||||
capture(webrtc::ViECapture::GetInterface(vie)),
|
||||
externalCodec(webrtc::ViEExternalCodec::GetInterface(vie)) {
|
||||
CHECK(vie != NULL, "Video engine instance failed to be created");
|
||||
CHECK(base != NULL, "Failed to acquire base interface");
|
||||
CHECK(codec != NULL, "Failed to acquire codec interface");
|
||||
CHECK(network != NULL, "Failed to acquire network interface");
|
||||
CHECK(rtp != NULL, "Failed to acquire rtp interface");
|
||||
CHECK(render != NULL, "Failed to acquire render interface");
|
||||
CHECK(capture != NULL, "Failed to acquire capture interface");
|
||||
CHECK(externalCodec != NULL, "Failed to acquire externalCodec interface");
|
||||
}
|
||||
|
||||
~VideoEngineData() {
|
||||
CHECK(channel_transports_.empty(),
|
||||
"ViE transports must be deleted before terminating");
|
||||
CHECK(observers_.empty(),
|
||||
"ViE observers must be deleted before terminating");
|
||||
CHECK(external_decoders_.empty(),
|
||||
"ViE external decoders must be deleted before terminating");
|
||||
ReleaseSubApi(externalCodec);
|
||||
ReleaseSubApi(capture);
|
||||
ReleaseSubApi(render);
|
||||
ReleaseSubApi(rtp);
|
||||
ReleaseSubApi(network);
|
||||
ReleaseSubApi(codec);
|
||||
ReleaseSubApi(base);
|
||||
webrtc::VideoEngine* vie_pointer = vie;
|
||||
CHECK(webrtc::VideoEngine::Delete(vie_pointer), "ViE failed to be deleted");
|
||||
}
|
||||
|
||||
int CreateChannel() {
|
||||
int channel;
|
||||
CHECK(base->CreateChannel(channel) == 0, "Failed to create channel");
|
||||
CreateTransport(channel);
|
||||
return channel;
|
||||
}
|
||||
|
||||
int DeleteChannel(int channel) {
|
||||
if (base->DeleteChannel(channel) != 0) {
|
||||
return -1;
|
||||
}
|
||||
DeleteTransport(channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
webrtc::test::VideoChannelTransport* GetTransport(int channel) {
|
||||
ChannelTransports::iterator found = channel_transports_.find(channel);
|
||||
if (found == channel_transports_.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return found->second;
|
||||
}
|
||||
|
||||
int RegisterObserver(int channel, jobject j_observer) {
|
||||
CHECK(observers_.find(channel) == observers_.end(),
|
||||
"Observer already created for channel, inconsistent state");
|
||||
observers_[channel] = new VideoDecodeEncodeObserver(j_observer);
|
||||
int ret_val = codec->RegisterDecoderObserver(channel, *observers_[channel]);
|
||||
ret_val |= codec->RegisterEncoderObserver(channel, *observers_[channel]);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int DeregisterObserver(int channel) {
|
||||
Observers::iterator found = observers_.find(channel);
|
||||
if (observers_.find(channel) == observers_.end()) {
|
||||
return -1;
|
||||
}
|
||||
int ret_val = codec->DeregisterDecoderObserver(channel);
|
||||
ret_val |= codec->DeregisterEncoderObserver(channel);
|
||||
delete found->second;
|
||||
observers_.erase(found);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int RegisterExternalReceiveCodec(jint channel, jint pl_type, jobject decoder,
|
||||
bool internal_source) {
|
||||
CHECK(external_decoders_.find(channel) == external_decoders_.end(),
|
||||
"External decoder already created for channel, inconsistent state");
|
||||
external_decoders_[channel] =
|
||||
new webrtc::MediaCodecVideoDecoder(g_vm, decoder);
|
||||
return externalCodec->RegisterExternalReceiveCodec(
|
||||
channel, pl_type, external_decoders_[channel], internal_source);
|
||||
}
|
||||
|
||||
int DeRegisterExternalReceiveCodec(jint channel, jint pl_type) {
|
||||
ExternalDecoders::iterator found = external_decoders_.find(channel);
|
||||
CHECK(found != external_decoders_.end(),
|
||||
"ViE channel missing external decoder, inconsistent state");
|
||||
CHECK(externalCodec->DeRegisterExternalReceiveCodec(channel, pl_type) == 0,
|
||||
"Failed to register external receive decoder");
|
||||
delete found->second;
|
||||
external_decoders_.erase(found);
|
||||
return 0;
|
||||
}
|
||||
|
||||
webrtc::VideoEngine* const vie;
|
||||
webrtc::ViEBase* const base;
|
||||
webrtc::ViECodec* const codec;
|
||||
webrtc::ViENetwork* const network;
|
||||
webrtc::ViERTP_RTCP* const rtp;
|
||||
webrtc::ViERender* const render;
|
||||
webrtc::ViECapture* const capture;
|
||||
webrtc::ViEExternalCodec* const externalCodec;
|
||||
|
||||
private:
|
||||
// Video engine no longer provides a socket implementation. There is,
|
||||
// however, a socket implementation in webrtc::test.
|
||||
typedef std::map<int, webrtc::test::VideoChannelTransport*>
|
||||
ChannelTransports;
|
||||
typedef std::map<int, VideoDecodeEncodeObserver*> Observers;
|
||||
typedef std::map<int, webrtc::MediaCodecVideoDecoder*> ExternalDecoders;
|
||||
|
||||
void CreateTransport(int channel) {
|
||||
CHECK(GetTransport(channel) == NULL,
|
||||
"Transport already created for ViE channel, inconsistent state");
|
||||
channel_transports_[channel] =
|
||||
new webrtc::test::VideoChannelTransport(network, channel);
|
||||
}
|
||||
void DeleteTransport(int channel) {
|
||||
CHECK(GetTransport(channel) != NULL,
|
||||
"ViE channel missing transport, inconsistent state");
|
||||
delete channel_transports_[channel];
|
||||
channel_transports_.erase(channel);
|
||||
}
|
||||
|
||||
ChannelTransports channel_transports_;
|
||||
Observers observers_;
|
||||
ExternalDecoders external_decoders_;
|
||||
};
|
||||
|
||||
webrtc::VideoCodec* GetCodecInst(JNIEnv* jni, jobject j_codec) {
|
||||
jclass j_codec_class = jni->GetObjectClass(j_codec);
|
||||
jfieldID native_codec_id =
|
||||
jni->GetFieldID(j_codec_class, "nativeCodecInst", "J");
|
||||
jlong j_p = jni->GetLongField(j_codec, native_codec_id);
|
||||
return reinterpret_cast<webrtc::VideoCodec*>(j_p);
|
||||
}
|
||||
|
||||
CameraDesc* GetCameraDesc(JNIEnv* jni, jobject j_camera) {
|
||||
jclass j_camera_class = jni->GetObjectClass(j_camera);
|
||||
jfieldID native_camera_id =
|
||||
jni->GetFieldID(j_camera_class, "nativeCameraDesc", "J");
|
||||
jlong j_p = jni->GetLongField(j_camera, native_camera_id);
|
||||
return reinterpret_cast<CameraDesc*>(j_p);
|
||||
}
|
||||
|
||||
VideoEngineData* GetVideoEngineData(JNIEnv* jni, jobject j_vie) {
|
||||
jclass j_vie_class = jni->GetObjectClass(j_vie);
|
||||
jfieldID native_vie_id =
|
||||
jni->GetFieldID(j_vie_class, "nativeVideoEngine", "J");
|
||||
jlong j_p = jni->GetLongField(j_vie, native_vie_id);
|
||||
return reinterpret_cast<VideoEngineData*>(j_p);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace webrtc_examples {
|
||||
|
||||
static const char* g_classes[] = {
|
||||
"org/webrtc/webrtcdemo/CameraDesc",
|
||||
"org/webrtc/webrtcdemo/RtcpStatistics",
|
||||
"org/webrtc/webrtcdemo/VideoCodecInst",
|
||||
"org/webrtc/webrtcdemo/VideoDecodeEncodeObserver",
|
||||
"org/webrtc/webrtcdemo/MediaCodecVideoDecoder"};
|
||||
|
||||
void SetVieDeviceObjects(JavaVM* vm) {
|
||||
CHECK(vm, "Trying to register NULL vm");
|
||||
CHECK(!g_vm, "Trying to re-register vm");
|
||||
g_vm = vm;
|
||||
webrtc::AttachThreadScoped ats(g_vm);
|
||||
JNIEnv* jni = ats.env();
|
||||
g_class_reference_holder = new ClassReferenceHolder(
|
||||
jni, g_classes, arraysize(g_classes));
|
||||
}
|
||||
|
||||
void ClearVieDeviceObjects() {
|
||||
CHECK(g_vm, "Clearing vm without it being set");
|
||||
{
|
||||
webrtc::AttachThreadScoped ats(g_vm);
|
||||
g_class_reference_holder->FreeReferences(ats.env());
|
||||
}
|
||||
g_vm = NULL;
|
||||
delete g_class_reference_holder;
|
||||
g_class_reference_holder = NULL;
|
||||
}
|
||||
|
||||
} // namespace webrtc_examples
|
||||
|
||||
JOWW(jlong, VideoEngine_create)(JNIEnv* jni, jclass) {
|
||||
VideoEngineData* vie_data = new VideoEngineData();
|
||||
return jlongFromPointer(vie_data);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_init)(JNIEnv* jni, jobject j_vie) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->base->Init();
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setVoiceEngine)(JNIEnv* jni, jobject j_vie,
|
||||
jobject j_voe) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
webrtc::VoiceEngine* voe = GetVoiceEngine(jni, j_voe);
|
||||
return vie_data->base->SetVoiceEngine(voe);
|
||||
}
|
||||
|
||||
JOWW(void, VideoEngine_dispose)(JNIEnv* jni, jobject j_vie) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
delete vie_data;
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_startSend)(JNIEnv* jni, jobject j_vie, jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->base->StartSend(channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_stopRender)(JNIEnv* jni, jobject j_vie, jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->render->StopRender(channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_stopSend)(JNIEnv* jni, jobject j_vie, jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->base->StopSend(channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_startReceive)(JNIEnv* jni, jobject j_vie, jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->base->StartReceive(channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_stopReceive)(JNIEnv* jni, jobject j_vie, jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->base->StopReceive(channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_createChannel)(JNIEnv* jni, jobject j_vie) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->CreateChannel();
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_deleteChannel)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->DeleteChannel(channel);
|
||||
}
|
||||
|
||||
JOWW(jint,
|
||||
VideoEngine_connectAudioChannel(JNIEnv* jni, jobject j_vie,
|
||||
jint video_channel, jint audio_channel)) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->base->ConnectAudioChannel(video_channel, audio_channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setLocalReceiver)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel, jint port) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->GetTransport(channel)->SetLocalReceiver(port);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setSendDestination)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel, jint port,
|
||||
jstring j_addr) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
std::string addr = JavaToStdString(jni, j_addr);
|
||||
webrtc::test::VideoChannelTransport* transport =
|
||||
vie_data->GetTransport(channel);
|
||||
return transport->SetSendDestination(addr.c_str(), port);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setReceiveCodec)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel, jobject j_codec) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
webrtc::VideoCodec* codec = GetCodecInst(jni, j_codec);
|
||||
return vie_data->codec->SetReceiveCodec(channel, *codec);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setSendCodec)(JNIEnv* jni, jobject j_vie, jint channel,
|
||||
jobject j_codec) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
webrtc::VideoCodec* codec = GetCodecInst(jni, j_codec);
|
||||
return vie_data->codec->SetSendCodec(channel, *codec);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_numberOfCodecs)(JNIEnv* jni, jobject j_vie) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->codec->NumberOfCodecs();
|
||||
}
|
||||
|
||||
JOWW(jobject, VideoEngine_getCodec)(JNIEnv* jni, jobject j_vie, jint index) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
webrtc::VideoCodec* codec = new webrtc::VideoCodec();
|
||||
CHECK(vie_data->codec->GetCodec(index, *codec) == 0,
|
||||
"getCodec must be called with valid index");
|
||||
jclass j_codec_class = GetClass("org/webrtc/webrtcdemo/VideoCodecInst");
|
||||
jmethodID j_codec_ctor = GetMethodID(jni, j_codec_class, "<init>", "(J)V");
|
||||
jobject j_codec =
|
||||
jni->NewObject(j_codec_class, j_codec_ctor, jlongFromPointer(codec));
|
||||
CHECK_JNI_EXCEPTION(jni, "error during NewObject");
|
||||
return j_codec;
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_addRenderer)(JNIEnv* jni, jobject j_vie, jint channel,
|
||||
jobject gl_surface, jint z_order,
|
||||
jfloat left, jfloat top, jfloat right,
|
||||
jfloat bottom) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->render->AddRenderer(channel, gl_surface, z_order, left, top,
|
||||
right, bottom);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_removeRenderer)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->render->RemoveRenderer(channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_registerExternalReceiveCodec)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel, jint pl_type,
|
||||
jobject decoder,
|
||||
bool internal_source) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->RegisterExternalReceiveCodec(channel, pl_type, decoder,
|
||||
true);
|
||||
}
|
||||
|
||||
JOWW(jint,
|
||||
VideoEngine_deRegisterExternalReceiveCodec)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel, jint pl_type) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->DeRegisterExternalReceiveCodec(channel, pl_type);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_startRender)(JNIEnv* jni, jobject j_vie, jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->render->StartRender(channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_numberOfCaptureDevices)(JNIEnv* jni, jobject j_vie) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->capture->NumberOfCaptureDevices();
|
||||
}
|
||||
|
||||
JOWW(jobject,
|
||||
VideoEngine_getCaptureDevice(JNIEnv* jni, jobject j_vie, jint index)) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
CameraDesc* camera_info = new CameraDesc();
|
||||
if (vie_data->capture->GetCaptureDevice(
|
||||
index, camera_info->name, sizeof(camera_info->name),
|
||||
camera_info->unique_id, sizeof(camera_info->unique_id)) != 0) {
|
||||
delete camera_info;
|
||||
return NULL;
|
||||
}
|
||||
jclass j_camera_class = GetClass("org/webrtc/webrtcdemo/CameraDesc");
|
||||
jmethodID j_camera_ctor = GetMethodID(jni, j_camera_class, "<init>", "(J)V");
|
||||
jobject j_camera = jni->NewObject(j_camera_class, j_camera_ctor,
|
||||
jlongFromPointer(camera_info));
|
||||
CHECK_JNI_EXCEPTION(jni, "error during NewObject");
|
||||
return j_camera;
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_allocateCaptureDevice)(JNIEnv* jni, jobject j_vie,
|
||||
jobject j_camera) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
CameraDesc* camera_info = GetCameraDesc(jni, j_camera);
|
||||
jint capture_id;
|
||||
if (vie_data->capture->AllocateCaptureDevice(camera_info->unique_id,
|
||||
sizeof(camera_info->unique_id),
|
||||
capture_id) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return capture_id;
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_connectCaptureDevice)(JNIEnv* jni, jobject j_vie,
|
||||
jint camera_num, jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->capture->ConnectCaptureDevice(camera_num, channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_disconnectCaptureDevice)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->capture->DisconnectCaptureDevice(channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_startCapture)(JNIEnv* jni, jobject j_vie,
|
||||
jint camera_num) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->capture->StartCapture(camera_num);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_stopCapture)(JNIEnv* jni, jobject j_vie,
|
||||
jint camera_id) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->capture->StopCapture(camera_id);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_releaseCaptureDevice)(JNIEnv* jni, jobject j_vie,
|
||||
jint camera_id) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->capture->ReleaseCaptureDevice(camera_id);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_getOrientation)(JNIEnv* jni, jobject j_vie,
|
||||
jobject j_camera) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
CameraDesc* camera_info = GetCameraDesc(jni, j_camera);
|
||||
webrtc::VideoRotation orientation;
|
||||
if (vie_data->capture->GetOrientation(camera_info->unique_id, orientation) !=
|
||||
0) {
|
||||
return -1;
|
||||
}
|
||||
return static_cast<jint>(orientation);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setVideoRotations)(JNIEnv* jni,
|
||||
jobject j_vie,
|
||||
jint capture_id,
|
||||
jint degrees) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->capture->SetVideoRotation(
|
||||
capture_id, static_cast<webrtc::VideoRotation>(degrees));
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setNackStatus)(JNIEnv* jni, jobject j_vie, jint channel,
|
||||
jboolean enable) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->rtp->SetNACKStatus(channel, enable);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setKeyFrameRequestMethod)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel,
|
||||
jint request_method) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->rtp->SetKeyFrameRequestMethod(
|
||||
channel, static_cast<webrtc::ViEKeyFrameRequestMethod>(request_method));
|
||||
}
|
||||
|
||||
JOWW(jobject, VideoEngine_getReceivedRtcpStatistics)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel) {
|
||||
unsigned short fraction_lost; // NOLINT
|
||||
unsigned int cumulative_lost; // NOLINT
|
||||
unsigned int extended_max; // NOLINT
|
||||
unsigned int jitter; // NOLINT
|
||||
int64_t rtt_ms;
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
if (vie_data->rtp->GetReceivedRTCPStatistics(channel, fraction_lost,
|
||||
cumulative_lost, extended_max,
|
||||
jitter, rtt_ms) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
jclass j_rtcp_statistics_class =
|
||||
GetClass("org/webrtc/webrtcdemo/RtcpStatistics");
|
||||
jmethodID j_rtcp_statistics_ctor =
|
||||
GetMethodID(jni, j_rtcp_statistics_class, "<init>", "(IIIII)V");
|
||||
jobject j_rtcp_statistics =
|
||||
jni->NewObject(j_rtcp_statistics_class, j_rtcp_statistics_ctor,
|
||||
fraction_lost, cumulative_lost, extended_max, jitter,
|
||||
static_cast<int>(rtt_ms));
|
||||
CHECK_JNI_EXCEPTION(jni, "error during NewObject");
|
||||
return j_rtcp_statistics;
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_registerObserver)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel, jobject callback) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->RegisterObserver(channel, callback);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_deregisterObserver)(JNIEnv* jni, jobject j_vie,
|
||||
jint channel) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->DeregisterObserver(channel);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setTraceFile)(JNIEnv* jni, jobject, jstring j_filename,
|
||||
jboolean file_counter) {
|
||||
std::string filename = JavaToStdString(jni, j_filename);
|
||||
return webrtc::VideoEngine::SetTraceFile(filename.c_str(), file_counter);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_nativeSetTraceFilter)(JNIEnv* jni, jobject,
|
||||
jint filter) {
|
||||
return webrtc::VideoEngine::SetTraceFilter(filter);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_startRtpDump)(JNIEnv* jni, jobject j_vie, jint channel,
|
||||
jstring j_filename, jint direction) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
std::string filename = JavaToStdString(jni, j_filename);
|
||||
return vie_data->rtp->StartRTPDump(
|
||||
channel, filename.c_str(), static_cast<webrtc::RTPDirections>(direction));
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_stopRtpDump)(JNIEnv* jni, jobject j_vie, jint channel,
|
||||
jint direction) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->rtp->StopRTPDump(
|
||||
channel, static_cast<webrtc::RTPDirections>(direction));
|
||||
}
|
||||
|
||||
JOWW(void, VideoCodecInst_dispose)(JNIEnv* jni, jobject j_codec) {
|
||||
delete GetCodecInst(jni, j_codec);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoCodecInst_plType)(JNIEnv* jni, jobject j_codec) {
|
||||
return GetCodecInst(jni, j_codec)->plType;
|
||||
}
|
||||
|
||||
JOWW(jstring, VideoCodecInst_name)(JNIEnv* jni, jobject j_codec) {
|
||||
return jni->NewStringUTF(GetCodecInst(jni, j_codec)->plName);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoCodecInst_width)(JNIEnv* jni, jobject j_codec) {
|
||||
return GetCodecInst(jni, j_codec)->width;
|
||||
}
|
||||
|
||||
JOWW(void, VideoCodecInst_setWidth)(JNIEnv* jni, jobject j_codec, jint width) {
|
||||
GetCodecInst(jni, j_codec)->width = width;
|
||||
}
|
||||
|
||||
JOWW(jint, VideoCodecInst_height)(JNIEnv* jni, jobject j_codec) {
|
||||
return GetCodecInst(jni, j_codec)->height;
|
||||
}
|
||||
|
||||
JOWW(void, VideoCodecInst_setHeight)(JNIEnv* jni, jobject j_codec,
|
||||
jint height) {
|
||||
GetCodecInst(jni, j_codec)->height = height;
|
||||
}
|
||||
|
||||
JOWW(jint, VideoCodecInst_startBitRate)(JNIEnv* jni, jobject j_codec) {
|
||||
return GetCodecInst(jni, j_codec)->startBitrate;
|
||||
}
|
||||
|
||||
JOWW(void, VideoCodecInst_setStartBitRate)(JNIEnv* jni, jobject j_codec,
|
||||
jint bitrate) {
|
||||
GetCodecInst(jni, j_codec)->startBitrate = bitrate;
|
||||
}
|
||||
|
||||
JOWW(jint, VideoCodecInst_maxBitRate)(JNIEnv* jni, jobject j_codec) {
|
||||
return GetCodecInst(jni, j_codec)->maxBitrate;
|
||||
}
|
||||
|
||||
JOWW(void, VideoCodecInst_setMaxBitRate)(JNIEnv* jni, jobject j_codec,
|
||||
jint bitrate) {
|
||||
GetCodecInst(jni, j_codec)->maxBitrate = bitrate;
|
||||
}
|
||||
|
||||
JOWW(jint, VideoCodecInst_maxFrameRate)(JNIEnv* jni, jobject j_codec) {
|
||||
return GetCodecInst(jni, j_codec)->maxFramerate;
|
||||
}
|
||||
|
||||
JOWW(void, VideoCodecInst_setMaxFrameRate)(JNIEnv* jni, jobject j_codec,
|
||||
jint framerate) {
|
||||
GetCodecInst(jni, j_codec)->maxFramerate = framerate;
|
||||
}
|
||||
|
||||
JOWW(void, CameraDesc_dispose)(JNIEnv* jni, jobject j_camera) {
|
||||
delete GetCameraDesc(jni, j_camera);
|
||||
}
|
||||
|
||||
JOWW(jint, VideoEngine_setLocalSSRC)(JNIEnv* jni, jobject j_vie, jint channel,
|
||||
jint ssrc) {
|
||||
VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
|
||||
return vie_data->rtp->SetLocalSSRC(channel, ssrc);
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_EXAMPLES_ANDROID_MEDIA_DEMO_JNI_VIDEO_ENGINE_H_
|
||||
#define WEBRTC_EXAMPLES_ANDROID_MEDIA_DEMO_JNI_VIDEO_ENGINE_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
namespace webrtc_examples {
|
||||
|
||||
void SetVieDeviceObjects(JavaVM* vm);
|
||||
void ClearVieDeviceObjects();
|
||||
|
||||
} // namespace webrtc_examples
|
||||
|
||||
#endif // WEBRTC_EXAMPLES_ANDROID_MEDIA_DEMO_JNI_VIDEO_ENGINE_H_
|
@ -8,10 +8,6 @@
|
||||
android:orientation="vertical"
|
||||
android:layout_width="120dip"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout android:id="@+id/llLocalView"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="80dip">
|
||||
</LinearLayout>
|
||||
<TextView android:id="@+id/tvStats"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="60dip"
|
||||
@ -22,18 +18,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:text="@string/stats"/>
|
||||
<Button android:id="@+id/btSwitchCamera"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"/>
|
||||
<Button android:id="@+id/btStartStopCall"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout android:id="@+id/llRemoteView"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="1">
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@ -13,16 +13,6 @@
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent">
|
||||
<CheckBox android:id="@+id/cbVideoReceive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enableVideoReceive">
|
||||
</CheckBox>
|
||||
<CheckBox android:id="@+id/cbVideoSend"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enableVideoSend">
|
||||
</CheckBox>
|
||||
<CheckBox android:id="@+id/cbAudio"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@ -43,29 +33,4 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:imeOptions="actionDone">
|
||||
</EditText>
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent">
|
||||
<RadioGroup android:id="@+id/rRenderMechanism"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<RadioButton android:id="@+id/rOpenGl"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="OpenGL"
|
||||
android:checked="true"
|
||||
android:textColor="#fff"/>
|
||||
<RadioButton android:id="@+id/rSurfaceView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SurfaceView"
|
||||
android:textColor="#fff" />
|
||||
<RadioButton android:id="@+id/rMediaCodec"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Android:MediaCodec"
|
||||
android:textColor="#fff" />
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical">
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:textSize="24dip"
|
||||
android:text="@string/vSettings">
|
||||
</TextView>
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/codecType">
|
||||
</TextView>
|
||||
<Spinner android:id="@+id/spCodecType"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
</Spinner>
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/codecSize">
|
||||
</TextView>
|
||||
<Spinner android:id="@+id/spCodecSize"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent">
|
||||
</Spinner>
|
||||
<LinearLayout android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent">
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/vTxPort">
|
||||
</TextView>
|
||||
<EditText android:id="@+id/etVTxPort"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="number">
|
||||
</EditText>
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/vRxPort">
|
||||
</TextView>
|
||||
<EditText android:id="@+id/etVRxPort"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="number">
|
||||
</EditText>
|
||||
</LinearLayout>
|
||||
<LinearLayout android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent">
|
||||
<CheckBox android:id="@+id/cbNack"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/nack">
|
||||
</CheckBox>
|
||||
<CheckBox android:id="@+id/cbVideoRTPDump"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/rtpDump">
|
||||
</CheckBox>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
package org.webrtc.webrtcdemo;
|
||||
|
||||
public class CameraDesc {
|
||||
private final long nativeCameraDesc;
|
||||
|
||||
// CameraDesc can only be created from the native layer.
|
||||
private CameraDesc(long nativeCameraDesc) {
|
||||
this.nativeCameraDesc = nativeCameraDesc;
|
||||
}
|
||||
|
||||
// Dispose must be called before all references to CameraDesc are lost as it
|
||||
// will free memory allocated in the native layer.
|
||||
public native void dispose();
|
||||
}
|
@ -30,10 +30,6 @@ public class MainMenuFragment extends Fragment implements MediaEngineObserver {
|
||||
private Button btStartStopCall;
|
||||
private TextView tvStats;
|
||||
|
||||
// Remote and local stream displays.
|
||||
private LinearLayout llRemoteSurface;
|
||||
private LinearLayout llLocalSurface;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
@ -41,9 +37,6 @@ public class MainMenuFragment extends Fragment implements MediaEngineObserver {
|
||||
|
||||
TAG = getResources().getString(R.string.tag);
|
||||
|
||||
llRemoteSurface = (LinearLayout) v.findViewById(R.id.llRemoteView);
|
||||
llLocalSurface = (LinearLayout) v.findViewById(R.id.llLocalView);
|
||||
|
||||
Button btStats = (Button) v.findViewById(R.id.btStats);
|
||||
boolean stats = getResources().getBoolean(R.bool.stats_enabled_default);
|
||||
enableStats(btStats, stats);
|
||||
@ -56,20 +49,6 @@ public class MainMenuFragment extends Fragment implements MediaEngineObserver {
|
||||
});
|
||||
tvStats = (TextView) v.findViewById(R.id.tvStats);
|
||||
|
||||
Button btSwitchCamera = (Button) v.findViewById(R.id.btSwitchCamera);
|
||||
if (getEngine().hasMultipleCameras()) {
|
||||
btSwitchCamera.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View button) {
|
||||
toggleCamera((Button) button);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
btSwitchCamera.setEnabled(false);
|
||||
}
|
||||
btSwitchCamera.setText(getEngine().frontCameraIsSet() ?
|
||||
R.string.backCamera :
|
||||
R.string.frontCamera);
|
||||
|
||||
btStartStopCall = (Button) v.findViewById(R.id.btStartStopCall);
|
||||
btStartStopCall.setText(getEngine().isRunning() ?
|
||||
R.string.stopCall :
|
||||
@ -109,28 +88,6 @@ public class MainMenuFragment extends Fragment implements MediaEngineObserver {
|
||||
return stateProvider.getEngine();
|
||||
}
|
||||
|
||||
private void setViews() {
|
||||
SurfaceView remoteSurfaceView = getEngine().getRemoteSurfaceView();
|
||||
if (remoteSurfaceView != null) {
|
||||
llRemoteSurface.addView(remoteSurfaceView);
|
||||
}
|
||||
SurfaceView svLocal = getEngine().getLocalSurfaceView();
|
||||
if (svLocal != null) {
|
||||
llLocalSurface.addView(svLocal);
|
||||
}
|
||||
}
|
||||
|
||||
private void clearViews() {
|
||||
SurfaceView remoteSurfaceView = getEngine().getRemoteSurfaceView();
|
||||
if (remoteSurfaceView != null) {
|
||||
llRemoteSurface.removeView(remoteSurfaceView);
|
||||
}
|
||||
SurfaceView svLocal = getEngine().getLocalSurfaceView();
|
||||
if (svLocal != null) {
|
||||
llLocalSurface.removeView(svLocal);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableStats(Button btStats, boolean enable) {
|
||||
if (enable) {
|
||||
getEngine().setObserver(this);
|
||||
@ -144,21 +101,6 @@ public class MainMenuFragment extends Fragment implements MediaEngineObserver {
|
||||
btStats.setText(enable ? R.string.statsOff : R.string.statsOn);
|
||||
}
|
||||
|
||||
private void toggleCamera(Button btSwitchCamera) {
|
||||
SurfaceView svLocal = getEngine().getLocalSurfaceView();
|
||||
boolean resetLocalView = svLocal != null;
|
||||
if (resetLocalView) {
|
||||
llLocalSurface.removeView(svLocal);
|
||||
}
|
||||
getEngine().toggleCamera();
|
||||
if (resetLocalView) {
|
||||
svLocal = getEngine().getLocalSurfaceView();
|
||||
llLocalSurface.addView(svLocal);
|
||||
}
|
||||
btSwitchCamera.setText(getEngine().frontCameraIsSet() ?
|
||||
R.string.backCamera :
|
||||
R.string.frontCamera);
|
||||
}
|
||||
|
||||
public void toggleStart() {
|
||||
if (getEngine().isRunning()) {
|
||||
@ -172,12 +114,10 @@ public class MainMenuFragment extends Fragment implements MediaEngineObserver {
|
||||
}
|
||||
|
||||
public void stopAll() {
|
||||
clearViews();
|
||||
getEngine().stop();
|
||||
}
|
||||
|
||||
private void startCall() {
|
||||
getEngine().start();
|
||||
setViews();
|
||||
}
|
||||
}
|
@ -10,52 +10,20 @@
|
||||
|
||||
package org.webrtc.webrtcdemo;
|
||||
|
||||
import org.webrtc.videoengine.ViERenderer;
|
||||
import org.webrtc.videoengine.VideoCaptureAndroid;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.Camera.CameraInfo;
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.SensorManager;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.view.OrientationEventListener;
|
||||
import android.view.SurfaceView;
|
||||
import java.io.File;
|
||||
|
||||
public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
// TODO(henrike): Most of these should be moved to xml (since static).
|
||||
private static final int VCM_VP8_PAYLOAD_TYPE = 100;
|
||||
private static final int SEND_CODEC_FPS = 30;
|
||||
// TODO(henrike): increase INIT_BITRATE_KBPS to 2000 and ensure that
|
||||
// 720p30fps can be acheived (on hardware that can handle it). Note that
|
||||
// setting 2000 currently leads to failure, so that has to be resolved first.
|
||||
private static final int INIT_BITRATE_KBPS = 500;
|
||||
private static final int MAX_BITRATE_KBPS = 3000;
|
||||
public class MediaEngine {
|
||||
private static final String LOG_DIR = "webrtc";
|
||||
private static final int WIDTH_IDX = 0;
|
||||
private static final int HEIGHT_IDX = 1;
|
||||
private static final int[][] RESOLUTIONS = {
|
||||
{176,144}, {320,240}, {352,288}, {640,480}, {1280,720}
|
||||
};
|
||||
// Arbitrary choice of 4/5 volume (204/256).
|
||||
private static final int volumeLevel = 204;
|
||||
|
||||
public static int numberOfResolutions() { return RESOLUTIONS.length; }
|
||||
|
||||
public static String[] resolutionsAsString() {
|
||||
String[] retVal = new String[numberOfResolutions()];
|
||||
for (int i = 0; i < numberOfResolutions(); ++i) {
|
||||
retVal[i] = RESOLUTIONS[i][0] + "x" + RESOLUTIONS[i][1];
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Checks for and communicate failures to user (logcat and popup).
|
||||
private void check(boolean value, String message) {
|
||||
@ -78,21 +46,6 @@ public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
// Converts device rotation to camera rotation. Rotation depends on if the
|
||||
// camera is back facing and rotate with the device or front facing and
|
||||
// rotating in the opposite direction of the device.
|
||||
private static int rotationFromRealWorldUp(CameraInfo info,
|
||||
int deviceRotation) {
|
||||
int coarseDeviceOrientation =
|
||||
(int)(Math.round((double)deviceRotation / 90) * 90) % 360;
|
||||
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
|
||||
// The front camera rotates in the opposite direction of the
|
||||
// device.
|
||||
int inverseDeviceOrientation = 360 - coarseDeviceOrientation;
|
||||
return (inverseDeviceOrientation + info.orientation) % 360;
|
||||
}
|
||||
return (coarseDeviceOrientation + info.orientation) % 360;
|
||||
}
|
||||
|
||||
// Shared Audio/Video members.
|
||||
private final Context context;
|
||||
@ -119,30 +72,6 @@ public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
private boolean audioRtpDump;
|
||||
private boolean apmRecord;
|
||||
|
||||
// Video
|
||||
private VideoEngine vie;
|
||||
private int videoChannel;
|
||||
private boolean receiveVideo;
|
||||
private boolean sendVideo;
|
||||
private boolean vieRunning;
|
||||
private int videoCodecIndex;
|
||||
private int resolutionIndex;
|
||||
private int videoTxPort;
|
||||
private int videoRxPort;
|
||||
|
||||
// Indexed by CameraInfo.CAMERA_FACING_{BACK,FRONT}.
|
||||
private CameraInfo cameras[];
|
||||
private boolean useFrontCamera;
|
||||
private int currentCameraHandle;
|
||||
private boolean enableNack;
|
||||
// openGl, surfaceView or mediaCodec (integers.xml)
|
||||
private int viewSelection;
|
||||
private boolean videoRtpDump;
|
||||
|
||||
private SurfaceView svLocal;
|
||||
private SurfaceView svRemote;
|
||||
MediaCodecVideoDecoder externalCodec;
|
||||
|
||||
private int inFps;
|
||||
private int inKbps;
|
||||
private int outFps;
|
||||
@ -150,49 +79,17 @@ public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
private int inWidth;
|
||||
private int inHeight;
|
||||
|
||||
private OrientationEventListener orientationListener;
|
||||
private int deviceOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
|
||||
|
||||
public MediaEngine(Context context) {
|
||||
this.context = context;
|
||||
voe = new VoiceEngine();
|
||||
check(voe.init() == 0, "Failed voe Init");
|
||||
audioChannel = voe.createChannel();
|
||||
check(audioChannel >= 0, "Failed voe CreateChannel");
|
||||
vie = new VideoEngine();
|
||||
check(vie.init() == 0, "Failed voe Init");
|
||||
check(vie.setVoiceEngine(voe) == 0, "Failed setVoiceEngine");
|
||||
videoChannel = vie.createChannel();
|
||||
check(audioChannel >= 0, "Failed voe CreateChannel");
|
||||
check(vie.connectAudioChannel(videoChannel, audioChannel) == 0,
|
||||
"Failed ConnectAudioChannel");
|
||||
|
||||
cameras = new CameraInfo[2];
|
||||
CameraInfo info = new CameraInfo();
|
||||
for (int i = 0; i < Camera.getNumberOfCameras(); ++i) {
|
||||
Camera.getCameraInfo(i, info);
|
||||
cameras[info.facing] = info;
|
||||
}
|
||||
setDefaultCamera();
|
||||
check(voe.setAecmMode(VoiceEngine.AecmModes.SPEAKERPHONE, false) == 0,
|
||||
"VoE set Aecm speakerphone mode failed");
|
||||
check(vie.setKeyFrameRequestMethod(videoChannel,
|
||||
VideoEngine.VieKeyFrameRequestMethod.
|
||||
KEY_FRAME_REQUEST_PLI_RTCP) == 0,
|
||||
"Failed setKeyFrameRequestMethod");
|
||||
check(vie.registerObserver(videoChannel, this) == 0,
|
||||
"Failed registerObserver");
|
||||
|
||||
// TODO(hellner): SENSOR_DELAY_NORMAL?
|
||||
// Listen to changes in device orientation.
|
||||
orientationListener =
|
||||
new OrientationEventListener(context, SensorManager.SENSOR_DELAY_UI) {
|
||||
public void onOrientationChanged (int orientation) {
|
||||
deviceOrientation = orientation;
|
||||
compensateRotation();
|
||||
}
|
||||
};
|
||||
orientationListener.enable();
|
||||
// Set audio mode to communication
|
||||
AudioManager audioManager =
|
||||
((AudioManager) context.getSystemService(Context.AUDIO_SERVICE));
|
||||
@ -214,17 +111,6 @@ public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
public void dispose() {
|
||||
check(!voeRunning && !voeRunning, "Engines must be stopped before dispose");
|
||||
context.unregisterReceiver(headsetListener);
|
||||
orientationListener.disable();
|
||||
check(vie.deregisterObserver(videoChannel) == 0,
|
||||
"Failed deregisterObserver");
|
||||
if (externalCodec != null) {
|
||||
check(vie.deRegisterExternalReceiveCodec(videoChannel,
|
||||
VCM_VP8_PAYLOAD_TYPE) == 0,
|
||||
"Failed to deregister external decoder");
|
||||
externalCodec = null;
|
||||
}
|
||||
check(vie.deleteChannel(videoChannel) == 0, "DeleteChannel");
|
||||
vie.dispose();
|
||||
check(voe.deleteChannel(audioChannel) == 0, "VoE delete channel failed");
|
||||
voe.dispose();
|
||||
}
|
||||
@ -233,18 +119,14 @@ public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
if (audioEnabled) {
|
||||
startVoE();
|
||||
}
|
||||
if (receiveVideo || sendVideo) {
|
||||
startViE();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
stopVoe();
|
||||
stopVie();
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return voeRunning || vieRunning;
|
||||
return voeRunning;
|
||||
}
|
||||
|
||||
public void setRemoteIp(String remoteIp) {
|
||||
@ -254,15 +136,6 @@ public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
|
||||
public String remoteIp() { return remoteIp; }
|
||||
|
||||
public void setTrace(boolean enable) {
|
||||
if (enable) {
|
||||
vie.setTraceFile("/sdcard/trace.txt", false);
|
||||
vie.setTraceFilter(VideoEngine.TraceLevel.TRACE_ALL);
|
||||
return;
|
||||
}
|
||||
vie.setTraceFilter(VideoEngine.TraceLevel.TRACE_NONE);
|
||||
}
|
||||
|
||||
private String getDebugDirectory() {
|
||||
// Should create a folder in /scard/|LOG_DIR|
|
||||
return Environment.getExternalStorageDirectory().toString() + "/" +
|
||||
@ -412,13 +285,13 @@ public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
public void setIncomingVoeRtpDump(boolean enable) {
|
||||
audioRtpDump = enable;
|
||||
if (!enable) {
|
||||
check(voe.stopRtpDump(videoChannel,
|
||||
check(voe.stopRtpDump(audioChannel,
|
||||
VoiceEngine.RtpDirections.INCOMING) == 0,
|
||||
"voe stopping rtp dump");
|
||||
return;
|
||||
}
|
||||
String debugDirectory = getDebugDirectory();
|
||||
check(voe.startRtpDump(videoChannel, debugDirectory +
|
||||
check(voe.startRtpDump(audioChannel, debugDirectory +
|
||||
String.format("/voe_%d.rtp", System.currentTimeMillis()),
|
||||
VoiceEngine.RtpDirections.INCOMING) == 0,
|
||||
"voe starting rtp dump");
|
||||
@ -431,122 +304,6 @@ public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
audioManager.setSpeakerphoneOn(useSpeaker);
|
||||
}
|
||||
|
||||
public void startViE() {
|
||||
check(!vieRunning, "ViE already started");
|
||||
|
||||
if (receiveVideo) {
|
||||
if (viewSelection ==
|
||||
context.getResources().getInteger(R.integer.openGl)) {
|
||||
svRemote = ViERenderer.CreateRenderer(context, true);
|
||||
} else if (viewSelection ==
|
||||
context.getResources().getInteger(R.integer.surfaceView)) {
|
||||
svRemote = ViERenderer.CreateRenderer(context, false);
|
||||
} else {
|
||||
externalCodec = new MediaCodecVideoDecoder(context);
|
||||
svRemote = externalCodec.getView();
|
||||
}
|
||||
if (externalCodec != null) {
|
||||
check(vie.registerExternalReceiveCodec(videoChannel,
|
||||
VCM_VP8_PAYLOAD_TYPE, externalCodec, true) == 0,
|
||||
"Failed to register external decoder");
|
||||
} else {
|
||||
check(vie.addRenderer(videoChannel, svRemote,
|
||||
0, 0, 0, 1, 1) == 0, "Failed AddRenderer");
|
||||
check(vie.startRender(videoChannel) == 0, "Failed StartRender");
|
||||
}
|
||||
check(vie.startReceive(videoChannel) == 0, "Failed StartReceive");
|
||||
}
|
||||
if (sendVideo) {
|
||||
startCamera();
|
||||
check(vie.startSend(videoChannel) == 0, "Failed StartSend");
|
||||
}
|
||||
vieRunning = true;
|
||||
}
|
||||
|
||||
private void stopVie() {
|
||||
if (!vieRunning) {
|
||||
return;
|
||||
}
|
||||
check(vie.stopSend(videoChannel) == 0, "StopSend");
|
||||
check(vie.stopReceive(videoChannel) == 0, "StopReceive");
|
||||
if (externalCodec != null) {
|
||||
check(vie.deRegisterExternalReceiveCodec(videoChannel,
|
||||
VCM_VP8_PAYLOAD_TYPE) == 0,
|
||||
"Failed to deregister external decoder");
|
||||
externalCodec.dispose();
|
||||
externalCodec = null;
|
||||
} else {
|
||||
check(vie.stopRender(videoChannel) == 0, "StopRender");
|
||||
check(vie.removeRenderer(videoChannel) == 0, "RemoveRenderer");
|
||||
}
|
||||
stopCamera(); // Stop capturer after remote renderer.
|
||||
svRemote = null;
|
||||
vieRunning = false;
|
||||
}
|
||||
|
||||
public void setReceiveVideo(boolean receiveVideo) {
|
||||
this.receiveVideo = receiveVideo;
|
||||
}
|
||||
|
||||
public boolean receiveVideo() { return receiveVideo; }
|
||||
|
||||
public void setSendVideo(boolean sendVideo) { this.sendVideo = sendVideo; }
|
||||
|
||||
public boolean sendVideo() { return sendVideo; }
|
||||
|
||||
public int videoCodecIndex() { return videoCodecIndex; }
|
||||
|
||||
public void setVideoCodec(int codecNumber) {
|
||||
videoCodecIndex = codecNumber;
|
||||
updateVideoCodec();
|
||||
}
|
||||
|
||||
public String[] videoCodecsAsString() {
|
||||
String[] retVal = new String[vie.numberOfCodecs()];
|
||||
for (int i = 0; i < vie.numberOfCodecs(); ++i) {
|
||||
VideoCodecInst codec = vie.getCodec(i);
|
||||
retVal[i] = codec.toString();
|
||||
codec.dispose();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public int resolutionIndex() { return resolutionIndex; }
|
||||
|
||||
public void setResolutionIndex(int resolution) {
|
||||
resolutionIndex = resolution;
|
||||
updateVideoCodec();
|
||||
}
|
||||
|
||||
private void updateVideoCodec() {
|
||||
VideoCodecInst codec = getVideoCodec(videoCodecIndex, resolutionIndex);
|
||||
check(vie.setSendCodec(videoChannel, codec) == 0, "Failed setReceiveCodec");
|
||||
codec.dispose();
|
||||
}
|
||||
|
||||
private VideoCodecInst getVideoCodec(int codecNumber, int resolution) {
|
||||
VideoCodecInst retVal = vie.getCodec(codecNumber);
|
||||
retVal.setStartBitRate(INIT_BITRATE_KBPS);
|
||||
retVal.setMaxBitRate(MAX_BITRATE_KBPS);
|
||||
retVal.setWidth(RESOLUTIONS[resolution][WIDTH_IDX]);
|
||||
retVal.setHeight(RESOLUTIONS[resolution][HEIGHT_IDX]);
|
||||
retVal.setMaxFrameRate(SEND_CODEC_FPS);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void setVideoRxPort(int videoRxPort) {
|
||||
this.videoRxPort = videoRxPort;
|
||||
check(vie.setLocalReceiver(videoChannel, videoRxPort) == 0,
|
||||
"Failed setLocalReceiver");
|
||||
}
|
||||
|
||||
public int videoRxPort() { return videoRxPort; }
|
||||
|
||||
public void setVideoTxPort(int videoTxPort) {
|
||||
this.videoTxPort = videoTxPort;
|
||||
UpdateSendDestination();
|
||||
}
|
||||
|
||||
private void UpdateSendDestination() {
|
||||
if (remoteIp == null) {
|
||||
return;
|
||||
@ -555,195 +312,10 @@ public class MediaEngine implements VideoDecodeEncodeObserver {
|
||||
check(voe.setSendDestination(audioChannel, audioTxPort,
|
||||
remoteIp) == 0, "VoE set send destination failed");
|
||||
}
|
||||
if (videoTxPort != 0) {
|
||||
check(vie.setSendDestination(videoChannel, videoTxPort, remoteIp) == 0,
|
||||
"Failed setSendDestination");
|
||||
}
|
||||
|
||||
// Setting localSSRC manually (arbitrary value) for loopback test,
|
||||
// As otherwise we will get a clash and a new SSRC will be set,
|
||||
// Which will reset the receiver and other minor issues.
|
||||
if (remoteIp.equals("127.0.0.1")) {
|
||||
check(vie.setLocalSSRC(videoChannel, 0x01234567) == 0,
|
||||
"Failed setLocalSSRC");
|
||||
}
|
||||
}
|
||||
|
||||
public int videoTxPort() {
|
||||
return videoTxPort;
|
||||
}
|
||||
|
||||
public boolean hasMultipleCameras() {
|
||||
return Camera.getNumberOfCameras() > 1;
|
||||
}
|
||||
|
||||
public boolean frontCameraIsSet() {
|
||||
return useFrontCamera;
|
||||
}
|
||||
|
||||
// Set default camera to front if there is a front camera.
|
||||
private void setDefaultCamera() {
|
||||
useFrontCamera = hasFrontCamera();
|
||||
}
|
||||
|
||||
public void toggleCamera() {
|
||||
if (vieRunning) {
|
||||
stopCamera();
|
||||
}
|
||||
useFrontCamera = !useFrontCamera;
|
||||
if (vieRunning) {
|
||||
startCamera();
|
||||
}
|
||||
}
|
||||
|
||||
private void startCamera() {
|
||||
CameraDesc cameraInfo = vie.getCaptureDevice(getCameraId(getCameraIndex()));
|
||||
currentCameraHandle = vie.allocateCaptureDevice(cameraInfo);
|
||||
cameraInfo.dispose();
|
||||
check(vie.connectCaptureDevice(currentCameraHandle, videoChannel) == 0,
|
||||
"Failed to connect capture device");
|
||||
// Camera and preview surface.
|
||||
svLocal = new SurfaceView(context);
|
||||
VideoCaptureAndroid.setLocalPreview(svLocal.getHolder());
|
||||
check(vie.startCapture(currentCameraHandle) == 0, "Failed StartCapture");
|
||||
compensateRotation();
|
||||
}
|
||||
|
||||
private void stopCamera() {
|
||||
check(vie.stopCapture(currentCameraHandle) == 0, "Failed StopCapture");
|
||||
svLocal = null;
|
||||
check(vie.disconnectCaptureDevice(videoChannel) == 0,
|
||||
"Failed to disconnect capture device");
|
||||
check(vie.releaseCaptureDevice(currentCameraHandle) == 0,
|
||||
"Failed ReleaseCaptureDevice");
|
||||
}
|
||||
|
||||
private boolean hasFrontCamera() {
|
||||
return cameras[CameraInfo.CAMERA_FACING_FRONT] != null;
|
||||
}
|
||||
|
||||
public SurfaceView getRemoteSurfaceView() {
|
||||
return svRemote;
|
||||
}
|
||||
|
||||
public SurfaceView getLocalSurfaceView() {
|
||||
return svLocal;
|
||||
}
|
||||
|
||||
public void setViewSelection(int viewSelection) {
|
||||
this.viewSelection = viewSelection;
|
||||
}
|
||||
|
||||
public int viewSelection() { return viewSelection; }
|
||||
|
||||
public boolean nackEnabled() { return enableNack; }
|
||||
|
||||
public void setNack(boolean enable) {
|
||||
enableNack = enable;
|
||||
check(vie.setNackStatus(videoChannel, enableNack) == 0,
|
||||
"Failed setNackStatus");
|
||||
}
|
||||
|
||||
// Collates current state into a multiline string.
|
||||
public String sendReceiveState() {
|
||||
int packetLoss = 0;
|
||||
if (vieRunning) {
|
||||
RtcpStatistics stats = vie.getReceivedRtcpStatistics(videoChannel);
|
||||
if (stats != null) {
|
||||
// Calculate % lost from fraction lost.
|
||||
// Definition of fraction lost can be found in RFC3550.
|
||||
packetLoss = (stats.fractionLost * 100) >> 8;
|
||||
}
|
||||
}
|
||||
String retVal =
|
||||
"fps in/out: " + inFps + "/" + outFps + "\n" +
|
||||
"kBps in/out: " + inKbps / 1024 + "/ " + outKbps / 1024 + "\n" +
|
||||
"resolution: " + inWidth + "x" + inHeight + "\n" +
|
||||
"loss: " + packetLoss + "%";
|
||||
return retVal;
|
||||
}
|
||||
|
||||
MediaEngineObserver observer;
|
||||
public void setObserver(MediaEngineObserver observer) {
|
||||
this.observer = observer;
|
||||
}
|
||||
|
||||
// Callbacks from the VideoDecodeEncodeObserver interface.
|
||||
public void incomingRate(int videoChannel, int framerate, int bitrate) {
|
||||
inFps = framerate;
|
||||
inKbps = bitrate;
|
||||
newStats();
|
||||
}
|
||||
|
||||
public void incomingCodecChanged(int videoChannel,
|
||||
VideoCodecInst videoCodec) {
|
||||
inWidth = videoCodec.width();
|
||||
inHeight = videoCodec.height();
|
||||
videoCodec.dispose();
|
||||
newStats();
|
||||
}
|
||||
|
||||
public void requestNewKeyFrame(int videoChannel) {}
|
||||
|
||||
public void outgoingRate(int videoChannel, int framerate, int bitrate) {
|
||||
outFps = framerate;
|
||||
outKbps = bitrate;
|
||||
newStats();
|
||||
}
|
||||
|
||||
private void newStats() {
|
||||
if (observer != null) {
|
||||
observer.newStats(sendReceiveState());
|
||||
}
|
||||
}
|
||||
|
||||
// Debug helpers.
|
||||
public boolean videoRtpDump() { return videoRtpDump; }
|
||||
|
||||
public void setIncomingVieRtpDump(boolean enable) {
|
||||
videoRtpDump = enable;
|
||||
if (!enable) {
|
||||
check(vie.stopRtpDump(videoChannel,
|
||||
VideoEngine.RtpDirections.INCOMING) == 0,
|
||||
"vie StopRTPDump");
|
||||
return;
|
||||
}
|
||||
String debugDirectory = getDebugDirectory();
|
||||
check(vie.startRtpDump(videoChannel, debugDirectory +
|
||||
String.format("/vie_%d.rtp", System.currentTimeMillis()),
|
||||
VideoEngine.RtpDirections.INCOMING) == 0,
|
||||
"vie StartRtpDump");
|
||||
}
|
||||
|
||||
private int getCameraIndex() {
|
||||
return useFrontCamera ? Camera.CameraInfo.CAMERA_FACING_FRONT :
|
||||
Camera.CameraInfo.CAMERA_FACING_BACK;
|
||||
}
|
||||
|
||||
private int getCameraId(int index) {
|
||||
for (int i = Camera.getNumberOfCameras() - 1; i >= 0; --i) {
|
||||
CameraInfo info = new CameraInfo();
|
||||
Camera.getCameraInfo(i, info);
|
||||
if (index == info.facing) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Index does not match a camera");
|
||||
}
|
||||
|
||||
private void compensateRotation() {
|
||||
if (svLocal == null) {
|
||||
// Not rendering (or sending).
|
||||
return;
|
||||
}
|
||||
if (deviceOrientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
int cameraRotation = rotationFromRealWorldUp(
|
||||
cameras[getCameraIndex()], deviceOrientation);
|
||||
// Egress streams should have real world up as up.
|
||||
check(vie.setVideoRotations(currentCameraHandle, cameraRotation) == 0,
|
||||
"Failed setVideoRotations: camera " + currentCameraHandle +
|
||||
"rotation " + cameraRotation);
|
||||
}
|
||||
}
|
||||
|
@ -41,24 +41,6 @@ public class SettingsMenuFragment extends Fragment
|
||||
|
||||
TAG = getResources().getString(R.string.tag);
|
||||
|
||||
CheckBox cbVideoReceive = (CheckBox) v.findViewById(R.id.cbVideoReceive);
|
||||
cbVideoReceive.setChecked(getEngine().receiveVideo());
|
||||
cbVideoReceive.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View checkBox) {
|
||||
CheckBox cbVideoReceive = (CheckBox) checkBox;
|
||||
getEngine().setReceiveVideo(cbVideoReceive.isChecked());
|
||||
cbVideoReceive.setChecked(getEngine().receiveVideo());
|
||||
}
|
||||
});
|
||||
CheckBox cbVideoSend = (CheckBox) v.findViewById(R.id.cbVideoSend);
|
||||
cbVideoSend.setChecked(getEngine().sendVideo());
|
||||
cbVideoSend.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View checkBox) {
|
||||
CheckBox cbVideoSend = (CheckBox) checkBox;
|
||||
getEngine().setSendVideo(cbVideoSend.isChecked());
|
||||
cbVideoSend.setChecked(getEngine().sendVideo());
|
||||
}
|
||||
});
|
||||
CheckBox cbAudio = (CheckBox) v.findViewById(R.id.cbAudio);
|
||||
cbAudio.setChecked(getEngine().audioEnabled());
|
||||
cbAudio.setOnClickListener(new View.OnClickListener() {
|
||||
@ -87,19 +69,6 @@ public class SettingsMenuFragment extends Fragment
|
||||
});
|
||||
// Has to be after remote IP as loopback changes it.
|
||||
loopbackChanged(cbLoopback);
|
||||
RadioGroup rRenderMechanism =
|
||||
(RadioGroup) v.findViewById(R.id.rRenderMechanism);
|
||||
rRenderMechanism.clearCheck();
|
||||
if (getEngine().viewSelection() ==
|
||||
getResources().getInteger(R.integer.openGl)) {
|
||||
rRenderMechanism.check(R.id.rOpenGl);
|
||||
} else if (getEngine().viewSelection() ==
|
||||
getResources().getInteger(R.integer.surfaceView)) {
|
||||
rRenderMechanism.check(R.id.rSurfaceView);
|
||||
} else {
|
||||
rRenderMechanism.check(R.id.rMediaCodec);
|
||||
}
|
||||
rRenderMechanism.setOnCheckedChangeListener(this);
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -154,22 +123,7 @@ public class SettingsMenuFragment extends Fragment
|
||||
return stateProvider.getEngine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||
switch (checkedId) {
|
||||
case R.id.rOpenGl:
|
||||
getEngine().setViewSelection(
|
||||
getResources().getInteger(R.integer.openGl));
|
||||
break;
|
||||
case R.id.rSurfaceView:
|
||||
getEngine().setViewSelection(
|
||||
getResources().getInteger(R.integer.surfaceView));
|
||||
break;
|
||||
case R.id.rMediaCodec:
|
||||
getEngine().setViewSelection(
|
||||
getResources().getInteger(R.integer.mediaCodec));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
package org.webrtc.webrtcdemo;
|
||||
|
||||
public class VideoCodecInst {
|
||||
private final long nativeCodecInst;
|
||||
|
||||
// VideoCodecInst can only be created from the native layer.
|
||||
private VideoCodecInst(long nativeCodecInst) {
|
||||
this.nativeCodecInst = nativeCodecInst;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name() + " " +
|
||||
"PlType: " + plType() + " " +
|
||||
"Width: " + width() + " " +
|
||||
"Height: " + height() + " " +
|
||||
"StartBitRate: " + startBitRate() + " " +
|
||||
"MaxFrameRate: " + maxFrameRate();
|
||||
}
|
||||
|
||||
// Dispose must be called before all references to VideoCodecInst are lost as
|
||||
// it will free memory allocated in the native layer.
|
||||
public native void dispose();
|
||||
public native int plType();
|
||||
public native String name();
|
||||
public native int width();
|
||||
public native void setWidth(int width);
|
||||
public native int height();
|
||||
public native void setHeight(int height);
|
||||
public native int startBitRate();
|
||||
public native void setStartBitRate(int bitrate);
|
||||
public native int maxBitRate();
|
||||
public native void setMaxBitRate(int bitrate);
|
||||
public native int maxFrameRate();
|
||||
public native void setMaxFrameRate(int framerate);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
package org.webrtc.webrtcdemo;
|
||||
|
||||
public interface VideoDecodeEncodeObserver {
|
||||
void incomingRate(int videoChannel, int framerate, int bitrate);
|
||||
|
||||
// VideoCodecInst.dispose must be called for |videoCodec| before all
|
||||
// references to it are lost as it will free memory allocated in the native
|
||||
// layer.
|
||||
void incomingCodecChanged(int videoChannel, VideoCodecInst videoCodec);
|
||||
|
||||
void requestNewKeyFrame(int videoChannel);
|
||||
|
||||
void outgoingRate(int videoChannel, int framerate, int bitrate);
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
package org.webrtc.webrtcdemo;
|
||||
|
||||
public class VideoEngine {
|
||||
private final long nativeVideoEngine;
|
||||
|
||||
// Keep in sync (including this comment) with webrtc/common_types.h:TraceLevel
|
||||
public enum TraceLevel {
|
||||
TRACE_NONE(0x0000),
|
||||
TRACE_STATE_INFO(0x0001),
|
||||
TRACE_WARNING(0x0002),
|
||||
TRACE_ERROR(0x0004),
|
||||
TRACE_CRITICAL(0x0008),
|
||||
TRACE_API_CALL(0x0010),
|
||||
TRACE_DEFAULT(0x00ff),
|
||||
TRACE_MODULE_CALL(0x0020),
|
||||
TRACE_MEMORY(0x0100),
|
||||
TRACE_TIMER(0x0200),
|
||||
TRACE_STREAM(0x0400),
|
||||
TRACE_DEBUG(0x0800),
|
||||
TRACE_INFO(0x1000),
|
||||
TRACE_TERSE_INFO(0x2000),
|
||||
TRACE_ALL(0xffff);
|
||||
|
||||
public final int level;
|
||||
TraceLevel(int level) {
|
||||
this.level = level;
|
||||
}
|
||||
};
|
||||
|
||||
// Keep in sync (including this comment) with
|
||||
// webrtc/video_engine/include/vie_rtp_rtcp.h:ViEKeyFrameRequestMethod
|
||||
public enum VieKeyFrameRequestMethod {
|
||||
KEY_FRAME_REQUEST_NONE, KEY_FRAME_REQUEST_PLI_RTCP,
|
||||
KEY_FRAME_REQUEST_FIR_RTP, KEY_FRAME_REQUEST_FIR_RTCP
|
||||
}
|
||||
|
||||
// Keep in sync (including this comment) with
|
||||
// webrtc/common_types.h:RtpDirections
|
||||
public enum RtpDirections { INCOMING, OUTGOING }
|
||||
|
||||
public VideoEngine() {
|
||||
nativeVideoEngine = create();
|
||||
}
|
||||
|
||||
// API comments can be found in VideoEngine's native APIs. Not all native
|
||||
// APIs are available.
|
||||
private static native long create();
|
||||
public native int init();
|
||||
public native int setVoiceEngine(VoiceEngine voe);
|
||||
public native void dispose();
|
||||
public native int startSend(int channel);
|
||||
public native int stopRender(int channel);
|
||||
public native int stopSend(int channel);
|
||||
public native int startReceive(int channel);
|
||||
public native int stopReceive(int channel);
|
||||
public native int createChannel();
|
||||
public native int deleteChannel(int channel);
|
||||
public native int connectAudioChannel(int videoChannel, int voiceChannel);
|
||||
public native int setLocalReceiver(int channel, int port);
|
||||
public native int setSendDestination(int channel, int port, String ipAddr);
|
||||
public native int numberOfCodecs();
|
||||
public native VideoCodecInst getCodec(int index);
|
||||
public native int setReceiveCodec(int channel, VideoCodecInst codec);
|
||||
public native int setSendCodec(int channel, VideoCodecInst codec);
|
||||
public native int addRenderer(int channel, Object glSurface, int zOrder,
|
||||
float left, float top,
|
||||
float right, float bottom);
|
||||
public native int removeRenderer(int channel);
|
||||
public native int registerExternalReceiveCodec(int channel, int plType,
|
||||
MediaCodecVideoDecoder decoder, boolean internal_source);
|
||||
public native int deRegisterExternalReceiveCodec(int channel, int plType);
|
||||
public native int startRender(int channel);
|
||||
public native int numberOfCaptureDevices();
|
||||
public native CameraDesc getCaptureDevice(int index);
|
||||
public native int allocateCaptureDevice(CameraDesc camera);
|
||||
public native int connectCaptureDevice(int cameraId, int channel);
|
||||
public native int disconnectCaptureDevice(int channel);
|
||||
public native int startCapture(int cameraId);
|
||||
public native int stopCapture(int cameraId);
|
||||
public native int releaseCaptureDevice(int cameraId);
|
||||
public native int getOrientation(CameraDesc camera);
|
||||
public native int setVideoRotations(int cameraId, int degrees);
|
||||
public native int setNackStatus(int channel, boolean enable);
|
||||
public int setKeyFrameRequestMethod(int channel,
|
||||
VieKeyFrameRequestMethod requestMethod) {
|
||||
return setKeyFrameRequestMethod(channel, requestMethod.ordinal());
|
||||
}
|
||||
private native int setKeyFrameRequestMethod(int channel,
|
||||
int requestMethod);
|
||||
public native RtcpStatistics getReceivedRtcpStatistics(int channel);
|
||||
public native int registerObserver(int channel,
|
||||
VideoDecodeEncodeObserver callback);
|
||||
public native int deregisterObserver(int channel);
|
||||
public native int setTraceFile(String fileName,
|
||||
boolean fileCounter);
|
||||
public int setTraceFilter(TraceLevel filter) {
|
||||
return nativeSetTraceFilter(filter.level);
|
||||
}
|
||||
private native int nativeSetTraceFilter(int filter);
|
||||
public int startRtpDump(int channel, String file,
|
||||
RtpDirections direction) {
|
||||
return startRtpDump(channel, file, direction.ordinal());
|
||||
}
|
||||
private native int startRtpDump(int channel, String file,
|
||||
int direction);
|
||||
public int stopRtpDump(int channel, RtpDirections direction) {
|
||||
return stopRtpDump(channel, direction.ordinal());
|
||||
}
|
||||
private native int stopRtpDump(int channel, int direction);
|
||||
public native int setLocalSSRC(int channel, int ssrc);
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
package org.webrtc.webrtcdemo;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import java.lang.Integer;
|
||||
|
||||
public class VideoMenuFragment extends Fragment {
|
||||
|
||||
private String TAG;
|
||||
private MenuStateProvider stateProvider;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.videomenu, container, false);
|
||||
|
||||
TAG = getResources().getString(R.string.tag);
|
||||
|
||||
String[] videoCodecsString = getEngine().videoCodecsAsString();
|
||||
Spinner spCodecType = (Spinner) v.findViewById(R.id.spCodecType);
|
||||
spCodecType.setAdapter(new SpinnerAdapter(getActivity(),
|
||||
R.layout.dropdownitems,
|
||||
videoCodecsString,
|
||||
inflater));
|
||||
spCodecType.setSelection(getEngine().videoCodecIndex());
|
||||
spCodecType.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view,
|
||||
int position, long id) {
|
||||
getEngine().setVideoCodec(position);
|
||||
}
|
||||
public void onNothingSelected(AdapterView<?> arg0) {
|
||||
Log.d(TAG, "No setting selected");
|
||||
}
|
||||
});
|
||||
Spinner spCodecSize = (Spinner) v.findViewById(R.id.spCodecSize);
|
||||
spCodecSize.setAdapter(new SpinnerAdapter(getActivity(),
|
||||
R.layout.dropdownitems,
|
||||
MediaEngine.resolutionsAsString(),
|
||||
inflater));
|
||||
// -2 means selecting the 2nd highest resolution. This maintains legacy
|
||||
// behavior. Also higher resolutions lead to lower framerate at same
|
||||
// bit rate.
|
||||
// TODO(hellner): make configuration in the form [width]x[height] instead of
|
||||
// an opaque index. Also configuration should happen in a res/values xml
|
||||
// file rather than inline.
|
||||
spCodecSize.setSelection(getEngine().resolutionIndex() - 2);
|
||||
spCodecSize.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view,
|
||||
int position, long id) {
|
||||
getEngine().setResolutionIndex(position);
|
||||
}
|
||||
public void onNothingSelected(AdapterView<?> arg0) {
|
||||
Log.d(TAG, "No setting selected");
|
||||
}
|
||||
});
|
||||
|
||||
EditText etVTxPort = (EditText) v.findViewById(R.id.etVTxPort);
|
||||
etVTxPort.setText(Integer.toString(getEngine().videoTxPort()));
|
||||
etVTxPort.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View editText) {
|
||||
EditText etVTxPort = (EditText) editText;
|
||||
getEngine()
|
||||
.setVideoTxPort(Integer.parseInt(etVTxPort.getText().toString()));
|
||||
}
|
||||
});
|
||||
EditText etVRxPort = (EditText) v.findViewById(R.id.etVRxPort);
|
||||
etVRxPort.setText(Integer.toString(getEngine().videoRxPort()));
|
||||
etVRxPort.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View editText) {
|
||||
EditText etVRxPort = (EditText) editText;
|
||||
getEngine()
|
||||
.setVideoRxPort(Integer.parseInt(etVRxPort.getText().toString()));
|
||||
}
|
||||
});
|
||||
|
||||
CheckBox cbEnableNack = (CheckBox) v.findViewById(R.id.cbNack);
|
||||
cbEnableNack.setChecked(getEngine().nackEnabled());
|
||||
cbEnableNack.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View checkBox) {
|
||||
CheckBox cbEnableNack = (CheckBox) checkBox;
|
||||
getEngine().setNack(cbEnableNack.isChecked());
|
||||
}
|
||||
});
|
||||
|
||||
CheckBox cbEnableVideoRTPDump =
|
||||
(CheckBox) v.findViewById(R.id.cbVideoRTPDump);
|
||||
cbEnableVideoRTPDump.setChecked(getEngine().videoRtpDump());
|
||||
cbEnableVideoRTPDump.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View checkBox) {
|
||||
CheckBox cbEnableVideoRTPDump = (CheckBox) checkBox;
|
||||
getEngine().setIncomingVieRtpDump(cbEnableVideoRTPDump.isChecked());
|
||||
}
|
||||
});
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
// This makes sure that the container activity has implemented
|
||||
// the callback interface. If not, it throws an exception.
|
||||
try {
|
||||
stateProvider = (MenuStateProvider) activity;
|
||||
} catch (ClassCastException e) {
|
||||
throw new ClassCastException(activity +
|
||||
" must implement MenuStateProvider");
|
||||
}
|
||||
}
|
||||
|
||||
private MediaEngine getEngine() {
|
||||
return stateProvider.getEngine();
|
||||
}
|
||||
}
|
@ -94,8 +94,6 @@ public class WebRTCDemo extends Activity implements MenuStateProvider {
|
||||
// Load all settings dictated in xml.
|
||||
mediaEngine = new MediaEngine(this);
|
||||
mediaEngine.setRemoteIp(getResources().getString(R.string.loopbackIp));
|
||||
mediaEngine.setTrace(getResources().getBoolean(
|
||||
R.bool.trace_enabled_default));
|
||||
|
||||
mediaEngine.setAudio(getResources().getBoolean(
|
||||
R.bool.audio_enabled_default));
|
||||
@ -109,22 +107,6 @@ public class WebRTCDemo extends Activity implements MenuStateProvider {
|
||||
mediaEngine.setDebuging(getResources().getBoolean(
|
||||
R.bool.apm_debug_enabled_default));
|
||||
|
||||
mediaEngine.setReceiveVideo(getResources().getBoolean(
|
||||
R.bool.video_receive_enabled_default));
|
||||
mediaEngine.setSendVideo(getResources().getBoolean(
|
||||
R.bool.video_send_enabled_default));
|
||||
mediaEngine.setVideoCodec(getResources().getInteger(
|
||||
R.integer.video_codec_default));
|
||||
// TODO(hellner): resolutions should probably be in the xml as well.
|
||||
mediaEngine.setResolutionIndex(MediaEngine.numberOfResolutions() - 2);
|
||||
mediaEngine.setVideoTxPort(getResources().getInteger(
|
||||
R.integer.vTxPortDefault));
|
||||
mediaEngine.setVideoRxPort(getResources().getInteger(
|
||||
R.integer.vRxPortDefault));
|
||||
mediaEngine.setNack(getResources().getBoolean(R.bool.nack_enabled_default));
|
||||
mediaEngine.setViewSelection(getResources().getInteger(
|
||||
R.integer.defaultView));
|
||||
|
||||
// Create action bar with all tabs.
|
||||
ActionBar actionBar = getActionBar();
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
@ -142,12 +124,6 @@ public class WebRTCDemo extends Activity implements MenuStateProvider {
|
||||
this, "Settings", SettingsMenuFragment.class));
|
||||
actionBar.addTab(tab);
|
||||
|
||||
tab = actionBar.newTab()
|
||||
.setText("Video")
|
||||
.setTabListener(new TabListener<VideoMenuFragment>(
|
||||
this, "video", VideoMenuFragment.class));
|
||||
actionBar.addTab(tab);
|
||||
|
||||
tab = actionBar.newTab()
|
||||
.setText("Audio")
|
||||
.setTabListener(new TabListener<AudioMenuFragment>(
|
||||
|
@ -17,19 +17,15 @@
|
||||
'dependencies': [
|
||||
'<(DEPTH)/third_party/icu/icu.gyp:icuuc',
|
||||
'<(webrtc_root)/common.gyp:webrtc_common',
|
||||
'<(webrtc_root)/modules/modules.gyp:video_capture_module_internal_impl',
|
||||
'<(webrtc_root)/modules/modules.gyp:video_render_module_internal_impl',
|
||||
'<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers_default',
|
||||
'<(webrtc_root)/test/test.gyp:channel_transport',
|
||||
'<(webrtc_root)/video_engine/video_engine.gyp:video_engine_core',
|
||||
'<(webrtc_root)/voice_engine/voice_engine.gyp:voice_engine',
|
||||
],
|
||||
'sources': [
|
||||
'examples/android/media_demo/jni/jni_helpers.cc',
|
||||
'examples/android/media_demo/jni/on_load.cc',
|
||||
'examples/android/media_demo/jni/video_engine_jni.cc',
|
||||
'examples/android/media_demo/jni/voice_engine_jni.cc',
|
||||
'examples/android/media_demo/jni/media_codec_video_decoder.cc',
|
||||
],
|
||||
'variables': {
|
||||
# This library uses native JNI exports; tell GYP so that the
|
||||
@ -63,8 +59,6 @@
|
||||
},
|
||||
'inputs' : [
|
||||
'<(PRODUCT_DIR)/lib.java/audio_device_module_java.jar',
|
||||
'<(PRODUCT_DIR)/lib.java/video_capture_module_java.jar',
|
||||
'<(PRODUCT_DIR)/lib.java/video_render_module_java.jar',
|
||||
'<(PRODUCT_DIR)/libwebrtcdemo-jni.so',
|
||||
'<!@(find <(android_webrtc_demo_root)/src -name "*.java")',
|
||||
'<!@(find <(android_webrtc_demo_root)/res -type f)',
|
||||
@ -79,8 +73,6 @@
|
||||
'mkdir -p <(INTERMEDIATE_DIR) && ' # Must happen _before_ the cd below
|
||||
'mkdir -p <(android_webrtc_demo_root)/libs/<(android_app_abi) && '
|
||||
'cp <(PRODUCT_DIR)/lib.java/audio_device_module_java.jar <(android_webrtc_demo_root)/libs/ &&'
|
||||
'cp <(PRODUCT_DIR)/lib.java/video_capture_module_java.jar <(android_webrtc_demo_root)/libs/ &&'
|
||||
'cp <(PRODUCT_DIR)/lib.java/video_render_module_java.jar <(android_webrtc_demo_root)/libs/ &&'
|
||||
'<(android_strip) -o <(android_webrtc_demo_root)/libs/<(android_app_abi)/libwebrtcdemo-jni.so <(PRODUCT_DIR)/libwebrtcdemo-jni.so && '
|
||||
'cd <(android_webrtc_demo_root) && '
|
||||
'{ ANDROID_SDK_ROOT=<(android_sdk_root) '
|
||||
|
Loading…
x
Reference in New Issue
Block a user