日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

WebRTC Linux ADM 实现中的符号延迟加载机制

發(fā)布時間:2024/4/11 linux 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WebRTC Linux ADM 实现中的符号延迟加载机制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

ADM(AudioDeviceModule)在 WebRTC 中主要用于音頻數(shù)據(jù)的錄制采集和音頻數(shù)據(jù)的播放,這里是 WebRTC 的實時音視頻系統(tǒng)與系統(tǒng)的音頻硬件銜接的地方。WebRTC 為 Linux 平臺實現(xiàn)了 ALSA 和 Pulse 等類型的 ADM AudioDeviceLinuxALSA 和 AudioDeviceLinuxPulse,它們分別基于 Linux 系統(tǒng)提供的庫 libasound 和 libpulse 實現(xiàn)。

WebRTC 為做到 Linux ADM 實現(xiàn)的高度靈活性,實現(xiàn)了一套符號的延遲加載機制,即在 WebRTC 編譯的時候,無需鏈接 libasound 和 libpulse 庫,在創(chuàng)建需要的 ADM 對象時,才通過動態(tài)鏈接加載機制加載需要的庫及其中的符號。

這套機制在底層基于 Linux 平臺的 libdl 提供的 dlopen()、dlclose()、dlsym() 和 dlerror() 等接口實現(xiàn)動態(tài)鏈接庫的動態(tài)加載,及符號的查找。更上一層,WebRTC 為每種 ADM 實現(xiàn)基于 libdl 提供的接口,封裝一個用于符號延遲加載及訪問的 wrapper 類。在 ADM 的具體實現(xiàn)中,借助于一個宏,以類似于普通的符號訪問的方式,訪問延遲加載的符號。

在 webrtc/modules/audio_device/linux/latebindingsymboltable_linux.h 中的 libdl 接口的 wrapper 類 LateBindingSymbolTable 聲明如下:

#ifdef WEBRTC_LINUX typedef void* DllHandle;const DllHandle kInvalidDllHandle = NULL; #else #error Not implemented #endif// These are helpers for use only by the class below. DllHandle InternalLoadDll(const char dll_name[]);void InternalUnloadDll(DllHandle handle);bool InternalLoadSymbols(DllHandle handle,int num_symbols,const char* const symbol_names[],void* symbols[]);template <int SYMBOL_TABLE_SIZE,const char kDllName[],const char* const kSymbolNames[]> class LateBindingSymbolTable {public:LateBindingSymbolTable(): handle_(kInvalidDllHandle), undefined_symbols_(false) {memset(symbols_, 0, sizeof(symbols_));}~LateBindingSymbolTable() { Unload(); }static int NumSymbols() { return SYMBOL_TABLE_SIZE; }// We do not use this, but we offer it for theoretical convenience.static const char* GetSymbolName(int index) {assert(index < NumSymbols());return kSymbolNames[index];}bool IsLoaded() const { return handle_ != kInvalidDllHandle; }// Loads the DLL and the symbol table. Returns true iff the DLL and symbol// table loaded successfully.bool Load() {if (IsLoaded()) {return true;}if (undefined_symbols_) {// We do not attempt to load again because repeated attempts are not// likely to succeed and DLL loading is costly.return false;}handle_ = InternalLoadDll(kDllName);if (!IsLoaded()) {return false;}if (!InternalLoadSymbols(handle_, NumSymbols(), kSymbolNames, symbols_)) {undefined_symbols_ = true;Unload();return false;}return true;}void Unload() {if (!IsLoaded()) {return;}InternalUnloadDll(handle_);handle_ = kInvalidDllHandle;memset(symbols_, 0, sizeof(symbols_));}// Retrieves the given symbol. NOTE: Recommended to use LATESYM_GET below// instead of this.void* GetSymbol(int index) const {assert(IsLoaded());assert(index < NumSymbols());return symbols_[index];}private:DllHandle handle_;bool undefined_symbols_;void* symbols_[SYMBOL_TABLE_SIZE];RTC_DISALLOW_COPY_AND_ASSIGN(LateBindingSymbolTable); };

LateBindingSymbolTable 是一個模板類,其類定義中調用的幾個用于動態(tài)鏈接庫加載和符號查找的函數(shù)在 webrtc/modules/audio_device/linux/latebindingsymboltable_linux.cc 文件中的定義如下:

inline static const char* GetDllError() { #ifdef WEBRTC_LINUXchar* err = dlerror();if (err) {return err;} else {return "No error";} #else #error Not implemented #endif }DllHandle InternalLoadDll(const char dll_name[]) { #ifdef WEBRTC_LINUXDllHandle handle = dlopen(dll_name, RTLD_NOW); #else #error Not implemented #endifif (handle == kInvalidDllHandle) {RTC_LOG(LS_WARNING) << "Can't load " << dll_name << " : " << GetDllError();}return handle; }void InternalUnloadDll(DllHandle handle) { #ifdef WEBRTC_LINUX // TODO(pbos): Remove this dlclose() exclusion when leaks and suppressions from // here are gone (or AddressSanitizer can display them properly). // // Skip dlclose() on AddressSanitizer as leaks including this module in the // stack trace gets displayed as <unknown module> instead of the actual library // -> it can not be suppressed. // https://code.google.com/p/address-sanitizer/issues/detail?id=89 #if !defined(ADDRESS_SANITIZER)if (dlclose(handle) != 0) {RTC_LOG(LS_ERROR) << GetDllError();} #endif // !defined(ADDRESS_SANITIZER) #else #error Not implemented #endif }static bool LoadSymbol(DllHandle handle,const char* symbol_name,void** symbol) { #ifdef WEBRTC_LINUX*symbol = dlsym(handle, symbol_name);char* err = dlerror();if (err) {RTC_LOG(LS_ERROR) << "Error loading symbol " << symbol_name << " : " << err;return false;} else if (!*symbol) {RTC_LOG(LS_ERROR) << "Symbol " << symbol_name << " is NULL";return false;}return true; #else #error Not implemented #endif }// This routine MUST assign SOME value for every symbol, even if that value is // NULL, or else some symbols may be left with uninitialized data that the // caller may later interpret as a valid address. bool InternalLoadSymbols(DllHandle handle,int num_symbols,const char* const symbol_names[],void* symbols[]) { #ifdef WEBRTC_LINUX// Clear any old errors.dlerror(); #endiffor (int i = 0; i < num_symbols; ++i) {if (!LoadSymbol(handle, symbol_names[i], &symbols[i])) {return false;}}return true; }

符號表大小,動態(tài)鏈接庫的名稱,及符號表的定義是模板類 LateBindingSymbolTable 的模板參數(shù),這幾個模板參數(shù)都是數(shù)值參數(shù),而不是類型參數(shù)。LateBindingSymbolTable 也可以不實現(xiàn)為模板類,比如,把符號表大小,動態(tài)鏈接庫的名稱,及符號表的定義作為構造函數(shù)的參數(shù)傳入 LateBindingSymbolTable 類。但將動態(tài)鏈接庫名稱、符號表大小及符號表定義做成類的模板參數(shù)更方便對這些數(shù)據(jù)進行訪問,同時也有利于為符號地址數(shù)組分配空間。

WebRTC 定義了幾個宏,用于方便符號表的定義(webrtc/modules/audio_device/linux/latebindingsymboltable_linux.h),具體的 LateBindingSymbolTable 類的特化,及符號的訪問:

// This macro must be invoked in a header to declare a symbol table class. #define LATE_BINDING_SYMBOL_TABLE_DECLARE_BEGIN(ClassName) enum { // This macro must be invoked in the header declaration once for each symbol // (recommended to use an X-Macro to avoid duplication). // This macro defines an enum with names built from the symbols, which // essentially creates a hash table in the compiler from symbol names to their // indices in the symbol table class. #define LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY(ClassName, sym) \ClassName##_SYMBOL_TABLE_INDEX_##sym,// This macro completes the header declaration. #define LATE_BINDING_SYMBOL_TABLE_DECLARE_END(ClassName) \ClassName##_SYMBOL_TABLE_SIZE \} \; \\extern const char ClassName##_kDllName[]; \extern const char* const \ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE]; \\typedef ::webrtc::adm_linux::LateBindingSymbolTable< \ClassName##_SYMBOL_TABLE_SIZE, ClassName##_kDllName, \ClassName##_kSymbolNames> \ClassName;// This macro must be invoked in a .cc file to define a previously-declared // symbol table class. #define LATE_BINDING_SYMBOL_TABLE_DEFINE_BEGIN(ClassName, dllName) \const char ClassName##_kDllName[] = dllName; \const char* const ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE] = { // This macro must be invoked in the .cc definition once for each symbol // (recommended to use an X-Macro to avoid duplication). // This would have to use the mangled name if we were to ever support C++ // symbols. #define LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY(ClassName, sym) #sym,#define LATE_BINDING_SYMBOL_TABLE_DEFINE_END(ClassName) \} \;

LATE_BINDING_SYMBOL_TABLE_DECLARE_BEGIN、LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY 和 LATE_BINDING_SYMBOL_TABLE_DECLARE_END 這幾個宏,需要在頭文件中調用,它們首先定義了一個 enum,用于得到每個符號在符號表中的索引。LATE_BINDING_SYMBOL_TABLE_DECLARE_END 宏除了給 enum 定義添加結束的 } 和 ; 之外,它還為 enum 增加了最后一個 item,用于得到符號表的大小。此外,LATE_BINDING_SYMBOL_TABLE_DECLARE_END 宏還聲明了動態(tài)鏈接庫名稱,符號表,及具體 LateBindingSymbolTable 類的特化。

