[pvrusb2] Setting "the" video standard [was: PVR USB2 - how to check if it's dead?]

Mike Isely isely at isely.net
Sun Dec 23 22:29:32 CST 2012


On Sat, 22 Dec 2012, Helmut Jarausch wrote:

> 
> Last time I've been using my PVRUSB2 (one or two years ago)
> this wasn't necessary. And neither VLC nor MPLAYER2 are able
> to read /dev/video0 unless I issue that control in advance.

Well I can't exactly explain why it's different for you now.  But I can 
explain a few other things which hopefully should allow you to find a 
good solution.  This might get lengthy, requiring some history...

Way way back apparently in the early days of V4L there was a concept of 
a single video standard setting.  That was an enumeration.  The V4L API 
had a means whereby an app could get a list of the possible settings and 
then the app could choose one, communicating the choice back into the 
driver.

Some time later (this is still before the pvrusb2 driver showed up), a 
concept arose in the V4L subsystem whereby the "video standard" was 
represented as a set of flags, implemented as a collection of bits in a 
bit mask.  I think the rationale at the time was that this became a 
means for controlling / setting what subset of possible video standards 
a given driver / piece of hardware supports or was allowed to select 
from.  There is a "video standard" bit mask concept throughout V4L; this 
mask is a 64 bit integer and there are well over 32 possible different 
standards defined / represented within that bit mask.  This actually 
makes some sense when you realize that a lot of video hardware is more 
or less able to detect things correctly anyway, so it does sort of 
follow that you need a way to describe multiple possible standards at 
once...

Some time after that, the pvrusb2 driver arrived on the scene and I 
chose to reconcile this dual-mechanism in the driver.  Yes, it seems 
like something that every V4L should have to deal with, but at the time 
I was still learning how all this work, so I naively just "made it 
work".  So what I did was to expose "both" mechanisms, which 
unfortunately seemed confusing.  But within the driver what basically 
happened was that it computed the full set of available video standards 
as the bit mask, based on the detected hardware and some other bits of 
inference in the driver.  The driver then used that subset to generate 
the old-style enumerated list which then also became available to 
applications that wanted to work in that format.

Now, an aside about the sysfs interface: That sysfs driver interface is 
not a "real" V4L API of course, but it does make available at the shell 
all the "knobs" that can be adjusted in the driver.  The part of the 
pvrusb2 driver that implements the sysfs interface doesn't "implicitly 
know" what all the controls are.  Rather what that code does is it 
queries the rest of the driver for the set of controls and then makes 
each one appropriately visible (as an integer, enumeration, bit mask, 
etc) under /sys/class/pvrusb2/....  The nice thing about this approach 
is that now when the underlying controls change, there's no need to 
change the sysfs code in the driver because it automatically tracks.  
But this also means that as the underlying API changes, the sysfs 
representation can change as well...

For this dicussion, the sysfs controls in question are:

ctl_video_standard - enumerated list of standards
ctl_video_standard_mask_available - bit mask of available standards
ctl_video_standard_mask_active - bit mask of active standards
ctl_video_standard_mask_detected - bit mask of detected standards

More explained about this further down...

The control that is simplest to understand of course is just 
ctl_video_standard, but it is based on that computed enumerated list 
that dates from the early days of the driver.  The other three work from 
bit masks.  The pvrusb2 driver internally ensures that they all stay in 
sync with one another.  Keep reading...

Now because the sysfs part of the pvrusb2 driver doesn't "know" all the 
controls, it will only export what it finds.  And what's happened is 
that within V4L that old concept of enumerated standards has gone 
obsolete and disappeared from the V4L core.  And when that happened, I 
removed from the pvrusb2 driver all the old logic that generated that 
enumerated list.  The removal happened roughly coincident with the 3.0 
kernel.  With the removal of that logic, the underlying enumeration is 
gone and THAT is why the simple-to-understand ctl_video_standard is no 
longer present when you're running under a recent-enough kernel.

However you can still control things with the *_mask_active sysfs 
control.

Bit masks, as operated through the driver's sysfs interface, are a 
little wierd.  Each defined bit in a bit mask is just a token, e.g. 
"NTSC-M" or "PAL-B1".  You can retrieve a list of the legal tokens just 
by cat'ing the bit_val file.  For example, assuming you are sitting in 
the pvrusb2 driver's sysfs control directory at the shell prompt, then:

cat ctl_video_standard_mask_active/bit_val

will spit back a list of legal tokens, each on its own line.

If you just echo some set of whitespace-separated tokens into the 
control, then that set replaces what was there.  For example, this:

echo "NTSC-M PAL-M" >ctl_video_standard_mask_active/cur_val

will replace the current bit mask with a new bit mask with just NTSC-M 
and PAL-M set.  But this can get clumsy.  There's a second syntax you 
can use to set and clear bits.  This works for *ALL* sysfs controls 
which happen to be bit masks.  Just prefix each token with "+" or "-".  
Use "+" to add that token to the set, and "-" to remove that token from 
the set.  For the video standards, here's how you can just turn on, say, 
SECAM-B:

echo "+SECAM-B" >ctl_video_standard_mask_active/cur_val

Likewise, to turn off NTSC-M, assuming of course that it was on before:

echo "-NTSC-M" >ctl_video_standard_mask_active/cur_val

I said earlier there were three controls of interest here.  They are 
inter-related:

ctl_video_standard_mask_active - This controls the actual video standard 
bits that are enabled and that the rest of V4L sees.  This is the bit 
mask that gets directly adjusted via the V4L2 API, and this is what you 
have to change to affect the hardware.  (Note that when the old video 
standard enumeration was changed, the driver sync'ed this control to 
that enumeration's state and then used the resulting set bits to pass 
the information down into the rest of V4L.)

ctl_video_standard_mask_detected - This is just the set of video 
standards available that was detected by the hardware.  Not that unlike 
*_mask_active, this one is read-only in the file system.  You can't 
change it.  It's really just for informational purposes.  This "detected 
set" is used to help determine the default video mode - however if the 
device reports ability to support "too many" standards, then that leaves 
an ambiguity.  The driver will pick "something" as the starting default 
bit it might not be what you want.  (This is more of an issue for 
European multi-standard devices, then North American variants where 
there's really only one standard anyway.)

ctl_video_standard_mask_available - This is the set of actual available 
video standards, which is normally a superset of *_mask_detected.  The 
driver uses the detected set as a hint for enabling additional potential 
video standards.  You can change this, which causes the driver to 
constrain what standards an app is allowed to set as active (or to 
expand the available list).  This is useful to override cases where the 
driver might be too cautious.

Everyone still follow?

There's one more sysfs control field of interest "custom_val".  This is 
a different string representation for a given control that is more 
compact.  Yes, you can echo into that as well, but honestly right now 
I've forgotten the exact mechanics there so I'll leave that for now as 
an exercise to the reader :-)

So, in short, to set a different video standard via sysfs, then you need 
to enumerate the list of tokens by doing:

cat ctl_video_standard_mask_active/bit_val

Then pick what you want and echo the desired token(s) as a 
whitespace-separated list into the cur_val field.

No, you really can't set them all at once.  Well, I mean you *can*, but 
the hardware probably won't like it very much.  Some subsets do make 
sense when combined together, like probably PAL-B and PAL-G, but the 
answer of what works with what is really a hardware thing that the 
pvrusb2 driver can't know.  Just pick what you want and set it.

Or better still, if you are really running with a V4L2 app, then set the 
desired standard in the app and let the app control the driver 
appropriately.

I hope that helps clear things up.

I know there's a few other pending questions on this list.  More 
later...

  -Mike


-- 

Mike Isely
isely @ isely (dot) net
PGP: 03 54 43 4D 75 E5 CC 92 71 16 01 E2 B5 F5 C1 E8


More information about the pvrusb2 mailing list