分享
 
 
 

DVD的界解码

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

这是很久以前的东西,如果有不准确的地方还请见谅

DVD的解码

本节主要包括DirectShow属性设置和特定DVD及扩展解码所用的接口描述,此外还有支持通用 DirectShow 过滤器接口的解码器及其管脚属性描述。

本节主要包含以下主题:

l 解码器音量控制

l Windows 支持的DVD区码变换

以及:

l DVD Karaoke 属性设置

l DVD 复制保护属性设置

l DVD 子图属性设置

l 管脚属性设置

l IKsPropertySet 接口

l IVideoFrameStep 接口(硬件解码器专用)

l IVPConfig 接口(硬件解码器专用)

1、音量控制

应用程序通过iBasicAudio接口管理音量控制,而iBasicAudio接口是由KSProxy进行管理,所以为了使解码器处理这些命令,就必须在KSPPROPSETID_Wave属性设置中增加一些注册键。下来我们就来创建这些新的驱动注册键:

HKLM\SYSTEM CurrentControlSet\Control

DeviceClasses

(decoder guid, eg 2721AE....)

(Pnp id, eg ##?#VDGENDEV#...)

#GLOBAL

Device Parameters

CLSID REG_SZ {17CCA...}

FriendlyName REG_SZ WDM DVD Driver

Interfaces <--- create this key

{b9f8ac3e-0f71-11d2-b72c-00c04fb6bd3d} <-- also create this key, it is not a value)

MediaInterfaces

{b9f8ac3e-0f71-11d2-b72c-00c04fb6bd3d} <-- create this key

(default) REG_SZ 'KsProxy IBasicAudio handler' <-- set this value

IID REG_SZ 56 a8 68 b3 0a d4 11 ce b0 3a 00 20 af 0b a7 70 <-- create this string value

实现音量控制,驱动程序必需支持KSPROPSETID_Wave及KsProperty.Id=KSPROPERTY_WAVE_VOLUME。该属性是驱动程序通过IksPropertySet::Get和IksPropertySet::Set方法进行控制的。左、右音频控制的音量大小是0x0000到0xffff的线性值 。

2、DVD的区码变换

本段解释windows9x和windows2000下选择DVD区码的工作过程。首先描述三种DVD区码信息的来源,随后描述PC厂商如何设置系统进行DVD区码初始化,接着解释DVD导航怎样通过驱动、解码器和碟片来决定区码的匹配,最后揭示应用程序和解码器开发者怎样才能实现正确的DVD区码选择。

2.1、DVD区码信息的来源

DVD区码信息有三种来源,这些来源一起就决定了windows的DVD播放器区码。

DVD标题

大部分DVD标题被标记为特定区码。有些标题只能在某个区域播放,但另一些却可以在很多区域播放,还有的可以全区域播放。

DVD-ROM驱动器

有两种DVD-ROM驱动器:RPC 1和RPC 2。RPC 1驱动器没有内置硬件支持的区码管理,所以对于这些驱动器来说,需要由Windows来管理区码改变次数信息,且只能改变一次;而RPC 2驱动器将这些管理放到了硬件里,因此这些驱动器的区码可以被改变5次。

DVD解码器

一些DVD解码器,无论硬件或者软件,都被设置为特定区码服务。通常情况下,用户不能改变解码器本身设置的区码。

2.2、如何在Windows98和Windows 2000中设置初始化区码

此问题主要是DVD驱动器生产商的责任,他们会在DVD驱动器出厂之前选择一个合适的区码。在Windows98中,生产商可以通过设定注册键值HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Current\Version\Default DVD的区码(二进制)来确定DVD驱动器默认区码。该值决定Windows中DVD解码的首选解码器,如果此值在系统DVD播放之前被设定,那么Windows组件会自动选择该解码器进行DVD播放。

如果生产商在注册表中设定了默认的区码,然后却播放不同区码的碟片(包括默认区码DVD驱动器),用户将会被提示需要改变所要求的区码。如果厂商没有指定默认的区码,那么Windows将选择一个基于操作系统的本地区码、时区和其它因素。如果第一张碟片是多区码碟片,那么Windows将还将寻找相匹配的最小区码数。如果找不到相匹配的区码,则选择的区码就是最小区码数最小的那个区码。

