Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync master #32

Merged
merged 3 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions flutter/lib/consts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ const String kKeyReverseMouseWheel = "reverse_mouse_wheel";
const String kEnvPortableExecutable = "RUSTDESK_APPNAME";

const Color kColorWarn = Color.fromARGB(255, 245, 133, 59);
const Color kColorCanvas = Colors.black;

const int kMobileDefaultDisplayWidth = 720;
const int kMobileDefaultDisplayHeight = 1280;
Expand Down
4 changes: 3 additions & 1 deletion flutter/lib/desktop/pages/remote_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ class _RemotePageState extends State<RemotePage>
_ffi.inputModel.enterOrLeave(false);
DesktopMultiWindow.removeListener(this);
_ffi.dialogManager.hideMobileActionsOverlay();
_ffi.imageModel.disposeImage();
_ffi.cursorModel.disposeImages();
_ffi.recordingModel.onClose();
_rawKeyFocusNode.dispose();
await _ffi.close(closeSession: closeSession);
Expand Down Expand Up @@ -277,7 +279,7 @@ class _RemotePageState extends State<RemotePage>
return Stack(
children: [
Container(
color: Colors.black,
color: kColorCanvas,
child: RawKeyFocusScope(
focusNode: _rawKeyFocusNode,
onFocusChange: (bool imageFocused) {
Expand Down
7 changes: 6 additions & 1 deletion flutter/lib/desktop/widgets/tabbar_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ class DesktopTab extends StatelessWidget {

List<Widget> _tabWidgets = [];
Widget _buildPageView() {
return _buildBlock(
final child = _buildBlock(
child: Obx(() => PageView(
controller: state.value.pageController,
physics: NeverScrollableScrollPhysics(),
Expand All @@ -358,6 +358,11 @@ class DesktopTab extends StatelessWidget {
return newList;
}
}())));
if (tabType == DesktopTabType.remoteScreen) {
return Container(color: kColorCanvas, child: child);
} else {
return child;
}
}

/// Check whether to show ListView
Expand Down
4 changes: 3 additions & 1 deletion flutter/lib/mobile/pages/remote_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class _RemotePageState extends State<RemotePage> {
super.dispose();
gFFI.dialogManager.hideMobileActionsOverlay();
gFFI.inputModel.listenToMouse(false);
gFFI.imageModel.disposeImage();
gFFI.cursorModel.disposeImages();
await gFFI.invokeMethod("enable_soft_keyboard", true);
_mobileFocusNode.dispose();
_physicalFocusNode.dispose();
Expand Down Expand Up @@ -310,7 +312,7 @@ class _RemotePageState extends State<RemotePage> {
initialEntries: [
OverlayEntry(builder: (context) {
return Container(
color: Colors.black,
color: kColorCanvas,
child: isWebDesktop
? getBodyForDesktopWithListener(keyboard)
: SafeArea(
Expand Down
16 changes: 16 additions & 0 deletions flutter/lib/models/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,7 @@ class ImageModel with ChangeNotifier {
parent.target?.canvasModel.updateViewStyle();
}
}
_image?.dispose();
_image = image;
if (image != null) notifyListeners();
}
Expand All @@ -1231,6 +1232,11 @@ class ImageModel with ChangeNotifier {
final yscale = size.height / _image!.height;
return min(xscale, yscale) / 1.5;
}

void disposeImage() {
_image?.dispose();
_image = null;
}
}

enum ScrollStyle {
Expand Down Expand Up @@ -1702,6 +1708,7 @@ class PredefinedCursor {
final defaultImg = _image2!;
// This function is called only one time, no need to care about the performance.
Uint8List data = defaultImg.getBytes(order: img2.ChannelOrder.rgba);
_image?.dispose();
_image = await img.decodeImageFromPixels(
data, defaultImg.width, defaultImg.height, ui.PixelFormat.rgba8888);

Expand Down Expand Up @@ -1937,6 +1944,11 @@ class CursorModel with ChangeNotifier {
notifyListeners();
}

disposeImages() {
_images.forEach((_, v) => v.item1.dispose());
_images.clear();
}

updateCursorData(Map<String, dynamic> evt) async {
final id = int.parse(evt['id']);
final hotx = double.parse(evt['hotx']);
Expand All @@ -1947,7 +1959,11 @@ class CursorModel with ChangeNotifier {
final rgba = Uint8List.fromList(colors.map((s) => s as int).toList());
final image = await img.decodeImageFromPixels(
rgba, width, height, ui.PixelFormat.rgba8888);
if (image == null) {
return;
}
if (await _updateCache(rgba, image, id, hotx, hoty, width, height)) {
_images[id]?.item1.dispose();
_images[id] = Tuple3(image, hotx, hoty);
}

Expand Down
82 changes: 60 additions & 22 deletions flutter/lib/utils/image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:flutter/widgets.dart';

import 'package:flutter_hbb/common.dart';

Future<ui.Image> decodeImageFromPixels(
Future<ui.Image?> decodeImageFromPixels(
Uint8List pixels,
int width,
int height,
Expand All @@ -18,36 +18,74 @@ Future<ui.Image> decodeImageFromPixels(
}) async {
if (targetWidth != null) {
assert(allowUpscaling || targetWidth <= width);
if (!(allowUpscaling || targetWidth <= width)) {
print("not allow upscaling but targetWidth > width");
return null;
}
}
if (targetHeight != null) {
assert(allowUpscaling || targetHeight <= height);
if (!(allowUpscaling || targetHeight <= height)) {
print("not allow upscaling but targetHeight > height");
return null;
}
}

final ui.ImmutableBuffer buffer =
await ui.ImmutableBuffer.fromUint8List(pixels);
onPixelsCopied?.call();
final ui.ImageDescriptor descriptor = ui.ImageDescriptor.raw(
buffer,
width: width,
height: height,
rowBytes: rowBytes,
pixelFormat: format,
);
if (!allowUpscaling) {
if (targetWidth != null && targetWidth > descriptor.width) {
targetWidth = descriptor.width;
}
if (targetHeight != null && targetHeight > descriptor.height) {
targetHeight = descriptor.height;
final ui.ImmutableBuffer buffer;
try {
buffer = await ui.ImmutableBuffer.fromUint8List(pixels);
onPixelsCopied?.call();
} catch (e) {
return null;
}

final ui.ImageDescriptor descriptor;
try {
descriptor = ui.ImageDescriptor.raw(
buffer,
width: width,
height: height,
rowBytes: rowBytes,
pixelFormat: format,
);
if (!allowUpscaling) {
if (targetWidth != null && targetWidth > descriptor.width) {
targetWidth = descriptor.width;
}
if (targetHeight != null && targetHeight > descriptor.height) {
targetHeight = descriptor.height;
}
}
} catch (e) {
print("ImageDescriptor.raw failed: $e");
buffer.dispose();
return null;
}

final ui.Codec codec = await descriptor.instantiateCodec(
targetWidth: targetWidth,
targetHeight: targetHeight,
);
final ui.Codec codec;
try {
codec = await descriptor.instantiateCodec(
targetWidth: targetWidth,
targetHeight: targetHeight,
);
} catch (e) {
print("instantiateCodec failed: $e");
buffer.dispose();
descriptor.dispose();
return null;
}

final ui.FrameInfo frameInfo;
try {
frameInfo = await codec.getNextFrame();
} catch (e) {
print("getNextFrame failed: $e");
codec.dispose();
buffer.dispose();
descriptor.dispose();
return null;
}

final ui.FrameInfo frameInfo = await codec.getNextFrame();
codec.dispose();
buffer.dispose();
descriptor.dispose();
Expand Down
35 changes: 21 additions & 14 deletions libs/scrap/src/common/hwcodec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,23 @@ use hbb_common::{
serde_json, ResultType,
};
use hwcodec::{
common::DataFormat,
common::{
DataFormat,
Quality::{self, *},
RateControl::{self, *},
},
ffmpeg::AVPixelFormat,
ffmpeg_ram::{
decode::{DecodeContext, DecodeFrame, Decoder},
encode::{EncodeContext, EncodeFrame, Encoder},
CodecInfo,
Quality::{self, *},
RateControl::{self, *},
},
};

const DEFAULT_PIXFMT: AVPixelFormat = AVPixelFormat::AV_PIX_FMT_NV12;
pub const DEFAULT_TIME_BASE: [i32; 2] = [1, 30];
const DEFAULT_GOP: i32 = i32::MAX;
const DEFAULT_HW_QUALITY: Quality = Quality_Default;
#[cfg(target_os = "android")]
const DEFAULT_RC: RateControl = RC_VBR; // android cbr poor quality
#[cfg(not(target_os = "android"))]
const DEFAULT_RC: RateControl = RC_CBR;

#[derive(Debug, Clone)]
pub struct HwRamEncoderConfig {
Expand All @@ -59,6 +57,7 @@ impl EncoderApi for HwRamEncoder {
{
match cfg {
EncoderCfg::HWRAM(config) => {
let rc = Self::rate_control(&config);
let b = Self::convert_quality(&config.name, config.quality);
let base_bitrate = base_bitrate(config.width as _, config.height as _);
let mut bitrate = base_bitrate * b / 100;
Expand All @@ -78,7 +77,8 @@ impl EncoderApi for HwRamEncoder {
timebase: DEFAULT_TIME_BASE,
gop,
quality: DEFAULT_HW_QUALITY,
rc: DEFAULT_RC,
rc,
q: -1,
thread_count: codec_thread_num(16) as _, // ffmpeg's thread_count is used for cpu
};
let format = match Encoder::format_from_name(config.name.clone()) {
Expand Down Expand Up @@ -175,6 +175,7 @@ impl EncoderApi for HwRamEncoder {
self.encoder.set_bitrate(bitrate as _).ok();
self.bitrate = bitrate;
}
self.config.quality = quality;
Ok(())
}

Expand Down Expand Up @@ -232,6 +233,14 @@ impl HwRamEncoder {
}
}

fn rate_control(config: &HwRamEncoderConfig) -> RateControl {
#[cfg(target_os = "android")]
if config.name.contains("mediacodec") {
return RC_VBR;
}
RC_CBR
}

pub fn convert_quality(name: &str, quality: crate::codec::Quality) -> u32 {
use crate::codec::Quality;
let quality = match quality {
Expand All @@ -241,11 +250,8 @@ impl HwRamEncoder {
Quality::Custom(b) => b,
};
let factor = if name.contains("mediacodec") {
if name.contains("h264") {
6
} else {
3
}
// https://stackoverflow.com/questions/26110337/what-are-valid-bit-rates-to-set-for-mediacodec?rq=3
5
} else {
1
};
Expand Down Expand Up @@ -510,7 +516,8 @@ pub fn check_available_hwcodec() {
timebase: DEFAULT_TIME_BASE,
gop: DEFAULT_GOP,
quality: DEFAULT_HW_QUALITY,
rc: DEFAULT_RC,
rc: RC_CBR,
q: -1,
thread_count: 4,
};
#[cfg(feature = "vram")]
Expand Down
Loading