Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.03.2017, 15:29   #1
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию Извлечение звуковой дорожки из видео с конвертацией в WAV

Искал информацию по работе со звуком и наткнулся на это:

Это тоже давно было нужно, но целенаправленно оно не находилось.
В общем, если собрать такую цепочку в GraphStudio, то всё работает. На выходе получается WAV-файл.
А если делать это в программе, то выдаётся ошибка.
Код:
  Result := CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER ,
                           IID_IGraphBuilder, pGraphBuilder);
  Result := CoCreateInstance(CLSID_CaptureGraphBuilder2, NIL,
                          CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
                         pCaptureGraphBuilder);
  pCaptureGraphBuilder.SetFiltergraph(pGraphBuilder);
  Result := pGraphBuilder.AddSourceFilter(StringToOleStr(Fn),'source',fsource);
  if Result <> S_OK then
  begin
    MessageBox(Application.Handle,'AddSourceFilter error','error', MB_ICONERROR);
    ClearGraph;
    Exit;
  end;


  Result :=  coCreateInstance(CLSID_ffdshowAudioDecoder, nil,
                                   CLSCTX_INPROC_SERVER,
                                   IID_IBaseFilter, faudiodecoder);

  Result :=  coCreateInstance(CLSID_FileWriter, nil,
                                   CLSCTX_INPROC_SERVER,
                                   IID_IFileSinkFilter2, pSink);

  Result := pSink.QueryInterface(IID_IBaseFilter, fwd);

  pGraphBuilder.AddFilter(fAudioDecoder,'decoder');
  pGraphBuilder.AddFilter(fWD,'wavedest');

  pSink.SetFileName('c:\test.wav',nil);

  Result := pCaptureGraphBuilder.RenderStream(nil, @mediatype_audio,
                       fSource, fAudioDecoder, fwd);
        case Result of
          S_OK:                ErrorCodeText := 'S_OK';
          VFW_S_NOPREVIEWPIN:  ErrorCodeText := 'VFW_S_NOPREVIEWPIN';
          E_FAIL:              ErrorCodeText := 'E_FAIL';
          E_INVALIDARG:        ErrorCodeText := 'E_INVALIDARG';
          E_POINTER:           ErrorCodeText := 'E_POINTER';
          VFW_E_NOT_IN_GRAPH:  ErrorCodeText := 'VFW_E_NOT_IN_GRAPH';
        else
          ErrorCodeText := IntToStr(Result);
        end;

  if Result <> 0 then
  begin
    ClearGraph;
    ShowMessage('fail');
    Exit;
  end;
А именно RenderStream() выдаёт код ошибки -2147220969. В гугле по этой ошибке мало инфы. А в случае с RenderStream() вообще ничего.

Последний раз редактировалось BLACK_RAIN; 22.03.2017 в 15:32.
BLACK_RAIN вне форума Ответить с цитированием
Старый 22.03.2017, 15:52   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

-2147220969 говорит, что система не нашла подходящей комбинации соединения для вашего графа.
Есть два основных варианта:
1. проблема в битности/установке фильтров 64битные и 32битные это отдельные компоненты
2. у вас проблема в графе - например, где сплиттер?
p51x вне форума Ответить с цитированием
Старый 22.03.2017, 16:19   #3
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

сплиттер вот:
Код:
  Result := pGraphBuilder.AddSourceFilter(StringToOleStr(Fn),'source',fsource);
  if Result <> S_OK then
  begin
    MessageBox(Application.Handle,'AddSourceFilter error','error', MB_ICONERROR);
    ClearGraph;
    Exit;
  end;
Может надо граф полностью вручную строить?
pSink.SetFileName('c:\test.wav',nil);
А сюда какой MediaType надо запихнуть? Который в WavDest input pin или от сплиттера?
BLACK_RAIN вне форума Ответить с цитированием
Старый 23.03.2017, 10:13   #4
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

