亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? dsoundrenderer.pas

?? 一套及時通訊的原碼
?? PAS
字號:

    (*********************************************************************
     *                                                                   *
     * The contents of this file are used with permission, subject to    *
     * the Mozilla Public License Version 1.1 (the "License"); you may   *
     * not use this file except in compliance with the License. You may  *
     * obtain a copy of the License at                                   *
     * http://www.mozilla.org/MPL/MPL-1.1.html                           *
     *                                                                   *
     * Software distributed under the License is distributed on an       *
     * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or    *
     * implied. See the License for the specific language governing      *
     * rights and limitations under the License.                         *
     *                                                                   *
     * (C) 2004 Milenko Mitrovic <dcoder@dsp-worx.de>                    *
     *                                                                   *
     *********************************************************************)

unit DSoundRenderer;

interface
uses
  BaseClass, DirectSound, ActiveX, Math, Windows, SysUtils, Classes,
  DirectShow9, MMSystem, PropSettings, DSoundDevices, DSUtil;

const
  CLSID_DelphiDSoundRenderer: TGUID = '{093A27B5-3AA1-4375-9389-71EB9D62BA97}';

  PREBUFFER_SIZE_MS = 1500; // Buffersize in MilliSeconds of PreBuffering
  BUFFER_SIZE_MS    = 5000; // Buffersize in MilliSeconds

type
  TDelphiDSoundRenderer = class(TBCBaseRenderer, IReferenceClock, IBasicAudio,
                                IPersist, IMediaFilter, ISpecifyPropertyPages)
  private
    fDispatch : TBCBaseDispatch;
    fFormat : TWaveFormatExtensible;
    fCurrentBufferSize : DWORD;
    fPreBufferSize : DWORD;
    fRefClock : TBCSystemClock;
    fVolume : integer;
    fBalance : integer;
    fDevice : IDirectSound8;
    fBuffer : IDirectSoundBuffer8;
    fPos : DWORD;
    fBufferSize : DWORD;
    (*** Misc methods ***)
    function CreateDirectSoundBuffer(MediaType : PAMMediaType) : HRESULT;
  public
    (*** TBCBaseRenderer methods ***)
    constructor Create(ObjName: String; Unk: IUnknown; out hr : HResult);
    constructor CreateFromFactory(Factory: TBCClassFactory; const Controller: IUnknown); override;
    destructor Destroy; override;
    function CheckMediaType(MediaType: PAMMediaType): HResult; override;
    function DoRenderSample(MediaSample: IMediaSample): HResult; override;
    function SetMediaType(MediaType: PAMMediaType): HResult; override;
    function Run(StartTime: TReferenceTime): HResult; override; stdcall;
    function Stop: HResult; override; stdcall;
    function Pause: HResult; override; stdcall;
    function Receive(MediaSample: IMediaSample): HResult; override;
    function BeginFlush: HResult; override;
    function PrepareReceive(MediaSample: IMediaSample): HResult; override;
    (*** IDispatch methods ***)
    function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
    function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
    function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
    function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
    (*** IBasicAudio methods ***)
    function put_Volume(lVolume: Longint): HResult; stdcall;
    function get_Volume(out plVolume: Longint): HResult; stdcall;
    function put_Balance(lBalance: Longint): HResult; stdcall;
    function get_Balance(out plBalance: Longint): HResult; stdcall;
    (*** IReferenceClock methods ***)
    function GetTime(out pTime: int64): HResult; stdcall;
    function AdviseTime(rtBaseTime, rtStreamTime: int64; hEvent: THandle; out pdwAdviseCookie: DWORD): HResult; stdcall;
    function AdvisePeriodic(const rtStartTime, rtPeriodTime: int64; hSemaphore: THandle; out pdwAdviseCookie: DWORD): HResult; stdcall;
    function Unadvise(dwAdviseCookie: DWORD): HResult; stdcall;
    (*** ISpecifyPropertyPages methods ***)
    function GetPages(out pages: TCAGUID): HResult; stdcall;
  end;

