[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