Воскресенье, 22.10.2017, 05:42
Приветствую Вас Гость

Не ошибается тот, кто ничего не делает.
Но и ничего не делать - ошибка.

Эмиль Кроткий

[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
Страница 1 из 11
Форум » Delphi » DirectShow и Delphi. » Видеоплеер DirectShow - эффект хрипящего звука (у некоторых форматов)
Видеоплеер DirectShow - эффект хрипящего звука
BLACK_CRAFTER666Дата: Воскресенье, 07.07.2013, 12:50 | Сообщение # 1
Сержант
Группа: Пользователи
Сообщений: 31
Репутация: 0
Статус: Offline
Здравствуйте.
Я пишу видеоплеер с использованием DirectShow.
Строю граф вручную:

Код
const  // глобальные константы
CLSID_FfdshowVideoDecoder : TGUID = '{04FE9017-F873-410E-871E-AB91661A4EF7}';
CLSID_ffdshowAudioDecoder : TGUID = '{0F40E1E5-4F79-4988-B1A9-CC98794E6B55}';
CLSID_haaliMediaSplitter : TGUID = '{55DA30FC-F16B-49FC-BAA5-AE59FC65F82D}';
CLSID_AC3ParserFilter : TGUID = '{280A3020-86CF-11D1-ABE6-00A0C905F375}'; //mpg2splt.ax
CLSID_AC3Filter : TGUID = '{A753A1EC-973E-4718-AF8E-A3F554D45C44}'; //ac3filter.ax
CLSID_ElecardMPEGDemultiplexer : TGUID = '{136DCBF5-3874-4B70-AE3E-15997D6334F7}';

var // глобальные переменные
   pGraphBuilder        : IGraphBuilder         = nil;  
   pCaptureGraphBuilder : ICaptureGraphBuilder2 = nil;
   pMediaControl        : IMediaControl         = nil;
   pMediaEvent          : IMediaEvent           = nil;
   pVideoWindow         : IVideoWindow          = nil;
   pMediaPosition       : IMediaPosition        = nil;
   pBasicAudio          : IBasicAudio           = nil;  
   pBasicVideo : IBasicVideo = nil;
   fSource : IBaseFilter = nil;
   ffdshow_video : IBaseFilter = nil;
   ffdshow_audio : IBaseFilter = nil;
//  haali : IBaseFilter = nil;
   ac3filter : IBaseFilter = nil;
   ac3parser : IBaseFilter = nil;
   ElecardDemultiplexer : IBaseFilter = nil;
   pAudioRender : IBaseFilter = nil;
   pVideoRender : IBaseFilter = nil;

function FindPin(const filter: IBaseFilter; const pinDir: _PinDirection; var pinOut: IPin):Boolean;
var
    enumPins: IEnumPins;
    Direction : _PinDirection;
begin
    Result := False;
    enumPins := nil;
    filter.EnumPins(enumPins);
    while enumPins.Next(1,pinOut,0)=s_ok do
      begin
        pinOut.QueryDirection(Direction);
        if Direction=pinDir then
        begin
          Result := True;
          enumPins := nil;
          Exit;
        end;
      end;
    if Assigned(enumPins) then enumPins := nil;
end;

function buildgraph: hresult;
var
    pin : IPin;
    mediatype : TAMMediaType;
    InPin, OutPin : IPin;
begin
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER , IID_IGraphBuilder, pGraphBuilder);
CoCreateInstance(CLSID_CaptureGraphBuilder2, NIL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
                           pCaptureGraphBuilder);
pCaptureGraphBuilder.SetFiltergraph(pGraphBuilder);
pGraphBuilder.AddSourceFilter(StringToOleStr(FileName),'source file',fSource);

CoCreateInstance(CLSID_AudioRender, nil, CLSCTX_INPROC, IID_IBaseFilter, pAudioRender);
pGraphBuilder.AddFilter(pAudioRender, 'DirectSound Audio Renderer');

CoCreateInstance(CLSID_VideoMixingRenderer9, nil, CLSCTX_INPROC, IID_IBaseFilter, pVideoRender);
pGraphBuilder.AddFilter(pVideoRender, 'Video Mixing Renderer 9');

CoCreateInstance(CLSID_ElecardMPEGDemultiplexer,nil,CLSCTX_INPROC_SERVER,IID_IBaseFilter,ElecardDemultiplexer);
pGraphBuilder.AddFilter(ElecardDemultiplexer,'elecard demultiplexer');

CoCreateInstance(CLSID_FfdshowVideoDecoder,nil,CLSCTX_INPROC,IID_IBaseFilter,ffdshow_video);
pGraphBuilder.AddFilter(ffdshow_video,'ffdshow video decoder');

