DirectShow как управлять аудио потоками?
От: Аноним  
Дата: 08.06.08 05:13
Оценка:
Вот такой граф создается когда открываю файл.

Вопрос в том как управлять аудио потоками?(т.е. как сделать, чтобы при нажатии кнопки переключать аудио дорожки)
Когда граф запускается проигрывается и первая и вторая, возможно ли сделать так, чтобы при запуске громкость второй дорожки была 0.
Граф строится примерно так:

procedure TForm1.VideoPlay;
var
 pSourceFilter : IBaseFilter;
 I             : Integer;
begin
 FilterGraph.Active := True;
 FilterGraph.ClearGraph;
 CoCreateInstance(CLSID_MKVSource, nil,CLSCTX_INPROC, IID_IBASEFilter, pSourceFilter);
 (FilterGraph as IGraphBuilder).AddFilter(pSourceFilter, StringToOleStr(FFileName));
 (pSourceFilter as IFileSourceFilter).Load(StringToOleStr(FFileName),nil);
 with TPinList.Create(pSourceFilter) do
  try
   for I := 0 to Count - 1 do
   if PinInfo[I].dir = PINDIR_OUTPUT then
   (FilterGraph as IGraphBuilder).Render(Items[I])
  finally
   Free;
  end;
 FilterGraph.Play;
end;
Re: DirectShow как управлять аудио потоками?
От: Аноним  
Дата: 08.06.08 09:22
Оценка:
Здравствуйте, Аноним:

А можно узнать — что за исходный файл ?
Re: DirectShow как управлять аудио потоками?
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 08.06.08 09:25
Оценка:
Я бы получил у аудио рендереров интерфейсы IBasicAudio и дергал бы put_Volume. Это теоретически, сам не пробовал.
Re[2]: DirectShow как управлять аудио потоками?
От: XoSteL  
Дата: 09.06.08 07:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А можно узнать — что за исходный файл ?

Если вы про фильтр, то Haali Simple Media Splitter, а файл фильм в формате MKV.
Re[2]: DirectShow как управлять аудио потоками?
От: XoSteL  
Дата: 09.06.08 07:43
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Я бы получил у аудио рендереров интерфейсы IBasicAudio и дергал бы put_Volume. Это теоретически, сам не пробовал.

Спасибо буду пробовать.
Re[2]: DirectShow как управлять аудио потоками?
От: XoSteL  
Дата: 09.06.08 14:31
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Я бы получил у аудио рендереров интерфейсы IBasicAudio и дергал бы put_Volume. Это теоретически, сам не пробовал.

А как мне найти аудио рендереры в графе? Есть функция FindAudioRenderer, но как ее использовать, чтобы узнать количество аудио рендереров?
Я пока еще учусь и буду рад примеру или помощи
Re[3]: DirectShow как управлять аудио потоками?
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 10.06.08 06:52
Оценка:
Здравствуйте, XoSteL, Вы писали:

XSL>А как мне найти аудио рендереры в графе?


Сразу после построения цепочки фильтров для данного пина пройдите по ней до конца (придется написать вспомогательную функцию, которая у выходного пина будет узнавать к кому он подсоединен, а у фильтров будет узнавать выходной пин). Так будет ясно, какой рендерер к какому пину относится. Потому что другой вариант — через EnumFilters — такой информации не даст.
Re[4]: DirectShow как управлять аудио потоками?
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 10.06.08 07:09
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Здравствуйте, XoSteL, Вы писали:


XSL>>А как мне найти аудио рендереры в графе?


DM>Так будет ясно, какой рендерер к какому пину относится. Потому что другой вариант — через EnumFilters — такой информации не даст.


но ведь можно через EnumFilters, пробежаться по каждому фильтру и проверить его на наличие IBasicAudio
Re[5]: DirectShow как управлять аудио потоками?
От: XoSteL  
Дата: 10.06.08 10:27
Оценка:
Вот Функции:
function FindRenderer, function FindAudioRenderer, function FindVideoRenderer, function CountFilterPins.
function FindRenderer(pGB: IGraphBuilder; const mediatype: PGUID; out ppFilter: IBaseFilter): HRESULT;
var
  Enum  : IEnumFilters;
  Filter: IBaseFilter;
  Pin   : IPin;
  Fetched,
  InPins,
  OutPins: Cardinal;
  Found: Boolean;
  MediaType_: TAMMediaType;
