Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
single_frame_codec.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
9
10namespace flutter {
11
13 const fml::RefPtr<ImageDescriptor>& descriptor,
14 uint32_t target_width,
15 uint32_t target_height,
17 : descriptor_(descriptor),
18 target_width_(target_width),
19 target_height_(target_height),
20 target_format_(target_format) {}
21
23
25 return 1;
26}
27
29 return 0;
30}
31
32Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle callback_handle) {
33 if (!Dart_IsClosure(callback_handle)) {
34 return tonic::ToDart("Callback must be a function");
35 }
36
37 if (status_ == Status::kComplete) {
38 if (!cached_image_) {
39 return tonic::ToDart("Image failed to decode");
40 }
41 if (!cached_image_->image()) {
42 return tonic::ToDart("Decoded image has been disposed");
43 }
44 tonic::DartInvoke(callback_handle, {tonic::ToDart(cached_image_),
46 return Dart_Null();
47 }
48
49 // This has to be valid because this method is called from Dart.
50 auto dart_state = UIDartState::Current();
51
52 pending_callbacks_.emplace_back(dart_state, callback_handle);
53
54 if (status_ == Status::kInProgress) {
55 // Another call to getNextFrame is in progress and will invoke the
56 // pending callbacks when decoding completes.
57 return Dart_Null();
58 }
59
60 auto decoder = dart_state->GetImageDecoder();
61
62 if (!decoder) {
63 return tonic::ToDart(
64 "Failed to access the internal image decoder "
65 "registry on this isolate. Please file a bug on "
66 "https://github.com/flutter/flutter/issues.");
67 }
68
69 // The SingleFrameCodec must be deleted on the UI thread. Allocate a RefPtr
70 // on the heap to ensure that the SingleFrameCodec remains alive until the
71 // decoder callback is invoked on the UI thread. The callback can then
72 // drop the reference.
73 fml::RefPtr<SingleFrameCodec>* raw_codec_ref =
75
76 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
77 decoder->Decode(
78 descriptor_,
79 {.target_width = target_width_,
80 .target_height = target_height_,
81 .target_format = target_format_},
82 [raw_codec_ref](const auto& image, const auto& decode_error) {
83 std::unique_ptr<fml::RefPtr<SingleFrameCodec>> codec_ref(raw_codec_ref);
84 fml::RefPtr<SingleFrameCodec> codec(std::move(*codec_ref));
85
86 auto state = codec->pending_callbacks_.front().dart_state().lock();
87
88 if (!state) {
89 // This is probably because the isolate has been terminated before the
90 // image could be decoded.
91
92 return;
93 }
94
95 tonic::DartState::Scope scope(state.get());
96
97 if (image) {
98 auto canvas_image = fml::MakeRefCounted<CanvasImage>();
99 canvas_image->set_image(std::move(image));
100
101 codec->cached_image_ = std::move(canvas_image);
102 }
103
104 // The cached frame is now available and should be returned to any
105 // future callers.
106 codec->status_ = Status::kComplete;
107
108 // Invoke any callbacks that were provided before the frame was decoded.
110 codec->pending_callbacks_) {
112 {tonic::ToDart(codec->cached_image_),
113 tonic::ToDart(0), tonic::ToDart(decode_error)});
114 }
115 codec->pending_callbacks_.clear();
116 });
117
118 // The encoded data is no longer needed now that it has been handed off
119 // to the decoder.
120 descriptor_ = nullptr;
121
122 status_ = Status::kInProgress;
123
124 return Dart_Null();
125}
126
127} // namespace flutter
int frameCount() const override
int repetitionCount() const override
SingleFrameCodec(const fml::RefPtr< ImageDescriptor > &descriptor, uint32_t target_width, uint32_t target_height, ImageDecoder::TargetPixelFormat destination_format)
Dart_Handle getNextFrame(Dart_Handle args) override
static UIDartState * Current()
FlutterVulkanImage * image
FlutterDesktopBinaryReply callback
Dart_Handle ToDart(const T &object)
Dart_Handle DartInvoke(Dart_Handle closure, std::initializer_list< Dart_Handle > args)