{CoCreateInstance(CLSID_ffdshowAudioDecoder,nil,CLSCTX_INPROC,IID_IBaseFilter,ffdshow_audio);
pGraphBuilder.AddFilter(ffdshow_audio,'ffdshow audio decoder');}

CoCreateInstance(CLSID_AC3Filter,nil,CLSCTX_INPROC,IID_IBaseFilter,ac3filter);
pGraphBuilder.AddFilter(ac3filter,'ac3filter');

{CoCreateInstance(CLSID_AC3ParserFilter,nil,CLSCTX_INPROC,IID_IBaseFilter,ac3parser);
pGraphBuilder.AddFilter(ac3parser,'ac3parser');}

    if not FindPin(fSource,PINDIR_OUTPUT,pin) then
    begin
      ClearGraph;
      Result := S_FALSE;
      Exit;
    end;
    pin.ConnectionMediaType(mediatype);

    Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, fSource, nil ,pAudioRender);
    Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, fSource, nil ,pVideoRender);

    MoFreeMediaType(@mediatype);

     pGraphBuilder.QueryInterface(IID_IBasicAudio,pBasicAudio);
     pGraphBuilder.QueryInterface(IID_IBasicVideo,pBasicVideo);
     pGraphBuilder.QueryInterface(IID_IMediaControl,pMediaControl);
     pGraphBuilder.QueryInterface(IID_IMediaPosition,pMediaPosition);
     pGraphBuilder.QueryInterface(IID_IVideoWindow,pVideoWindow);


Большинство файлов воспроизводятся на ура. Но у некоторых файлов происходит либо рассинхрон звука, либо хрип. Особенно у тех, где звук в формате AC-3.
При этом, в трее нет ни значка ac3filter (что очень странно), ни значка ffdshow audio decoder'а. Т.е. не понятно, каким фильтром обрабатывается звук.
На тех файлах, где есть значки ac3filter/ffdshow, со звуком всё ок.
В чем может быть прикол?
Пробовал связывать фильтры через Pin'ы, но не уверен, что правильно это делал.


Сообщение отредактировал BLACK_CRAFTER666 - Воскресенье, 07.07.2013, 12:59
 
xaramamburuДата: Понедельник, 08.07.2013, 11:23 | Сообщение # 2
Полковник
Группа: Администраторы
Сообщений: 240
Репутация: 26
Статус: Offline
Цитата
В чем может быть прикол?
Не знаю. Можно попробовать установить последнюю версию кодеков, может, что и изменится.
Цитата
Т.е. не понятно, каким фильтром обрабатывается звук.
Это можно узнать только посмотрев как выглядит граф с помощью GraphStudio. Но здесь есть одно но. Я уже писал, что это работает только под Windows XP и ваш граф должен быть зарегистрирован в системе (это можно сделать с помощью функции AddGraphToRot ее тело можно найти в интернете или установить пакет DSPack и подключить к проекту модуль DSUtils). По крайней мере я когда с этим копался, создавал проект на ноутбуке с Windows Vista, а потом шел включал старенький компьютер Windows XP и смотрел как выглядит граф, я понимаю, что это извращение, но по другому посмотреть что там у меня строилось не было возможности.
Цитата
Строю граф вручную:
Судя по вашему коду это не совсем правильно. Вы вручную добавляете фильтры в граф, затем вы определяете MediaType данных за что вы огромное спасибо, я в свое время до этого не допер.  А вот далее вы используете функции:

Код
Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, fSource, nil ,pAudioRender);      
Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, fSource, nil ,pVideoRender);
 RenderStream - это функция интеллектуального построения графа, причем в ней вы указываете fSource (источник) и pAudioRender (рендер) а между ними nil (в место nil можно указать конкретный фильтр для кодирования или декодирования потока) , т.е. все промежуточные фильтры вы предлагаете установить самому графу. Я уже писал, что он отдает предпочтение тем фильтрам, что вы добавили в граф, но не факт, что он установит именно их. Я не знаю знаете ли вы что эта функция позволяет строит граф по частям.
Например:
Вам надо построить граф из нескольких фильтров и вы точно знаете, что для данного MediaType будет использоваться фильтр А - источник, фильтр В - декодер и фильтр С - рендер, а остальные фильтры вы отдаете на усмотрение графа. Тогда функцию можно задать таким образом:
1) Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, А, В , С); - строим цепь от А до С с промежуточным фильтром В.
или
2) Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, А, nil ,В) ; - строим цепь от А до В промежуточные фильтры добавляет сам граф;
Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, В, nil ,С); - аналогично от В до С.
Да, первый вариант у меня почему то не всегда срабатывал, возможно из - за того что промежуточных фильтров было больше чем один.
smile
 
BLACK_CRAFTER666Дата: Понедельник, 08.07.2013, 15:44 | Сообщение # 3
Сержант
Группа: Пользователи
Сообщений: 31
Репутация: 0
Статус: Offline
Цитата (xaramamburu)
Можно попробовать установить последнюю версию кодеков, может, что и изменится

