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

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

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

[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
Страница 1 из 11
Форум » Delphi » DirectShow и Delphi. » Видеоплеер DirectShow - ручное построение графа (в зависимости от типа/формата видео)
Видеоплеер DirectShow - ручное построение графа
BLACK_CRAFTER666Дата: Вторник, 02.07.2013, 11:14 | Сообщение # 1
Сержант
Группа: Пользователи
Сообщений: 31
Репутация: 0
Статус: Offline
Здравствуйте.
Основываясь на статье: http://basicsprog.ucoz.ru/publ/6-1-0-25 , написал свой видеоплеер.
Но воспроизведение иногда глючит, а некоторые файлы вообще не открываются.
В связи с этим, возник логичный вопрос: Как построить граф вручную в зависимости от типа/формата исходного видео-файла?
Как узнать, какие сплиттеры/кодеки нужны и как правильно подключить их к Графу(Дракуле)? И как получить список сплиттеров/декодеров, установленных в системе?
Дополнительный вопрос: как вытащить информацию о видео-файле? Такую, как: FourCC, битрейт аудио/видео, количество кадров в секунду (fps), и т.п.
 
xaramamburuДата: Среда, 03.07.2013, 19:07 | Сообщение # 2
Полковник
Группа: Администраторы
Сообщений: 240
Репутация: 26
Статус: Offline
Честно говоря не знаю, я когда этим занимался то для просмотра графа использовал программы GraphEdit и GraphStudio, смотрел граф и добавлял соответствующие фильтры в проект. Смотрите урок 4.2
(добавление фильтра в граф:
//создаем объект для построения фильтра вывода видео FVideoRender
CoCreateInstance(CLSID_VideoMixingRenderer, nil, CLSCTX_INPROC, IID_IBaseFilter, FVideoRender);
// Добавляем его в граф
FGraphBuilder.AddFilter(FVideoRender, 'Video Renderer');),
и уроки 5.1 и 5.2 (построение графа по ключевым фильтрам в зависимости от расширения:
(//если расширение wmv
if lowercase(ExtractFileExt(FileNameVideo))='.wmv' then  begin
//строим участок графа от фильтра источника  fl_SrcFile  до фильтра FDirectVobSub
if FAILED(RenderStream(nil,  @MEDIATYPE_Video, fl_SrcFile, nil , FDirectVobSub)) then
Begin
ShowMessage('Внимание! Произошла ошибка на участке от фильтра источника  fl_SrcFile  до фильтра FDirectVobSub');
Exit;
End;).
Для получения списка фильтров или устройств из конкретной категории
используется объект перечислитель устройств. Смотрите уроки по работе с
видеокамерой 3.1 и 3.2, а здесь пример получения списка видео, аудио устройств и фильтров для сжатия http://basicsprog.ucoz.ru/uroki_delphi/multimedia/urok3_1/kamera000.zip
Вообще по DirectShow есть книга "DirectShow и телевидение", но примеры в ней на С.
Да если необходимо соединить только конкретные заданные фильтры, то используют соединение через Pin (т.е. фильтры добавляются в граф, затем ищутся входные и выходные контакты Pin, а затем соединяются, но до этого я так и не дошел, но информацию в интернете видел). Юзайте сайт и форум "DirectShow по русский" http://directshow.wonderu.com /  .))))
 
xaramamburuДата: Среда, 03.07.2013, 19:18 | Сообщение # 3
Полковник
Группа: Администраторы
Сообщений: 240
Репутация: 26
Статус: Offline
Цитата
Дополнительный вопрос: как вытащить информацию о видео-файле? Такую, как: FourCC,
битрейт аудио/видео, количество кадров в секунду (fps), и т.п.
Как получить битрейт аудио/видео, количество кадров в секунду (fps), разрешение видео (длину/ширину) можно посмотреть здесь http://www.cyberforum.ru/blogs/140240/blog136.html там сложного ничего нет.))))
 
BLACK_CRAFTER666Дата: Четверг, 04.07.2013, 13:03 | Сообщение # 4
Сержант
Группа: Пользователи
Сообщений: 31
Репутация: 0
Статус: Offline
Цитата (xaramamburu)
GraphEdit и GraphStudio
Насколько я понял, надо запустить любое видео в любом плеере, а в проге нажать "connect to remote graph"? Но это действие выдает пустой список и
прога никуда не подключается.
Цитата (xaramamburu)
Смотрите урок 4.2(добавление фильтра в граф:
Добавлять фильтры в граф я вроде как уже умею smile
Цитата (xaramamburu)
и уроки 5.1 и 5.2 (построение графа по ключевым фильтрам в зависимости от расширения:
(//если расширение wmv
if lowercase(ExtractFileExt(FileNameVideo))='.wmv' then begin
А причем тут расширение? Расширение определяет только тип контейнера и какой нужен сплиттер. А как определить, какой для файла нужен декодер? Например, в MP4 может быть всё, что угодно.
Цитата (xaramamburu)
а здесь пример получения списка видео, аудио устройств и фильтров для сжатия http://basicsprog.ucoz.ru/uroki_delphi/multimedia/urok3_1/kamera000.zip
Там идет получение списка фильтров для сжатия. А мне, я так понимаю, нужны фильтры для декодирования. Я не знаю, какой CLSID_* подставить, чтобы их получить.
p.s. В ходе испытания "своего" плеера, заметил, что функция RenderFile() не хочет подгружать FFDShow, а всегда использует Microsoft DTV-DVD Video Decoder. Читал в MSDN, что функция RenderFile() вроде как ищет фильтры в зависимости толи от формата толи от чего-то еще по гуйдам в реестре (точно не понял). Может в реестре только стандартные форматы прописаны, такие как AVI,MPG,WMV,AVC, по-этому он другие не знает, чем открывать. Отсюда могу сделать вывод, что при таком раскладе плеер будет читать только те форматы, декодирование которых поддерживается Microsoft DTV-DVD Video Decoder'ом. Может, если насильно подгрузить FFDShow, то будут читаться и другие форматы? Понятное дело, что не все. Но, по-идее, их количество должно прибавиться?
Кстати, для декодирования звука используется как-раз FFDShow audio decoder, либо AC3Filter (в зависимости от настроек приоритета).
Цитата (xaramamburu)
Вообще по DirectShow есть книга "DirectShow и телевидение", но примеры в ней на С.
Книга это штука хорошая, но читать ее долго smile
Цитата (xaramamburu)
Да если необходимо соединить только конкретные заданные фильтры, то используют соединение через Pin (т.е. фильтры добавляются в граф, затем ищутся входные и выходные контакты Pin, а затем соединяются,
Не совсем понимаю, чем отличается соединение фильтров от добавления их в граф и что это дает. Можете доступно объяснить? И еще не понимаю, что такое null_renderer и зачем он нужен и что делает.
Цитата (xaramamburu)
Юзайте сайт и форум "DirectShow по русский" http://directshow.wonderu.com / .))))
Дак я бы с радостью smile Но их форум это белая страница с надписью "It works!" smile Туда бы еще trollface прилепить smile
Цитата (xaramamburu)
Как получить битрейт аудио/видео, количество кадров в секунду (fps), разрешение видео (длину/ширину) можно посмотреть здесь http://www.cyberforum.ru/blogs/140240/blog136.html там сложного ничего нет.))))
Cпасибо. FPS и разрешение определились без проблем. А вот битрейт определяется либо сильно завышенным, либо вообще равным нулю.
 
xaramamburuДата: Пятница, 05.07.2013, 16:53 | Сообщение # 5
Полковник
Группа: Администраторы
Сообщений: 240
Репутация: 26
Статус: Offline
Как вы заметили сайт уже почти год не обновлялся. Все, что здесь написано было давно и я многое уже забыл. Поэтому сильно не ругайтесь.)))
Цитата
Насколько я понял, надо запустить любое видео в любом плеере, а в проге нажать "connect to remote graph"? Но это
действие выдает пустой список и прога никуда не подключается.

К сожалению на Windows Vista и 7 этот способ у меня тоже не работал, так я делал только под Windows XP. Кроме этого можно выбирать "Render Media File", он автоматом вам построит и покажет граф. Далее вы можете удалять нужные вам фильтры и добавлять другие. Одно и тоже видео можно воспроизвести с помощью разного набора фильтров.
Цитата
А причем тут расширение? Расширение определяет только тип контейнера и какой нужен сплиттер. А как определить, какой
для файла нужен декодер? Например, в MP4 может быть всё, что угодно.

Я это понимаю, но как определить не знаю. Я строил граф в GraphStudio, смотрел какие фильтры он добавлял и использовал их как ключевые в цепи построения графа.

Цитата
Книга это штука хорошая, но читать ее долго

Думаю, что почитать ее все равно придется, как раз в ней вы можете найти названия CLSID_* скачать ее можно здесь Книга 'DirectShow и телевидение'.
Далее фильтры в граф добавляются по величине "Merit" эта такая характеристика, которая есть у каждого фильтра и чем он выше, тем больше вероятность, что данный фильтр будет добавлен в фильтр.
Цитата
Не совсем понимаю, чем отличается соединение фильтров от добавления их в граф и что это дает. Можете доступно объяснить?

Как я понял фильтр, добавленный в граф не означает, что он будет соединен в цепь с другими фильтрами. Он может просто висеть ни к чему не подключенным. Но при этом при сборке графа отдается предпочтение фильтрам которые вы добавили и если они не подходят, то происходит поиск фильтров зарегистрированных в системе. Кроме интеллектуального построения графа, его можно строить в ручную. Добавляются необходимые фильтры в граф. Далее находятся входные и выходные контакты для этого есть (EnumPins, FindPin и т.д. интерфейсы у IBaseFilter)
и проверяется попытка соединения и так по цепочке строим весь граф целиком. На практике у меня до этого дело так и не дошло, как то пробовал накидать пример тестовый пример, но сейчас найти не могу. Давно это было.(((
Цитата
И еще не понимаю, что такое null_renderer и зачем он нужен и что делает.

Чтобы граф работал цепь должна начинаться Source (источником) и Render (приемником) фильтрами (по крайней мере я так думаю, возможно и неправ). Пока цепь графа фильтров не закончена - граф не запустится.  Поэтому null_renderer - вывод в никуда используется для того, чтобы закончить цепь, например при захвате видео (изображения) с камеры, но без вывода на экран (можно написать шпиона).
Цитата
directshow.wonderu.com

Да форум похоже действительно накрылся.(((
Ищите инфу в интернете, хотя именно для Delphi ее очень мало и она разрознена по разным форумам. В основном надо искать по конкретным словам (название фильтров, интерфейсов и т.д.), просто по DirectShow выдается всякая дрянь.))))
 
BLACK_CRAFTER666Дата: Суббота, 06.07.2013, 17:21 | Сообщение # 6
Сержант
Группа: Пользователи
Сообщений: 31
Репутация: 0
Статус: Offline
Цитата (xaramamburu)
Как я понял фильтр, добавленный в граф не означает, что он будет соединен в цепь с другими фильтрами. Он может просто висеть ни к чему не подключенным.
Это я уже тоже понял smile Сегодня методом тыка и статьи 5.1 научился доставать из системы нужные фильтры по их guid smile
Но прикол вот в чем:
подключаю к графу ac3filter или ffdshow audio decoder. Если открыть mpg/ts (внутри mpeg), то граф при рендеринге звука их грузит. Если открыть FLV (внутри AAC), то выдается ошибка. Но если открыть тот же FLV-файл с помощью функции RenderFile(), т.е. используя автоматическое построение Графа(Дракулы), то в граф добавляется именно AC3FILTER. Не знаю, как это понимать smile
а как программно узнать, что прицепилось, а что висит?
Цитата (xaramamburu)
Далее находятся входные и выходные контакты для этого есть (EnumPins, FindPin и т.д. интерфейсы у IBaseFilter)
Т.е. нужно добавить фильтры и прицепить их друг к другу в той последовательности,  в которой они идут в graphEdit'e?
p.s. книга по ссылке не качается) ошибками ругается)

Добавлено (06.07.2013, 10:40)
---------------------------------------------
Я нашел ошибку!
надо писать

Код
res := FCaptureGraphBuilder.RenderStream(nil, @MEDIATYPE_AUDIO, fl_SrcFile, nil ,FAudioRender);


вместо

Код
res := FCaptureGraphBuilder.RenderStream(nil, nil, fl_SrcFile, nil ,FAudioRender);


тогда фильтры звука грузятся и звук в подопытном FLV есть smile
Исправьте это в статье 5.1 smile
На других контейнерах еще не пробовал. Попробую - отпишусь.
А пока(липсис) - всем спасибо! smile

Добавлено (06.07.2013, 17:21)
---------------------------------------------
но и это не правильно smile
надо вот так:
сначала строим граф и цепляем ffdshow + ac3filter (можно радиобоксы/чекбоксы сделать, что будем цеплять):

Код
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER , IID_IGraphBuilder, pGraphBuilder);
CoCreateInstance(CLSID_CaptureGraphBuilder2, NIL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
                            pCaptureGraphBuilder);
pCaptureGraphBuilder.SetFiltergraph(pGraphBuilder);
//FileName := 'd:\(2013) Disney - June 13 15 43 17.mpg';
//FileName := 'c:\1.flv';
pGraphBuilder.AddSourceFilter(StringToOleStr(FileName),'source file',fSource);
CoCreateInstance(CLSID_VideoMixingRenderer, nil, CLSCTX_INPROC, IID_IBaseFilter, pVideoRender);
pGraphBuilder.AddFilter(pVideoRender, 'Video Mixing Renderer');
CoCreateInstance(CLSID_FfdshowVideoDecoder,nil,CLSCTX_INPROC,IID_IBaseFilter,ffdshow_video);
pGraphBuilder.AddFilter(ffdshow_video,'ffdshow video decoder');
CoCreateInstance(CLSID_AC3Filter,nil,CLSCTX_INPROC_SERVER,IID_IBaseFilter,ac3filter);
pGraphBuilder.AddFilter(ac3filter,'ac3filter');
CoCreateInstance(CLSID_AudioRender, nil, CLSCTX_INPROC, IID_IBaseFilter, pAudioRender);
pGraphBuilder.AddFilter(pAudioRender, 'DirectSound Audio Renderer');


потом ищем MediaType фильтра-источника (fSource), предварительно найдя его Output Pin:

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

функция поиска первого нужного Pin'а:

Код
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;

ежели Pin найден и MediaType определен, рендерим аудио и видео в любой последовательности:

   
Код
Result := pCaptureGraphBuilder.RenderStream(nil, mediatype.pbFormat, fSource,  
nil ,pVideoRender); // строим цепочку видео (подсунув сюда MediaType)
     Result := pCaptureGraphBuilder.RenderStream(nil, MEDIATYpe.pbFormat, fSource,  
nil ,pAudioRender); // строим цепочку аудио (так же подсунув сюда  
MediaType)
     MoFreeMediaType(@mediatype); // освободим MediaType


и не забываем проверять результат каждой функции на ошибки!

Вот, кажется, и всё smile Интерфейсы управления доставать, как обычно.
Не знаю, насколько это правильно. Но теперь прога стала читать те файлы, которые раньше не читала.
*Проверил на нескольких файлах. Видео и звук есть.
Спасибо Харамамбуре за духовную наставку! smile


Сообщение отредактировал BLACK_CRAFTER666 - Суббота, 06.07.2013, 17:35
 
xaramamburuДата: Суббота, 06.07.2013, 20:53 | Сообщение # 7
Полковник
Группа: Администраторы
Сообщений: 240
Репутация: 26
Статус: Offline
BLACK_CRAFTER666
Я смотрю вы упрямый. Респект. smile Выкладывайте если еще, что то накопаете, может кому пригодится. smile
 
Форум » Delphi » DirectShow и Delphi. » Видеоплеер DirectShow - ручное построение графа (в зависимости от типа/формата видео)
Страница 1 из 11
Поиск:


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