如 Pulse ADM 的 webrtc/modules/audio_device/linux/pulseaudiosymboltable_linux.h 頭文件:

// The PulseAudio symbols we need, as an X-Macro list. // This list must contain precisely every libpulse function that is used in // the ADM LINUX PULSE Device and Mixer classes #define PULSE_AUDIO_SYMBOLS_LIST \X(pa_bytes_per_second) \X(pa_context_connect) \X(pa_context_disconnect) \X(pa_context_errno) \X(pa_context_get_protocol_version) \X(pa_context_get_server_info) \X(pa_context_get_sink_info_list) \X(pa_context_get_sink_info_by_index) \X(pa_context_get_sink_info_by_name) \X(pa_context_get_sink_input_info) \X(pa_context_get_source_info_by_index) \X(pa_context_get_source_info_by_name) \X(pa_context_get_source_info_list) \X(pa_context_get_state) \X(pa_context_new) \X(pa_context_set_sink_input_volume) \X(pa_context_set_sink_input_mute) \X(pa_context_set_source_volume_by_index) \X(pa_context_set_source_mute_by_index) \X(pa_context_set_state_callback) \X(pa_context_unref) \X(pa_cvolume_set) \X(pa_operation_get_state) \X(pa_operation_unref) \X(pa_stream_connect_playback) \X(pa_stream_connect_record) \X(pa_stream_disconnect) \X(pa_stream_drop) \X(pa_stream_get_device_index) \X(pa_stream_get_index) \X(pa_stream_get_latency) \X(pa_stream_get_sample_spec) \X(pa_stream_get_state) \X(pa_stream_new) \X(pa_stream_peek) \X(pa_stream_readable_size) \X(pa_stream_set_buffer_attr) \X(pa_stream_set_overflow_callback) \X(pa_stream_set_read_callback) \X(pa_stream_set_state_callback) \X(pa_stream_set_underflow_callback) \X(pa_stream_set_write_callback) \X(pa_stream_unref) \X(pa_stream_writable_size) \X(pa_stream_write) \X(pa_strerror) \X(pa_threaded_mainloop_free) \X(pa_threaded_mainloop_get_api) \X(pa_threaded_mainloop_lock) \X(pa_threaded_mainloop_new) \X(pa_threaded_mainloop_signal) \X(pa_threaded_mainloop_start) \X(pa_threaded_mainloop_stop) \X(pa_threaded_mainloop_unlock) \X(pa_threaded_mainloop_wait)LATE_BINDING_SYMBOL_TABLE_DECLARE_BEGIN(PulseAudioSymbolTable) #define X(sym) \LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY(PulseAudioSymbolTable, sym) PULSE_AUDIO_SYMBOLS_LIST #undef X LATE_BINDING_SYMBOL_TABLE_DECLARE_END(PulseAudioSymbolTable)

這個頭文件里,X 宏是對 LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY 的封裝。webrtc/modules/audio_device/linux/pulseaudiosymboltable_linux.h 頭文件中調用的各個宏都展開之后,得到如下內容:

enum {PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_bytes_per_second, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_connect, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_disconnect, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_errno, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_protocol_version, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_server_info, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_sink_info_list, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_sink_info_by_index, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_sink_info_by_name, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_sink_input_info, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_source_info_by_index, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_source_info_by_name, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_source_info_list, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_get_state, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_new, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_set_sink_input_volume, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_set_sink_input_mute, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_set_source_volume_by_index, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_set_source_mute_by_index, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_set_state_callback, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_context_unref, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_cvolume_set, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_operation_get_state, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_operation_unref, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_connect_playback, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_connect_record, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_disconnect, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_drop, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_get_device_index, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_get_index, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_get_latency, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_get_sample_spec, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_get_state, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_new, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_peek, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_readable_size, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_set_buffer_attr, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_set_overflow_callback, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_set_read_callback, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_set_state_callback, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_set_underflow_callback, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_set_write_callback, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_unref, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_writable_size, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_stream_write, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_strerror, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_threaded_mainloop_free, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_threaded_mainloop_get_api, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_threaded_mainloop_lock, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_threaded_mainloop_new, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_threaded_mainloop_signal, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_threaded_mainloop_start, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_threaded_mainloop_stop, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_threaded_mainloop_unlock, \PulseAudioSymbolTable_SYMBOL_TABLE_INDEX_pa_threaded_mainloop_wait,PulseAudioSymbolTable_SYMBOL_TABLE_SIZE \} \; \\extern const char PulseAudioSymbolTable_kDllName[]; \extern const char* const \PulseAudioSymbolTable_kSymbolNames[PulseAudioSymbolTable_SYMBOL_TABLE_SIZE]; \\typedef ::webrtc::adm_linux::LateBindingSymbolTable< \PulseAudioSymbolTable_SYMBOL_TABLE_SIZE, PulseAudioSymbolTable_kDllName, \PulseAudioSymbolTable_kSymbolNames> \PulseAudioSymbolTable;

