—————————————————————————————————————————————- 一分钟快速搭建 rtmpd 服务器: https://blog.csdn.net/freeabc/article/details/102880984 软件下载地址: https://www.qiyicc.com/download/rtmpd.rar github 地址:https://github.com/superconvert/smart_rtmpd —————————————————————————————————————————————– //——————————————————————————————– 2. 3. ./sdk/android/src/jni/pc/peer_connection_factory.cc //———————————————————————————- 上面的流程中,就有关相关的变量我们具体讲解一下 3.1 network_thread 就是我们的 socket 类厂,并自带线程驱动机制,具体运作机制参考博文里的分析 https://blog.csdn.net/freeabc/article/details/106000923 3.2 CreateDefaultTaskQueueFactory 就是创建一个任务队列工厂, 这个根据操作系统类型,分为好几种 我们就以 std 的为例吧,其中我们的 pacer 发送队列用到的就是这个 ./api/task_queue/default_task_queue_factory_stdlib.cc ./rtc_base/task_queue_stdlib.cc ./rtc_base/task_queue_stdlib.cc 3.3 CreateCallFactory 呼叫对象类厂分析 ./call/call_factory.cc 后续具体创建一个 call 对象,其实就是调用的 Call::Create(config); 3.4 创建视频编码器类厂 CreateVideoEncoderFactory ./sdk/android/src/jni/pc/video.cc ./sdk/android/src/jni/video_encoder_factory_wrapper.cc 创建视频编码器接口 3.5 创建解码器类厂 CreateVideoDecoderFactory ./sdk/android/src/jni/pc/video.cc ./sdk/android/src/jni/video_decoder_factory_wrapper.cc 创建解码器接口 3.6 媒体引擎类厂的创建 CreateMediaEngine ./media/engine/webrtc_media_engine.cc 我们看到 media_engine 是 CompositeMediaEngine 对象, 主要包含 audio_engine 和 video_engine audio_engine 包含音频的编码类厂,解码类厂,混音处理,声音处理 video_engine 包含视频的编码类厂,解码类厂 我们后续的代码中经常出现的 media_engine() 其实就是 CompositeMediaEngine 对象 media_engine()->voice() 和 media_engine()->video() 分别代表上面的 WebRtcVoiceEngine 和 WebRtcVideoEngine 4. 产生 PeerConnectionFactory 对象 CreateModularPeerConnectionFactory 其实这个里面做了两件事, PeerConnectionFactory 构造与初始化 初始化接口里很重要,这里面产生 default_network_manager_( 网络管理 ), default_socket_factory_(socket 类厂 ), channel_manager_(通道管理) default_network_manager_ : 主要是网络类型,网络地址等信息的管理 default_socket_factory_ : 我们用到的 socket 的通讯都是通过它进行创建的 channel_manager_ : 呼叫通道管理,包含媒体引擎 media_engine 和 data_engine ./pc/channel_manager.cc 通道管理最重要的作用是为一路呼叫创建 VoiceChannel (同时创建 VoiceMediaChannel) 和 VideoChannel (同时创建 VideoMediaChannel)。 下面以 VideoChannel 为例,讲一下,这个里面包含什么对象: VideoChannel 包含发送参数,接收参数,VideoMediaChannel ( WebRtcVideoChannel ), 带宽估算信息, 本地流参数,远端流参数,以及 rtp_transport_ ( P2PTransportChannel 传输相关的处理 ) VideoMediaChannel 其实就是 WebRtcVideoChannel 对象,这个里面包含了,发送流对象,接收流对象,编码类厂, 解码类厂, 码率分配类厂, 发送 rtp 扩展,接收 rtp 扩展, 发送状态统计,接收状态统计,带宽估算统计,发送和接收的 编码信息统计等诸多信息, 是个需要关注的重点类!!!!!! ./media/engine/webrtc_video_engine.h 一个 WebRtcVideoChannel 包含多个发送对象 ( WebRtcVideoSendStream ) 和接收对象 ( WebRtcVideoReceiveStream ) 这两个对象也非常关键,需要重点分析这些类,才能更好的理解 webrtc 的运作机制, 其实就是封装了整个视频的 发送 pipeline ( capture —> encoder —-> pacer —-> socket ) 接收 pipeline ( socket —> jitterbuffer —> decoder —> render )PeerConnectionFactory 的初始化流程分析
// PeerConnectionFactory 的初始化流程分析
//——————————————————————————————–
1.
void CallActivity::onCreate(Bundle savedInstanceState) { peerConnectionClient = new PeerConnectionClient( getApplicationContext(), eglBase, roomUri.toString(), peerConnectionParameters, CallActivity.this); peerConnectionClient.createPeerConnectionFactory(options); }
PeerConnectionClient::PeerConnectionClient(Context appContext, EglBase eglBase, String roomServerUrl, PeerConnectionParameters peerConnectionParameters, PeerConnectionEvents events) PeerConnectionFactory.initialize( PeerConnectionFactory.InitializationOptions.builder(appContext) .setFieldTrials(fieldTrials) .setEnableInternalTracer(true) .createInitializationOptions()); void PeerConnectionFactory::initialize(InitializationOptions options) { // 这个是加载 JNI 库,具体代码就不帖了 NativeLibrary.initialize(options.nativeLibraryLoader, options.nativeLibraryName); nativeInitializeAndroidGlobals(); nativeInitializeFieldTrials(options.fieldTrials); if (options.enableInternalTracer && !internalTracerInitialized) { initializeInternalTracer(); } if (options.loggable != null) { Logging.injectLoggable(options.loggable, options.loggableSeverity); nativeInjectLoggable(new JNILogging(options.loggable), options.loggableSeverity.ordinal()); } }
void PeerConnectionClient::createPeerConnectionFactory(PeerConnectionFactory.Options options) { if (factory != null) { throw new IllegalStateException("PeerConnectionFactory has already been constructed"); } executor.execute(() -> createPeerConnectionFactoryInternal(options)); } void PeerConnectionClient::createPeerConnectionFactoryInternal(PeerConnectionFactory.Options options) { final VideoEncoderFactory encoderFactory; final VideoDecoderFactory decoderFactory; if (peerConnectionParameters.videoCodecHwAcceleration) { encoderFactory = new DefaultVideoEncoderFactory( rootEglBase.getEglBaseContext(), true /* enableIntelVp8Encoder */, enableH264HighProfile); decoderFactory = new DefaultVideoDecoderFactory(rootEglBase.getEglBaseContext()); } else { encoderFactory = new SoftwareVideoEncoderFactory(); decoderFactory = new SoftwareVideoDecoderFactory(); } factory = PeerConnectionFactory.builder() .setOptions(options) .setAudioDeviceModule(adm) .setVideoEncoderFactory(encoderFactory) .setVideoDecoderFactory(decoderFactory) .createPeerConnectionFactory(); } PeerConnectionFactory PeerConnectionFactory::createPeerConnectionFactory() { return nativeCreatePeerConnectionFactory(ContextUtils.getApplicationContext(), options, audioDeviceModule.getNativeAudioDeviceModulePointer(), audioEncoderFactoryFactory.createNativeAudioEncoderFactory(), audioDecoderFactoryFactory.createNativeAudioDecoderFactory(), videoEncoderFactory, videoDecoderFactory, audioProcessingFactory == null ? 0 : audioProcessingFactory.createNative(), fecControllerFactoryFactory == null ? 0 : fecControllerFactoryFactory.createNative(), networkControllerFactoryFactory == null ? 0 : networkControllerFactoryFactory.createNativeNetworkControllerFactory(), networkStatePredictorFactoryFactory == null ? 0 : networkStatePredictorFactoryFactory.createNativeNetworkStatePredictorFactory(), mediaTransportFactoryFactory == null ? 0 : mediaTransportFactoryFactory.createNativeMediaTransportFactory(), neteqFactoryFactory == null ? 0 : neteqFactoryFactory.createNativeNetEqFactory()); }
JNI_GENERATOR_EXPORT jobject Java_org_webrtc_PeerConnectionFactory_nativeCreatePeerConnectionFactory( JNIEnv* env, jclass jcaller, jobject context, jobject options, jlong nativeAudioDeviceModule, jlong audioEncoderFactory, jlong audioDecoderFactory, jobject encoderFactory, jobject decoderFactory, jlong nativeAudioProcessor, jlong nativeFecControllerFactory, jlong nativeNetworkControllerFactory, jlong nativeNetworkStatePredictorFactory, jlong mediaTransportFactory, jlong neteqFactory) { return JNI_PeerConnectionFactory_CreatePeerConnectionFactory(env, base::android::JavaParamRef<jobject>(env, context), base::android::JavaParamRef<jobject>(env, options), nativeAudioDeviceModule, audioEncoderFactory, audioDecoderFactory, base::android::JavaParamRef<jobject>(env, encoderFactory), base::android::JavaParamRef<jobject>(env, decoderFactory), nativeAudioProcessor, nativeFecControllerFactory, nativeNetworkControllerFactory, nativeNetworkStatePredictorFactory, mediaTransportFactory, neteqFactory).Release(); }
static ScopedJavaLocalRef<jobject> JNI_PeerConnectionFactory_CreatePeerConnectionFactory( JNIEnv* jni, const JavaParamRef<jobject>& jcontext, const JavaParamRef<jobject>& joptions, jlong native_audio_device_module, jlong native_audio_encoder_factory, jlong native_audio_decoder_factory, const JavaParamRef<jobject>& jencoder_factory, const JavaParamRef<jobject>& jdecoder_factory, jlong native_audio_processor, jlong native_fec_controller_factory, jlong native_network_controller_factory, jlong native_network_state_predictor_factory, jlong native_media_transport_factory, jlong native_neteq_factory) { rtc::scoped_refptr<AudioProcessing> audio_processor = reinterpret_cast<AudioProcessing*>(native_audio_processor); return CreatePeerConnectionFactoryForJava( jni, jcontext, joptions, reinterpret_cast<AudioDeviceModule*>(native_audio_device_module), TakeOwnershipOfRefPtr<AudioEncoderFactory>(native_audio_encoder_factory), TakeOwnershipOfRefPtr<AudioDecoderFactory>(native_audio_decoder_factory), jencoder_factory, jdecoder_factory, audio_processor ? audio_processor : CreateAudioProcessing(), TakeOwnershipOfUniquePtr<FecControllerFactoryInterface>( native_fec_controller_factory), TakeOwnershipOfUniquePtr<NetworkControllerFactoryInterface>( native_network_controller_factory), TakeOwnershipOfUniquePtr<NetworkStatePredictorFactoryInterface>( native_network_state_predictor_factory), TakeOwnershipOfUniquePtr<MediaTransportFactory>( native_media_transport_factory), TakeOwnershipOfUniquePtr<NetEqFactory>(native_neteq_factory)); }
// 这个流程里,初始化很多有用的东西,有 socket server, 音视频编解码,fec 工厂,
// 任务队列等
//———————————————————————————-
./sdk/android/src/jni/pc/peer_connection_factory.cc
ScopedJavaLocalRef<jobject> CreatePeerConnectionFactoryForJava( JNIEnv* jni, const JavaParamRef<jobject>& jcontext, const JavaParamRef<jobject>& joptions, rtc::scoped_refptr<AudioDeviceModule> audio_device_module, rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory, rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory, const JavaParamRef<jobject>& jencoder_factory, const JavaParamRef<jobject>& jdecoder_factory, rtc::scoped_refptr<AudioProcessing> audio_processor, std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory, std::unique_ptr<NetworkControllerFactoryInterface> network_controller_factory, std::unique_ptr<NetworkStatePredictorFactoryInterface> network_state_predictor_factory, std::unique_ptr<MediaTransportFactory> media_transport_factory, std::unique_ptr<NetEqFactory> neteq_factory) { // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but // ThreadManager only WrapCurrentThread()s the thread where it is first // created. Since the semantics around when auto-wrapping happens in // webrtc/rtc_base/ are convoluted, we simply wrap here to avoid having to // think about ramifications of auto-wrapping there. rtc::ThreadManager::Instance()->WrapCurrentThread(); //------------------------------------------ // 这个就是我们的 socket server 对象 //------------------------------------------ std::unique_ptr<rtc::Thread> network_thread = rtc::Thread::CreateWithSocketServer(); network_thread->SetName("network_thread", nullptr); RTC_CHECK(network_thread->Start()) << "Failed to start thread"; std::unique_ptr<rtc::Thread> worker_thread = rtc::Thread::Create(); worker_thread->SetName("worker_thread", nullptr); RTC_CHECK(worker_thread->Start()) << "Failed to start thread"; std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create(); signaling_thread->SetName("signaling_thread", NULL); RTC_CHECK(signaling_thread->Start()) << "Failed to start thread"; rtc::NetworkMonitorFactory* network_monitor_factory = nullptr; //------------------------------------------ // 这个待分析。。。 //------------------------------------------ const absl::optional<PeerConnectionFactoryInterface::Options> options = JavaToNativePeerConnectionFactoryOptions(jni, joptions); // Do not create network_monitor_factory only if the options are // provided and disable_network_monitor therein is set to true. if (!(options && options->disable_network_monitor)) { network_monitor_factory = new AndroidNetworkMonitorFactory(); rtc::NetworkMonitorFactory::SetFactory(network_monitor_factory); } PeerConnectionFactoryDependencies dependencies; dependencies.network_thread = network_thread.get(); dependencies.worker_thread = worker_thread.get(); dependencies.signaling_thread = signaling_thread.get(); //------------------------------------------ // 任务队列工厂 //------------------------------------------ dependencies.task_queue_factory = CreateDefaultTaskQueueFactory(); //------------------------------------------ // call 对象工厂 //------------------------------------------ dependencies.call_factory = CreateCallFactory(); dependencies.event_log_factory = std::make_unique<RtcEventLogFactory>( dependencies.task_queue_factory.get()); //------------------------------------------ // fec 对象工厂 //------------------------------------------ dependencies.fec_controller_factory = std::move(fec_controller_factory); dependencies.network_controller_factory = std::move(network_controller_factory); dependencies.network_state_predictor_factory = std::move(network_state_predictor_factory); dependencies.media_transport_factory = std::move(media_transport_factory); dependencies.neteq_factory = std::move(neteq_factory); cricket::MediaEngineDependencies media_dependencies; media_dependencies.task_queue_factory = dependencies.task_queue_factory.get(); media_dependencies.adm = std::move(audio_device_module); //------------------------------------------ // Java 层已经创建过了音频编码工厂 //------------------------------------------ media_dependencies.audio_encoder_factory = std::move(audio_encoder_factory); //------------------------------------------ // Java 层已经创建过了音频解码工厂 //------------------------------------------ media_dependencies.audio_decoder_factory = std::move(audio_decoder_factory); media_dependencies.audio_processing = std::move(audio_processor); //------------------------------------------ // 产生视频编码器工厂 //------------------------------------------ media_dependencies.video_encoder_factory = absl::WrapUnique(CreateVideoEncoderFactory(jni, jencoder_factory)); //------------------------------------------ // 产生视频解码器工厂 //------------------------------------------ media_dependencies.video_decoder_factory = absl::WrapUnique(CreateVideoDecoderFactory(jni, jdecoder_factory)); dependencies.media_engine = cricket::CreateMediaEngine(std::move(media_dependencies)); //------------------------------------------ // 创建 PeerConnectionFactory //------------------------------------------ rtc::scoped_refptr<PeerConnectionFactoryInterface> factory = CreateModularPeerConnectionFactory(std::move(dependencies)); RTC_CHECK(factory) << "Failed to create the peer connection factory; " << "WebRTC/libjingle init likely failed on this device"; // TODO(honghaiz): Maybe put the options as the argument of // CreatePeerConnectionFactory. if (options) factory->SetOptions(*options); return NativeToScopedJavaPeerConnectionFactory( jni, factory, std::move(network_thread), std::move(worker_thread), std::move(signaling_thread), network_monitor_factory); }
std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() { return CreateTaskQueueStdlibFactory(); }
std::unique_ptr<TaskQueueFactory> CreateTaskQueueStdlibFactory() { return std::make_unique<TaskQueueStdlibFactory>(); }
class TaskQueueStdlibFactory final : public TaskQueueFactory { public: std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue( absl::string_view name, Priority priority) const override { return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>( new TaskQueueStdlib(name, TaskQueuePriorityToThreadPriority(priority))); } };
std::unique_ptr<CallFactoryInterface> CreateCallFactory() { return std::unique_ptr<CallFactoryInterface>(new CallFactory()); }
Call* CallFactory::CreateCall(const Call::Config& config) { absl::optional<webrtc::BuiltInNetworkBehaviorConfig> send_degradation_config = ParseDegradationConfig(true); absl::optional<webrtc::BuiltInNetworkBehaviorConfig> receive_degradation_config = ParseDegradationConfig(false); if (send_degradation_config || receive_degradation_config) { return new DegradedCall(std::unique_ptr<Call>(Call::Create(config)), send_degradation_config, receive_degradation_config, config.task_queue_factory); } return Call::Create(config); }
VideoEncoderFactory* CreateVideoEncoderFactory( JNIEnv* jni, const JavaRef<jobject>& j_encoder_factory) { return IsNull(jni, j_encoder_factory) ? nullptr : new VideoEncoderFactoryWrapper(jni, j_encoder_factory); }
VideoEncoderFactoryWrapper::VideoEncoderFactoryWrapper( JNIEnv* jni, const JavaRef<jobject>& encoder_factory) : encoder_factory_(jni, encoder_factory) { const ScopedJavaLocalRef<jobjectArray> j_supported_codecs = Java_VideoEncoderFactory_getSupportedCodecs(jni, encoder_factory); supported_formats_ = JavaToNativeVector<SdpVideoFormat>( jni, j_supported_codecs, &VideoCodecInfoToSdpVideoFormat); const ScopedJavaLocalRef<jobjectArray> j_implementations = Java_VideoEncoderFactory_getImplementations(jni, encoder_factory); implementations_ = JavaToNativeVector<SdpVideoFormat>( jni, j_implementations, &VideoCodecInfoToSdpVideoFormat); }
std::unique_ptr<VideoEncoder> VideoEncoderFactoryWrapper::CreateVideoEncoder( const SdpVideoFormat& format) { JNIEnv* jni = AttachCurrentThreadIfNeeded(); ScopedJavaLocalRef<jobject> j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format); ScopedJavaLocalRef<jobject> encoder = Java_VideoEncoderFactory_createEncoder( jni, encoder_factory_, j_codec_info); if (!encoder.obj()) return nullptr; return JavaToNativeVideoEncoder(jni, encoder); }
VideoDecoderFactory* CreateVideoDecoderFactory( JNIEnv* jni, const JavaRef<jobject>& j_decoder_factory) { return IsNull(jni, j_decoder_factory) ? nullptr : new VideoDecoderFactoryWrapper(jni, j_decoder_factory); }
VideoDecoderFactoryWrapper::VideoDecoderFactoryWrapper( JNIEnv* jni, const JavaRef<jobject>& decoder_factory) : decoder_factory_(jni, decoder_factory) {}
std::unique_ptr<VideoDecoder> VideoDecoderFactoryWrapper::CreateVideoDecoder( const SdpVideoFormat& format) { JNIEnv* jni = AttachCurrentThreadIfNeeded(); ScopedJavaLocalRef<jobject> j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format); ScopedJavaLocalRef<jobject> decoder = Java_VideoDecoderFactory_createDecoder( jni, decoder_factory_, j_codec_info); if (!decoder.obj()) return nullptr; return JavaToNativeVideoDecoder(jni, decoder); }
std::unique_ptr<MediaEngineInterface> CreateMediaEngine( MediaEngineDependencies dependencies) { auto audio_engine = std::make_unique<WebRtcVoiceEngine>( dependencies.task_queue_factory, std::move(dependencies.adm), std::move(dependencies.audio_encoder_factory), std::move(dependencies.audio_decoder_factory), std::move(dependencies.audio_mixer), std::move(dependencies.audio_processing)); #ifdef HAVE_WEBRTC_VIDEO auto video_engine = std::make_unique<WebRtcVideoEngine>( std::move(dependencies.video_encoder_factory), std::move(dependencies.video_decoder_factory)); #else auto video_engine = std::make_unique<NullWebRtcVideoEngine>(); #endif return std::make_unique<CompositeMediaEngine>(std::move(audio_engine), std::move(video_engine)); }
rtc::scoped_refptr<PeerConnectionFactoryInterface> CreateModularPeerConnectionFactory( PeerConnectionFactoryDependencies dependencies) { rtc::scoped_refptr<PeerConnectionFactory> pc_factory( new rtc::RefCountedObject<PeerConnectionFactory>( std::move(dependencies))); // Call Initialize synchronously but make sure it is executed on // |signaling_thread|. MethodCall<PeerConnectionFactory, bool> call( pc_factory.get(), &PeerConnectionFactory::Initialize); bool result = call.Marshal(RTC_FROM_HERE, pc_factory->signaling_thread()); if (!result) { return nullptr; } return PeerConnectionFactoryProxy::Create(pc_factory->signaling_thread(), pc_factory); }
PeerConnectionFactory::PeerConnectionFactory( PeerConnectionFactoryDependencies dependencies) : wraps_current_thread_(false), network_thread_(dependencies.network_thread), worker_thread_(dependencies.worker_thread), signaling_thread_(dependencies.signaling_thread), task_queue_factory_(std::move(dependencies.task_queue_factory)), media_engine_(std::move(dependencies.media_engine)), call_factory_(std::move(dependencies.call_factory)), event_log_factory_(std::move(dependencies.event_log_factory)), fec_controller_factory_(std::move(dependencies.fec_controller_factory)), network_state_predictor_factory_( std::move(dependencies.network_state_predictor_factory)), injected_network_controller_factory_( std::move(dependencies.network_controller_factory)), media_transport_factory_(std::move(dependencies.media_transport_factory)), neteq_factory_(std::move(dependencies.neteq_factory)), trials_(dependencies.trials ? std::move(dependencies.trials) : std::make_unique<FieldTrialBasedConfig>()) { if (!network_thread_) { owned_network_thread_ = rtc::Thread::CreateWithSocketServer(); owned_network_thread_->SetName("pc_network_thread", nullptr); owned_network_thread_->Start(); network_thread_ = owned_network_thread_.get(); } if (!worker_thread_) { owned_worker_thread_ = rtc::Thread::Create(); owned_worker_thread_->SetName("pc_worker_thread", nullptr); owned_worker_thread_->Start(); worker_thread_ = owned_worker_thread_.get(); } if (!signaling_thread_) { signaling_thread_ = rtc::Thread::Current(); if (!signaling_thread_) { // If this thread isn't already wrapped by an rtc::Thread, create a // wrapper and own it in this class. signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread(); wraps_current_thread_ = true; } } }
bool PeerConnectionFactory::Initialize() { RTC_DCHECK(signaling_thread_->IsCurrent()); rtc::InitRandom(rtc::Time32()); default_network_manager_.reset(new rtc::BasicNetworkManager()); if (!default_network_manager_) { return false; } default_socket_factory_.reset( new rtc::BasicPacketSocketFactory(network_thread_)); if (!default_socket_factory_) { return false; } channel_manager_ = std::make_unique<cricket::ChannelManager>( std::move(media_engine_), std::make_unique<cricket::RtpDataEngine>(), worker_thread_, network_thread_); channel_manager_->SetVideoRtxEnabled(true); if (!channel_manager_->Init()) { return false; } return true; }
ChannelManager::ChannelManager( std::unique_ptr<MediaEngineInterface> media_engine, std::unique_ptr<DataEngineInterface> data_engine, rtc::Thread* worker_thread, rtc::Thread* network_thread) : media_engine_(std::move(media_engine)), data_engine_(std::move(data_engine)), main_thread_(rtc::Thread::Current()), worker_thread_(worker_thread), network_thread_(network_thread) { RTC_DCHECK(data_engine_); RTC_DCHECK(worker_thread_); RTC_DCHECK(network_thread_); }
WebRtcVideoChannel::WebRtcVideoChannel( webrtc::Call* call, const MediaConfig& config, const VideoOptions& options, const webrtc::CryptoOptions& crypto_options, webrtc::VideoEncoderFactory* encoder_factory, webrtc::VideoDecoderFactory* decoder_factory, webrtc::VideoBitrateAllocatorFactory* bitrate_allocator_factory) : VideoMediaChannel(config), worker_thread_(rtc::Thread::Current()), call_(call), unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_), video_config_(config.video), encoder_factory_(encoder_factory), decoder_factory_(decoder_factory), bitrate_allocator_factory_(bitrate_allocator_factory), default_send_options_(options), last_stats_log_ms_(-1), discard_unknown_ssrc_packets_(webrtc::field_trial::IsEnabled( "WebRTC-Video-DiscardPacketsWithUnknownSsrc")), crypto_options_(crypto_options), unknown_ssrc_packet_buffer_( webrtc::field_trial::IsEnabled( "WebRTC-Video-BufferPacketsWithUnknownSsrc") ? new UnhandledPacketsBuffer() : nullptr) { RTC_DCHECK(thread_checker_.IsCurrent()); rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc; sending_ = false; recv_codecs_ = MapCodecs(AssignPayloadTypesAndDefaultCodecs(encoder_factory_)); recv_flexfec_payload_type_ = recv_codecs_.front().flexfec_payload_type; }
WebRtcVideoChannel::WebRtcVideoSendStream::WebRtcVideoSendStream( webrtc::Call* call, const StreamParams& sp, webrtc::VideoSendStream::Config config, const VideoOptions& options, bool enable_cpu_overuse_detection, int max_bitrate_bps, const absl::optional<VideoCodecSettings>& codec_settings, const absl::optional<std::vector<webrtc::RtpExtension>>& rtp_extensions, // TODO(deadbeef): Don't duplicate information between send_params, // rtp_extensions, options, etc. const VideoSendParameters& send_params) : worker_thread_(rtc::Thread::Current()), ssrcs_(sp.ssrcs), ssrc_groups_(sp.ssrc_groups), call_(call), enable_cpu_overuse_detection_(enable_cpu_overuse_detection), source_(nullptr), stream_(nullptr), encoder_sink_(nullptr), parameters_(std::move(config), options, max_bitrate_bps, codec_settings), rtp_parameters_(CreateRtpParametersWithEncodings(sp)), sending_(false) { // Maximum packet size may come in RtpConfig from external transport, for // example from QuicTransportInterface implementation, so do not exceed // given max_packet_size. parameters_.config.rtp.max_packet_size = std::min<size_t>(parameters_.config.rtp.max_packet_size, kVideoMtu); parameters_.conference_mode = send_params.conference_mode; sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); // ValidateStreamParams should prevent this from happening. RTC_CHECK(!parameters_.config.rtp.ssrcs.empty()); rtp_parameters_.encodings[0].ssrc = parameters_.config.rtp.ssrcs[0]; // RTX. sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, ¶meters_.config.rtp.rtx.ssrcs); // FlexFEC SSRCs. // TODO(brandtr): This code needs to be generalized when we add support for // multistream protection. if (IsFlexfecFieldTrialEnabled()) { uint32_t flexfec_ssrc; bool flexfec_enabled = false; for (uint32_t primary_ssrc : parameters_.config.rtp.ssrcs) { if (sp.GetFecFrSsrc(primary_ssrc, &flexfec_ssrc)) { if (flexfec_enabled) { RTC_LOG(LS_INFO) << "Multiple FlexFEC streams in local SDP, but " "our implementation only supports a single FlexFEC " "stream. Will not enable FlexFEC for proposed " "stream with SSRC: " << flexfec_ssrc << "."; continue; } flexfec_enabled = true; parameters_.config.rtp.flexfec.ssrc = flexfec_ssrc; parameters_.config.rtp.flexfec.protected_media_ssrcs = {primary_ssrc}; } } } parameters_.config.rtp.c_name = sp.cname; if (rtp_extensions) { parameters_.config.rtp.extensions = *rtp_extensions; rtp_parameters_.header_extensions = *rtp_extensions; } parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size ? webrtc::RtcpMode::kReducedSize : webrtc::RtcpMode::kCompound; parameters_.config.rtp.mid = send_params.mid; rtp_parameters_.rtcp.reduced_size = send_params.rtcp.reduced_size; if (codec_settings) { SetCodec(*codec_settings); } }
WebRtcVideoChannel::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( WebRtcVideoChannel* channel, webrtc::Call* call, const StreamParams& sp, webrtc::VideoReceiveStream::Config config, webrtc::VideoDecoderFactory* decoder_factory, bool default_stream, const std::vector<VideoCodecSettings>& recv_codecs, const webrtc::FlexfecReceiveStream::Config& flexfec_config) : channel_(channel), call_(call), stream_params_(sp), stream_(NULL), default_stream_(default_stream), config_(std::move(config)), flexfec_config_(flexfec_config), flexfec_stream_(nullptr), decoder_factory_(decoder_factory), sink_(NULL), first_frame_timestamp_(-1), estimated_remote_start_ntp_time_ms_(0) { config_.renderer = this; ConfigureCodecs(recv_codecs); ConfigureFlexfecCodec(flexfec_config.payload_type); MaybeRecreateWebRtcFlexfecStream(); RecreateWebRtcVideoStream(); }
有关 WebRTC 的更多知识可以参考我的其它的博客
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算