如果生产商没有设置区码,则第一次启动Windows 98操作系统基本组件时,将选择基于操作系统的语言、时区并设置驱动器为此种区码。生产厂家设置区码为“全部适应”,如果厂家没有成这些处理完,则最好选择推荐区码。

在Windows 2000下,默认DVD区码选择基于机器的设定。如果有碟片在驱动器中,Windows 2000通常使用默认和碟片相同的区码为DVD驱动器设置初始化区码,因此在Windows 2000 下 DVD驱动器生产商可以不为初始化DVD驱动器做任何事情。

对于Rpc1的驱动器,如果Windows启动时驱动器中没有DVD碟片,那么将会基于本地机器创建默认区码;如果有碟片在驱动器中,那么将选择驱动器的区码为默认区码,即驱动器中的碟片的区码,否则碟片的最低区码将被用来初始化驱动器的区码。万一默认值不正确,那么用户也有一次改变区码的权利。

对于Rpc2驱动器,如果在处理设置的时,没有对驱动器进行任何区码设置,将会试图按照以上的方法进行选择区码,但是要求驱动器中有碟片。(Rpc1可以选择区码而不要求碟片放在驱动器中。)一旦Rpc2驱动器的区码被设置,那么就无法通过重装windows或者卸载操作系统来自动改变区码了。

3、微软的DVD导航

在pc上播放DVD碟片时,微软的DVD导航使用以下方法来决定区码匹配:DVD导航获取碟片的区码、驱动器区码和解码器的区码。如果碟片区码是全区域的,则DVD导航将进行无条件播放;如果碟片不是全区域区码,DVD导航会检测解码器是否有预先设定区码;如果解码器包含的区码与碟片区码不匹配,则DVD导航会返回错误信息,以表明不能用当前DVD配置播放碟片;如果解码器区码与碟片区码相同,则DVD导航会继续检测驱动器区码是否与碟片区码相同,若相同,则DVD导航播放碟片。不同,则DVD导航调用代码来改变驱动器的区码;若允许改变区码的次数被用尽,则改变区码被视为失败,将不能进行播放。

4、DVD区码改变的发展

在Windows 9x系统中,当DVD导航检测到驱动器必要的区码改变时,使用DVDrgn.exe请求驱动器进行区码的改变。应用程序和操作系统的其它组件被分别安装到目标系统。示范方法如下:

在Windows 2000中,DVD导航调用设备管理中DVD-ROM驱动器设备的属性页。当区码需要被改变的时候,该属性页由DVDplay.exe应用程序产生。此属性页的用户界面非常类似DVDrgn.exe的,可被操作系统识别。

对于Rpc1驱动器,由Windows操作系统部件管理区码的改变;而Rpc2驱动器在其硬件中维持区码设置,在Rpc2驱动器中,当用尽允许改变的次数时,驱动器调用区码改变就会失败,操作系统的区码改变组件将会给用户这些情况和结果的说明。

5、安装支持Windows改变区码的部件

应用程序开发者可以利用DVD区码改变支持,在DVD应用程序中进行区码的改变。这里提供处理此问题的两种不同方法。

5.1、Windows 9x下

在Windows 9x 平台下,区码改变应用程序DVDrgn.exe,只有安装硬件解码和wdm的mini驱动后才被安装,且使用标准的inf文件。

对于软件解码器,可在inf文件中插入以下几行。(这是已安装程序加载DVDrgn.exe到目标系统的方法)

[Version]

Signature=$CHICAGO$

LayoutFile=layout.inf

[DestinationDirs]

DVDRgnCopy=25 ; Windows

DefaultDestDir=25 ; Windows

[DefaultInstall]

CopyFiles=DVDRgnCopy

[DVDRgnCopy]

DVDrgn.exe

5.2、Windows 2000 下

在Windows 2000 系统下,组件在Windows目录下的system32下的storprop.dll文件中提供了DVD区码改变的支持。此dll是通过默认方式安装的,没有额外的步骤来确认它的有效性。