Это, конечно, важная составляющая. Но тут дело не в этом.
Цитата (xaramamburu)
Я не знаю знаете ли вы что эта функция позволяет строит граф по частям.

Я не знал, но в какой-то момент начал догадываться smile
Цитата (xaramamburu)
Я уже писал, что он отдает предпочтение тем фильтрам, что вы добавили в граф, но не факт, что он установит именно их.

Я помню. Чтобы этого избежать, как вариант, можно рендерить стрим частями, от фильтра до фильтра. Вы об этом писали.
Цитата (xaramamburu)
включал старенький компьютер Windows XP и смотрел как выглядит граф, я понимаю, что это извращение, но по другому посмотреть что там у меня строилось не было возможности.

Если оперативки хватает и есть место на диске, то можно просто использовать виртуальные машины smile
Цитата (xaramamburu)
1) Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, А, В , С); - строим цепь от А до С с промежуточным фильтром В.

СПАСИБО!!! Вот в этом и был прикол! smile Я не мог допереть, что средний nil это промежуточный фильтр и что все промежуточные фильтры подбираются системой автоматически.
Поняв это, я сделал вот так:

Код
Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, fSource,nil,ffdshow_video);
        Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, ffdshow_video,fGrabber,pVideoRender);  // SampleGrabber еще никому не мешал ))
        Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, fSource,ac3filter,pAudioRender);

Т.е. рендеринг от фильтра до фильтра по-очереди. Таким образом, пропал тот самый хрип, а ac3filter cтал грузиться всегда. Но появились пара досадных косяков. А именно:
1) SampleGrabber начал выдавать либо шедевр Малевича, либо пустой (nil'ьный) указатель.
Но я постучал по компу ногой и всё стало S_OK smile
2) Пропали пропорции видео при ресайзе окна. Это решилось хитрой процедурой ручного просчета размеров двух TRect'ов.
3) В записи с каналов ТВЦ со спутника Yamal 201 рендеринг звука выдает ошибку. Какую именно - в дебаггере пока не смотрел. Возможно, нужно использовать другой фильтр аудио. Опять же, сделать возможность выбора фильтров, а если ошибка - пытаться грузить другой. Это уже из вопроса подхода к созданию интерфейса. У себя в проге я это, обязательно, сделаю. А видео с ТВЦ идет нормально.
4) Тормозят файлы приблизительно вот с такими параметрами:


Это HD видео. Как видно, в них есть какая-то дополнительная текстовая информация. Может, тормозит из-за нее? Может надо для текста еще какой-то фильтр подключить? Еще, при их проигрывании, сильно грузится процессор. Знаю, это тоже влияет.
При полностью автоматическом рендеринге RenderFile(), у этих файлов тормозов почти нет.
Если хотите потестить, могу залить на гугл-диск файлы, которые глючат.
Цитата (xaramamburu)
RenderStream - это функция интеллектуального построения

А я называл ее ручным построением smile Я в терминах запутался. Если это интеллектуальное, то RenderFile() это... автоматическое?
p.s. В один пост всё не вошло smile


Сообщение отредактировал BLACK_CRAFTER666 - Понедельник, 08.07.2013, 16:02
 
xaramamburuДата: Понедельник, 08.07.2013, 18:18 | Сообщение # 4
Полковник
Группа: Администраторы
Сообщений: 240
Репутация: 26
Статус: Offline
Цитата
Если это интеллектуальное, то RenderFile() это... автоматическое?
Это тоже интеллектуальное построение, когда граф сам подбирает фильтры. Руками это когда вы сами соединяете входные и выходные Pin у фильтров, но для этого нужно точно знать какие фильтры будут в цепочке графа, при этом граф строите чисто вы программно.
Цитата
Это HD видео.
К сожалению у меня старенький ноутбук и вряд ли потянет  HD видео. Да и скорость интернета пока не позволяет скачивать фильмы в HD качестве (и такое в наше время бывает). smile
 
BLACK_CRAFTER666Дата: Понедельник, 08.07.2013, 18:41 | Сообщение # 5
Сержант
Группа: Пользователи
Сообщений: 31
Репутация: 0
Статус: Offline
Цитата (xaramamburu)
К сожалению у меня старенький ноутбук и вряд ли потянет HD видео. Да и скорость интернета пока не позволяет скачивать фильмы в HD качестве (и такое в наше время бывает).

протестируйте тогда обычных файлах smile
 
Форум » Delphi » DirectShow и Delphi. » Видеоплеер DirectShow - эффект хрипящего звука (у некоторых форматов)
Страница 1 из 11
Поиск:


Copyright MyCorp © 2017Конструктор сайтов - uCoz