implementation
{*** IDispatch methods *** taken from CBasicAudio *** ctlutil.cpp *************}
function TDelphiDSoundRenderer.GetTypeInfoCount(out Count: Integer): HResult; stdcall;
begin
  Result := fDispatch.GetTypeInfoCount(Count);
end;

function TDelphiDSoundRenderer.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
begin
  Result := fDispatch.GetTypeInfo(IID_IBasicAudio,Index,LocaleID,TypeInfo);
end;

function TDelphiDSoundRenderer.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
begin
  Result := fDispatch.GetIDsOfNames(IID_IBasicAudio,Names,NameCount,LocaleID,DispIDs);
end;

function TDelphiDSoundRenderer.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
var
  pti : ITypeInfo;
begin
  if not IsEqualGUID(GUID_NULL,IID) then
  begin
    Result := DISP_E_UNKNOWNINTERFACE;
    Exit;
  end;

  Result := GetTypeInfo(0, LocaleID, pti);

  if FAILED(Result) then Exit;

  Result :=  pti.Invoke(Pointer(Self as IBasicAudio),DispID,Flags,
                        TDispParams(Params),VarResult,ExcepInfo,ArgErr);
  pti := nil;
end;
{*** IBasicAudio methods ******************************************************}
function TDelphiDSoundRenderer.put_Volume(lVolume: Longint): HResult; stdcall;
begin
  fVolume := EnsureRange(lVolume,-10000,0);
  if Assigned(fBuffer) then fBuffer.SetVolume(fVolume);
  Result := S_OK;
end;

function TDelphiDSoundRenderer.get_Volume(out plVolume: Longint): HResult; stdcall;
begin
  plVolume := fVolume;
  Result := S_OK;
end;

function TDelphiDSoundRenderer.put_Balance(lBalance: Longint): HResult; stdcall;
begin
  fBalance := EnsureRange(lBalance,-10000,10000);
  if Assigned(fBuffer) then fBuffer.SetPan(fBalance);
  Result := S_OK;
end;

function TDelphiDSoundRenderer.get_Balance(out plBalance: Longint): HResult; stdcall;
begin
  plBalance := fBalance;
  Result := S_OK;
end;
{*** IReferenceClock methods **************************************************}
function TDelphiDSoundRenderer.GetTime(out pTime: int64): HResult; stdcall;
begin
  Result := fRefClock.GetTime(pTime);
end;

function TDelphiDSoundRenderer.AdviseTime(rtBaseTime, rtStreamTime: int64; hEvent: THandle; out pdwAdviseCookie: DWORD): HResult; stdcall;
begin
  Result := fRefClock.AdviseTime(rtBaseTime,rtStreamTime,hEvent,pdwAdviseCookie);
end;

function TDelphiDSoundRenderer.AdvisePeriodic(const rtStartTime, rtPeriodTime: int64; hSemaphore: THandle; out pdwAdviseCookie: DWORD): HResult; stdcall;
begin
  Result := fRefClock.AdvisePeriodic(rtStartTime,rtPeriodTime,hSemaphore,pdwAdviseCookie);
end;

function TDelphiDSoundRenderer.Unadvise(dwAdviseCookie: DWORD): HResult; stdcall;
begin
  Result := fRefClock.Unadvise(dwAdviseCookie);
end;
{*** ISpecifyPropertyPages methods ********************************************}
function TDelphiDSoundRenderer.GetPages(out pages: TCAGUID): HResult; stdcall;
begin
  Pages.cElems := 1;
  Pages.pElems := CoTaskMemAlloc(sizeof(TGUID) * Pages.cElems);
  if (Pages.pElems = nil) then
  begin
    Result := E_OUTOFMEMORY;
    Exit;
  end;
  Pages.pElems^[0] := CLSID_PropPageSettings;
  Result := S_OK;
end;
{*** TBCBaseRenderer methods **************************************************}
constructor TDelphiDSoundRenderer.Create(ObjName: String; Unk: IUnknown; out hr: HResult);
var
  Res : HRESULT;
  Guid : TGUID;
