亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

iOS音頻系列(二)--CoreAudio

2019-11-14 11:09:21
字體:
來源:轉載
供稿:網友

這一篇主要是CoreAudio官方文檔的重點內容的筆記。

通過回調函數與CoreAudio交互

iOS的CoreAudio是通過callback函數與App交互的。其中需要設置回調函數有以下幾種情況:

CoreAudio會向回調函數給App傳入PCM音頻數據,然后App需要在回調函數中將音頻數據寫入文件文件系統。(錄音時候)CoreAudio會需要向App請求一些音頻數據,App通過從文件系統中讀取音頻數據,然后通過callback函數傳遞給CoreAudio。(播放時候)通過注冊屬性觀察者,監聽CoreAudio的屬性,注冊回調函數

下面是一個使用Audio Queue Services的屬性監聽器的callback函數的調用模板

12345
typedef void (*AudioQueuePRopertyListenerProc) (                void *                  inUserData,                AudioQueueRef           inAQ,                AudioQueuePropertyID    inID            );

在實現和使用這個callback函數時候,你需要完成兩件事:

實現這個函數。例如,你可以實現property listener callback,根據audio是否在running或者stop狀態,去改變更新UI。注冊callback函數時候帶上userData數據,在callback函數觸發時候使用。

下面是一個property listener callback函數的實現:

12345678910
static void propertyListenerCallback (    void                    *inUserData,    AudioQueueRef           queueObject,    AudioQueuePropertyID    propertyID) {    AudioPlayer *player = (AudioPlayer *) inUserData;        // gets a reference to the playback object    [player.notificationDelegate updateUserInterfaceOnAudioQueueStateChange: player];        // your notificationDelegate class implements the UI update method}

下面是注冊一個callback函數的例子:

123456
AudioQueueAddPropertyListener (    self.queueObject,                // the object that will invoke your callback    kAudioQueueProperty_IsRunning,   // the ID of the property you want to listen for    propertyListenerCallback,        // a reference to your callback function    self);

Audio Data Formats

這部分內容是iOS中支持的音頻格式,理解以后對后面的音頻相關的編程能夠理解更加深刻。

iOS中通用的音頻數據類型

在CoreAudio中,使用AudioStreamBasicDescriptionAudioStreamPacketDescription這兩個類型描述了通用的音頻數據類型,包括壓縮音頻數據,非壓縮的音頻數據。他們的數據結構如下:

12345678910111213141516171819
struct AudioStreamBasicDescription {    Float64 mSampleRate;    UInt32  mFormatID;    UInt32  mFormatFlags;    UInt32  mBytesPerPacket;    UInt32  mFramesPerPacket;    UInt32  mBytesPerFrame;    UInt32  mChannelsPerFrame;    UInt32  mBitsPerChannel;    UInt32  mReserved;				//0};typedef struct AudioStreamBasicDescription  AudioStreamBasicDescription;struct  AudioStreamPacketDescription {    SInt64  mStartOffset;    UInt32  mVariableFramesInPacket;    UInt32  mDataByteSize;};typedef struct AudioStreamPacketDescription AudioStreamPacketDescription;

compressed audio formats use a varying number of bits per sample. For these formats, the value of the mBitsPerChannel member is 0.

Audio Data Packets

前面定義過,將一個或者多個frames稱為一個packet?;蛘哒fpacket是最有意義的一組frames,它在audio file中代表一個有意義的時間單元。使用Core Audio中一般是對packets進行處理的。

每個audio data格式在packets被裝配完成以后,它的fromat就被確定了。ASBD數據結構通過mBytesPerPacketmFramesPerPacket描述音頻格式的packet信息,其中頁包含其他的信息。

在整個Core Audio中可能會用到三種不同的packets:

CBR (constant bit rate) formats:例如 linear PCM and IMA/ADPCM,所有的packet使用相同的大小。VBR (variable bit rate) formats:例如 AAC,Apple Lossless,MP3,所有的packets擁有相同的frames,但是每個sample中的bits數目不同。VFR (variable frame rate) formats:packets擁有數目不同的的frames。

在Core Audio中使用VBR或者VFR格式,使用aspD結構體只能用來描述單個packet。如果是record或者play VBR或者VFR音頻文件,需要涉及到多個ASPD結構。

在AudioFileService等接口中,都是通過pakcets工作的。例如AudioFileReadPackets會得到一系列的packets,同時會得到一個數組的AudioStreamPacketDescription。

下面是通過packets計算audio data buffer的大小:

12345678910111213141516171819202122232425262728293031323334353637
- (void) calculateSizesFor: (Float64) seconds {     UInt32 maxPacketSize;    UInt32 propertySize = sizeof (maxPacketSize);     AudioFileGetProperty (        audioFileID,        kAudioFilePropertyPacketSizeUpperBound,        &propertySize,        &maxPacketSize    );     static const int maxBufferSize = 0x10000;   // limit maximum size to 64K    static const int minBufferSize = 0x4000;    // limit minimum size to 16K     if (audioFormat.mFramesPerPacket) {        Float64 numPacketsForTime =            audioFormat.mSampleRate / audioFormat.mFramesPerPacket * seconds;        [self setBufferByteSize: numPacketsForTime * maxPacketSize];    } else {        // if frames per packet is zero, then the codec doesn't know the        // relationship between packets and time. Return a default buffer size        [self setBufferByteSize:            maxBufferSize > maxPacketSize ? maxBufferSize : maxPacketSize];    }     // clamp buffer size to our specified range    if (bufferByteSize > maxBufferSize && bufferByteSize > maxPacketSize) {        [self setBufferByteSize: maxBufferSize];    } else {        if (bufferByteSize < minBufferSize) {            [self setBufferByteSize: minBufferSize];        }    }     [self setNumPacketsToRead: self.bufferByteSize / maxPacketSize];}

Data Format Conversion

將音頻數據從一種audio data轉換成另外一種audio data。常見的有三中音頻格式轉換:

Decoding an audio format (such as AAC (Advanced Audio Coding)) to linear PCM format.Converting linear PCM data into a different audio format.Converting between different variants of linear PCM (for example, converting 16-bit signed integer linear PCM to 8.24 fixed-point linear PCM).

Sound Files

如果要使用聲音文件,你需要使用Audio File Services的接口。一般而且,在iOS中需要與音頻文件的創建,操作都離不開Audio File Services。

使用AudioFileGetGlobalInfoSizeAudioFileGetGlobalInfo分別分配info的內存和獲取info的內容。你可以獲取以下的內容:

Readable file typesWritable file typesFor each writable type, the audio data formats you can put into the file

Creating a New Sound File

為了創建一個能夠存儲音頻數據的audio file,你需要進行以下三步:

使用CFURL或者NSURL表示的系統文件的路徑你需要創建的文件的類型的標識identifier,這些identifier定義在Audio File Types枚舉中。例如,為了創建一個CAF文件,你需要使用kAudioFileCAFType的identifier。創建過程中你需要提供音頻數據的ASBD結構體。為了獲取ASBD,你可以先提供ASBD結構體的部分成員的值,然后通過函數讓Audio File Services將剩余的信息填滿。

下面是創建一個AudioFile的方法:

1234567
AudioFileCreateWithURL (    audioFileURL,    kAudioFileCAFType,    &audioFormat,    kAudioFileFlags_EraseFile,    &audioFileID   // the function provides the new file object here);

Opening a Sound File

為了打開sound file,需要使用AudioFileOpenURL函數,該函數會返回一個唯一ID,供后面使用。

為了獲取sound file的一些屬性,通常使用AudioFileGetPropertyInfoAudioFileGetProperty,日常使用的屬性以下:

kAudioFilePropertyFileFormatkAudioFilePropertyDataFormatkAudioFilePropertyMagicCookieDatakAudioFilePropertyChannelLayout

Reading From and Writing To a Sound File

iOS中,我們經常需要使用Audio File Services去讀寫audio data到sound file中。讀和寫是一對相反的內容,操作的對象都可以是bytes或者packets,但是一般而言都是直接使用的packets。

讀寫VBR數據,只能使用packet直接使用packet,更加容易計算時間

iPhone Audio File Formats

iOS支持的sound file格式如下:

Format nameFormat filename extensions
AIFF.aif, .aiff
CAF.caf
MPEG-1, layer 3.mp3
MPEG-2 or MPEG-4 ADTS.aac
MPEG-4.m4a, .mp4
WAV.wav

iOS中的native format是CAF file format。


Audio sessions: CoOperating with Core Audio

在iOS中,app在運行過程中有可能接到電話,如果此時正在播放sound,系統會做一定的處理。

AudioSession就是在這種情況的中間人,每個app都會有一個audio session。在播放或者錄音時候需要session在做正確的事情,需要我們自己弄清楚以下的情況:

app收到系統的中斷時候應該如何響應,比如收到phone call?你是否需要app的sound和其他后臺運行的app的sounds混合播放,或者需要獨占播放?你需要app如何響應遠音頻路徑的響應,比如拔插耳機時候

AudioSession提供了三種類型的接口:

Categories: A category is a key that identifies a set of audio behaviors for your application. By setting a category, you indicate your audio intentions to iOS, such as whether your audio should continue when the screen locks.Interruptions and route changes :Your audio session posts notifications when your audio is interrupted, when an interruption ends, and when the hardware audio route changes. These notifications let you respond to changes in the larger audio environment—such as an interruption due to in an incoming phone call—gracefully.Hardware characteristics:You can query the audio session to discover characteristics of the device your application is running on, such as hardware sample rate, number of hardware channels, and whether audio input is available.

Audio Session Default Behavior

Audio Session擁有一些默認的行為策略:

當用戶將靜音開關靜音時,audio就會靜音。當用戶鎖屏(手動,自動)時候,audio就會靜音。當你app的audio啟動時,其他app正在使用的audio就會靜音。

audio session的這個特定的默認的行為策略被稱為kAudioSessionCategory_SoloAmbientSound。同時,它還包括其他的多種策略選擇。

Interruptions: Deactivation and Activation

默認的audio session的一個典型的特征是,audio會在中斷以后自動恢復活動。Audio session有兩個重要的狀態:activeinactive。只有當Audio session處于active狀態時候,app才能使用audio。

在app啟動以后,你的默認的audio session就會是active狀態。然而,如果一個電話被打進來,你的session就會立刻被置為inactive,然后app中的audio就會停止。這個電話就被稱為一個中斷,如果用戶選擇忽略電話,app就會繼續運行。但是此時你的audio session依然會是inactive狀態,audio也就不會工作。

如果你使用 Audio Queue Services操作audio,我們就需要給中斷注冊listener回調函數,手動去重啟audio session。具體內容可以見Audio Session Programming Guide。

Determining if Audio Input is Available

一個錄音的app只有在設備的音頻硬件可用的時候才能錄音。為了檢查這個屬性,需要使用audio session的kAudioSessionProperty_AudioInputAvailable屬性。

123456789
UInt32 audioInputIsAvailable;UInt32 propertySize = sizeof (audioInputIsAvailable); AudioSessionGetProperty (    kAudioSessionProperty_AudioInputAvailable,    &propertySize,    &audioInputIsAvailable // A nonzero value on output means that                           // audio input is available);

Using Your Audio Session

你的app同時只能有一個audio session策略,你的所有的audio都需要遵循這個active策略的特點。如何響應中斷,在Audio Session Programming Guide`中有更加詳細的內容。

如果要測試Audio session,需要使用真機


Playback using the AVAudioPlayer Class

AVAudioPlayer提供了簡單的OC接口用于audio播放。如果非網絡stream,或者需要精確控制,apple推薦使用這個類,它可以用于播放iOS支持的任何audio format,同時這個類并不需要去設置audio session,因為它會在中斷發生以后自動恢復播放,除非你需要指定特地的行為。

它可以完成以下工作:

Play sounds of any durationPlay sounds from files or memory buffersLoop soundsPlay multiple sounds simultaneouslyControl relative playback level for each sound you are playingSeek to a particular point in a sound file, which supports such application features as fast forward and rewindObtain data that you can use for audio level metering

下面就是使用AVAudioPlayer的具體流程:

Configuring an AVAudioPlayer object
12345678910111213141516
NSString *soundFilePath =                [[NSBundle mainBundle] pathForResource: @"sound"                                                ofType: @"wav"]; NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath]; AVAudioPlayer *newPlayer =                [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL                                                       error: nil];[fileURL release]; self.player = newPlayer;[newPlayer release]; [self.player prepareToPlay];[self.player setDelegate: self];

你的delegate對象用于處理interruptions或者音頻播放停止以后的操作。

Implementing an AVAudioPlayer delegate method
123456
- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) player                        successfully: (BOOL) flag {    if (flag == YES) {        [self.button setTitle: @"Play" forState: UIControlStateNormal];    }}
Controlling an AVAudioPlayer object
123456789101112131415
- (IBAction) playOrPause: (id) sender {     // if already playing, then pause    if (self.player.playing) {        [self.button setTitle: @"Play" forState: UIControlStateHighlighted];        [self.button setTitle: @"Play" forState: UIControlStateNormal];        [self.player pause];     // if stopped or paused, start playing    } else {        [self.button setTitle: @"Pause" forState: UIControlStateHighlighted];        [self.button setTitle: @"Pause" forState: UIControlStateNormal];        [self.player play];    }}

Recording and Playback using Audio Queue Services

Audio Queue Services是一個更加直觀的record和play audio的方式。同時它還有更多個高級功能,可以使用這個服務完成更多的工作,比如對LPCM數據進行壓縮等等。它和AVAudioPlayer是iOS中唯二可以播放壓縮后音頻格式的接口。使用Audio Queue Service播放和錄音都是通過回調方法完成的。

Creating an Audio Queue Object

為了創建Audio Queue對象,它分成兩類:

AudioQueueNewInput用于錄音AudioQueueNewOutput用于播放

使用audio queue object播放audio file,需要一些幾個步驟:

創建數據結構用于管理audio queue需要的信息,例如audio format,audio fileID等。定義callback函數,用于管理audio queue buffers。callback會使用Audio File Service去讀取audio file用來播放使用AudioQueueNewOutput用來播放audio file。

Creating an audio queue object具體的代碼如下:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
static const int kNumberBuffers = 3;// Create a data structure to manage information needed by the audio queuestruct myAQStruct {    AudioFileID                     mAudioFile;    CAStreamBasicDescription        mDataFormat;    AudioQueueRef                   mQueue;    AudioQueueBufferRef             mBuffers[kNumberBuffers];    SInt64                          mCurrentPacket;    UInt32                          mNumPacketsToRead;    AudioStreamPacketDescription    *mPacketDescs;    bool                            mDone;};// Define a playback audio queue callback functionstatic void AQTestBufferCallback(    void                   *inUserData,    AudioQueueRef          inAQ,    AudioQueueBufferRef    inCompleteAQBuffer) {    myAQStruct *myInfo = (myAQStruct *)inUserData;    if (myInfo->mDone) return;    UInt32 numBytes;    UInt32 nPackets = myInfo->mNumPacketsToRead;     AudioFileReadPackets (        myInfo->mAudioFile,        false,        &numBytes,        myInfo->mPacketDescs,        myInfo->mCurrentPacket,        &nPackets,        inCompleteAQBuffer->mAudioData    );    if (nPackets > 0) {        inCompleteAQBuffer->mAudioDataByteSize = numBytes;        AudioQueueEnqueueBuffer (            inAQ,            inCompleteAQBuffer,            (myInfo->mPacketDescs ? nPackets : 0),            myInfo->mPacketDescs        );        myInfo->mCurrentPacket += nPackets;    } else {        AudioQueueStop (            myInfo->mQueue,            false        );        myInfo->mDone = true;    }}// Instantiate an audio queue objectAudioQueueNewOutput (    &myInfo.mDataFormat,    AQTestBufferCallback,    &myInfo,    CFRunLoopGetCurrent(),    kCFRunLoopCommonModes,    0,    &myInfo.mQueue);

Controlling Audio Queue Playback Level

Audio Queue對象提供了兩個方式控制音頻level。第一種是直接使用AudioQueueSetParameter以及kAudioQueueParam_Volume參數,就可以設置,設置完成以后會立即生效。

123456
Float32 volume = 1;AudioQueueSetParameter (    myAQstruct.audioQueueObject,    kAudioQueueParam_Volume,    volume);

也可以通過AudioQueueEnqueueBufferWithParameters給audio queue buffer設置。這種方式只有在audio queue buffer 開始播放時候才起作用。

Indicating Audio Queue Playback Level

你也可以直接查詢audio queue的kAudioQueueProperty_CurrentLevelMeterDB屬性,得到的值是一組AudioQueueLevelMeterState結構體(一個channel一個數組),具體的結構體是AudioQueueLevelMeterState,顯示如下:

1234
typedef struct AudioQueueLevelMeterState {    Float32     mAveragePower;    Float32     mPeakPower;};  AudioQueueLevelMeterState;

System Sounds: Alerts and Sound Effects

如果你需要播放的音頻時間少于30s,那么可以使用System Sound Services。調用AudioServicesPlaySystemSound函數可以立即播放一個sound file。你也可以調用AudioServicesPlayAlertSound播放alert聲音。這兩個方法都會在手機靜音的情況下振動。

當然,你也在調用AudioServicesPlaySystemSound方法使用kSystemSoundID_Vibrate屬性,顯示的觸發振動。

為了使用AudioServicesPlaySystemSound方法播放sound,首先需要將sound file注冊到系統中,得到一個sound ID,然后才能播放。

下面一段代碼顯示了使用System Sound Services去play sound:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
#include <AudioToolbox/AudioToolbox.h>#include <CoreFoundation/CoreFoundation.h> // Define a callback to be called when the sound is finished// playing. Useful when you need to free memory after playing.static void MyCompletionCallback (    SystemSoundID  mySSID,    void * myURLRef) {        AudioServicesDisposeSystemSoundID (mySSID);        CFRelease (myURLRef);        CFRunLoopStop (CFRunLoopGetCurrent());} int main (int argc, const char * argv[]) {    // Set up the pieces needed to play a sound.    SystemSoundID    mySSID;    CFURLRef        myURLRef;    myURLRef = CFURLCreateWithFileSystemPath (        kCFAllocatorDefault,        CFSTR ("../../ComedyHorns.aif"),        kCFURLPOSIXPathStyle,        FALSE    );     // create a system sound ID to represent the sound file    OSStatus error = AudioServicesCreateSystemSoundID (myURLRef, &mySSID);     // Register the sound completion callback.    // Again, useful when you need to free memory after playing.    AudioServicesAddSystemSoundCompletion (        mySSID,        NULL,        NULL,        MyCompletionCallback,        (void *) myURLRef    );     // Play the sound file.    AudioServicesPlaySystemSound (mySSID);     // Invoke a run loop on the current thread to keep the application    // running long enough for the sound to play; the sound completion    // callback later stops this run loop.    CFRunLoopRun ();    return 0;}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美老女人性视频| 粉嫩av一区二区三区免费野| 欧美另类高清videos| 日韩电视剧在线观看免费网站| 欧美老妇交乱视频| 成人精品aaaa网站| 日本19禁啪啪免费观看www| 国产精品国产三级国产aⅴ浪潮| 亚洲欧洲日产国码av系列天堂| 精品中文字幕乱| 国产精品无av码在线观看| 亚洲一区二区三区成人在线视频精品| 欧美日韩国产一区在线| 国产成+人+综合+亚洲欧洲| 亚洲国产精品电影在线观看| 亚洲精品97久久| 欧美乱大交做爰xxxⅹ性3| 欧美激情中文网| 亚洲一区二区久久久久久久| 久久久国产精品免费| 国产精品高潮呻吟久久av无限| 黑人巨大精品欧美一区二区一视频| 黑人巨大精品欧美一区免费视频| 亚洲欧洲免费视频| 久久免费视频网| 国产婷婷色综合av蜜臀av| 欧美精品在线观看| 精品福利在线视频| 成人激情综合网| 91久久精品国产91性色| 91av视频在线播放| 色www亚洲国产张柏芝| 日韩在线不卡视频| 国产精品爽黄69天堂a| 日韩av网站导航| 国产综合色香蕉精品| 日韩在线视频国产| 国外色69视频在线观看| 欧美日韩激情视频| 亚洲第五色综合网| 97久久国产精品| 亚洲国产中文字幕在线观看| 国产精品男人的天堂| 国产自产女人91一区在线观看| 国产激情综合五月久久| 欧美日韩在线影院| 亚洲欧美日韩网| 精品福利免费观看| 亚洲免费视频网站| 亚洲欧美国产精品专区久久| 欧美性猛交xxxx富婆| 欧美日韩一区二区在线| 日韩欧美999| 欧美黑人一级爽快片淫片高清| 8x拔播拔播x8国产精品| 91手机视频在线观看| 69av成年福利视频| 欧美丰满片xxx777| 日韩成人av网址| 国产精品入口夜色视频大尺度| 青青草成人在线| 亚洲国产欧美自拍| 国产精品白丝av嫩草影院| 亚洲国产99精品国自产| 91久久在线观看| 亚洲精品午夜精品| 久热精品视频在线观看| 77777亚洲午夜久久多人| 亚洲欧洲一区二区三区在线观看| 热99精品里视频精品| 亚洲欧美另类自拍| 久久精视频免费在线久久完整在线看| 91日本在线视频| 韩国v欧美v日本v亚洲| 欧美激情综合色综合啪啪五月| 日韩精品中文字幕在线播放| 蜜臀久久99精品久久久久久宅男| 日韩精品日韩在线观看| 中文字幕精品久久久久| 亚洲精品综合精品自拍| 久久综合五月天| 最近2019中文字幕第三页视频| 成人国产亚洲精品a区天堂华泰| 久久国产精品久久国产精品| 日韩欧美一区二区三区| 亚洲国产精品久久久久秋霞不卡| 国产精品久久av| 美女性感视频久久久| 91爱视频在线| 亚洲午夜av久久乱码| 欧美丝袜一区二区三区| 伊人亚洲福利一区二区三区| 色悠悠久久久久| 一区二区三区四区视频| 日本韩国欧美精品大片卡二| 色阁综合伊人av| 国精产品一区一区三区有限在线| 欧美日韩一区二区精品| 精品视频—区二区三区免费| 亚洲日韩中文字幕| 国产精品扒开腿做爽爽爽视频| 色综合导航网站| 97国产精品人人爽人人做| 91在线观看免费网站| 中文字幕欧美在线| 欧美激情在线视频二区| 国产精品aaaa| 国产aⅴ夜夜欢一区二区三区| 色偷偷888欧美精品久久久| 668精品在线视频| 国产精品精品视频| 国产精品视频专区| 日韩精品视频在线播放| 国产在线观看精品一区二区三区| 国产69久久精品成人看| 亚洲人成电影网站色| 欧美精品18videos性欧美| 精品国产拍在线观看| 久久中文字幕视频| 富二代精品短视频| 久久99精品视频一区97| 91av中文字幕| 九九九热精品免费视频观看网站| 欧美午夜精品久久久久久浪潮| 欧美有码在线视频| 国产精品爱啪在线线免费观看| 日韩精品中文字| 日韩高清免费在线| 久久久久久久久中文字幕| 精品无码久久久久久国产| 国产精品吊钟奶在线| 成人a视频在线观看| 亚洲精品美女在线观看| 久久久国产视频91| 国产精品视频内| 精品激情国产视频| 久久免费成人精品视频| 亚洲一级黄色av| 欧美国产精品人人做人人爱| 欧美在线不卡区| 亚洲成年网站在线观看| 欧美日韩中文字幕日韩欧美| 亚洲人成在线一二| 国产精品入口夜色视频大尺度| 亚洲福利影片在线| 91精品国产乱码久久久久久蜜臀| 美女视频黄免费的亚洲男人天堂| 日韩视频中文字幕| 日韩av在线一区二区| 欧美综合第一页| 一本色道久久88精品综合| 美女扒开尿口让男人操亚洲视频网站| 91久久精品国产91久久性色| 国产精品一久久香蕉国产线看观看| 国产精品黄色影片导航在线观看| 久久久久久久国产| 成人亲热视频网站| 成人黄色av免费在线观看| 欧美日韩视频在线| 欧美一乱一性一交一视频| 欧美在线视频在线播放完整版免费观看| 欧美精品一本久久男人的天堂| 欧美黄色小视频| 亚洲91精品在线|