6、在应用程序中加入整合区码改变支持

下面的代码为软件开发者提供了在DVD应用程序中加入DVD区码变化的代码:

/////////////////////////////////////////////////////////////////////

// ChangeDVDRegion : Function to change the DVD drive region.

//

// Parameters:

// In: hWnd - window handle of the application

// that calls this function

// Out: none.

//

// Returns:

// TRUE: if the drive region change is successful

// FALSE: if drive region change fails (probably because

// no drive was found with a valid DVD-V disc).

/////////////////////////////////////////////////////////////////////

BOOL ChangeDVDRegion(HWND hWnd)

{

typedef BOOL (APIENTRY *DVDPPLAUNCHER) (HWND hWnd, CHAR DriveLetter);

BOOL

bRegionChanged = FALSE;

TCHAR szCmdLine[MAX_PATH];

// First find out which drive is a DVD drive with a valid DVD-V disc.

TCHAR szDVDDrive[4];

if (! GetDriveLetter (szDVDDrive) )

{

MessageBox(hWnd,

TEXT("No DVD drive was found with DVD-V disc.")

TEXT("\nCannot change DVD region of the drive."),

TEXT("Error"), MB_OK | MB_INFORMATION) ;

return FALSE;

}

// Detect which OS we are running on. For Windows NT, use the storprop.dll,

// while for Windows 9x use the DVDRgn.exe application to change the region.

OSVERSIONINFO ver;

ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

GetVersionEx(&ver);

if (VER_PLATFORM_WIN32_NT == ver.dwPlatformId)

{

// Windows NT platform

HINSTANCE hInstDLL;

DVDPPLAUNCHER DVDPPLauncher;

CHAR szDVDDriveA[4];

#ifdef UNICODE

WideCharToMultiByte(0, 0, szDVDDrive, -1,

szDVDDriveA, sizeof(szDVDDriveA),

NULL, NULL );

#else

strcpy(szDVDDriveA, szDVDDrive);

#endif // UNICODE

GetSystemDirectory(szCmdLine, MAX_PATH);

lstrcat(szCmdLine, TEXT("\\storprop.dll"));

hInstDLL = LoadLibrary (szCmdLine);

if (hInstDLL)

{

DVDPPLauncher = (DVDPPLAUNCHER) GetProcAddress(hInstDLL,

"DVDLauncher");

if (DVDPPLauncher)

{

bRegionChanged = DVDPPLauncher(hWnd, szDVDDriveA[0]);

}

FreeLibrary(hInstDLL);

}

} // end of region change code for Windows NT platform

else // Windows 9x platform

{

// Get path of \windows\DVDrgn.exe for command line string

GetWindowsDirectory(szCmdLine, MAX_PATH);

lstrcat(szCmdLine, TEXT("\\DVDRgn.exe "));

// Add only the drive letter as command line parameter

lstrncat(szCmdLine, szDVDDrive, 1);

// Prepare to execute DVDRgn.exe

STARTUPINFO StartupInfo;

PROCESS_INFORMATION ProcessInfo;

StartupInfo.cb = sizeof(StartupInfo);

StartupInfo.dwFlags = STARTF_USESHOWWINDOW;

StartupInfo.wShowWindow = SW_SHOWNORMAL;

StartupInfo.lpReserved = NULL;

StartupInfo.lpDesktop = NULL;

StartupInfo.lpTitle = NULL;

StartupInfo.cbReserved2 = 0;

StartupInfo.lpReserved2 = NULL;

if (CreateProcess(csModuleName, szCmdLine,

NULL, NULL, TRUE,

NORMAL_PRIORITY_CLASS,

NULL, NULL, &StartupInfo, &ProcessInfo) )

{

// Wait until DVDRgn.exe finishes

WaitForSingleObject(ProcessInfo.hProcess, INFINITE);

DWORD dwRet = 1;

BOOL bRet = GetExitCodeProcess(ProcessInfo.hProcess,

&dwRet);

// If the user changed the drive region

// successfully, the exit code of DVDRgn.exe is 0.

if (bRet && 0 == dwRet)

{

bRegionChanged = TRUE;

}

}

} // end of region change code for Windows 9x platform

if (bRegionChanged) // if region changed successfully

{

// Delete old filter graph and create new filter graph

// via IDVDGraphBuilder::RenderDVDVideoVolume().

}

else // DVD region didn't happen

{

MessageBox(hWnd,

TEXT("DVD drive region could not be changed.")

TEXT("Error"), MB_OK | MB_INFORMATION) ;

}

} //End function ChangeDVDRegion

