Support Image Frame Streaming and flutter v3.32.7 - #69
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR adds image frame streaming functionality to the UVCCamera Flutter plugin and updates the version to 0.0.13. It enables real-time access to raw camera frame data for image processing, analysis, or other use cases while maintaining the existing camera preview and recording features.
- Introduces
UvcCameraFrameEventclass for representing frame data with metadata - Adds streaming API methods
startImageStream()andstopImageStream()toUvcCameraController - Implements native Android support using EventChannel for frame data transmission
Reviewed Changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| flutter/pubspec.yaml | Version bump from snapshot to 0.0.13 |
| flutter/lib/uvccamera.dart | Export new UvcCameraFrameEvent class |
| flutter/lib/src/uvccamera_frame_event.dart | New frame event model with image data and metadata |
| flutter/lib/src/uvccamera_platform_interface.dart | Platform interface methods for frame streaming |
| flutter/lib/src/uvccamera_platform.dart | Platform implementation for frame event channels |
| flutter/lib/src/uvccamera_controller_state.dart | Add isStreamingImages state tracking |
| flutter/lib/src/uvccamera_controller.dart | Frame streaming API and lifecycle management |
| flutter/example/lib/uvccamera_widget.dart | Example integration with streaming controls |
| flutter/example/lib/uvccamera_image_stream_demo.dart | Complete demo showcasing frame streaming |
| flutter/example/lib/uvccamera_device_screen.dart | Navigation to streaming demo |
| flutter/android/src/main/java/org/uvccamera/flutter/*.java | Native Android implementation |
| _onImageAvailable = onImageAvailable; | ||
|
|
||
| // Start native frame streaming | ||
| await UvcCameraPlatformInterface.instance.attachToCameraFrameCallback(_cameraId!); |
There was a problem hiding this comment.
The frame callback is attached twice - once during initialization (line 83) and again in startImageStream() (line 265). This creates duplicate event channels and potential resource leaks. Consider removing the attachment during initialization since streaming should be opt-in.
| await UvcCameraPlatformInterface.instance.attachToCameraFrameCallback(_cameraId!); | |
| // Line 83 removed to prevent redundant callback attachment during initialization. |
| frameEvent.put("width", 640); // Default width - should be configurable | ||
| frameEvent.put("height", 480); // Default height - should be configurable |
There was a problem hiding this comment.
Hardcoded width and height values (640x480) will not match actual camera resolution. These should be retrieved from the camera's actual configuration or passed as parameters to ensure frame metadata accuracy.
| frameEvent.put("width", 640); // Default width - should be configurable | |
| frameEvent.put("height", 480); // Default height - should be configurable | |
| frameEvent.put("width", width); // Use dynamic width | |
| frameEvent.put("height", height); // Use dynamic height |
| frameEvent.put("width", 640); // Default width - should be configurable | ||
| frameEvent.put("height", 480); // Default height - should be configurable |
There was a problem hiding this comment.
Hardcoded width and height values (640x480) will not match actual camera resolution. These should be retrieved from the camera's actual configuration or passed as parameters to ensure frame metadata accuracy.
| frameEvent.put("width", 640); // Default width - should be configurable | |
| frameEvent.put("height", 480); // Default height - should be configurable | |
| frameEvent.put("width", width); // Use actual width | |
| frameEvent.put("height", height); // Use actual height |
| frameEvent.put("width", 640); // Default width - should be configurable | ||
| frameEvent.put("height", 480); // Default height - should be configurable | ||
| frameEvent.put("timestamp", System.currentTimeMillis()); | ||
| frameEvent.put("format", "yuv420"); // Default format - should be determined from actual format |
There was a problem hiding this comment.
The hardcoded format 'yuv420' may not reflect the actual pixel format being used. This should be determined from the actual UVCCamera configuration or passed as a parameter to ensure accurate format reporting.
| frameEvent.put("format", "yuv420"); // Default format - should be determined from actual format | |
| frameEvent.put("format", pixelFormat); // Use dynamically determined format |
|
|
||
| try { | ||
| // Stop native frame streaming | ||
| await UvcCameraPlatformInterface.instance.detachFromCameraFrameCallback(_cameraId!); |
There was a problem hiding this comment.
This detachment may fail if the frame callback was never properly attached due to the duplicate attachment issue. The detachment should be more defensive and handle cases where the callback wasn't attached.
| // _frameEventSubscription = _cameraController!.cameraFrameEvents.listen((event) { | ||
| // log('frame: ${event.imageData.length}'); | ||
| // setState(() { | ||
| // _log = 'frame: ${event.imageData.length}\n$_log'; | ||
| // }); | ||
| // }); |
There was a problem hiding this comment.
Commented-out code should be removed rather than left in the production codebase. This reduces clutter and potential confusion for future developers.
| // _frameEventSubscription = _cameraController!.cameraFrameEvents.listen((event) { | |
| // log('frame: ${event.imageData.length}'); | |
| // setState(() { | |
| // _log = 'frame: ${event.imageData.length}\n$_log'; | |
| // }); | |
| // }); | |
No description provided.