begin
  inherited Create(CLSID_DelphiDSoundRenderer, 'Delphi DirectSound Renderer', Unk, hr);
  Guid := GetSavedDevice;
  Res := DirectSoundCreate8(@Guid,fDevice,nil);
  if (Res <> DS_OK) or not Assigned(fDevice) then
  begin
    hr := E_FAIL;
    Exit;
  end;
  fDevice.SetCooperativeLevel(GetDesktopWindow,DSSCL_PRIORITY);
  fDispatch := TBCBaseDispatch.Create;
  fRefClock := TBCSystemClock.Create('TBCSystemClock',nil,hr);
  fPos := 0;
  fVolume := 0;
  fBalance := 0;
  fCurrentBufferSize := 0;
end;

constructor TDelphiDSoundRenderer.CreateFromFactory(Factory: TBCClassFactory;  const Controller: IUnknown);
var
  hr: HRESULT;
begin
  Create(Factory.Name, Controller, hr);
end;

destructor TDelphiDSoundRenderer.Destroy;
begin
  if Assigned(fBuffer) then fBuffer := nil;
  if Assigned(fDevice) then fDevice := nil;
  if Assigned(fRefClock) then FreeAndNil(fRefClock);
  if Assigned(fDispatch) then FreeAndNil(fDispatch);
  inherited Destroy;
end;

function TDelphiDSoundRenderer.PrepareReceive(MediaSample: IMediaSample): HResult;
begin
  Result := inherited PrepareReceive(MediaSample);
  FSignalTime := FSignalTime + (PREBUFFER_SIZE_MS * UNITS div MILLISECONDS);
end;

function TDelphiDSoundRenderer.Receive(MediaSample: IMediaSample): HResult;
var
  lStatus : DWORD;
  mi, mo : TReferenceTime;
  lDelayMS : Int64;
begin
  if fPreBufferSize > fCurrentBufferSize then
  begin
    MediaSample.SetTime(nil,nil);
    fCurrentBufferSize := fCurrentBufferSize + int64(MediaSample.GetActualDataLength);
    Result := inherited Receive(MediaSample);
    Exit;
  end;

  if MediaSample.GetTime(mi,mo) = S_OK then
  begin
    lDelayMS := fCurrentBufferSize * UNITS div fFormat.Format.nAvgBytesPerSec;
    mo := mo - lDelayMS;
    mi := mi - lDelayMS;
    MediaSample.SetTime(@mi,@mo);
  end;

  Result := inherited Receive(MediaSample);
  if fPreBufferSize < fCurrentBufferSize then
  begin
    if Assigned(fBuffer) then
    begin
      fBuffer.GetStatus(lStatus);
      if lStatus and DSBSTATUS_PLAYING = 0 then
      begin
        if (FState = State_Running) and Assigned(fBuffer)
          then fBuffer.Play(0,0,DSBPLAY_LOOPING);
      end;
    end;
  end;
end;

function TDelphiDSoundRenderer.BeginFlush: HResult;
begin
  fBuffer.Stop;
  fPos := 0;
  fBuffer.SetCurrentPosition(0);
  fCurrentBufferSize := 0;
  Result := inherited BeginFlush;
end;

function TDelphiDSoundRenderer.Run(StartTime: TReferenceTime): HResult;
begin
  Result := inherited Run(StartTime);
end;

function TDelphiDSoundRenderer.Stop: HResult;
begin
  Result := inherited Stop;
  if Assigned(fBuffer) then fBuffer.Stop;
end;

function TDelphiDSoundRenderer.Pause: HResult;
begin
  Result := inherited Pause;
  if Assigned(fBuffer) then fBuffer.Stop;
end;