cобрал граф вручную
Код:
function FindPin(const filter: IBaseFilter; const iPinID : Integer;
                  const pinDir: _PinDirection; var pinOut: IPin):Boolean;
var
  enumPins: IEnumPins;
  Direction : _PinDirection;
  t : string;
  n : Integer;
begin
  Result := False;
  enumPins := nil;
  pinOut := nil;
  n := 0;
  filter.EnumPins(enumPins);
  while enumPins.Next(1,pinOut,0)=s_ok do
    begin
      pinOut.QueryDirection(Direction);
      if (direction=pinDir) then
      begin
        if n=iPinID then
        begin
        Result := True;
        enumPins := nil;
        Exit;
        end else
        inc(n);
      end;
    end;
  if Assigned(enumPins) then enumPins := nil;
end;

function buildGraph(fn : string): HRESULT;
var
  ErrorCodeText,t : string;
  PinIn, PinOut : IPin;
  src , haali, ffd, wavDest, wrt : IBaseFilter;
  pSink : IFileSinkFilter2;
  mt : TAMMediaType;
  mt2 : winapi.directshow9._AMMediaType;
begin
  Result := CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER ,
                           IID_IGraphBuilder, pGraphBuilder);
  Result := CoCreateInstance(CLSID_CaptureGraphBuilder2, NIL,
                          CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
                         pCaptureGraphBuilder);
  pCaptureGraphBuilder.SetFiltergraph(pGraphBuilder);

  Result := coCreateInstance(CLSID_FileSourceAsync, nil,
                               CLSCTX_INPROC_SERVER,
                               IID_IFileSourceFilter, pSource);
  Result := pSource.Load(StringToOleStr(fn),nil);

  pSource.QueryInterface(IID_IBaseFilter,src);

  Result := coCreateInstance(CLSID_HaaliMediaSplitterAR, nil,
                             CLSCTX_INPROC_SERVER,
                             IID_IBaseFilter, haali);

  pGraphBuilder.AddFilter(src,'source');
  pGraphBuilder.AddFilter(haali,'haali');

  FindPin(src,0, PINDIR_OUTPUT,PinOut);
  FindPin(haali,0,PINDIR_INPUT,PinIn);
  Result := pGraphBuilder.Connect(PinOut,PinIn);


  Result := coCreateInstance(CLSID_ffdshowAudioDecoder, nil,
                             CLSCTX_INPROC_SERVER,
                             IID_IBaseFilter, ffd);
  pGraphBuilder.AddFilter(ffd, 'ffd');
  FindPin(haali,1,PINDIR_OUTPUT,PinOut);
  FindPin(ffd,0,PINDIR_INPUT,PinIn);
  pGraphBuilder.Connect(PinOut,PinIn);

  Result := coCreateInstance(CLSID_WavDest, nil,
                             CLSCTX_INPROC_SERVER,
                             IID_IBaseFilter, wavdest);
  pGraphBuilder.AddFilter(wavDest,'wavdest');
  FindPin(ffd,0,PINDIR_OUTPUT,PinOut);
  FindPin(wavDest,0,PINDIR_INPUT,PinIn);
  Result := pGraphBuilder.Connect(PinOut,PinIn);

  Result := coCreateInstance(CLSID_FileWriter, nil,
                               CLSCTX_INPROC_SERVER,
                               IID_IFileSinkFilter2, pSink);
  pSink.QueryInterface(IID_IBaseFilter,wrt);

  Result := PinIn.ConnectionMediaType(mt2);
  mt.majortype := mt2.majortype;
  mt.subtype := mt2.subtype;
  mt.bFixedSizeSamples := mt2.bFixedSizeSamples;
  mt.lSampleSize := mt2.lSampleSize;
  mt.formattype := mt2.formattype;
  mt.pUnk := mt2.pUnk;
  mt.cbFormat := mt2.cbFormat;
  mt.pbFormat := mt2.pbFormat;
  Result := pSink.SetFileName('c:\0.wav', @mt);

  pGraphBuilder.AddFilter(wrt, 'writer');

  FindPin(wavDest,0,PINDIR_OUTPUT,PinOut);
  FindPin(wrt, 0,PINDIR_INPUT,PinIn);
  Result := pGraphBuilder.Connect(PinOut,PinIn);
  case Result of
    VFW_S_PARTIAL_RENDER:
    begin
      ErrorCodeText := 'VFW_S_PARTIAL';
    end;
    E_ABORT:
    begin
      ErrorCodeText := 'E_ABORT';
    end;
    E_POINTER:
    begin
      ErrorCodeText := 'E_POINTER';
    end;
    VFW_E_CANNOT_CONNECT:
    begin
      ErrorCodeText := 'VFW_E_CANNOT_CONNECT';
    end;
    VFW_E_NOT_IN_GRAPH:
    begin
      ErrorCodeText := 'VFW_E_NOT_IN_GRAPH';
    end;
    else ErrorCodeText := IntToStr(Result);
  end;
