Daniel
Could you please give a reference where "YUV" preview is required for
Android devices? The Android 2.1 Compatibility Definition document [1]
doesn't even include the string "YUV", and it's pretty clear that YCbCr is
not required in section 8.9.
Thanks,
Daniel
@aricblumer - NV21 is a specific encoding of YUV. For some details, see:
http://www.fourcc.org/yuv.php YUV alone is not sufficient since it doesn't
specify byte ordering within each field, nor whether it's a planar
representation, etc.
So, by specifying NV21 as the default preview format, we are specifying a
byte-specific representation of YUV for the preview format.
Section 8.9, item #2 in the bulleted list.
There is a huge difference between a default and a requirement. Section
8.9 #2 is quite clear that it only applies when the default preview format
is used. That default preview format is not required.
So back to my original question: Could you please give a reference
where "YUV" preview is required for Android devices? If it's not required,
then zxing should not require it.
Are we reading the same text?
Device implementations MUST implement the following behaviors for the
camera-related APIs [Resources, 27]:
1. If an application has never called
android.hardware.Camera.Parameters.setPreviewFormat(int), then the device
MUST use android.hardware.PixelFormat.YCbCr_420_SP for preview data
provided to application callbacks.
2. If an application registers an android.hardware.Camera.PreviewCallback
instance and the
system calls the onPreviewFrame() method when the preview format is
YCbCr_420_SP, the
data in the byte[] passed into onPreviewFrame() must further be in the NV21
encoding format.
(This is the format used natively by the 7k hardware family.) That is, NV21
MUST be the default.
It's pretty black and white there: The device must use YCbCr_420_SP / NV21
(nee "YUV") as the default, supported preview format. Whether the app has
set a preview format is irrelevant. This requirement cannot be fulfilled
unless the format is supported -- it happens to be a moot point for an app
that *does* set a preview format, but, naturally an app can exist that does
not. How does a device behave correctly for that app without supporting
YUV, in light of the text above?
Backing up, what's the problem you're facing? It's not desirable to use RGB
here if you don't have to, since it will involve luminance conversion
overhead. If you have a device that can't support YUV, then the CDD doc
seems to be pretty clear that's the device problem, but, you can still
write RGB support, per above. You're welcome to do it, and even contribute
if you like.
Yes, we're reading the same text, but I believe the confusion lies with the
use of the term "application" in this context. From the Linux side of
things, I did not take that as the end-user code, but as the Video4Linux
CameraHardwareInterface code. Our camera produces Bayer format images
(converted to RGB565), not YCbCr, so we call setPreviewFormat() to let the
system know that and satisfy requirement 1. Works fine.
There is also a comment in the Android code that indicates YCbCr is not
required: From
frameworks/base/graphics/java/android/graphics/PixelFormat.java:
/**
* YCbCr formats, used for video. These are not necessarily supported
* by the hardware.
*/
public static final int YCbCr_422_SP= 0x10;
If they meant only end-user code, then I understand your viewpoint. But,
IMHO, if they wanted to require that all cameras produce YCbCr_420_SP, they
should have listed that at the beginning of section 8.9 where it does list
the camera's requirements, rather than imply it in the context of software
API behavior (and then say the opposite in the code).
Regardless, it was fairly straightforward to get an RGB video source
working, although RGB to grayscale in Java is pretty slow.
I'm certain the CDD is specifying requirements on the API exposed to
applications here. It's differentiating between "implementation"
and "application". The method it mentions is an application API method. And
at least, there's the confirmation of two people actually working on this
bit of Android.
I read that comment as it reads: the hardware itself may do as it likes.
The implementation must however expose particular behavior to applications.
This implies the implementation must convert to YUV if the hardware does
not. It is not required that the hardware produce YUV, so it doesn't say
that. This all looks consistent to me.
I guess a soft corollary is this, which is I think what you're getting at:
if the upstream Android source code does not have a sort of 'driver' for
hardware that's not already producing this format, then it can't be used
without modification with cameras that don't output YUV. (I don't know the
source well enough to know that it doesn't have such support, but for the
sake of argument...)
I don't know if that means Android would like to have a patch with such
support, or whether the idea is you'd want to patch and maintain this
difference in your downstream source to go with your device. I think it's
the latter. You'd want to be able to support this translation inside the
implementation anyway, rather than patching one application.
It has been a while since I've been able to work on this. I've converted
one of our camera interfaces from RGB to YCbCr for a camera that supports
YCbCr. To my surprise, Android shows the preview in grayscale rather than
color in the camera application (at least as of Android 2.1 r2).
Investigating, I found code like this
(frameworks/base/libs/surfaceflinger/Layer.cpp in this case):
case GGL_PIXEL_FORMAT_YCbCr_422_SP:
case GGL_PIXEL_FORMAT_YCbCr_420_SP:
// just show the Y plane of YUV buffers
bpp = 1;
break;
Similar comments are in frameworks/base/libs/surfaceflinger/LayerBase.cpp.
So it appears that Android requires preview in a format that it does not
fully support. I'm not sure what direction we'll go, but grayscale preview
is out of the question.
Bleh, you may be on to something there.
But I think most (?) Android device cameras output YUV already, and of
course preview frames are available in color. What's the difference here
again?
There are 3 differences I can think of:
1. The phone vendors have already fixed Android to handle YCbCr properly in
their previews.
2. They have hardware overlays or accelerators that convert the YCbCr of
the camera preview back to RGB for LCD display without any processor
intervention. This option is not available on our platform.
3. The publicly available Android source is not what the phone vendors are
using.