LATE_BINDING_SYMBOL_TABLE_DEFINE_BEGIN 、LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY 和 LATE_BINDING_SYMBOL_TABLE_DEFINE_END 宏,需要在 C++ 源文件中調用,用于定義動態(tài)鏈接庫的名稱,及符號表。如在 webrtc/modules/audio_device/linux/pulseaudiosymboltable_linux.cc 文件中:

#include "modules/audio_device/linux/pulseaudiosymboltable_linux.h"namespace webrtc { namespace adm_linux_pulse {LATE_BINDING_SYMBOL_TABLE_DEFINE_BEGIN(PulseAudioSymbolTable, "libpulse.so.0") #define X(sym) \LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY(PulseAudioSymbolTable, sym) PULSE_AUDIO_SYMBOLS_LIST #undef X LATE_BINDING_SYMBOL_TABLE_DEFINE_END(PulseAudioSymbolTable)} // namespace adm_linux_pulse } // namespace webrtc

在這個源文件中,X 宏是對 LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY 宏的封裝。這些宏展開之后得到如下內容:

const char PulseAudioSymbolTable_kDllName[] = "libpulse.so.0"; \const char* const PulseAudioSymbolTable_kSymbolNames[PulseAudioSymbolTable_SYMBOL_TABLE_SIZE] = { "pa_bytes_per_second", \"pa_context_connect", \"pa_context_disconnect", \"pa_context_errno", \"pa_context_get_protocol_version", \"pa_context_get_server_info", \"pa_context_get_sink_info_list", \"pa_context_get_sink_info_by_index", \"pa_context_get_sink_info_by_name", \"pa_context_get_sink_input_info", \"pa_context_get_source_info_by_index", \"pa_context_get_source_info_by_name", \"pa_context_get_source_info_list", \"pa_context_get_state", \"pa_context_new", \"pa_context_set_sink_input_volume", \"pa_context_set_sink_input_mute", \"pa_context_set_source_volume_by_index", \"pa_context_set_source_mute_by_index", \"pa_context_set_state_callback", \"pa_context_unref", \"pa_cvolume_set", \"pa_operation_get_state", \"pa_operation_unref", \"pa_stream_connect_playback", \"pa_stream_connect_record", \"pa_stream_disconnect", \"pa_stream_drop", \"pa_stream_get_device_index", \"pa_stream_get_index", \"pa_stream_get_latency", \"pa_stream_get_sample_spec", \"pa_stream_get_state", \"pa_stream_new", \"pa_stream_peek", \"pa_stream_readable_size", \"pa_stream_set_buffer_attr", \"pa_stream_set_overflow_callback", \"pa_stream_set_read_callback", \"pa_stream_set_state_callback", \"pa_stream_set_underflow_callback", \"pa_stream_set_write_callback", \"pa_stream_unref", \"pa_stream_writable_size", \"pa_stream_write", \"pa_strerror", \"pa_threaded_mainloop_free", \"pa_threaded_mainloop_get_api", \"pa_threaded_mainloop_lock", \"pa_threaded_mainloop_new", \"pa_threaded_mainloop_signal", \"pa_threaded_mainloop_start", \"pa_threaded_mainloop_stop", \"pa_threaded_mainloop_unlock", \"pa_threaded_mainloop_wait", } \;

WebRTC 定義了幾個宏(webrtc/modules/audio_device/linux/latebindingsymboltable_linux.h),用于方便對符號的調用:

// Index of a given symbol in the given symbol table class. #define LATESYM_INDEXOF(ClassName, sym) (ClassName##_SYMBOL_TABLE_INDEX_##sym)// Returns a reference to the given late-binded symbol, with the correct type. #define LATESYM_GET(ClassName, inst, sym) \(*reinterpret_cast<__typeof__(&sym)>( \(inst)->GetSymbol(LATESYM_INDEXOF(ClassName, sym))))

需要訪問動態(tài)加載的庫的符號的組件,需要包含符號聲明的頭文件,如 AudioDeviceLinuxPulse 類需要調用 Pulse 庫的函數(shù),則在頭文件webrtc/modules/audio_device/linux/audio_device_pulse_linux.h 中包含了 pulse/pulseaudio.h 頭文件。上面看到的 LATESYM_GET 宏,通過符號的聲明及編譯器的 __typeof__ 擴展得到一個符號的類型,以方便對于函數(shù)的調用

LATESYM_GET 宏用于借助具體的 LateBindingSymbolTable 類的對象實例,訪問某個函數(shù),LATESYM_INDEXOF 宏用于獲得某個符號在符號表中的索引。對動態(tài)加載的庫的符號的調用,需要配合在源文件中定義的另一個宏來實現(xiàn),如 webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc 文件中:

webrtc::adm_linux_pulse::PulseAudioSymbolTable PaSymbolTable;// Accesses Pulse functions through our late-binding symbol table instead of // directly. This way we don't have to link to libpulse, which means our binary // will work on systems that don't have it. #define LATE(sym) \LATESYM_GET(webrtc::adm_linux_pulse::PulseAudioSymbolTable, &PaSymbolTable, \sym)

如 AudioDeviceLinuxPulse 類的 RecordingDevices() 函數(shù)調用 Pulse 庫的 pa_context_get_source_info_list() 函數(shù):

