-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[camera] Add ability to concurrently record and stream video #6290
[camera] Add ability to concurrently record and stream video #6290
Conversation
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
084ea88
to
a33f148
Compare
Looks like I need to update |
One of the checks is failing because it doesn't want the PR to include both changes to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only reviewed the iOS part
return _frameStreamController!.stream; | ||
} | ||
|
||
void _installStreamController({Function()? onListen}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In startVideoRecording
Can we directly pass streamCallback
into _installStreamController()
and make it nonNull? A no-op onListen seems a bad state to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I totally understand. streamCallback
is the callback which receives each frame that is processed. onListen
is different, it's a callback invoked once when the stream is listened on. In the case of onStreamedFrameAvailable
it needs to call the native startImageStream
to begin the stream, but on the startVideoRecording
the camera stream has already been initialised during the call to the native startVideoRecording
. Therefore, in the case of startVideoRecording
, onListen
should be a no-op.
I could make onListen non-null, and have it up to the caller to default it to a no-op function, but that seems to put more burden on the caller. Is that preferable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant do we want to have onListen
for both use cases? It's a bit odd to have one streaming API with onListen, but the other streaming API without.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
onListen
isn't part of the public API though. It's an implementation detail inside this class. Nobody using the camera plugin will have to deal with it at all. The only reason that onListen
is nullable is that, in the case where they want to both stream and record, the initialization is another section of the (internal) code. StreamController
itself is a class external to the camera plugin and can't be easily modified.
Given that the method is private and internal to the class, is the difference still a concern? If it is, could you maybe code a quick mockup of what you're after, just so that I can understand?
packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart
Outdated
Show resolved
Hide resolved
_frameStreamController = StreamController<CameraImageData>( | ||
onListen: _onFrameStreamListen, | ||
onListen: onListen ?? () {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when do we want a no-op onListen
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully addressed in this comment, but let me know if not.
Thanks for the feedback @hellohuanlin , I'll wait for some feedback on the other modules as well and then address everything you raised. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed Android part!
packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java
Show resolved
Hide resolved
packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java
Outdated
Show resolved
Hide resolved
_frameStreamController = StreamController<CameraImageData>( | ||
onListen: _onFrameStreamListen, | ||
onListen: onListen ?? () {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider https://github.com/flutter/plugins/pull/6290/files#r952963757 here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replied in this comment, I don't think it applies unless I'm misunderstanding something.
082b493
to
837ddcd
Compare
Saw a few updates in my email. Just double check - let me know when it's ready for a second review. |
@stuartmorgan this is ready for re-review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
* 63f1b8fb6 [camera] Handle empty grantResults on permission request (flutter/plugins#6758) * 1579f2f33 Roll Flutter from 33f3e13 to 30fc993 (6 revisions) (flutter/plugins#6791) * 345bddbd8 [gh_actions]: Bump github/codeql-action from 2.1.27 to 2.1.35 (flutter/plugins#6788) * 374e59804 [camera] Add ability to concurrently record and stream video (flutter/plugins#6290)
We'll need to revert this; the new Android integration test is failing. See #6796 for details. I should have pushed a trivial change to this PR to trigger the Android tests, but forgot. @adam-harwood Are you able to reproduce that failure locally to debug it for an updated version of the PR? |
I ran them just now on an Android phone and cannot replicate the error you posted. I did get a different error though:
which I can fix, but I think it's unlikely it will solve the problem you posted. Applying the fix locally, all tests are then green. I'm testing this on an Android device, what device do the automatic runs execute on @stuartmorgan ? For reference, I'm running the tests with:
Which I assume is correct. |
…#116591) * 63f1b8fb6 [camera] Handle empty grantResults on permission request (flutter/plugins#6758) * 1579f2f33 Roll Flutter from 33f3e13 to 30fc993 (6 revisions) (flutter/plugins#6791) * 345bddbd8 [gh_actions]: Bump github/codeql-action from 2.1.27 to 2.1.35 (flutter/plugins#6788) * 374e59804 [camera] Add ability to concurrently record and stream video (flutter/plugins#6290)
Could you post a new PR that starts as a revert of the revert, and then has a commit that fixes the test issue you found locally (so we can easily review just the diff)? I can then push a commit to that PR to trigger the tests and we can see how it looks in CI.
It looks like it's a Samsung Galaxy S9 and a Pixel 5.
That should run the same tests. Unfortunately there's no easy way to run them exactly the same way as the CI runs them (we hope to add simulator tests at some point to avoid this disconnect), but that's usually not an issue. |
This re-commits the content from flutter#6290. Will make a subsequent commit to try and fix the broken integ tests.
Sure @stuartmorgan : #6808 |
…6808) * Re-enable stream and record This re-commits the content from #6290. Will make a subsequent commit to try and fix the broken integ tests. * Fix broken integration test for streaming The `whenComplete` call was sometimes causing a race condition. It is also isn't needed for the test (to reset the value of isDetecting, given it's local), so removing it makes the test reliable. * Trivial CHANGELOG change to trigger full CI tests Co-authored-by: stuartmorgan <[email protected]>
…#116591) * 63f1b8fb6 [camera] Handle empty grantResults on permission request (flutter/plugins#6758) * 1579f2f33 Roll Flutter from 33f3e13 to 30fc993 (6 revisions) (flutter/plugins#6791) * 345bddbd8 [gh_actions]: Bump github/codeql-action from 2.1.27 to 2.1.35 (flutter/plugins#6788) * 374e59804 [camera] Add ability to concurrently record and stream video (flutter/plugins#6290)
…#6290) * Implement interface methods to allow concurrent stream and record There will be a subsequent change to the `camera` package to make use of these implementations. * Fix android test * Format android_camera_test.dart * Resolve analyze failures * Fix version bumps * Fix MethodChannelCameraTest * Fix comment on FLTCam * Add tests to confirm can't stream on windows or web * CHANGELOG updates * Fix analyze errors * Fix dart analyze warnings for web * Formatted
…lutter#6290)" (flutter#6796) This reverts commit 374e598.
…lutter#6808) * Re-enable stream and record This re-commits the content from flutter#6290. Will make a subsequent commit to try and fix the broken integ tests. * Fix broken integration test for streaming The `whenComplete` call was sometimes causing a race condition. It is also isn't needed for the test (to reset the value of isDetecting, given it's local), so removing it makes the test reliable. * Trivial CHANGELOG change to trigger full CI tests Co-authored-by: stuartmorgan <[email protected]>
…lutter#6808) * Re-enable stream and record This re-commits the content from flutter/plugins#6290. Will make a subsequent commit to try and fix the broken integ tests. * Fix broken integration test for streaming The `whenComplete` call was sometimes causing a race condition. It is also isn't needed for the test (to reset the value of isDetecting, given it's local), so removing it makes the test reliable. * Trivial CHANGELOG change to trigger full CI tests Co-authored-by: stuartmorgan <[email protected]>
This PR adds the ability to optionally also enable streaming when starting recording of a video. This feature is useful, for example, in applications that use image recognition. The customer will want some immediate feedback as the video is being recorded (where an ML model might be run on the captured images), as well as to upload the video to a server at the end for final server-side processing.
Functionally, the new optional named parameter on
startVideoRecording
will combine the existing implementation with that ofstartImageStream
. Besides this, all functionality remains the same. For existing code, that does not use the new parameter, there is no change to the code path.I have added unit tests to the higher-level dart abstractions, added integration tests for the underlying android and iOS implementations, and tested manually on Android and iOS devices. I have updated
camera_web
to throw an exception if the user attempts to enable streaming when recording (given that streaming is not yet supported).Closes flutter/flutter#83634
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the [pub versioning philosophy], or this PR is [exempt from version changes].CHANGELOG.md
to add a description of the change, [following repository CHANGELOG style].///
).