изменение разрешения камеры
|
|
booratino | Дата: Четверг, 06.11.2014, 15:06 | Сообщение # 1 |
Рядовой
Группа: Пользователи
Сообщений: 4
Статус: Offline
| Принципиально изменять разрешение получилось, и я думал, что дальше сам справлюсь. Как я был наивен.
Первоначально размер устанавливался так:
FGraphBuilder.QueryInterface(IID_IVideoWindow, FVideoWindow); FVideoWindow.put_WindowStyle(WS_CHILD or WS_CLIPSIBLINGS); FVideoWindow.put_Owner(Panel1.Handle); vr := Panel1.ClientRect; FVideoWindow.SetWindowPosition(vr.Left,vr.Top, vr.Right - vr.Left,vr.Bottom - vr.Top); FVideoWindow.put_Visible(TRUE);
После изменения разрешения камеры я делаю так:
// читаю установленные размеры камеры FCaptureGraphBuilder.FindInterface(@PIN_CATEGORY_CAPTURE,@MEDIATYPE_Video,FVideoCaptureFilter,IID_IAMStreamConfig,StreamConfig); StreamConfig.GetFormat(m_VideoType); kinow := PVideoInfoHeader(m_VideoType.pbFormat)^.bmiHeader.biWidth; kinoh := PVideoInfoHeader(m_VideoType.pbFormat)^.bmiHeader.biHeight; m_VideoType := nil; StreamConfig := nil;
// меняю панельку Panel1.Width := kinow; Panel1.Height := kinoh;
// думал, что так все прекрасно получится FVideoWindow.SetWindowPosition(0,0,kinow,kinoh);
Да, размер панельки меняется. Но рендер идет не на всю панельку, а на четверть. Если размер панельки не менять, то как раз будет 320х240 в углу.
Как сказать графу, чтобы он на всю панель рендерил? Добавлено (06.11.2014, 15:06) --------------------------------------------- Не, ну, конечно, можно после выбора новых параметров пересоздать граф заново с новыми значениями FVideoCaptureFilter, и тогда все норм. Но, может, можно не разбирая в каком-то фильтре размеры поправить?
|
|
| |
xaramamburu | Дата: Четверг, 06.11.2014, 16:31 | Сообщение # 2 |
Полковник
Группа: Администраторы
Сообщений: 240
Статус: Offline
| booratino, Судя по всему здесь привязка окна идет не к координатам панели, а к чему то другому, точнее окно видео накладывается на панель.((( Поэтому надо вначале получить ссылку на координаты окна вывода видео, а потом их изменить.
Код var pleft,pwidth,ptop,pheight:integer; -------------------------------------------- --------------------------------------------
// меняю панельку Panel1.Width := kinow; Panel1.Height := kinoh; FVideoWindow.GetWindowPosition(pleft,ptop,pwidth,pheight) ; pwidth:=Panel1.Width; pheight:= Panel1.Height; FVideoWindow.SetWindowPosition(0,0,pwidth,pheight); -------------------------------------------- -------------------------------------------- Хотел спросить, как там с квадратом "Малевичя" разобрались?
|
|
| |
booratino | Дата: Пятница, 07.11.2014, 02:41 | Сообщение # 3 |
Рядовой
Группа: Пользователи
Сообщений: 4
Статус: Offline
| Да, с Малевичем вопрос решился. Как вы и велели, сделал FVideoRender, и добавил его в FCaptureGraphBuilder.RenderStream. Все отлично.
А вот Ваше предположение сперва получить, а потом поменять - не помогает. результат тот же. Панель стала 320х240, а картинка в левом нижнем углу 160х120.
Кстати, GetWindowPosition возвращает w = 640, h = 480, это понятно, а вот тор и left = 624 и top = 160 - это совсем не понятно.
Кстати 2. Попробовал сделать так:
FGraphBuilder.RemoveFilter(FVideoCaptureFilter); поменял FVideoCaptureFilter размеры FGraphBuilder.AddFilter(FVideoCaptureFilter, 'VideoCaptureFilter'); и потом заново FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, FVideoCaptureFilter, FGrabFilter, FVideoRender);
фигня полная. Картинка правильная, но "кина" нет. и граф весь порван, и какие-то левые Smart Tree добавились.
Ужасно интеллектуальная, эта самая, директ-шоу. В RenderStream указано всего 3 блока, так нет, а граф добавляется 6 штук квадратов. Вынул один, вставил обратно - 8 штук квадратов. Моя голова очень медленно такое принимает... удивляюсь, как Вы в этом вообще разобрались...... :))Добавлено (07.11.2014, 02:32) --------------------------------------------- Я помню, Вы меня учили, типа, в графстудио возьми камеру и video mixing renderer 9, соедини и посмотри что она еще добавит. так вот она не добавляла ничего, работало на 2х квадратах.
когда программа рендерит из 3х частей, то графстудио показывает следующее:
videocaptureFilter - SmartTree - LAV video decoder (камера дает mjpeg) - grabber - ColorSpaceConverter - VideoRenderer (простой, а не 9й)
и я так подозреваю, что после смены разрешения в 1м квадрате, остальные квадраты "помнят", что спереди было 640х480. они же рендерились в связке под то разрешение...
не понятно почему после RemoveFilter с последующим AddFilter и повторным RenderStream все квадраты разорваны и лишний SmartTree непонятный добавляется... :)) Добавлено (07.11.2014, 02:41) --------------------------------------------- да, и еще что интересно.... ТА процедура не переключала камеру в другой режим насовсем, а только на время жизни графа. Т.е. первый квадрат камеру переключил, а как его обnilили, камера опять вернулась в разрешение по умолчанию.
|
|
| |
xaramamburu | Дата: Пятница, 07.11.2014, 13:11 | Сообщение # 4 |
Полковник
Группа: Администраторы
Сообщений: 240
Статус: Offline
| booratino, Цитата удивляюсь, как Вы в этом вообще разобрались...... :)) К сожалению, я в этом так и не разобрался, мучаюсь как и вы, правда стал знать немного больше чем когда писал эти статьи и если я их писал сейчас, то наверное сделал бы много по другому.))) Цитата когда программа рендерит из 3х частей, то графстудио показывает следующее:
videocaptureFilter - SmartTree - LAV video decoder (камера дает mjpeg) - grabber - ColorSpaceConverter - VideoRenderer (простой, а не 9й) Фильтр SmartTree ращеплят поток на 2 для просмотра и записи, как я понял его добавляет граф захвата FCaptureGraphBuilder, а когда вы просто соединяете камеру и рендерер в GraphStudio этот объект не добавляется.
Цитата и я так подозреваю, что после смены разрешения в 1м квадрате, остальные квадраты "помнят", что спереди было 640х480. они же рендерились в связке под то разрешение... Про это сказать ничего не могу. У меня при до и после смены разрешения граф строится одинаковый. Цитата не понятно почему после RemoveFilter с последующим AddFilter и повторным RenderStream все квадраты разорваны и лишний SmartTree непонятный добавляется... :)) Попробуйте сохранять граф после запуска, граф должен собраться. Код FMediaControl.Run(); SaveGraphFile(FGraphBuilder,'d:\граф захвата.GRF'); Цитата А вот Ваше предположение сперва получить, а потом поменять - не помогает. результат тот же. Панель стала 320х240, а картинка в левом нижнем углу 160х120. Попробуйте так: Код var pleft,pwidth,ptop,pheight:integer; ---------------------------------------------- ---------------------------------------------- // меняю панельку Panel1.Width := kinow; Panel1.Height := kinoh; //меняю разрешение SetVideoParams(kinow, kinoh); //останавливаем граф FMediaControl.Stop; //скрываем окно FVideoWindow.put_Visible(False); //Задаем размеры окна во всю панель FVideoWindow.SetWindowPosition(0,0,panel1.Width,panel1.Height); //показываем окно FVideoWindow.put_Visible(TRUE); //запускаем граф FMediaControl.Run(); end; У меня заработало.))) Цитата Кстати, GetWindowPosition возвращает w = 640, h = 480, это понятно, а вот тор и left = 624 и top = 160 - это совсем не понятно. left и top похоже указаны в глобальной системе координат, т.е. по отношению к рабочему столу, а вот SetWindowPosition похоже задает координаты в локальной системе, т.е. по отношению к панели. Возможно я и ошибаюсь.)))
|
|
| |
booratino | Дата: Пятница, 07.11.2014, 13:37 | Сообщение # 5 |
Рядовой
Группа: Пользователи
Сообщений: 4
Статус: Offline
| А как получить список всех разрешений, которые камера поддерживает?
StreamConfig.QueryInterface(ISpecifyPropertyPages, PropertyPages); PropertyPages.GetPages(Pages);
подозреваю, что в Pages это можно найти. Но pElems это array[0..65535] of TGUID. и что с ним делать уже не могу догадаться. Добавлено (07.11.2014, 13:37) ---------------------------------------------
Код //скрываем окно FVideoWindow.put_Visible(False); //Задаем размеры окна во всю панель FVideoWindow.SetWindowPosition(0,0,panel1.Width,panel1.Height); //показываем окно FVideoWindow.put_Visible(TRUE); да, если сперва скрыть окно, и только потом менять, то меняется.
Но это еще не все! У меня
OleCreatePropertyFrame(Handle, 0, 0, PWideChar(ListVI.Items.Strings[cameraptr]), 1, @StreamConfig, Pages.cElems, Pages.pElems, 0, 0, nil );
меняет параметры только один раз. при последующих нажатиях на кнопку OK получаю сообщение "данный формат не доступен".
при этом если просто каждый раз пересоздавать граф, и вот в этом месте
Код // Создаю фильтр захвата из камеры varray[cameraptr].BindToObject(nil, nil, IID_IBaseFilter, FVideoCaptureFilter);
if nadoSetWH then {ставим нужное разрешение} SetVideoParams(FCaptureGraphBuilder, PIN_CATEGORY_CAPTURE, FVideoCaptureFilter,kinow,kinoh);
//добавляем устройство в граф фильтров FGraphBuilder.AddFilter(FVideoCaptureFilter, 'VideoCaptureFilter');
устанавливать разрешение, то это можно делать любое к-во раз.
так что я вижу самое простое решение, это получить список всех возможных разрешений камеры, самостоятельно их предлагать пользователю и не связываться с косячной OleCreatePropertyFrame.
А как получить список разрешений?
Сообщение отредактировал booratino - Пятница, 07.11.2014, 13:19 |
|
| |
xaramamburu | Дата: Пятница, 07.11.2014, 15:50 | Сообщение # 6 |
Полковник
Группа: Администраторы
Сообщений: 240
Статус: Offline
| booratino, Цитата А как получить список разрешений? Вот нарыл в интернете. Вроде работает, но только список разрешений выдает почему то два раза, но думаю в цикле можно отрезать лишнее, хотя это может быть только у меняю.(((
Код procedure TForm1.Button3Click(Sender: TObject); //получение всех видео разрешений Web-камеры var StreamConfig: IAMStreamConfig; capCount,CapSize: integer; pmt: PAMMEDIATYPE; scc: VIDEO_STREAM_CONFIG_CAPS; W,H: Integer; i: Integer; Begin // Если отсутствует интерфейс работы с видео, то завершаем работу if FVideoCaptureFilter = NIL then EXIT; // Останавливаем работу графа FMediaControl.Stop; try // Ищем интерфейс управления форматом данных выходного потока // Если интерфейс найден, то ... if SUCCEEDED(FCaptureGraphBuilder.FindInterface(@PIN_CATEGORY_CAPTURE, @MEDIATYPE_Video, FVideoCaptureFilter, IID_IAMStreamConfig, StreamConfig)) then // получаем количество форматов StreamConfig.GetNumberOfCapabilities(CapCount,CapSize); for i := 0 to CapCount-1 do begin //заполняет структуры AM_MEDIA_TYPE и VIDEO_STREAM_CONFIG_CAPS StreamConfig.GetStreamCaps(i,pmt,scc); W := scc.InputSize.cx; H := scc.InputSize.cy; ShowMessage('[' + IntToStr(w) + 'x' + IntToStr(h) + ']'); end; // Освобождаем память StreamConfig := NIL; finally // Восстанавливаем работу графа FMediaControl.Run; end; end;
|
|
| |
booratino | Дата: Суббота, 08.11.2014, 02:36 | Сообщение # 7 |
Рядовой
Группа: Пользователи
Сообщений: 4
Статус: Offline
| круто, я не нашел.
да, действительно... много кажущихся повторений, но у некоторых гуиды разные, явно видно... остальные, наверное, тоже в чем-то отличаются. но вытащить отсюда разрешения вполне возможно. спасибо!Добавлено (08.11.2014, 02:36) --------------------------------------------- а два круга двойных повторений, это, возможно, из-за сжатия. моя камера умеет mjpeg и еще что-то... потому и, вероятно.
|
|
| |
xaramamburu | Дата: Суббота, 08.11.2014, 19:38 | Сообщение # 8 |
Полковник
Группа: Администраторы
Сообщений: 240
Статус: Offline
| booratino, Цитата а два круга двойных повторений, это, возможно, из-за сжатия. моя камера умеет mjpeg и еще что-то... потому и, вероятно. Я тоже так думаю. Моя камера на ноутбуке поддерживает два формата RGB24 и YUY2. Поэтому и два списка разрешений.
|
|
| |
|