Некоторые разъяснения по поводу AUTO-HDMI и вообще переключения режимов монитора (телевизора) при полноэкранном выводе.
В настоящий момент все должно работать только с
прогрессивными режимами!!!
Для того, чтобы установить чрезстрочный режим нужно выполнить
dmScreenSettings.dmPelsWidth = dm.size.cx;
dmScreenSettings.dmPelsHeight = dm.size.cy;
dmScreenSettings.dmBitsPerPel = dm.bpp;
dmScreenSettings.dmDisplayFrequency = dm.freq;
dmScreenSettings. dmDisplayFlags = DM_INTERLACED;
dmScreenSettings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
Присвоение dmDisplayFlags = DM_INTERLACED говорит системе, что режим чрезстрочный. В настоящий момент поле dmDisplayFlags нигде не устанавливается и имеет по-умолчанию нулевое значение, что говорит о том, что режим будет устанавливаться
прогрессивным.
Для того , чтобы хоть как-то работать в MPC-HC с чрезстрочными режимами (хотя бы отображать в списке, что режим прогрессивный или чрезстрочный) нужно изменение структуры dispmode
Сейчас она имеет такой тип:
typedef struct
{
bool fValid;
CSize size;
int bpp, freq;
} dispmode;
Нужно добавить поле DWORD dmDisplayFlags;
typedef struct
{
bool fValid;
CSize size;
int bpp, freq;
DWORD dmDisplayFlags;
} dispmode;
Оно будет соответствовать полю dmDisplayFlags структуры DEVMODE .
Как сейчас работает на примере моей системы Win7 ATI4850 Driver 8.681.0.0 от 24.11.2009, CCC 2009.1124.2131.38610.
Режимы для телевизора
Видно, что прогрессивные режимы 24, 50, 60Гц, чрезстрочные 25, 29, 30.
MPC-HC выдает эти режимы так
Без признаков интерлейза, объясняю, почему. В GetDispMode(int i, dispmode& dm, CString& DisplayName) (mplayerc.cpp)
Выполняется определение всех параметров дисплеев через вызов EnumDisplaySettings(DisplayName1, i, &devmode)
и в поля dm типа dispmode записываются параметры выбранного режима
dm.fValid = true; //Режим существует
dm.size = CSize(devmode.dmPelsWidth, devmode.dmPelsHeight) // размер экрана
dm.bpp = devmode.dmBitsPerPel; //глубина цвета
dm.freq = devmode.dmDisplayFrequency;// частота
и здесь теряется информация о чрезстрочности.
Если бы была
dm. dmDisplayFlags = devmode. dmDisplayFlags; // признак чрезстрочности, то не пропадала бы.
Но поля dmDisplayFlags в структуре dm типа dispmode нет.
Дальше везде в программе используется именно тип dispmode и соответственно вывести признак интерлейза в списке режима нельзя.
Для установки режима используется функция void SetDispMode(dispmode& dm, CString& DisplayName) в mplayerc.cpp
В ней перед выполнением ChangeDisplaySettingsEx(DisplayName1, &dmScreenSettings, NULL, CDS_FULLSCREEN, NULL);
Заполняется структура dmScreenSettings
DEVMODE dmScreenSettings; //Создается структура типа DEVMODE
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); //делается ее обнуление
dmScreenSettings.dmSize = sizeof(dmScreenSettings);// заносится размер структуры
dmScreenSettings.dmPelsWidth = dm.size.cx; //ширина экрана
dmScreenSettings.dmPelsHeight = dm.size.cy;//высота экрана
dmScreenSettings.dmBitsPerPel = dm.bpp;//глубина цвета
dmScreenSettings.dmDisplayFrequency = dm.freq; //частота
dmScreenSettings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
если бы была запись
dmScreenSettings. dmDisplayFlags y = dm. dmDisplayFlags; //интерлайз
, то можно было бы установить чрезстрочный режим.
А так, только прогрессивные.
И когда я выставляю в настройках полноэкранного режима 25Гц, раскрываю окно на весь экран, то смены частоты не происходит. Как была 60 так и осталась. Драйвер дисплея 25P просто проигнорировал. Проверял в режиме AUTO-HDMI файлы с частотой контента 25 и 29.97Гц – частота не меняется.
Драйвер игнорирует 25P и 30P.
С Nvidea вообще все шоколадно, там все переключения работают во всех режимах без проблем. Т.ч. мои рекомендации для HTPC.
Как работает AUTO-HDMI.
Комментариев, сделанных на русском в исходнике нет, это я только здесь привел.
if (dm.freq > 0) // If not AUTO-HDMI mode
{
// Здесь просто выдается команда на смену параметров монитора на выбранные из списка.
//Это не моя часть кода - наследие. И здесь скрыт описанный выше баг с выставлением
//чрезстрочного режима. Если в драйвере режим чрезстрочный, то он был удачно потерян,
//и сейчас будет выдаваться команда на прогрессивный. Команда может быть
//проигнорирована драйвером видео-карточки.
SetDispMode(dm, s.f_hmonitor);
}
Else // If AUTO-HDMI mode
{
//считывается из Pin длительность кадра и запивывается в m_rtTimePerFrame
LONGLONG m_rtTimePerFrame = 1;
// if ExtractAvgTimePerFrame isn't executed then MediaFPS=10000000.0,
// dm1.freq=10000000 and SetDispMode isn't executed too.
BeginEnumFilters(pGB, pEF, pBF)
{
BeginEnumPins(pBF, pEP, pPin)
{
CMediaTypeEx mt;
PIN_DIRECTION dir;
if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_OUTPUT
|| FAILED(pPin->ConnectionMediaType(&mt))) continue;
ExtractAvgTimePerFrame (&mt, m_rtTimePerFrame);
if (m_rtTimePerFrame == 0) m_rtTimePerFrame=1;
}
EndEnumPins
}
EndEnumFilters
//определяется частота контента
double MediaFPS = 10000000.0 / m_rtTimePerFrame;
//создается и инициализируюетя переменная dm1 типа dispmode для функции SetDispMode
dispmode dm1=dm;
//частота контента записывается в поле частоты freq dm1.
dm1.freq = (int)(MediaFPS + 0.5);
m_dmBeforeFullscreen.fValid=false; // пока не ясно будет смена параметров или нет
// -1 в dm.freq говорит о том, что выбран режим AUTO 23.97@24, 25.00@25, 29.97@30
if (dm.freq == -1)
{
if (dm1.freq == 24 || dm1.freq == 25 || dm1.freq == 30)
{
SetDispMode(dm1, s.f_hmonitor);
//Если частота контента равна 24,25,30Гц, то выставляем эти частоты на выбранном экране
m_dmBeforeFullscreen.fValid=true; //смена параметров была
}
}
// -2 в dm.freq говорит о том, что выбран режим AUTO 23.97@24, 25.00@50, 29.97@60
if (dm.freq == -2)
{
if (dm1.freq == 24 || dm1.freq == 25 || dm1.freq == 30)
{
// Если частота контента равна 24,25,30Гч, то выставляем удвоенные частоты 25,30Гц, или 24Гц на выбранном экране
if (dm1.freq == 25) dm1.freq = 50;
if (dm1.freq == 30) dm1.freq = 60;
SetDispMode(dm1, s.f_hmonitor);
m_dmBeforeFullscreen.fValid=true; //смена параметров была
}
}
}
Значение частоты контента можно сверить в этом экране MPC-HC.
Сам код AUTO-HDMI не вычисляет длительность кадра, он берет ее из PIN.
Aleksoid Ну, как будем менять структуру dispmode?
Добавление поля не повлияет на весь остальной код, это не удаление и не написание программы с прямым распределением адресов.
.
Позволит правильно работать с чрезстрочкой, сможем удалить имеющиеся баги и улучшить визуальное отображение.