/////////////////////////////////////////////////////////////////////

// GetDriveLetter : Function to get the drive letter of the currently

// active DVD drive

// Parameters:

// In: pDVDC - pointer to IDVDControl interface of

// DVDNavigator filter..

// Out: pszDrive - the first DVD drive that is found

// to have a valid DVD-V disc.

//

// Returns:

// TRUE: if a DVD drive is found (with valid disc)

// FALSE: if no DVD drive was found with valid DVD-V disc.

/////////////////////////////////////////////////////////////////////

BOOL GetDriveLetter(IDVDControl *pDVDC, TCHAR *pszDrive)

{

CHAR szPathA[MAX_PATH];

TCHAR szPath[MAX_PATH];

ULONG ulActualSize;

pszDrive[0] = pszDrive[3] = 0;

// Get the current root directory

if (pDVDC ->GetRoot(szPathA, MAX_PATH, &ulActualSize))

{

#ifdef UNICODE

MultiByteToWideChar(CP_ACP, 0, szPathA, 0, szPath, MAX_PATH);

#else

lstrcpy(szPath, szPathA);

#endif // UNICODE

lstrcpyn(pszDrive, szPath, 3);

if (DRIVE_CDROM == GetDriveType(pszDrive)) // could be a DVD drive

return TRUE;

}

// Now loop through all the valid drives to detect which one

// is a DVD drive with a valid DVD-V disc in it.

// Get all valid drives

DWORD dwLeng = GetLogicalDriveStrings(MAX_PATH, szPath);

TCHAR *pszTemp = szPath;

// Try all drives one by one

for (DWORD dw = 0; dw < dwLeng; dw += 4)

{

// Look only for CD-ROM drives that has a disc with required (.ifo) files

if (DRIVE_CDROM == GetDriveType(pszTemp))

{

TCHAR szDVDPath1[MAX_PATH]

TCHAR szDVDPath2[MAX_PATH];

lstrcpyn(szDVDPath1, pszTemp, 4);

lstrcpyn(szDVDPath 2, pszTemp, 4);

lstrcat(szDVDPath1, TEXT("Video_ts\\Video_ts.ifo"));

lstrcat(szDVDPath2, TEXT("Video_ts\\Vts_01_0.ifo"));

// If the .ifo files exist on this drive then it has a valid DVD-V disc

if (DoesFileExist(achDVDPath1) && DoesFileExist(achDVDPath2))

{

lstrcpyn(pszDrive, pszTemp, 3);

return TRUE; // return the first drive that has a valid DVD-V disc

}

}

pszTemp += 4;

}

return FALSE ; // didn't find any DVD drive (with DVD-V content)

} //End function GetDriveLetter

/////////////////////////////////////////////////////////////////////

// DoesFileExist : Function to determine if the given filename is an existing file.

//

// Parameters:

// In: pszFile - filename string to check for existence.

// Out: none.

//

// Returns:

// TRUE: if the specified file is found.

// FALSE: if the specified file is not found.

/////////////////////////////////////////////////////////////////////

BOOL DoesFileExist(LPTSTR pszFile)

{

HANDLE hFile = NULL ;

// We don't want any error message box to pop up when we try to test

// if the required file is available to open for read.

UINT uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS |

SEM_NOOPENFILEERRORBOX);

hFile = CreateFile(pszFile, GENERIC_READ,

FILE_SHARE_READ, NULL,

OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,

NULL);

SetErrorMode(uErrorMode); // restore error mode

If (INVALID_HANDLE_VALUE == hFile)

return FALSE ;

CloseHandle(hFile);

return TRUE;

} //End function DoesFileExist

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有