function TDelphiDSoundRenderer.CheckMediaType(MediaType: PAMMediaType): HResult;
begin
  if (MediaType = nil) then
  begin
    Result := E_POINTER;
    Exit;
  end;

  if not IsEqualGUID(MediaType.majortype, MEDIATYPE_Audio) or
     (not IsEqualGUID(MediaType.subtype, MEDIASUBTYPE_PCM) and
      not IsEqualGUID(MediaType.subtype, MEDIASUBTYPE_IEEE_FLOAT) and
      not IsEqualGUID(MediaType.subtype, MEDIASUBTYPE_DOLBY_AC3_SPDIF) and
      not IsEqualGUID(MediaType.subtype, MEDIASUBTYPE_RAW_SPORT) and
      not IsEqualGUID(MediaType.subtype, MEDIASUBTYPE_SPDIF_TAG_241h) and
      not IsEqualGUID(MediaType.subtype, MEDIASUBTYPE_DRM_Audio)) or
     not IsEqualGUID(MediaType.formattype, FORMAT_WaveFormatEx) then
  begin
    Result := E_INVALIDARG;
    Exit;
  end;

  Result := S_OK;
end;

function TDelphiDSoundRenderer.DoRenderSample(MediaSample: IMediaSample): HResult;
var
  pmt : PAMMediaType;
  Buffer : PByte;
  Size : Integer;
  hr : HRESULT;
  p1, p2 : Pointer;
  s1, s2 : Cardinal;
begin
  FLock.Lock;
  try
    if MediaSample.GetMediaType(pmt) = S_OK then
    begin
      hr := CheckMediaType(pmt);
      if hr = S_OK then hr := CreateDirectSoundBuffer(pmt);
      if hr <> DS_OK then
      begin
        Result := E_FAIL;
        Exit;
      end;
      fCurrentBufferSize := 0;
      fPos := 0;
    end;

    MediaSample.GetPointer(Buffer);
    Size := MediaSample.GetActualDataLength;

    if Assigned(fBuffer) then
    begin
      // Lock the Buffer
      hr := fBuffer.Lock(fPos,Size,p1,s1,p2,s2,0);

      // If the Buffer is lost, then Restore it and Lock it again
      if hr = DSERR_BUFFERLOST then
      begin
        fBuffer.Restore;
        fBuffer.Lock(fPos,Size,p1,s1,p2,s2,0);
      end;

      // store the next WriteCursor Position
      inc(fPos, Size);
      if fPos > fBufferSize then dec(fPos,  fBufferSize);

      // Copy the Buffer from the MediaSample to the Buffer(s)
      Move(Buffer^,p1^,s1);
      if s2 > 0 then Move(PChar(Buffer)[s1],p2^,s2);

      fBuffer.Unlock(p1,s1,p2,s2);
    end;
  finally
    fLock.UnLock;
  end;

  Result := NOERROR;
end;

function TDelphiDSoundRenderer.SetMediaType(MediaType: PAMMediaType): HResult;
begin
  if (MediaType = nil) then
  begin
    Result := E_POINTER;
    Exit;
  end;

  Result := CreateDirectSoundBuffer(MediaType);
end;

function TDelphiDSoundRenderer.CreateDirectSoundBuffer(MediaType : PAMMediaType) : HRESULT;
var
  lDesc : TDSBufferDesc;
  lBuffer : IDirectSoundBuffer;
begin
  fLock.Lock;
  try
    ZeroMemory(@lDesc,SizeOf(TDSBufferDesc));

    if Assigned(fBuffer) then
    begin
      fBuffer.Stop;
      fBuffer := nil;
    end;

    lDesc.dwSize := SizeOf(TDSBufferDesc);
    lDesc.dwFlags := DSBCAPS_GLOBALFOCUS or  DSBCAPS_CTRLFREQUENCY or DSBCAPS_CTRLVOLUME or DSBCAPS_CTRLPAN;

    lDesc.lpwfxFormat := CoTaskMemAlloc(MediaType.cbFormat);
    Move(MediaType.pbFormat^, lDesc.lpwfxFormat^ ,MediaType.cbFormat);
    lDesc.guid3DAlgorithm := GUID_NULL;
    fBufferSize  := PWaveformatEx(MediaType.pbFormat)^.nSamplesPerSec *
                    PWaveformatEx(MediaType.pbFormat)^.nChannels *
                    (PWaveformatEx(MediaType.pbFormat)^.wBitsPerSample div 8) *
                    BUFFER_SIZE_MS div 1000;

    lDesc.dwBufferBytes := fBufferSize;
    fPreBufferSize := PWaveformatEx(MediaType.pbFormat)^.nAvgBytesPerSec * PREBUFFER_SIZE_MS div 1000;

    Result := fDevice.CreateSoundBuffer(lDesc,lBuffer,nil);

    if (Result = DS_OK) and Assigned(lBuffer) then
    begin
      Result := lBuffer.QueryInterface(IID_IDirectSoundBuffer8,fBuffer);
      if (Result = DS_OK) and Assigned(fBuffer) then
      begin
        fBuffer.SetVolume(fVolume);
        fBuffer.SetPan(fBalance);
        fBuffer.GetFormat(@fFormat,SizeOf(fFormat), nil);
      end;
      lBuffer := nil;
    end;
  finally
    fLock.UnLock;
  end;
