UVCAndroid
repository·main·Indexed 19 days ago
https://github.com/shiyinghan/uvcandroidA library and sample project that enables non-rooted Android devices (Android 5.0+) to access UVC (USB Video Class) cameras. It provides the CameraConnectionService for managing USB device lifecycles, permission requests, and camera operations including preview, image capture, and video recording. The project incorporates native components such as libuvc for camera communication, libjpeg-turbo for JPEG processing, and RapidJSON for JSON parsing.
What's inside UVCAndroid
- UVCAndroid requires a device running Android 5.0 or higher. It is designed to access UVC cameras on non-rooted Android devices.
Overview of RapidJSON stream types
mainRapidJSON provides several specialized stream classes to optimize JSON parsing and generation depending on the data source:
- Memory Streams: Simple streams for handling data in memory (e.g.,
StringBufferfor output,StringStreamfor input). - File Streams: Reduces memory footprint by reading/writing directly to the file system (e.g.,
FileReadStreamfor input,FileWriteStreamfor output). - Encoded Streams: Handles conversion between byte streams and character streams (e.g.,
EncodedInputStream,EncodedOutputStream,AutoUTFInputStream,AutoUTFOutputStream). - Custom Streams: Users can implement their own stream interface to wrap existing objects or custom logic.
- Memory Streams: Simple streams for handling data in memory (e.g.,
Filter JSON content using intermediate SAX handlers
mainYou can create intermediate layers between a
Readerand aWriterto transform or filter JSON data on the fly. This allows for tasks like removing whitespace (condensing), reformatting (pretty printing), or modifying values (e.g., capitalizing strings) without ever building a DOM.Implementation Pattern:
- Create a filter struct that implements the SAX handler interface.
- The filter's methods should perform the desired transformation.
- The filter then calls the corresponding method on an underlying
OutputHandler(usually aWriterorPrettyWriter).
Note: Because SAX is event-based, you only see one piece of data at a time. If your filter requires context (like the current path from the root), you must manually track that state within your filter struct.
template<typename OutputHandler> struct CapitalizeFilter { CapitalizeFilter(OutputHandler& out) : out_(out) {} bool String(const char* str, SizeType length, bool copy) { std::string upper_str; for (SizeType i = 0; i < length; i++) { upper_str.push_back(std::toupper(str[i])); } return out_.String(upper_str.c_str(), upper_str.length(), true); } // Forward all other events to the output handler... bool StartObject() { return out_.StartObject(); } bool EndObject(SizeType n) { return out_.EndObject(n); } // ... etc OutputHandler& out_; };Handle JSON strings with null characters
mainRapidJSON supports JSON strings containing the Unicode character
U+0000(escaped as"\u0000"). Because C/C++ strings are typically null-terminated,strlen()will return an incorrect length for such strings.To correctly handle these, use
GetStringLength()to get the actual number of characters. This is also more efficient for buffer allocation.// If JSON is { "s" : "a\u0000b" } // strlen(document["s"].GetString()) would return 1 // Use GetStringLength() for the correct value (3) size_t len = document["s"].GetStringLength();Query JSON values and types
mainOnce parsed, you can query the
Documentor anyValueobject. Because aValuecan hold different types, you should first verify the type usingIsXXX()methods before callingGetXXX()to avoid undefined behavior or assertion failures.Common type checks and getters:
- String:
IsString()/GetString() - Boolean:
IsBool()/GetBool() - Null:
IsNull() - Number:
IsNumber()/IsInt()/IsDouble()/ etc. - Array:
IsArray() - Object:
IsObject()
assert(document.HasMember("hello")); assert(document["hello"].IsString()); printf("hello = %s\n", document["hello"].GetString());- String:
How up-sampling works in LibYuv
mainWhen up-sampling, the behavior varies significantly by filter:
- Point up-sampling: Uses a stepping rate of
src_width / dst_widthand starts at coordinatex = 0. Each pixel is replicated by the scale factor. - Bilinear up-sampling: Stretches the image so the first and last source pixels map exactly to the first and last destination pixels. This is achieved using
dx = (src_width - 1) / (dst_width - 1)andx = 0. - Box up-sampling: Switches to Bilinear filtering logic.
- Point up-sampling: Uses a stepping rate of
Customize RapidJSON Document and Value templates
mainRapidJSON's
ValueandDocumentare typedefs of template classes. You can customize them by providing specificEncodingandAllocatorparameters.Encoding: Specifies how JSON strings are stored in memory (e.g.,UTF8<>,UTF16<>,UTF32<>).Allocator: Defines the memory management strategy.Documentowns the allocator, whileValueonly references it.
Commonly used typedefs:
Value:GenericValue<UTF8<>>Document:GenericDocument<UTF8<>>
namespace rapidjson { template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > class GenericValue { // ... }; template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > class GenericDocument : public GenericValue<Encoding, Allocator> { // ... }; typedef GenericValue<UTF8<> > Value; typedef GenericDocument<UTF8<> > Document; } // namespace rapidjsonInvert images vertically
mainVertical flipping (inversion) can be achieved in two ways:
- General Method: Pass a negative source height to almost any libyuv function.
- Mirror Functions: Use
I420MirrororARGBMirrorand pass a negative height to achieve a 180-degree rotation.
Understand core libyuv formats and conversion logic
mainlibyuv relies on two core formats as conversion hubs:
- I420 (YUV): All YUV formats can be converted to or from
I420. - ARGB (RGB): All RGB formats can be converted to or from
ARGB.
When performing operations like scaling or planar functions, use these core formats. Most filtering functions (e.g.,
ARGBScale) are either channel-order agnostic or specifically designed forARGBorI420.- I420 (YUV): All YUV formats can be converted to or from
Use AutoUTF for runtime encoding detection
mainIf you need to handle files or streams where the encoding is not known until runtime, useAutoUTF. This encoding automatically chooses the appropriate format based on the input or output stream. It is designed to be used specifically withEncodedInputStreamandEncodedOutputStream.Understand LibYuv filtering modes and behavior
mainLibYuv implements several filtering modes for image scaling (up-sampling and down-sampling). The behavior of these filters depends on the
FilterModeand whether you are scaling up or down.Filter Modes
- Point: Takes the middle pixel (down-sampling) or replicates pixels (up-sampling). It is reversible and matches FFmpeg behavior.
- Bilinear: Uses a 2x2 pixel neighborhood.
- In down-sampling, it is considered correct and centered.
- In up-sampling, it stretches the image such that the first source pixel maps to the first destination pixel and the last source pixel maps to the last destination pixel. This results in slight magnification.
- Box: Averages the entire box.
- In down-sampling, it is equivalent to bilinear for a 2x scale factor.
- In up-sampling, the Box filter switches over to Bilinear behavior.
- Linear: A variant of bilinear sampling used in specific scaling contexts.
Understand ARGB layout and memory ordering
mainThe
FOURCCdescribes the order of channels in a register. On little-endian machines, the memory layout is the reverse of the register order.For
FOURCC_ARGB:- Register order:
A,R,G,B. - Memory order (Little Endian):
B,G,R,A(Blue is the lowest byte).
Important Note on Blending: When using
ARGBBlend, the R, G, and B channels must be premultiplied by alpha (preattenuated). Other functions typically do not require this./* The FOURCC macro reverses the order for little endian */ #define FOURCC(a, b, c, d) (((uint32)(a)) | ((uint32)(b) << 8) | ((uint32)(c) << 16) | ((uint32)(d) << 24)) /* Example: ARGB string read as uint32 */ FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B');- Register order: