IkMijn pagina voor
prettig werken op de PC
www.pcpret.nl
Homepage Stuur bericht Gastenboek Website Blog Eindhoven

Software development, FM radio and Analog TV tuners in Windows

TV tuner specific subjects Analog TV tuner related subjects Introduction.
In november 2004, I decided to buy Windows Media Center Edition 2005. I also decided to build my own Media Center(Sorry in Dutch language). I choosed the Hauppauge Amity2 TV-card (with radio and teletext). That TV-card is quite similar to the Hauppauge PVR-150. The first impression was great. But after some time I discovered that the FM radio was unusable and the TV was hard to control. Compared with the FM radio, the TV was really great. You can get most of the broadcast stations, but the order, that is something that you should not want to change. A little bit strange because I can imagine that house-member has its/her own 10 favorite broadcaststations he/she wanted to choose easily. As result I am programming now, my own software using informatie available on the internet.

Ideas
What do I want to make? First of all I want to make a good FM radio plugin, programma that can be used on the Media Center computer, and maybe also within the Media Center program itselfs. The main reason, give me a good oversight of all broadcast stations (38 at this moment!) that I can receive. Than I want to have an better interface for adding and modifying the TV broadcast station list. Why is the UPC info screen on 10 while I never look at it, give met Omroep Flevoland or Talpa. It does not have a real high priority, but nevertheless I can give it a try. Surfing through the Teletext pages, just bij clicking the mouse or cursor on a 3-digit number looks great to me. Than I have some older external TV hardware that could be controlled by modern software. Even maybe even by real third-party programs. Finally I want to have user software (such as
Amcap) that can be used just within Windows to capture webcam video or VCR recordings.