end;

initialization

  TBCClassFactory.CreateFilter(
    TDelphiDSoundRenderer, 'Delphi DirectSound Renderer', CLSID_DelphiDSoundRenderer,
    CLSID_AudioRendererCategory, MERIT_DO_NOT_USE, 0, nil
  );

end.

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产精品三级在线观看| 国产欧美日韩在线观看| 免费在线一区观看| 精品电影一区二区| 成人午夜视频在线| 亚洲一区二区三区中文字幕 | 777奇米四色成人影色区| 午夜不卡av在线| 久久精品免视看| 欧美日韩国产欧美日美国产精品| 免费在线看成人av| 亚洲色欲色欲www| 日韩一区二区三区视频| 一本色道久久综合亚洲91| 视频一区在线视频| 国产亚洲一区二区三区四区| 欧美日本国产视频| 白白色 亚洲乱淫| 国产酒店精品激情| 丝袜a∨在线一区二区三区不卡| 日本一区二区三区国色天香| 欧美精品1区2区3区| 国产在线视频精品一区| 怡红院av一区二区三区| 国产精品久久夜| 国产欧美日本一区二区三区| 欧美一区二区三区公司| 欧美日韩国产123区| 日本高清不卡视频| 欧美色综合网站| 9191成人精品久久| 日韩欧美国产午夜精品| 日韩免费高清av| 精品电影一区二区三区| 日韩精品一区二区三区在线播放| 欧美日韩精品一区二区三区| 91精品国产综合久久精品性色| 欧美日韩另类一区| 欧美一区二区人人喊爽| 国产亚洲成aⅴ人片在线观看| 久久久久久久久蜜桃| 最新欧美精品一区二区三区| 亚洲综合丝袜美腿| 免费观看一级特黄欧美大片| 国精产品一区一区三区mba桃花 | 91精品国产日韩91久久久久久| 欧美一级二级三级乱码| 国产精品国产成人国产三级| 亚洲国产另类av| 三级欧美在线一区| 国产经典欧美精品| 欧美色图12p| 国产精品麻豆欧美日韩ww| 一区二区三区91| 懂色av中文一区二区三区| 欧美日韩一区在线观看| 精品久久久久久最新网址| 一区二区三区视频在线观看| 精品一区二区三区不卡| 欧美精品vⅰdeose4hd| 亚洲乱码国产乱码精品精可以看 | 日韩欧美成人激情| 亚洲免费高清视频在线| 国产丶欧美丶日本不卡视频| 制服丝袜av成人在线看| 亚洲一区在线电影| 色综合天天天天做夜夜夜夜做| 久久久久久久综合色一本| 精品亚洲免费视频| 日韩一卡二卡三卡四卡| 免费亚洲电影在线| 91精品欧美综合在线观看最新| 亚洲va韩国va欧美va| 91在线视频播放地址| 国产日本亚洲高清| 久久99久国产精品黄毛片色诱| 欧美一区二区三区成人| 美腿丝袜在线亚洲一区| 亚洲精品一区二区三区99| 国产一区二区三区在线观看免费视频| 日韩一区二区三区三四区视频在线观看 | 国产综合色在线视频区| 2021中文字幕一区亚洲| 国产成人自拍在线| 亚洲色图在线播放| 欧美肥妇bbw| 国产91精品一区二区麻豆亚洲| 亚洲视频免费在线| 欧美夫妻性生活| 高清国产午夜精品久久久久久| 日韩理论片一区二区| 欧美综合久久久| 国产一区二区三区最好精华液| 中文字幕中文字幕一区二区| 欧美另类变人与禽xxxxx| 加勒比av一区二区| 天堂影院一区二区| 中文字幕中文字幕在线一区| 欧美色图12p| 国产**成人网毛片九色 | 国产黄色成人av| 首页国产欧美日韩丝袜| 日韩伦理免费电影| 日本一二三不卡| 欧美成人伊人久久综合网| 欧洲av一区二区嗯嗯嗯啊| 99久久夜色精品国产网站| 麻豆成人av在线| 美脚の诱脚舐め脚责91| 视频一区国产视频| 天堂精品中文字幕在线| 亚洲亚洲人成综合网络| 亚洲午夜日本在线观看| 亚洲小说春色综合另类电影| 亚洲午夜在线电影| 亚洲h在线观看| 午夜亚洲国产au精品一区二区| 亚洲三级在线观看| 亚洲国产另类av| 国产真实乱对白精彩久久| 国产99精品国产| 热久久国产精品| 亚洲国产精品成人综合| 欧美一区二区视频网站| 色偷偷久久一区二区三区| 国产一区二区影院| 久久99精品久久只有精品| 91精品蜜臀在线一区尤物| 97精品电影院| 欧美男人的天堂一二区| 精品国产免费久久| 国产精品卡一卡二| 欧美一级xxx| 日韩理论片网站| 麻豆传媒一区二区三区| 成人高清在线视频| 欧美一区二区高清| 日韩美女视频一区| 亚洲国产一区二区a毛片| 美洲天堂一区二卡三卡四卡视频 | 欧美午夜寂寞影院| 97se亚洲国产综合在线| 一区二区三区日韩精品视频| 香蕉加勒比综合久久| 日韩精品一区二| 中文字幕免费一区| 捆绑调教一区二区三区| 欧美日韩色综合| 亚洲欧美另类久久久精品| 国产精选一区二区三区| 91国在线观看| 国产欧美一区二区三区在线看蜜臀 | 欧美裸体bbwbbwbbw| 亚洲黄网站在线观看| 成人不卡免费av| 欧美激情一区二区三区| 国产成人亚洲精品青草天美| 日韩欧美国产午夜精品| 狠狠网亚洲精品| 国产亚洲一区二区三区四区| 久久精品国产99| 中文字幕在线不卡国产视频| 狠狠狠色丁香婷婷综合久久五月| 欧美色倩网站大全免费| 丝瓜av网站精品一区二区| 日韩一区二区三区视频在线 | 欧美一区二区视频免费观看| 亚洲成人自拍偷拍| 日韩欧美高清在线| av一区二区三区四区| 夜夜精品浪潮av一区二区三区 | 日韩欧美你懂的| 国产成人在线免费| 亚洲第一在线综合网站| 亚洲精品一区二区三区99| 成人av网站免费| 午夜精品福利一区二区三区蜜桃| 欧美精品一区二区三区蜜桃| 一本色道久久综合狠狠躁的推荐| 五月天婷婷综合| ...中文天堂在线一区| 欧美一级二级三级蜜桃| 色欧美乱欧美15图片| 国产一区二区三区美女| 亚洲与欧洲av电影| 亚洲欧洲性图库| www久久精品| 日韩无一区二区| 国产一区二区影院| 亚洲成人黄色小说| 亚洲日本乱码在线观看| 久久只精品国产| 26uuu亚洲婷婷狠狠天堂| 欧美三片在线视频观看| 91亚洲男人天堂| 91麻豆国产精品久久| 91色在线porny| www.99精品| 在线精品视频一区二区三四| 91首页免费视频|