выдаёт ошибку VFW_E_CANNOT_CONNECT
может опять что-то пропустил? вроде всё правильно
BLACK_RAIN вне форума Ответить с цитированием
Старый 23.03.2017, 12:03   #5
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

если делать так:
Result := pSink.SetFileName('c:\0.wav', nil);
тогда всё работает. Объясните, почему?
И почему в интеллектуальном режиме не работает?
BLACK_RAIN вне форума Ответить с цитированием
Старый 24.03.2017, 10:49   #6
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

А можно как-то узнать позицию, сколько уже сконвертировано?
Код:
procedure TForm2.Update;
var
  d : Double;
  s : string;
begin
  if Assigned(pMediaPosition) then
  begin
    pMediaPosition.get_CurrentPosition(d);
    ListBox1.ItemIndex := ListBox1.Items.Add(FormatFloat('0.00',d));
    if d > 0 then
    s := FormatDateTime('hh:mm:ss',d /(3600*24)) else
    s := '00:00:00';
    lbl1.Caption := s;
  end else
  lbl1.Caption  := 'stop';
end;
выдаёт сколько времени прошло с момента запуска.

и размер файла во время выполнения узнать не получается.
Код:
function GetFileSize(fn : string): UInt64;
var
  SR: win32_find_data;
  fh : longword;
begin
    FH := FindFirstFile(PChar(fn), sr);
    if (FH <> INVALID_HANDLE_VALUE) then
    begin
      Result:= (sr.nFileSizeLow or Int64(sr.nFileSizeHigh) shl 32);
      Winapi.Windows.FindClose(fh);
    end else
    Result := 0;
end;
Всегда выдает столько, сколько было записано в файл при запуске графа. Как будто в файл ничего больше не пишется. Хотя в эксплорере видно, что размер файла растёт.
BLACK_RAIN вне форума Ответить с цитированием
Старый 24.03.2017, 11:34   #7
Filka
Форумчанин
 
Регистрация: 29.10.2015
Сообщений: 272
По умолчанию

http://www.programmersforum.ru/showp...8&postcount=18
Filka вне форума Ответить с цитированием
Старый 24.03.2017, 13:11   #8
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от Filka Посмотреть сообщение
Спасибо. Это работает. Пока не прочитал, сделал через TFileStream. Но ваш способ, по-идее, быстрее.
Осталась только проблема с определением позиции.
BLACK_RAIN вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
проблема с конвертацией файла NellyM Qt и кроссплатформенное программирование С/С++ 0 06.12.2016 15:23
Как убрать шум из звуковой дорожки? ScribaXXI Общие вопросы по Java, Java SE, Kotlin 0 24.06.2015 09:24
C++ CLR Проблема с конвертацией hvz- Помощь студентам 5 08.10.2011 18:21
играть сначала 1.wav потом 2.wav mma Мультимедиа в Delphi 9 23.12.2010 20:04
Как проиграть несколько звуковой файлов wav? Volkogriz Мультимедиа в Delphi 1 25.11.2008 10:12