The first steps
To get access to all media capabilities of the Windows computer, interface knowledge of specific Microsoft programs, such as DirectX (especially Directshow) is really needed. For more information on this, please
look here.And than there is Microsoft's Video Control (MsVidCtl), the new Multimedia interface in Windows XP.
My idea is that the DirectX functionality I want to use have not been changed. Happily the main concept of the DirectX looks quite simple. The disadvantage is, that it is rather complex and that in some cases, many many code is needed. So programming looks easy until something does not work. E.g. the TV audio (no audible sound) ...
Very nice utility is Graphedt.exe (a Directshow graph tool in Microsoft's DirectX SDK), see here for more information.

Analog TV, the first steps
I started with DSPack (see
Prodigy for DSPack in Delphi. A great package, only I did not have the DirectX knowledge yet. The example I started with, did not provide TV tuner support and could not switch pins.
The next step was to get insight information on DirectX. How? By looking around on the internet, getting the DirectX SDK, getting the Windows DDK. The DDK is needed in some cases because some header files and libraries are missing that seems to be needed for some SDK samples. I discovered that when I tried to compile some SDK Samples. Most interesting for me was Amcap and Audiocap, see here for more Amcap information.
The good thing was that it the functionality I wanted to make, worked with Graphedt. So I was sure that there was a solution. Thanks to the ChrisTV 4.70 TV program I got the idea what was going wrong: the TV-card is on a PCI bus and the TV-card does not have external audio. Okay, but what to do? Trying to figure out how every works and how everything should work ... and Graphedt was one of the answers ...
Finally I found that the example did do two things incorrectly: First, the sound was not rendered to the default WAVE device. Second, the needed (crossbar) pins were not connected.
The first one was quite easy to find because the code was just missing. The second one was much harder to find. Happily I used by accident two programs at the same time, and than there was sound. After some debugging it turned out that some pins were not connected.

Analog TV tuning, how to do?
Of course the first question that came up was how to tune. Well, a normal capture program gives access to the old fashioned looking Vfw tuner property. Here it is possible to select analog TV (or FMRadio) and select the wanted channel. But, what is a proper channel number? For TV the range of selectable channels seems to be for cable 1-368, and for antenna 1-69. In my country a proper channel has more to do with the last one and with S-channels for cable. What is the relation between this all (windows channels, Western Europe Broadcast Assignments, frequencies)? I tested a number of analog TV-tuners and there seems to be special mapping that is related to the frequency. I tested it with four analog TV tuners, the Hauppauge Amity2, a Lenco 878TV TV card, an oldy Miromedia PCTV and a Matrox Marvel G200. The mapping for three of them looks the same for all TV tuners, so that is nice to know. Okay, there are minor differences in the Vfw channel number range, e.g. the Amity 2 has 348 as maximum number.
The Matrox Marvel G200 works different from the rest, in all Windows versions (98, 2000 and XP). For cable the S channels (1-42), for antenna the normal TV channels (1-69) are taken into account. Furthermore the frequency settings do not match with the frequencies used by my provider (UPC Almere). Only for Windows 2000 a preliminary software version exists, in Windows XP the software seems to be incomplete, unstable or not working at all. Nevertheless Windows XP seems to support this TV-card with tuner. For TV the range of selectable channels seems to be for cable 1-368, and for antenna 1-69. For the Matrox Marvel additional investigation is needed.
The Code Project describes an example, DirectX.Capture project, the tuner property can be used by filling in the proper channel number. This example works also on Windows Media Center. Together with that example there was a suggestion for tuning also works on Windows XP (Media Center) via a registry update followed by a channel change request.

// TuningSpace is the Country number (eg for the Netherlands that is 31)
// IType is the tuner input type that could be cable=1 or antenna=0
// Example for opening the key
LocaleOverride = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
	"SOFTWARE\\Microsoft\\TV System Services\\TVAutoTune\\TS" +
	TuningSpace.ToString() +
	"-" +
	IType.ToString(), true);
But, in fact, this code using the registry did not work the way as I would expect. The registry update was not seen. But after understanding the frequency to Vfw channel mapping I found out that everything worked fine also without registry update ... So in a normal scenario the registry approach is probably not needed at all. Most of the broadcast station will probably be found by mapping the frequency to the proper channel. This was nice to know.
Why is the registry involved anyway? It took me some time to discover, but there is a good reason for that: finetuning. Finetuning might be needed when the broadcast station is (a little bit) mistuned. But than, the DirectX.Capture code, still did not work ... Finally I found out that when the program was restarted, the new registry value was found.
Finetuning via the register seems to be the new Microsoft way. It looks useful, however and it might be needed when the IKSPropertySet might not be supported anymore. In general Most TV-cards will probably work best in cable mode ... To use the Matrox Marvel G200 tuner properly, frequency (fine)tuning and switching the TV tuner between cable and antenna, seems to be needed.

For at least the Matrox Marvel G200, the channel number selection will be unusable as it is now. Mainly because there are differences in behavior compared with the other TV-cards. More specific information on the Matrox Marvel G200 can be found here.

Windows Media Center tuning help
As help for retrieving the Windows channel number I wrote the MCEtune program. This program can compose a TV tuner channel number from a TV tuner frequency and vica versa. This program can compose also the corresponding Windows tuning channel number, so the number could be filled in the Tuner property window. If you want try the program, look here for the download. The program supports video and audio preview, and also important: finetuning using IKsPropertySet. This makes tuning and finding a broadcast a lot easier ...
Windows MCE tuning help

Analog TV with DirectX.Capture
With DirectX.Capture (see The Code Project the TV tuner could be made more user friendly than the old-fashioned Vfw interface that askes for a channel number that is mapped to some TV broadcast frequency.
According to me, a big step forward would be, is to just select the wanted broadcast station. Than I need to have the names of the Broadcast Stations, and the correct frequencies (and/or channels) and the possibility to step through the list of names in the order that fits me the best. After that the program will figure out the Vfw channel mapping. The only thing the user should do is just select the broadcast station from a list. The order of broadcast station is following the order in the configuration file. Of course the program can be made more sophisticated, on the other hand, why is that really needed?
What I did than was to use my own broadcast station list, looked for the corresponding channel and when there was a special registry setting, that specific setting would be used. When using the most recent WDM drivers, this would work with most of the TV cards, and if there are no special registry settings, well there is no problem. The frequency to Vfw channel mapping is fixed and will do in most cases. Normally in the registry, the frequencies are stored in a tunerspace (country number) with the default Vfw channel number. However, there is no real need to use that specific Vfw channel number. The TV-tuner program should recognize that a different channel might be used ... In a bad scenario it would be possible that some frequencies become unreachable, however the chance on that, will be rare.
Pretty soon it turned out that the TV video display was not working properly. Mostly the TV display was slow or still, while the sound was going on. Finally I found out that the problem was caused by a minor (major) detail: the use of the preview pin for rendering video. For some reason I selected the capture pin instead of the preview pin and the TV is displayed as it should.

FM radio, get it working ...
How to tune the FM radio? Instead of channels, the frequency is used. I could not find much information on this on the internet or MSDN. The best information came again from The Code Project.
December 2005: Finally I wrote a nice FM Radio program which will run on the Hauppauge PVR150-MCE TV-Card (using drivers version 22280). The program uses the Windows Api for tuning so the program will probably also run on other brand/type TV-Cards supporting FM Radio. Of course the program got a tuning mechanism that shows the name of the Broadcast station and not the tuning frequency in the way the Media Center provides. And of course it is possible to select one of the 38 broadcast stations in an easy way. Even there is a little support for the Media Center remote control.
March 2006: I added audio file save support using the Windows Media Audio format. This functionality was quite easy to add because the program is based on the DirectX.Capture class example, the audio save method that was used, you can find here: Audio file save enhancements for the DirectX.Capture class or just here.
The user can select the channel wanted via the keyboard, the mouse or the Microsoft remote control. There is one big caveat: the FM Radio program (or the Media Center) may cause conflict if the programs run at the same time. The problem is that the Media Center does not tell (or at least I do not know how to check), if the TV or Radio mode is used. The TV tuner and the FM tuner are the same hardware and everything will work if no FM tuning is performed when the TV tuner is running. Another thing is that when the Media Center stops, the audio graph is torn down. This will affect the graph of the FM Radio program. There is an option in the FM Radio program that allows programming the FM Radio only. That is the most safe mode to use both programs at the same time. The TV tuner conflict is still there but Media Center will keep the audio (and video) control.
July 2006: Finally I installed the newest Hauppauge drivers (version 24103) for my PVR150-MCE TV-card. The drivers seems to work stable and correctly with my software now. Main problem was that the newest driver do not provide a separate audio capture driver. As result this driver will not work with a number of programs, such as the good old Amcap.
FMRadio program version 1.2

Something about Msvidctl.dll
When looking on internet for information on tv tuning, Visual Basic 6 examples using this Dll, will be found quite often. I hoped this gave me more insight in the use of the Dll within C#, but it seems that his Dll is not used that often. Happily, I was able to write a script that enabled me to control the FM radio. Funny, that there was not an example on the internet on that subject ... Hopefully there is a way to get rid of the video display box for FM radio, disabling video was not enough. And also, TV tuning was possible but I did not see the picture ... The advantage of this Dll above other solutions is that this Dll builds the full graph to get a "picture" and audible sound with only a few lines of code. I am wondering whether this Dll is used by the Media Center. The Media Center works slightly different because of the time-shifting. This would mean that a different graph is needed than the one MsVidCtl would make by default. So my impression, is that everythings works a little bit different than Microsoft tells us.

Set analog TV broadcast frequency directly ...
On www.codeproject.com, an interesting article was found: DirectShow - Fine TV Tuning Using IKsPropertySet. was found. Nice information, but what to do when programming C#, Delphi and not C++?
First I thougth, make a DLL and go on, however it is also a challenge to find the C# way ... So I started with investigations. What was the purpose of QueryInterface()? Why calling QuerySupported()? It turned out that QueryInterface() could be ignored, it is an implicit part of the interface. Well, QuerySupported() is needed, what is it doing? What does it need? And also, what to do with INSTANCEDATA_OF_PROPERTY_PTR and INSTANCEDATA_OF_PROPERTY_SIZE? What is instance data and what is property data? The property data seems to be the whole interface structure, is the instance data part? What is needed for using the IKsPropertySet interface is the IAMTVTuner interface which can be found via FindInterface(). In my case, the IAMTVTuner interface was already available, so I could just use it. Than the Tuner property ID and a number of structures and enumerations are needed, that are in ksmedia.h but not yet in DirectShowLib. So all the needed code was ported to Tuner.cs in the DirectX.Capture. The code could go into "any" file related to the TV tuner, and that one was the most appropriate one. The porting causes a number of difficulties, mainly because the structures needed to have the same layout as the C version but also should be usable for the C# implementation. But amazing some structures caused errors and needed to be resized. But finally I got access to KSPROPERTY_TUNER_MODE_CAPS and KSPROPERTY_TUNER_FREQUENCY. And it is very nice to have a function that can just set each tuning frequency, that you need without bothering about register settings.
TV finetuning using IksPropertySet interface Because it came on my way, I made also a Delphi version of the frequency tuning function. This was less work because DSPack234 covers the needed interfaces, enumerations and structures that looks as straight copy of the DirectX SDK. There were some code examples floating around (e.g. on Prodigy). These may probably not work because QuerySupported is used incorrectly, but also the PKSPROPERTY macro was not used as it was intended to be used. So, it was easier to start from scratch and just port from the C, C# code to Delphi. Interesting idea was to use the horizontal lock in the IAMAnalogVideoDecoder interface to check the tv finetuning. In the code example I saw this was combined with setting the video decoder to the PAL_B video standard. I removed that part, that is completely different functionality that needs to be used upon initializing the graph if it defaults to NTSC.

A C# tv finetuning code example can be found at www.codeproject.com, DirectShow - TV finetuning using the IKsPropertySet in C#.

Save captured audio/video to file ...
File saving in Avi, Asf, Mpeg2, Wav and MP3 format has been implemented. For Mpeg2 file saving the Hauppauge hardware Mpeg2 encoder and a suitable file writer are used. The standard file writer can not be used. For MP3 encoding the Lame Mp3 encoder is used. File saving for audio and video is quite different. For video the SetOutputFileName method in combination with a RenderStream for building the graph will do. For audio the graph needs to be built downstream, so filters needs to be added and connected downstream. For audio no SetOutputFileName can be used, instead of that the file writer property interface must be used.
For Mpeg2 additional information might be useful. The Hauppauge file writer is suitable for Mpeg2 file saving. However, for specifying the filename the property page must be used because the file writer interface is unknown. So I looked around for alternatives. I found some other dump filters that seems to be usable from Roxio, Nero and Intervideo. Initially these dump filters could not be used. This because my program did start/stop file saving more than once causing the file erasure before it could be used. At a certain moment I discovered the Dump filter in the Windows Media Format SDK: dump.ax This dump file is a coding sample, so you can look what it does: just writing the byte stream to file! After some debugging I found the problem in my program. After some more debugging, I added the IFileSinkFilter2 interface to this filter. Now I could simplify the coding a little bit.

Video format and video control settings ...
I found a way to set the video to Pal format and storing the video control settings (intensity, sharpness ...). Change Video Signal Format with DirectX library

Using TV audio in a program
Watching TV and listening to the sound with your own TV program is a great result. More nice is that the sound can be switched to stereo sound or can be switched to the first or second language, if possible ofcourse. Older TV cards have usually Mono sound, modern ones usually have Stereo sound. Selecting sound is possible via the TV Audio property page. The disadvantage is that the selection goes manually, usually via some mouse clicks. Nicer it is to select it via software, automatic if possible. For this the put_TVAudioMode method from the IAMTVAudio interface can be used. As parameter an TVAudioMode enumeration value should be specified. The allowed values for TVAudioMode are Mono (=0x0001), Stereo (=0x0002), LangA (=0x0010), LangB (=0x0020) and LangC (=0x0040). Using this with the Pinnacle PCTV Pro Hybrid 310i, I bought in december 2007, I got mono sound. After some research and try-outs, I found out that about 1,5 second after tuning a TV broadcast station, the stereo sound can be selected succuesfully. With the Hauppauge Amity2 and PVR150 TV-card, stereo sound will be switched on right away. Then I tried to switch to the second language (LangB), I used Eurosport TV broadcast for testing this. Well, the Hauppauge and the Pinnacle PCTV card behaves a little bit different but finally everything worked fine. With one difference, the Pinnacle PCTV card did something special with the third language (LangC). The Pinnacle PCTV card swiths to dual language, this means the first language coms via the left audio channel and the second language via the right audio channel. Interesting is the use of the methods GetAvailableTVAudioModes and GetHardwareSupportedTVAudioModes. The method GetAvailableTVAudioModes tells which TVAudioModes can be used for the TV broadcast station that is currently tuned. The method GetHardwareSupportedTVAudioModes tells which TVAudioModes are supported by the hardware.

Windows 7
Compared with previous Windows versions, in Windows 7 the TV tuner interface has changed, The mapping of channel numbers to TV broadcast frequencies is different so when using channel numbers, these channels needs to be re-calculated ...

TV tuner features and challenges (problems)';
The past years a lot of TV tuners came across. Several problems cause a TV card to become out of date. Sometimes it is because of the PC memory size, e.g. the Hauppauge PVR 150 fails working correctly starting from 4 GB memory size. Below 4GB the tuner can still be used but that does not help much if you are used to have 8 or 16 GB memory installed in your PC.
A stayer is the Pinnacle 310i, this TV card just keep working. Same is true for the Hauppauge PCI Express TV cards, I did some testing with the HVR 1200.
The old ones with BT848 or 878 chipset can hardly be used in Windows 7 and higher due to lack of suitable drivers. With the BtPCI drivers sometimes these old cards can still be used.

Interesting links
Interesting links, well: The Code Project, here you can find a lot of code examples; Prodigy, DSPack and Prodigy, DSPack forum, DSPack offers a DirectX interface to Delphi; Microsoft MSDN, here you can find a lot of information of how Windows can control the TV tuner hardware.

Back to the beginning? Click here.


Back to the Software Development page,
the Homepage or the Hobby activities page.


Contact me? Go back to/look at the Software Development page.
Date: march 26, 2015