begin
  Found := False;

  // Verify graph builder interface
  if not Assigned(pGB) then
  begin
    Result := E_NOINTERFACE;
    Exit;
  end;

  // Verify that a media type was passed
  if not Assigned(mediatype) then
  begin
    Result := E_POINTER;
    Exit;
  end;

  // Clear the filter pointer in case there is no match
  if Assigned(@ppFilter) then ppFilter := nil;

  // Get filter enumerator
  Result := pGB.EnumFilters(Enum);
  if FAILED(Result) then Exit;

  Enum.Reset;

  // Enumerate all filters in the graph
  while((not Found) and  (Enum.Next(1, Filter, @Fetched) = S_OK)) do
  begin
    // Find a filter with one input and no output pins
    Result := CountFilterPins(Filter, InPins, OutPins);
    if FAILED(Result) then break;

    if ((InPins = 1) and (OutPins = 0)) then
    begin
      // Get the first pin on the filter
      Pin := nil;
      Pin := GetInPin(Filter, 0);

      // Read this pin's major media type
      Result := Pin.ConnectionMediaType(MediaType_);
      if FAILED(Result) then  break;

      // Is this pin's media type the requested type?
      // If so, then this is the renderer for which we are searching.
      // Copy the interface pointer and return.
      if IsEqualGUID(MediaType_.majortype,mediatype^) then
      begin
        // Found our filter
        ppFilter := Filter;
        Found := True;
      end else
      begin
        // This is not the renderer, so release the interface.
        Filter := nil;
      end;

      // Delete memory allocated by ConnectionMediaType()
      UtilFreeMediaType(@MediaType_);
    end else
    begin
      // No match, so release the interface
      Filter := nil;
    end;
  end;

  Enum := nil;
end;

function FindAudioRenderer(pGB: IGraphBuilder; out ppFilter: IBaseFilter): HRESULT;
begin
  Result := FindRenderer(pGB, @MEDIATYPE_Audio, ppFilter);
end;

function FindVideoRenderer(pGB: IGraphBuilder; out ppFilter: IBaseFilter): HRESULT;
begin
  Result := FindRenderer(pGB, @MEDIATYPE_Video, ppFilter);
end;

function CountFilterPins(pFilter: IBaseFilter; out pulInPins: Cardinal; out pulOutPins: Cardinal): HRESULT;
var
  Enum: IEnumPins;
  Found: Cardinal;
  Pin: IPin;
  PinDir: TPinDirection;
begin
  // Verify input
  if (not Assigned(pFilter) or not Assigned(@pulInPins) or not Assigned(@pulOutPins)) then
  begin
    Result := E_POINTER;
    Exit;
  end;

  // Clear number of pins found
  pulInPins := 0;
  pulOutPins := 0;

  // Get pin enumerator
  Result := pFilter.EnumPins(Enum);
  if FAILED(Result) then Exit;

  Enum.Reset;

  // Count every pin on the filter
  while(S_OK = Enum.Next(1, Pin, @Found)) do
  begin
    Result := Pin.QueryDirection(PinDir);
    if (PinDir = PINDIR_INPUT) then inc(pulInPins)
                               else inc(pulOutPins);
    Pin := nil;
  end;

  Enum := nil;
end;

Как использовать функцию FindAudioRenderer?
Re[5]: DirectShow как управлять аудио потоками?
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 10.06.08 10:46
Оценка:
Здравствуйте, dabeat_bf, Вы писали:

_>но ведь можно через EnumFilters, пробежаться по каждому фильтру и проверить его на наличие IBasicAudio


А как узнать какой рендерер к какому потоку звука относится?
Re[6]: DirectShow как управлять аудио потоками?
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 10.06.08 10:55
Оценка:
Здравствуйте, XoSteL, Вы писали:

XSL>Как использовать функцию FindAudioRenderer?


Выбросить в помойку. Она возвращает первый попавшийся фильтр, принимающий аудио. Иногда в самых простых случаях это рендерер, но легко может быть и кодек или какой-нибудь конвертер. В общем, не рекомендую ее использовать.
Re[6]: DirectShow как управлять аудио потоками?
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 10.06.08 11:03
Оценка:
Здравствуйте, XoSteL, Вы писали:

XSL>Вот Функции:

... все погрыз бобер...
XSL>Как использовать функцию FindAudioRenderer?

ну как брать и вызывать эту функцию )))

что в стиле (я так понимаю вы DsPack используете?)

procedure BlahBlahBlah()
var arenderer : IBaseFilter
begin
  FindAudioRenderer(FilterGraps as IGraphBuilder, arenderer);
End;


но вот проблема, если у вас больше одного рендерера то вы эта функция будет всегда вам возвращать один и тот же рендерер!
Re[6]: DirectShow как управлять аудио потоками?
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 10.06.08 11:11
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Здравствуйте, dabeat_bf, Вы писали:


_>>но ведь можно через EnumFilters, пробежаться по каждому фильтру и проверить его на наличие IBasicAudio


DM>А как узнать какой рендерер к какому потоку звука относится?

хм... дилемма, как-то не обратил на это внимание... нет конечно можно теоретически рендерить пин запускать функцию поиска нового рендерера... но это так идея, чтоб ну совсем не хоронить мою прошлую идею
Re[2]: DirectShow как управлять аудио потоками?
От: XoSteL  
Дата: 06.07.08 15:48
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Я бы получил у аудио рендереров интерфейсы IBasicAudio и дергал бы put_Volume. Это теоретически, сам не пробовал.

Рендереры я нашел, теперь вопрос как ими управлять??? (т.е как можно изменять громкость каждого рендерера отдельно)

procedure TForm1.btASwitchClick(Sender: TObject);
var
i : integer;
FilterList : TFIlterList;
ClassID : TGUID;
begin
  try
   FilterList := TFilterList.Create(FilterGraph as IFilterGraph);
   for I := 0 to FilterList.Count - 1 do
   begin
   FilterList.Items[i].GetClassID(ClassID);
   if (IsEqualGUID(ClassID, CLSID_AudioRender)= True) or
      (IsEqualGUID(ClassID, CLSID_DSoundRender)= True) then
      begin
        //как здесь получить интерфейсы IBasicAudio и управлять ими????
      end;
   end;
  finally
   FilterList.Free;
  end;
end;
Re[3]: DirectShow как управлять аудио потоками?
От: Виктор Россия  
Дата: 07.07.08 05:22
Оценка:
Здравствуйте, XoSteL, Вы писали:

XSL>Здравствуйте, D. Mon, Вы писали:


DM>>Я бы получил у аудио рендереров интерфейсы IBasicAudio и дергал бы put_Volume. Это теоретически, сам не пробовал.

XSL>Рендереры я нашел, теперь вопрос как ими управлять??? (т.е как можно изменять громкость каждого рендерера отдельно)

XSL>
XSL>procedure TForm1.btASwitchClick(Sender: TObject);
XSL>var
XSL>i : integer;
XSL>FilterList : TFIlterList;
XSL>ClassID : TGUID;
XSL>begin
XSL>  try
XSL>   FilterList := TFilterList.Create(FilterGraph as IFilterGraph);
XSL>   for I := 0 to FilterList.Count - 1 do
XSL>   begin
XSL>   FilterList.Items[i].GetClassID(ClassID);
XSL>   if (IsEqualGUID(ClassID, CLSID_AudioRender)= True) or
XSL>      (IsEqualGUID(ClassID, CLSID_DSoundRender)= True) then
XSL>      begin
XSL>        //как здесь получить интерфейсы IBasicAudio и управлять ими????
XSL>      end;
XSL>   end;
XSL>  finally
XSL>   FilterList.Free;
XSL>  end;
XSL>end;
XSL>


у тебя есть объект, фильтр, который ты получил (с гуидом CLSID_DSoundRender).

IBasicAudio * m_pBasicAudio = NULL;

HRESULT hr = фильтр->QueryInterface(IID_IBasicAudio, (void **)&m_pBasicAudio);

if(SUCCEEDED(hr) && m_pBasicAudio)
{
long lVolume = 10;

m_pBasicAudio->put_Volume(lVolume);
}

по моему так. Может и не прав
Re[4]: DirectShow как управлять аудио потоками?
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 07.07.08 06:27
Оценка:
Здравствуйте, Виктор, Вы писали:

В>по моему так.


Так, только нужно не забыть зарелизить полученный интерфейс. В С++ лучше использовать CComPtr и CComQIPtr, тогда их деструкторы об этом позаботятся. Как в Дельфи — не в курсе.
Re[4]: DirectShow как управлять аудио потоками?
От: XoSteL  
Дата: 07.07.08 18:13
Оценка:
XSL>>Здравствуйте, D. Mon, Вы писали:


В>у тебя есть объект, фильтр, который ты получил (с гуидом CLSID_DSoundRender).


В>IBasicAudio * m_pBasicAudio = NULL;


В>HRESULT hr = фильтр->QueryInterface(IID_IBasicAudio, (void **)&m_pBasicAudio);


В>if(SUCCEEDED(hr) && m_pBasicAudio)

В>{
В> long lVolume = 10;

В> m_pBasicAudio->put_Volume(lVolume);

В>}

В>по моему так. Может и не прав



В>HRESULT hr = фильтр->QueryInterface(IID_IBasicAudio, (void **)&m_pBasicAudio);


//Если сделать так?
FilterList.Items[i].QueryInterface(IID_IBasicAudio, pBasicAudio);
//Значит я смогу получить интерфейсы IBasicAudio для всех рендереров????
// если так , то как можно можно управлять гомкостью дорожек используя индекс рендереров???
Re[5]: DirectShow как управлять аудио потоками?
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 08.07.08 04:16
Оценка:
Здравствуйте, XoSteL, Вы писали:

XSL>// если так , то как можно можно управлять гомкостью дорожек используя индекс рендереров???


Если угодно по индексу рендереров — сделайте массив, содержащий указатели на IBasicAudio для каждого рендерера, и по индексу к ним обращайтесь.
Re[6]: DirectShow как управлять аудио потоками?
От: XoSteL  
Дата: 14.07.08 18:37
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Здравствуйте, XoSteL, Вы писали:


XSL>>// если так , то как можно можно управлять гомкостью дорожек используя индекс рендереров???


DM>Если угодно по индексу рендереров — сделайте массив, содержащий указатели на IBasicAudio для каждого рендерера, и по индексу к ним обращайтесь.


Вот так все работает


procedure TForm1.btASwitchClick(Sender: TObject);
var
 FilterList: TDSoundFilterList;
 pBasicAudio: IBasicAudio;
 i : integer;
begin
 i := btASwitch.Tag + 1;
 FilterList := TDSoundFilterList.Create(FilterGraph as IFiltergraph);
 try
   if i <> FilterList.Count then
   begin
      FilterGraph.QueryInterface(IID_IBasicAudio, pBasicAudio);
      pBasicAudio.put_Volume(-10000);
      btASwitch.Tag := btASwitch.Tag + 1;
      FilterList.Items[btASwitch.Tag].QueryInterface(IID_IBasicAudio, pBasicAudio);
      pBasicAudio.put_Volume(0);
      ShowMessage('Audio ' + IntToStr(i) +  ' из ' + IntToStr(FilterList.Count));
    end else
    begin
      FilterGraph.QueryInterface(IID_IBasicAudio, pBasicAudio);
      pBasicAudio.put_Volume(-10000);
      btASwitch.Tag := 0;
      FilterList.Items[btASwitch.Tag].QueryInterface(IID_IBasicAudio, pBasicAudio);
      pBasicAudio.put_Volume(0);
      ShowMessage('Audio ' + IntToStr(i) +  ' из ' + IntToStr(FilterList.Count));
    end;
 finally
   FilterList.Free;
 end;
end;


Может можно сделать проще??? Подскажите как
Re[7]: DirectShow как управлять аудио потоками?
От: squid  
Дата: 15.07.08 01:48
Оценка:
Здравствуйте, XoSteL, Вы писали:

а вы кстати выбор потоков через IAMStreamSelect учитываете? там ведь один пин на выходе сплитера, один рендерер его играющий, но нескольно аудои потоков, выбирающихся этим интерфейсом внутри сплиттера, возможно даже играющих одновременно.

конкретный пример — сплиттер Matroska от Haali.

может у вас старая его версия, если вы о нем писали про кучу пинов?

вобщем основная мысль — про IAMStreamSelect забывать не следует
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.