int16_t AudioDeviceLinuxPulse::RecordingDevices() {PaLock();pa_operation* paOperation = NULL;_numRecDevices = 1; // Init to 1 to account for "default"// Get the whole list of devices and update _numRecDevicespaOperation = LATE(pa_context_get_source_info_list)(_paContext, PaSourceInfoCallback, this);WaitForOperationCompletion(paOperation);PaUnLock();return _numRecDevices; }

總結一下,WebRTC Linux ADM 實現(xiàn)中的符號延遲加載機制由如下這些部分組成:

  • libdl 的模板 wrapper 類
  • 輔助定義具體的 libdl wrapper 類的宏,定義方便訪問符號的 enum 的宏,用于聲明符號表和動態(tài)鏈接庫名稱的宏
  • 用于定義動態(tài)鏈接庫名稱和符號表的宏。
  • 用于訪問特定符號的宏。

WebRTC 實現(xiàn)的這套東西存在一些問題:

  • 重復邏輯沒有完全消除。為了訪問延遲加載的符號,重復定義了用于訪問符號的宏。如在 webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc、webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc、webrtc/modules/audio_device/linux/audio_mixer_manager_alsa_linux.cc、webrtc/modules/audio_device/linux/audio_mixer_manager_pulse_linux.cc 這幾個文件中重復定義了 LATE 宏。

  • 創(chuàng)建具體的 AudioDeviceGeneric 類型對象時,沒有判斷系統(tǒng)是否真的能夠支持。即在 webrtc/modules/audio_device/audio_device_impl.cc 文件中,僅僅根據(jù)編譯時的宏開關和傳入的 audio_layer 參數(shù)來決定創(chuàng)建的具體 AudioDeviceGeneric 類型對象,而沒有判斷系統(tǒng)是否能夠支持。

  • 對于上面的第 2 個問題,可以創(chuàng)建一個 AudioManager 類,用于判斷系統(tǒng)是否支持,如 AudioManager 的聲明如下:

    #ifndef MODULES_AUDIO_DEVICE_LINUX_AUDIO_MANAGER_H_ #define MODULES_AUDIO_DEVICE_LINUX_AUDIO_MANAGER_H_namespace webrtc {class AudioManager { public:AudioManager();virtual ~AudioManager();bool IsALSAAudioSupported();bool IsPulseAudioSupported(); };} // namespace webrtc#endif /* MODULES_AUDIO_DEVICE_LINUX_AUDIO_MANAGER_H_ */

    AudioManager 類的定義如下:

    #include "audio_manager.h"#if defined(LINUX_ALSA) #include "modules/audio_device/linux/alsasymboltable_linux.h" #endif#if defined(LINUX_PULSE) #include "modules/audio_device/linux/pulseaudiosymboltable_linux.h" #endif#if defined(LINUX_ALSA) extern webrtc::adm_linux_alsa::AlsaSymbolTable AlsaSymbolTable; #endif#if defined(LINUX_PULSE) extern webrtc::adm_linux_pulse::PulseAudioSymbolTable PaSymbolTable; #endifnamespace webrtc {AudioManager::AudioManager() {}AudioManager::~AudioManager() {}bool AudioManager::IsALSAAudioSupported() { #if defined(LINUX_ALSA)return AlsaSymbolTable.Load(); #elsereturn false; #endif }bool AudioManager::IsPulseAudioSupported() { #if defined(LINUX_PULSE)return PaSymbolTable.Load(); #elsereturn false; #endif }} // namespace webrtc

    而 webrtc/modules/audio_device/audio_device_impl.cc 中的相關邏輯則可以修改為如下這樣:

    #elif defined(WEBRTC_LINUX)std::unique_ptr<AudioManager> audio_manager(new AudioManager()); #if !defined(LINUX_PULSE)// Build flag 'rtc_include_pulse_audio' is set to false. In this mode:// - kPlatformDefaultAudio => ALSA, and// - kLinuxAlsaAudio => ALSA, and// - kLinuxPulseAudio => Invalid selection.RTC_LOG(WARNING) << "PulseAudio is disabled using build flag.";if ((audio_layer == kLinuxAlsaAudio) ||(audio_layer == kPlatformDefaultAudio)) {audio_device_.reset(new AudioDeviceLinuxALSA());RTC_LOG(INFO) << "Linux ALSA APIs will be utilized.";} #else// Build flag 'rtc_include_pulse_audio' is set to true (default). In this// mode:// - kPlatformDefaultAudio => PulseAudio, and// - kLinuxPulseAudio => PulseAudio, and// - kLinuxAlsaAudio => ALSA (supported but not default).RTC_LOG(INFO) << "PulseAudio support is enabled.";if (((audio_layer == kLinuxPulseAudio) ||(audio_layer == kPlatformDefaultAudio)) && audio_manager->IsPulseAudioSupported()) {// Linux PulseAudio implementation is default.audio_device_.reset(new AudioDeviceLinuxPulse());RTC_LOG(INFO) << "Linux PulseAudio APIs will be utilized";} else if ((audio_layer == kLinuxAlsaAudio) ||(audio_layer == kPlatformDefaultAudio)) {audio_device_.reset(new AudioDeviceLinuxALSA());RTC_LOG(WARNING) << "Linux ALSA APIs will be utilized.";} #endif // #if !defined(LINUX_PULSE) #endif // #if defined(WEBRTC_LINUX)

    不過這種做法也有一些問題,即在判斷系統(tǒng)是否支持時,就提前加載了對應的系統(tǒng)庫。

    總結

    以上是生活随笔為你收集整理的WebRTC Linux ADM 实现中的符号延迟加载机制的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    在线观看免费黄视频 | 国产中文自拍 | 久久久久久国产精品免费 | 欧美性极品xxxx娇小 | 亚洲日本精品 | 五月婷婷久 | 国产精品18久久久久久不卡孕妇 | 欧美国产日韩一区二区 | 99视频在线观看视频 | 色天天综合久久久久综合片 | 国产色秀视频 | 日韩在线播放视频 | 久久精品免费观看 | 久久免费电影网 | 国产精品岛国久久久久久久久红粉 | 久久深夜福利免费观看 | 人成午夜视频 | 精品久久久影院 | 久草网在线观看 | 93久久精品日日躁夜夜躁欧美 | 狠狠色狠狠色 | 麻豆一二三精选视频 | 香蕉久草在线 | 久久精国产| 久久人人爽人人片 | 又湿又紧又大又爽a视频国产 | 青青草国产在线 | 国产一区在线免费观看 | 欧美a级成人淫片免费看 | 夜夜操天天操 | 91亚洲精品乱码久久久久久蜜桃 | 色在线网 | 久久久久久久国产精品 | 亚洲视频中文 | 国产精品嫩草影院9 | 91在线精品秘密一区二区 | 中文在线天堂资源 | 午夜精品999 | 国内精品久久久久久久久久 | 亚洲精品动漫在线 | 91香蕉视频720p | 久久第四色 | 久久情爱 | 亚洲视频资源在线 | 99精品国产在热久久下载 | 黄色一级在线免费观看 | 日韩精品免费一线在线观看 | 人人插超碰 | 中文字幕高清在线 | 久久精品欧美一区二区三区麻豆 | 国产资源网 | 亚洲天天综合网 | 成人毛片a | 国产美女精品 | 黄网站色视频免费观看 | 中文字幕第 | 中文字幕乱码一区二区 | 日韩中文字幕一区 | 天天爱天天插 | 日韩欧美综合 | 婷婷六月激情 | 久久久一本精品99久久精品66 | 五月天丁香综合 | 99热这里只有精品免费 | 中文字幕婷婷 | 一区二区精品在线 | 麻豆91精品视频 | 在线国产片 | 亚洲一级片在线观看 | 国产破处在线视频 | 开心激情五月网 | 曰韩精品 | 免费在线国产精品 | 日韩高清在线看 | 99热这里只有精品8 久久综合毛片 | 国产自产高清不卡 | 日韩av一卡二卡三卡 | 操处女逼 | 这里有精品在线视频 | 又黄又爽又色无遮挡免费 | 丁香激情五月 | 国产精品国产三级国产aⅴ9色 | 天天操夜操| 日韩欧美综合在线视频 | 久久久久欧美精品999 | 丰满少妇在线观看资源站 | 亚洲 中文字幕av | 开心色激情网 | 久久综合给合久久狠狠色 | 亚洲毛片在线观看. | 色综合久久中文字幕综合网 | 美女免费视频一区二区 | 中文在线免费一区三区 | 98超碰在线观看 | 天天色棕合合合合合合 | 国产高清在线永久 | 成人在线观看资源 | 91在线看视频免费 | 亚洲自拍偷拍色图 | 四虎5151久久欧美毛片 | 欧美另类调教 | 日日摸日日爽 | 亚洲精品资源在线观看 | 亚洲一二视频 | 免费日韩一区二区三区 | 99热手机在线观看 | 一区二区三区视频在线 | 一区二区三区免费看 | 国产黄色片免费观看 | 色成人亚洲 | 成人精品一区二区三区电影免费 | 国产精品观看视频 | 欧美在线观看小视频 | 国产黄色观看 | 久久精品男人的天堂 | 欧美日韩在线观看不卡 | 国产尤物一区二区三区 | 97超碰超碰久久福利超碰 | 日韩欧美视频免费在线观看 | 97精品欧美91久久久久久 | 黄色在线观看www | 日本一区二区免费在线观看 | 国产在线观看免 | 国产精品毛片一区二区 | 五月天综合激情网 | 国产一区免费视频 | 免费av在线| av电影免费在线播放 | 在线成人一区二区 | av再线观看 | 97av在线| 国产精品一区二区久久精品 | 99成人免费视频 | 亚洲香蕉视频 | 欧美 激情在线 | 日韩欧美视频免费在线观看 | 天天曰夜夜操 | 精品久久福利 | 日韩av免费一区二区 | 五月婷婷黄色 | 国产中文字幕视频在线观看 | 91精品国产自产在线观看 | 成人av在线影院 | 日本美女xx| 在线观看一区二区视频 | 91亚洲成人 | 91九色国产视频 | 国产精品成人免费 | a国产精品 | 色a4yy| 日韩在线免费不卡 | 69av视频在线观看 | 91亚洲精品国产 | 亚洲码国产日韩欧美高潮在线播放 | 天天干天天天 | 国产99在线播放 | 91精彩在线视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 天天操·夜夜操 | 国产精品成人一区二区三区 | 91九色成人蝌蚪首页 | 国产美女在线观看 | 亚洲资源在线 | 国产精品一区二区三区在线看 | 成年人免费看片 | av网站免费在线 | 精品国产一区二区三区久久久蜜臀 | 中文字幕123区 | 精品一区二区av | 日韩av电影中文字幕在线观看 | 国产午夜一区二区 | 97人人添人澡人人爽超碰动图 | 中文字幕免费在线 | 中文字幕av影院 | 国产精品亚洲片夜色在线 | 亚洲欧美偷拍另类 | 在线观看黄色免费视频 | 国产综合香蕉五月婷在线 | 伊人天堂av| 日韩视频一区二区在线 | 97日日| 911国产| 丁香在线观看完整电影视频 | 免费福利在线观看 | 亚洲小视频在线观看 | 久久视频网 | 成人三级网址 | 99精品视频在线观看 | 国产女人40精品一区毛片视频 | 福利视频午夜 | 500部大龄熟乱视频使用方法 | 欧美一区免费观看 | 美女视频一区二区 | 中日韩在线 | 一区二区精| 国产精品美女免费看 | 97超碰人人爱 | 久久免费看av | 精品一区二区精品 | 欧美日韩不卡在线视频 | 日韩精品1区2区 | 最新av免费在线观看 | 欧美激情视频一二区 | 久久国产综合视频 | 欧美视屏一区二区 | 九九精品在线观看 | 亚洲精品视频在线观看视频 | 996久久国产精品线观看 | 国内精品视频在线 | 欧美精品天堂 | 久草在线最新视频 | 免费观看一级成人毛片 | 丁香影院在线 | 国产日韩欧美在线 | 欧美色综合天天久久综合精品 | 久草a在线 | 天天av在线播放 | 九九九九九九精品任你躁 | 亚洲精品自拍视频在线观看 | www日韩在线| 激情 一区二区 | 九九久久久久久久久激情 | 亚洲成人av电影在线 | 久久精品国产99 | 天天曰夜夜操 | 久久综合色天天久久综合图片 | 91在线观看视频 | 亚洲精品99 | 久久99精品久久久久久清纯直播 | 亚洲va天堂va欧美ⅴa在线 | 一级黄色大片在线观看 | 超碰97在线看 | 激情久久影院 | 亚洲精品激情 | 日日爱夜夜爱 | 国产不卡av在线 | 在线观看视频你懂得 | 中文字幕视频三区 | 四虎在线免费 | 国产一区免费观看 | 中文字幕 国产精品 | 日韩在线观看精品 | 国产精品综合久久久久 | 精品视频免费 | 欧美韩日视频 | 在线观看一区 | 国产一级性生活视频 | 精品久久久久免费极品大片 | 99久久这里只有精品 | 国产看片网站 | 麻豆一区在线观看 | 欧美一级小视频 | 久久久国产精品视频 | 精品国产亚洲在线 | 欧美aa级| 黄色特一级片 | 亚洲欧洲精品一区 | 不卡视频在线看 | 国产免费影院 | 欧美精品黑人性xxxx | 亚洲国产免费网站 | www日日| 成人免费视频网址 | 国产分类视频 | 97视频在线观看免费 | 丝袜av一区| 91在线播放视频 | 国产精品视频 | 国产午夜在线观看视频 | 日日日视频 | 久久1电影院 | 黄色精品久久久 | 国产精品九九久久久久久久 | 最新国产福利 | 丁香国产视频 | 国产精品亚洲视频 | 国产成人精品a | 精壮的侍卫呻吟h | 99精品国产免费久久 | 欧美成人中文字幕 | 人人干,人人爽 | 精品在线观看免费 | 黄色一二级片 | 在线观看国产福利片 | 日本亚洲国产 | 久久亚洲福利视频 | 国产97av | 久久久国际精品 | 日本一区二区三区视频在线播放 | 人人插人人看 | 日韩午夜电影 | 蜜臀久久99精品久久久酒店新书 | 丝袜美腿一区 | 波多野结衣在线观看一区二区三区 | 亚洲第二色 | 国产视频一 | 欧美日韩在线第一页 | 欧美一区二区三区激情视频 | 黄在线免费看 | 日本成人a | 九九久久精品视频 | 在线黄色观看 | 午夜精品久久久久久久99水蜜桃 | 91精品爽啪蜜夜国产在线播放 | 在线看一区二区 | 91成人精品一区在线播放 | 婷婷国产v亚洲v欧美久久 | 成人av电影免费观看 | 国产高清专区 | 久久亚洲私人国产精品va | 一区二区观看 | 久草在线播放视频 | 成人国产精品免费观看 | 精品国产大片 | 手机看片 | 精品国产一区二区三区蜜臀 | 日韩精品视频一二三 | 日韩成人精品一区二区 | 91在线播放综合 | 久久久免费观看完整版 | 91久久国产综合精品女同国语 | 激情五月色播五月 | 久色 网 | 久草在线国产 | 国产精品九九久久久久久久 | 免费视频久久久久 | 色婷婷啪啪免费在线电影观看 | 蜜臀av性久久久久av蜜臀三区 | 久久久综合香蕉尹人综合网 | 国产精品2018 | 亚洲伦理一区二区 | 亚洲一区不卡视频 | 久草线| 日本系列中文字幕 | 成人日韩av | 黄色大片国产 | 五月天久久综合网 | 亚洲免费精彩视频 | 亚洲激情视频 | www.午夜视频 | av看片在线观看 | mm1313亚洲精品国产 | 91探花视频 | 欧美日韩亚洲在线 | 久久夜色精品国产欧美一区麻豆 | 久久久久网址 | 精品国产激情 | 亚洲精品黄色片 | 黄色免费观看网址 | av免费在线观 | 91最新网址 | 成全在线视频免费观看 | 国产一级电影 | 在线视频日韩一区 | 啪啪免费视频网站 | 中文字幕免费观看视频 | 一本一本久久a久久精品综合妖精 | 13日本xxxxxⅹxxx20 | 久久久久久久久久国产精品 | 91香蕉国产在线观看软件 | 免费a视频在线 | 狠狠躁日日躁夜夜躁av | 国产在线观看地址 | 在线精品观看国产 | 六月丁香综合网 | 婷婷四房综合激情五月 | 五月婷婷丁香在线观看 | 亚洲aⅴ在线| 一区二区三区福利 | 久久激五月天综合精品 | 亚洲国产高清在线观看视频 | 精品国产亚洲日本 | 粉嫩av一区二区三区四区在线观看 | 日韩91精品 | 四虎国产精品永久在线国在线 | 久草视频在线资源 | 狠狠久久伊人 | 天天干视频在线 | 午夜黄色| 欧美日韩国产在线一区 | 免费精品人在线二线三线 | 免费在线观看91 | 成年人在线观看视频免费 | 在线看污网站 | 97国产超碰 | 一级久久久 | 欧美精品久久久久 | 99c视频高清免费观看 | 亚洲男男gⅴgay双龙 | 国产夫妻性生活自拍 | 在线免费观看羞羞视频 | 看全黄大色黄大片 | 丁香资源影视免费观看 | 亚洲日韩中文字幕 | 亚洲精品视频免费在线观看 | 亚洲在线日韩 | 91视频91蝌蚪| 中文字幕在线观看第三页 | 91中文在线观看 | 在线天堂中文在线资源网 | 日韩三级精品 | 有码中文字幕 | 亚洲涩涩网 | 九九久久成人 | 狠狠干网 | 日本性生活一级片 | 日韩欧美区 | 免费看网站在线 | 91视频免费观看 | 91免费观看国产 | 日韩精品一区二区三区三炮视频 | 成人小电影在线看 | 久久男人视频 | 在线观看亚洲精品 | 国产精品99爱 | 色网站在线免费观看 | 激情婷婷综合 | 国产精品手机看片 | 狠狠色狠狠色综合日日92 | 黄色大全免费网站 | 国产高清在线免费视频 | 欧美视频在线二区 | 手机在线看a | 国产高清av免费在线观看 | 五月天六月丁香 | 欧美午夜a | 波多野结衣精品在线 | av在线网站免费观看 | 久久久精品二区 | 久久久综合九色合综国产精品 | 成人av电影免费在线观看 | 天天干,天天插 | 在线观看黄网站 | 久章草在线 | 日韩视频一区二区三区在线播放免费观看 | 高清在线一区 | 免费看色网站 | 亚州视频在线 | 日韩在线观看一区 | 麻豆国产精品一区二区三区 | 精品国产一区二区久久 | 日韩av视屏| 久久综合婷婷综合 | 中文字幕在线日亚洲9 | 中文字幕永久免费 | 国产日韩欧美自拍 | 久久国产精品成人免费浪潮 | 欧美激情视频三区 | 97精产国品一二三产区在线 | 久久久国产高清 | 久久成人午夜 | 有没有在线观看av | 69国产在线观看 | 国产对白av | 99久久久成人国产精品 | 在线观看视频精品 | 91在线精品观看 | 久久久久亚洲精品男人的天堂 | 亚洲激情视频在线 | 三级动图 | 欧美一级性生活片 | 久热色超碰 | 午夜精品福利一区二区三区蜜桃 | 国产高清 不卡 | 亚洲午夜av久久乱码 | 91色影院| 人人爽人人爽人人爽学生一级 | 国产小视频你懂的 | 婷婷精品进入 | 国产精品网红福利 | 国内精品国产三级国产aⅴ久 | 欧美a在线免费观看 | 尤物一区二区三区 | 超碰97国产在线 | 久草免费在线 | 91在线成人 | 国产一级高清 | 国产韩国日本高清视频 | 国产精品男女视频 | 亚洲第五色综合网 | 在线观看视频黄色 | 激情欧美丁香 | 国产小视频在线免费观看视频 | 婷婷综合导航 | 亚洲精品在线一区二区三区 | 日本久久精品视频 | 国内毛片毛片 | 中文字幕乱码电影 | 在线观看理论 | 欧美91精品久久久久国产性生爱 | 免费av网站在线 | 成人动漫精品一区二区 | 久久99热久久99精品 | 成人三级网站在线观看 | 综合成人在线 | 一二区精品 | 久久一级片 | 97视频免费观看2区 亚洲视屏 | av黄色免费看| 午夜免费福利片 | 麻豆国产露脸在线观看 | 成人免费一区二区三区在线观看 | 久久亚洲综合国产精品99麻豆的功能介绍 | 亚洲视屏 | 亚洲在线黄色 | 久草青青在线观看 | 99综合视频 | 中文字幕在线观看免费高清完整版 | 天天干天天做 | 中文字幕在线观看视频网站 | 国语自产偷拍精品视频偷 | 亚洲最新视频在线 | 天天射天天添 | 99久久超碰中文字幕伊人 | 成年人在线观看视频免费 | 麻豆视传媒官网免费观看 | 在线观看亚洲精品视频 | av中文天堂在线 | 高清国产一区 | 久草网视频 | 国产乱码精品一区二区三区介绍 | 久久精品艹| 亚洲精品在线免费播放 | 国产一级片观看 | 国产精品一区二区 91 | 日韩精品欧美视频 | 国产日产精品一区二区三区四区的观看方式 | 色噜噜在线观看 | 中文字幕精品一区久久久久 | 99久久精品无码一区二区毛片 | 国产精品久久网站 | 国产成人精品亚洲a | 夜夜夜夜操 | 国产中文字幕三区 | 在线免费高清视频 | 久久免费看| 操天天操 | 久久婷婷五月综合色丁香 | 久久精国产| 最新日韩中文字幕 | 国产精品久久久久久久久久了 | 久久综合色天天久久综合图片 | 亚洲精品视频播放 | 成人在线视频你懂的 | 久久久久看片 | 91最新地址永久入口 | 日韩视频中文字幕在线观看 | 国产经典三级 | 国产不卡高清 | 99久久久久久国产精品 | 最近免费观看的电影完整版 | www.夜色.com| 国产精美视频 | 婷婷久月| 综合网天天 | 国产91aaa| 精品国产一区二区三区久久久蜜臀 | av一本久道久久波多野结衣 | 久久这里只有精品23 | 在线欧美日韩 | 欧美日韩亚洲第一 | 久99久在线 | 国产不卡精品 | 开心婷婷色 | 国产福利在线免费观看 | 国产精品9999久久久久仙踪林 | 久久另类视频 | 国产成人黄色在线 | 超碰公开在线 | 免费黄色网址网站 | 五月激情在线 | 国产一级淫片免费看 | 特级西西444www大精品视频免费看 | 午夜在线观看 | 久久久久久久久久影视 | 超碰97在线看 | 国产视频91在线 | 四虎影视精品 | 91九色porny蝌蚪视频 | www.亚洲视频.com| 在线av资源 | 一性一交视频 | 日韩系列 | 国产精品综合久久久久久 | 亚洲国产成人精品电影在线观看 | 在线观看v片 | 91热这里只有精品 | 国产精品第72页 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 国产中文字幕久久 | 狠狠干天天操 | 久久精品久久99 | 欧洲高潮三级做爰 | 欧美日本国产在线观看 | 69亚洲精品 | 久久久久久久久久久久久国产精品 | 人人插人人艹 | av在线播放国产 | 婷婷综合电影 | 国产一区二区不卡视频 | .国产精品成人自产拍在线观看6 | 国产裸体无遮挡 | 亚洲综合狠狠干 | 国产精品成久久久久三级 | 午夜精品久久久久久久久久 | 99精品在线直播 | 手机看片福利 | 午夜天使 | 亚洲欧美国产精品 | 人人超在线公开视频 | 五月激情视频 | 波多野结衣亚洲一区二区 | 久久这里 | 成年人在线免费看 | 99久久电影 | 伊人狠狠色丁香婷婷综合 | 欧美性久久久久久 | 手机av在线网站 | 丁香网五月天 | 美女视频免费一区二区 | 黄色一级大片免费看 | 国产免费三级在线观看 | 免费久草视频 | 肉色欧美久久久久久久免费看 | www.夜夜操 | 超碰国产97 | 亚洲精品乱码久久久久久按摩 | 这里只有精品视频在线观看 | 国产精品毛片一区视频播不卡 | 美女久久久 | 亚洲免费av在线播放 | 国内精品久久久久久中文字幕 | 狠狠色丁香婷婷综合橹88 | 欧美三级在线播放 | 精久久久久 | 69国产盗摄一区二区三区五区 | 在线久久| 久久久久久国产精品999 | 久久久久久综合 | 欧美91精品 | 久久精品久久久精品美女 | 日韩精品亚洲专区在线观看 | 久久国产高清视频 | 人人澡视频 | 欧美日韩中文字幕在线视频 | 久久午夜免费观看 | 国产精品第52页 | 国产福利一区二区三区视频 | 国产精品一区二区在线观看免费 | 久久久激情网 | 在线国产片| 最近的中文字幕大全免费版 | 久久久久久久久艹 | 亚洲欧美va| 91视频在线观看大全 | 久久电影日韩 | 久色免费视频 | 国产系列在线观看 | 免费一级片在线观看 | 亚洲精品国产区 | 成人av一级片 | 久久精品aaa | 91网免费观看| 成年人视频在线 | www.午夜视频| 色综合五月天 | 婷婷亚洲综合 | 国产在线观看一 | 久久久国产精品网站 | 亚洲黄色小说网 | 国产91精品久久久久久 | 国产无限资源在线观看 | av免费网站观看 | 国产福利精品视频 | 国产成人黄色在线 | 天天干亚洲 | 激情久久五月 | 夜夜高潮夜夜爽国产伦精品 | 婷婷丁香激情 | 亚洲精品字幕在线观看 | 激情婷婷综合 | 国产精品不卡 | 91精品久久久久久久久久久久久 | 亚洲精品合集 | 亚洲精品一区二区三区在线观看 | 久热免费在线观看 | 九九热久久久 | 国产精品不卡一区 | 久久久综合香蕉尹人综合网 | 亚洲精品美女久久17c | 2019国产精品| 麻豆免费在线播放 | 激情欧美网 | 美女视频黄免费的 | 天天艹天天| 久久精品视频在线观看 | 国产精品正在播放 | 国产亚洲精品久久久久久网站 | 一本大道久久精品懂色aⅴ 五月婷社区 | 91精品国 | 夜夜爽夜夜操 | 国产日韩欧美在线 | 激情 婷婷 | 国产精品v a免费视频 | 日韩免费一区二区三区 | 国产在线观看你懂的 | 一区二三国产 | 国产在线精品一区二区不卡了 | 日日碰夜夜爽 | 日韩在线视 | 99久久一区| 97国产在线视频 | 日韩a在线看 | 成年人在线电影 | 超碰免费观看 | 国产精品日韩在线播放 | 日韩精品欧美专区 | 激情综合网在线观看 | 一区 二区 精品 | 又污又黄的网站 | 免费91在线| 99久久99久久精品免费 | 欧美一级专区免费大片 | 在线免费精品视频 | 日韩欧美在线播放 | 在线播放视频一区 | 国产精品久久久久久久久久久久午 | 好看的国产精品视频 | 久草在线综合网 | 丁香婷婷综合网 | 国产在线播放一区 | 黄色成人av网址 | 国产 色 | 久草精品网 | 国产精品久久久久毛片大屁完整版 | 在线看一区 | 日韩在线视频免费播放 | 国产视频美女 | 超碰免费97| 激情小说 五月 | 亚洲永久精品一区 | 国产在线精品福利 | 国产小视频国产精品 | av黄色免费在线观看 | 97香蕉久久超级碰碰高清版 | 久久影视一区二区 | 波多野结衣视频一区 | 久久综合九色综合欧美就去吻 | 久久免费黄色大片 | 亚洲国产中文字幕 | www..com黄色片 | 免费av的网站| 天天爱综合 | 亚洲欧洲一区二区在线观看 | 五月天久久久久 | 国产精品视频不卡 | 偷拍福利视频一区二区三区 | 国产麻豆剧果冻传媒视频播放量 | 欧美激情综合五月色丁香 | 97国产精品亚洲精品 | 最近免费中文字幕 | 久久99精品久久久久婷婷 | 日日日天天天 | 胖bbbb搡bbbb擦bbbb | 国产精品理论片在线播放 | 亚洲最大av | 欧美一二三区在线观看 | 中文字幕在线视频第一页 | 日韩极品在线 | 久久久久免费视频 | 91试看 | 国外成人在线视频网站 | 成人av片在线观看 | 色综合天天视频在线观看 | 国产96在线视频 | sesese图片 | 日韩免费福利 | 日韩最新av在线 | 亚洲美女精品 | 成人av网站在线 | 久久久久久久久综合 | 国产一二区精品 | 六月色| 丁香av在线 | 天天干天天干天天干天天干天天干天天干 | 免费高清在线观看电视网站 | av久久在线| 九九视频免费在线观看 | 国产精品中文字幕在线观看 | 亚洲精品综合在线观看 | 91在线公开视频 | av中文在线影视 | 久久在线免费 | 少妇啪啪av入口 | 中文字幕在线看视频国产 | 久久久久久久久久久久久国产精品 | 天天射天天搞 | 天天操天天草 | 欧美污在线观看 | 超碰97人人在线 | 最新中文字幕在线资源 | 亚洲国产精品人久久电影 | 国产精品视频永久免费播放 | 精品欧美一区二区精品久久 | 亚洲欧洲精品一区二区精品久久久 | 国产福利一区二区在线 | 亚洲一区网站 | 日韩试看| 福利片视频区 | 亚洲国产中文字幕在线观看 | 日韩精品在线观看视频 | 成人夜晚看av | 免费在线激情电影 | 中文字幕在线视频免费播放 | 国产小视频91 | 91系列在线 | 91精品久久久久久久91蜜桃 | 四虎国产精品成人免费影视 | 午夜精品福利影院 | 日本丶国产丶欧美色综合 | 三级黄色片在线观看 | 国产成人精品久久亚洲高清不卡 | 午夜.dj高清免费观看视频 | 国产精品va| 日日日天天天 | www.狠狠 | 成人午夜剧场在线观看 | 日日干天天射 | 国产成在线观看免费视频 | 最新午夜 | 日本中文字幕在线电影 | 久久精品高清 | 国产黄色大片免费看 | 国产高清在线 | 国产精品久久久久久久久毛片 | 国产日产亚洲精华av | 欧美日本在线观看视频 | 97成人免费视频 | 久久99亚洲精品久久 | 色999精品 | 日本黄色免费播放 | 成人a在线观看高清电影 | 色偷偷人人澡久久超碰69 | 97在线免费视频观看 | 日p视频在线观看 | 国外av在线 | 不卡av在线免费观看 | 天天干人人干 | 人人澡人人舔 | 日韩在线| 久久香蕉国产 | 在线看片a| 超碰激情在线 | 国产成人精品久 | 天天草视频 | 精品专区一区二区 | av超碰在线 | 2021国产在线视频 | 亚洲日本欧美 | 日韩av一区二区在线影视 | 九九九九精品九九九九 | 国色天香第二季 | 一区二区三区视频在线 | 久久久免费观看完整版 | 欧美91精品久久久久国产性生爱 | 激情五月视频 | 99久久久国产精品免费观看 | 在线一区观看 | 国产成人久久精品 | 久久亚洲国产精品 | 欧美黄污视频 | 亚洲成人免费观看 | 99精品免费 | 在线日本v二区不卡 | 色婷婷啪啪免费在线电影观看 | 成年人在线视频观看 | 国色天香在线 | 一本一本久久a久久精品综合 | 亚洲一区天堂 | 中文字幕国内精品 | 激情图片久久 | www黄免费 | 人人干人人做 | 日韩高清免费无专码区 | 超碰97中文 | 亚州精品在线视频 | 色在线免费观看 | 99精品久久久久久久久久综合 | 国内精品中文字幕 | 91成人在线免费观看 | 午夜久久久影院 | 中文字幕黄色网 | 国产视频1| 色吊丝在线永久观看最新版本 | 黄色网在线免费观看 | 久久99久久久久 | 可以免费看av | www.xxxx欧美| 久久涩视频 | 91视频麻豆 | 粉嫩av一区二区三区四区在线观看 | 高清一区二区三区av | 最新日韩在线观看视频 | 五月婷婷丁香激情 | 亚洲成人av在线电影 | 在线免费观看视频a | 日本三级在线观看中文字 | 日日爽夜夜操 | 992tv在线观看 | 亚洲视频axxx | 日韩高清无线码2023 | 97影视 | 成 人 黄 色 视频免费播放 | 国产精品视频永久免费播放 | 婷婷丁香激情 | 亚洲 欧美 91 | 国产麻豆剧果冻传媒视频播放量 | 日韩免费三区 | 日韩色视频在线观看 | 不卡在线一区 | 欧美性粗大hdvideo | 亚洲一区二区视频 | 91久久久久久久一区二区 | 亚洲国产大片 | 99国产视频 | 国产精品美女www爽爽爽视频 | 日韩欧美电影网 | 国产精品精品国产 | 中文字幕高清有码 | 国产精品一区二区三区电影 | 亚洲精品乱码久久久久久蜜桃动漫 | 91久久国产自产拍夜夜嗨 | 久久一精品 | 久草视频视频在线播放 | 亚洲涩涩网 | 91麻豆传媒 | 久久视频6| 亚洲日韩精品欧美一区二区 | 91精品无人成人www | 久久久久久久亚洲精品 | 欧美人操人 | 天天天干夜夜夜操 | 久久久久久国产精品亚洲78 | 国产精品免费视频一区二区 | 久久精品www人人爽人人 | 中文一区二区三区在线观看 | 欧美综合在线视频 | 天天摸日日操 | 97香蕉久久超级碰碰高清版 | 丝袜美腿亚洲综合 | 美女视频又黄又免费 | 亚洲综合涩 | 中文区中文字幕免费看 | 亚洲 欧美 综合 在线 精品 | 综合在线观看色 | 国产精品激情在线观看 | 在线免费色 | 亚洲精品乱码久久久久久 | 在线视频观看国产 | 久久精品成人欧美大片古装 | 激情视频综合网 | 久久福利在线 | 国产在线观看一区 | 91.麻豆视频 | 欧美最猛性xxxx | 在线亚洲免费视频 | 国产麻豆精品95视频 | 成人动漫视频在线 | 欧美性性网 | 国产一区在线精品 | 久久免费观看少妇a级毛片 久久久久成人免费 | 免费观看国产成人 | 96精品视频 | 91精品国产麻豆国产自产影视 | 97色涩| 天天操天天弄 | 99性视频| 日韩在线观看第一页 | 在线观看网站黄 | 国产99久久久国产精品 | 国产精品12 | 日韩美女久久 | av电影免费在线看 | 深爱激情五月网 | 国产日韩欧美在线观看 | 最新精品视频在线 | 高清免费在线视频 | 亚洲精品激情 | 色视频在线看 | 日韩伦理片一区二区三区 | 久久婷婷一区二区三区 | 欧美性生活免费 | 久久久国产精品亚洲一区 | 久久综合欧美精品亚洲一区 | 国产精选视频 | 成人午夜电影网 | 中文字幕观看av | 美女免费视频黄 |