Skip to content

Commit

Permalink
[video_player_avplay] Add get streaming property interface and Update…
Browse files Browse the repository at this point in the history
… SetStreamingProperty interface (flutter-tizen#672)
  • Loading branch information
xiaowei-guan authored Mar 11, 2024
1 parent e5a7fb0 commit 7a4d26f
Show file tree
Hide file tree
Showing 15 changed files with 455 additions and 36 deletions.
3 changes: 2 additions & 1 deletion packages/video_player_avplay/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## NEXT
## 0.4.0

* Minor refactor.
* Add getStreamingProperty interface.

## 0.3.3

Expand Down
2 changes: 1 addition & 1 deletion packages/video_player_avplay/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ To use this package, add `video_player_avplay` as a dependency in your `pubspec.

```yaml
dependencies:
video_player_avplay: ^0.3.3
video_player_avplay: ^0.4.0
```
Then you can import `video_player_avplay` in your Dart code:
Expand Down
101 changes: 96 additions & 5 deletions packages/video_player_avplay/lib/src/messages.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,58 @@ class DurationMessage {
}
}

class StreamingPropertyMessage {
StreamingPropertyMessage({
required this.playerId,
required this.streamingProperty,
});

int playerId;

String streamingProperty;

Object encode() {
return <Object?>[
playerId,
streamingProperty,
];
}

static StreamingPropertyMessage decode(Object result) {
result as List<Object?>;
return StreamingPropertyMessage(
playerId: result[0]! as int,
streamingProperty: result[1]! as String,
);
}
}

class StreamingPropertyTypeMessage {
StreamingPropertyTypeMessage({
required this.playerId,
required this.streamingPropertyType,
});

int playerId;

String streamingPropertyType;

Object encode() {
return <Object?>[
playerId,
streamingPropertyType,
];
}

static StreamingPropertyTypeMessage decode(Object result) {
result as List<Object?>;
return StreamingPropertyTypeMessage(
playerId: result[0]! as int,
streamingPropertyType: result[1]! as String,
);
}
}

class _VideoPlayerAvplayApiCodec extends StandardMessageCodec {
const _VideoPlayerAvplayApiCodec();
@override
Expand Down Expand Up @@ -395,15 +447,21 @@ class _VideoPlayerAvplayApiCodec extends StandardMessageCodec {
} else if (value is SelectedTracksMessage) {
buffer.putUint8(136);
writeValue(buffer, value.encode());
} else if (value is TrackMessage) {
} else if (value is StreamingPropertyMessage) {
buffer.putUint8(137);
writeValue(buffer, value.encode());
} else if (value is TrackTypeMessage) {
} else if (value is StreamingPropertyTypeMessage) {
buffer.putUint8(138);
writeValue(buffer, value.encode());
} else if (value is VolumeMessage) {
} else if (value is TrackMessage) {
buffer.putUint8(139);
writeValue(buffer, value.encode());
} else if (value is TrackTypeMessage) {
buffer.putUint8(140);
writeValue(buffer, value.encode());
} else if (value is VolumeMessage) {
buffer.putUint8(141);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
Expand Down Expand Up @@ -431,10 +489,14 @@ class _VideoPlayerAvplayApiCodec extends StandardMessageCodec {
case 136:
return SelectedTracksMessage.decode(readValue(buffer)!);
case 137:
return TrackMessage.decode(readValue(buffer)!);
return StreamingPropertyMessage.decode(readValue(buffer)!);
case 138:
return TrackTypeMessage.decode(readValue(buffer)!);
return StreamingPropertyTypeMessage.decode(readValue(buffer)!);
case 139:
return TrackMessage.decode(readValue(buffer)!);
case 140:
return TrackTypeMessage.decode(readValue(buffer)!);
case 141:
return VolumeMessage.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
Expand Down Expand Up @@ -876,4 +938,33 @@ class VideoPlayerAvplayApi {
return;
}
}

Future<StreamingPropertyMessage> getStreamingProperty(
StreamingPropertyTypeMessage arg_msg) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.video_player_avplay.VideoPlayerAvplayApi.getStreamingProperty',
codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_msg]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as StreamingPropertyMessage?)!;
}
}
}
38 changes: 35 additions & 3 deletions packages/video_player_avplay/lib/src/video_player_tizen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';

Expand Down Expand Up @@ -42,7 +40,13 @@ class VideoPlayerTizen extends VideoPlayerPlatform {
message.httpHeaders = dataSource.httpHeaders;
message.drmConfigs = dataSource.drmConfigs?.toMap();
message.playerOptions = dataSource.playerOptions;
message.streamingProperty = dataSource.streamingProperty;
message.streamingProperty = dataSource.streamingProperty == null
? null
: <String, String>{
for (final MapEntry<StreamingPropertyType, String> entry
in dataSource.streamingProperty!.entries)
_streamingPropertyType[entry.key]!: entry.value
};
break;
case DataSourceType.file:
message.uri = dataSource.uri;
Expand Down Expand Up @@ -197,6 +201,16 @@ class VideoPlayerTizen extends VideoPlayerPlatform {
return Duration(milliseconds: response.position);
}

@override
Future<String> getStreamingProperty(
int playerId, StreamingPropertyType type) async {
final StreamingPropertyMessage streamingPropertyMessage =
await _api.getStreamingProperty(StreamingPropertyTypeMessage(
playerId: playerId,
streamingPropertyType: _streamingPropertyType[type]!));
return streamingPropertyMessage.streamingProperty;
}

@override
Stream<VideoEvent> videoEventsFor(int playerId) {
return _eventChannelFor(playerId)
Expand Down Expand Up @@ -286,4 +300,22 @@ class VideoPlayerTizen extends VideoPlayerPlatform {
2: AudioTrackChannelType.stereo,
3: AudioTrackChannelType.surround,
};

static const Map<StreamingPropertyType, String> _streamingPropertyType =
<StreamingPropertyType, String>{
StreamingPropertyType.adaptiveInfo: 'ADAPTIVE_INFO',
StreamingPropertyType.availableBitrate: 'AVAILABLE_BITRATE',
StreamingPropertyType.cookie: 'COOKIE',
StreamingPropertyType.currentBandwidth: 'CURRENT_BANDWIDTH',
StreamingPropertyType.getLiveDuration: 'GET_LIVE_DURATION',
StreamingPropertyType.inAppMultiView: 'IN_APP_MULTIVIEW',
StreamingPropertyType.isLive: 'IS_LIVE',
StreamingPropertyType.listenSparseTrack: 'LISTEN_SPARSE_TRACK',
StreamingPropertyType.portraitMode: 'PORTRAIT_MODE',
StreamingPropertyType.prebufferMode: 'PREBUFFER_MODE',
StreamingPropertyType.setMixedFrame: 'SET_MIXEDFRAME',
StreamingPropertyType.setMode4K: 'SET_MODE_4K',
StreamingPropertyType.userAgent: 'USER_AGENT',
StreamingPropertyType.useVideoMixer: 'USE_VIDEOMIXER',
};
}
10 changes: 9 additions & 1 deletion packages/video_player_avplay/lib/video_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
/// Sets specific feature values for HTTP, MMS, or specific streaming engine (Smooth Streaming, HLS, DASH, DivX Plus Streaming, or Widevine).
/// The available streaming properties depend on the streaming protocol or engine.
/// Only for [VideoPlayerController.network].
final Map<String, String>? streamingProperty;
final Map<StreamingPropertyType, String>? streamingProperty;

/// **Android only**. Will override the platform's generic file format
/// detection with whatever is set here.
Expand Down Expand Up @@ -714,6 +714,14 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
await _applyVolume();
}

/// Retrieves a specific property value obtained by the streaming engine (Smooth Streaming, HLS, DASH, or Widevine).
Future<String> getStreamingProperty(StreamingPropertyType type) async {
if (_isDisposedOrNotInitialized) {
return '';
}
return _videoPlayerPlatform.getStreamingProperty(_playerId, type);
}

/// Sets the playback speed of [this].
///
/// [speed] indicates a speed value with different platforms accepting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ abstract class VideoPlayerPlatform extends PlatformInterface {
throw UnimplementedError('getDuration() has not been implemented.');
}

/// Retrieves a specific property value obtained by the streaming engine (Smooth Streaming, HLS, DASH, or Widevine).
Future<String> getStreamingProperty(
int playerId, StreamingPropertyType type) {
throw UnimplementedError(
'getStreamingProperty() has not been implemented.');
}

/// Returns a widget displaying the video with a given playerId.
Widget buildView(int playerId) {
throw UnimplementedError('buildView() has not been implemented.');
Expand Down Expand Up @@ -217,7 +224,7 @@ class DataSource {
Map<String, dynamic>? playerOptions;

/// Sets specific feature values for HTTP, MMS, or specific streaming engine
Map<String, String>? streamingProperty;
Map<StreamingPropertyType, String>? streamingProperty;
}

/// The way in which the video was originally loaded.
Expand Down Expand Up @@ -253,6 +260,63 @@ enum VideoFormat {
other,
}

/// The streaming property type.
enum StreamingPropertyType {
/// HTTP request cookie used to establish the session with the HTTP server.
cookie,

/// HTTP user agent, used in the HTTP request header.
userAgent,

/// Property to initiate prebuffering mode. The second parameter indicates start-time for prebuffered content, in milliseconds.
prebufferMode,

/// Sets a custom streaming URL with various streaming parameters, such as "BITRATES", "STARTBITRATE", or "SKIPBITRATE".
/// String containing custom attributes for adaptive streaming playback.
/// "STARTBITRATE=" Valid values are "LOWEST", "HIGHEST", and "AVERAGE". You can also define a specific bandwidth for the start of playback.
/// "BITRATES=" Use '~' to define a bandwidth range (5000 ~ 20000). You can also define a specific bandwidth for playback.
/// "SKIPBITRATE=" Defines the bandwidth to use after a skip operation.
/// "STARTFRAGMENT=" For live content playback, defines the start fragment number.
/// "FIXED_MAX_RESOLUTION=max_widthXmax_height". Only if the given media URI such as mpd in MPEG-DASH or m3u8 in HLS through open()
/// method doesn't describe entire required video resolutions,application should use this attribute to complete the resolution information for the player.
adaptiveInfo,

/// Forces the player to use the 4K UHD decoder. Its parameter can be the string "TRUE" or "FALSE".
/// In the case of adaptive streaming which requires stream-change for different video resolution during the playback,
/// Only if the given media URI such as mpd in MPEG-DASH or m3u8 in HLS through open() method doesn't describe entire required video resolutions,
/// pass TRUE with this property in IDLE state.
setMode4K,

/// For the Smooth Streaming case, configures the player to listen for a "Sparse name" configured through "propertyParam" . The sparse track name is a string.
listenSparseTrack,

/// Whether the stream is LIVE or VOD. Applicable to all streaming types.
isLive,

/// String listing the available bit-rates for the currently-playing stream.
availableBitrate,

/// String describing the duration of live content.
getLiveDuration,

/// String describing the current streaming bandwidth.
currentBandwidth,

/// Property used for enabling/initializing video mixer feature on B2B product only. It should be set before
/// setting SET_MIXEDFRAME property on the player.
useVideoMixer,

/// Property to set the position of mixed frame. setDisplayRect with required position on corresponding
/// player instance to be called before setting this property.
setMixedFrame,

/// Property to force the playback the video in potrait mode on B2B proudct only.
portraitMode,

/// Property to select the Scaler type, By Default MAIN Scaler selected.
inAppMultiView,
}

/// Event emitted from the platform implementation.
@immutable
class VideoEvent {
Expand Down
14 changes: 14 additions & 0 deletions packages/video_player_avplay/pigeons/messages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ class DurationMessage {
List<int?>? durationRange;
}

class StreamingPropertyMessage {
StreamingPropertyMessage(this.playerId, this.streamingProperty);
int playerId;
String streamingProperty;
}

class StreamingPropertyTypeMessage {
StreamingPropertyTypeMessage(this.playerId, this.streamingPropertyType);
int playerId;
String streamingPropertyType;
}

@HostApi()
abstract class VideoPlayerAvplayApi {
void initialize();
Expand All @@ -109,4 +121,6 @@ abstract class VideoPlayerAvplayApi {
void pause(PlayerMessage msg);
void setMixWithOthers(MixWithOthersMessage msg);
void setDisplayGeometry(GeometryMessage msg);
StreamingPropertyMessage getStreamingProperty(
StreamingPropertyTypeMessage msg);
}
2 changes: 1 addition & 1 deletion packages/video_player_avplay/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: video_player_avplay
description: Flutter plugin for displaying inline video on Tizen TV devices.
homepage: https://github.com/flutter-tizen/plugins
repository: https://github.com/flutter-tizen/plugins/tree/master/packages/video_player_avplay
version: 0.3.3
version: 0.4.0

environment:
sdk: ">=2.18.0 <4.0.0"
Expand Down
6 changes: 3 additions & 3 deletions packages/video_player_avplay/tizen/src/media_player.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ int64_t MediaPlayer::Create(const std::string &uri,
return -1;
}

std::string cookie = flutter_common::GetValue(create_message.http_headers(),
"Cookie", std::string());
std::string cookie = flutter_common::GetValue(
create_message.streaming_property(), "COOKIE", std::string());
if (!cookie.empty()) {
int ret =
player_set_streaming_cookie(player_, cookie.c_str(), cookie.size());
Expand All @@ -97,7 +97,7 @@ int64_t MediaPlayer::Create(const std::string &uri,
}
}
std::string user_agent = flutter_common::GetValue(
create_message.http_headers(), "User-Agent", std::string());
create_message.streaming_property(), "USER_AGENT", std::string());
if (!user_agent.empty()) {
int ret = player_set_streaming_user_agent(player_, user_agent.c_str(),
user_agent.size());
Expand Down
Loading

0 comments on commit 7a4d26f

Please sign in to comment.