From 7a4d26fc84a11498797b5f85d858352ea8d9c529 Mon Sep 17 00:00:00 2001 From: xiaowei guan <60122246+xiaowei-guan@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:16:11 +0800 Subject: [PATCH] [video_player_avplay] Add get streaming property interface and Update SetStreamingProperty interface (#672) --- packages/video_player_avplay/CHANGELOG.md | 3 +- packages/video_player_avplay/README.md | 2 +- .../lib/src/messages.g.dart | 101 +++++++++++- .../lib/src/video_player_tizen.dart | 38 ++++- .../video_player_avplay/lib/video_player.dart | 10 +- .../lib/video_player_platform_interface.dart | 66 +++++++- .../video_player_avplay/pigeons/messages.dart | 14 ++ packages/video_player_avplay/pubspec.yaml | 2 +- .../tizen/src/media_player.cc | 6 +- .../video_player_avplay/tizen/src/messages.cc | 145 +++++++++++++++++- .../video_player_avplay/tizen/src/messages.h | 48 ++++++ .../tizen/src/plus_player.cc | 36 +++-- .../tizen/src/plus_player.h | 2 + .../tizen/src/video_player.h | 4 + .../tizen/src/video_player_tizen_plugin.cc | 14 ++ 15 files changed, 455 insertions(+), 36 deletions(-) diff --git a/packages/video_player_avplay/CHANGELOG.md b/packages/video_player_avplay/CHANGELOG.md index fdfbd115c..37b9537c9 100644 --- a/packages/video_player_avplay/CHANGELOG.md +++ b/packages/video_player_avplay/CHANGELOG.md @@ -1,6 +1,7 @@ -## NEXT +## 0.4.0 * Minor refactor. +* Add getStreamingProperty interface. ## 0.3.3 diff --git a/packages/video_player_avplay/README.md b/packages/video_player_avplay/README.md index c43db0328..ccad79227 100644 --- a/packages/video_player_avplay/README.md +++ b/packages/video_player_avplay/README.md @@ -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: diff --git a/packages/video_player_avplay/lib/src/messages.g.dart b/packages/video_player_avplay/lib/src/messages.g.dart index ec02d20f8..2e57826aa 100644 --- a/packages/video_player_avplay/lib/src/messages.g.dart +++ b/packages/video_player_avplay/lib/src/messages.g.dart @@ -364,6 +364,58 @@ class DurationMessage { } } +class StreamingPropertyMessage { + StreamingPropertyMessage({ + required this.playerId, + required this.streamingProperty, + }); + + int playerId; + + String streamingProperty; + + Object encode() { + return [ + playerId, + streamingProperty, + ]; + } + + static StreamingPropertyMessage decode(Object result) { + result as List; + 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 [ + playerId, + streamingPropertyType, + ]; + } + + static StreamingPropertyTypeMessage decode(Object result) { + result as List; + return StreamingPropertyTypeMessage( + playerId: result[0]! as int, + streamingPropertyType: result[1]! as String, + ); + } +} + class _VideoPlayerAvplayApiCodec extends StandardMessageCodec { const _VideoPlayerAvplayApiCodec(); @override @@ -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); } @@ -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); @@ -876,4 +938,33 @@ class VideoPlayerAvplayApi { return; } } + + Future getStreamingProperty( + StreamingPropertyTypeMessage arg_msg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.video_player_avplay.VideoPlayerAvplayApi.getStreamingProperty', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_msg]) as List?; + 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?)!; + } + } } diff --git a/packages/video_player_avplay/lib/src/video_player_tizen.dart b/packages/video_player_avplay/lib/src/video_player_tizen.dart index 24fe1d5d2..1350b71fc 100644 --- a/packages/video_player_avplay/lib/src/video_player_tizen.dart +++ b/packages/video_player_avplay/lib/src/video_player_tizen.dart @@ -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'; @@ -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 + : { + for (final MapEntry entry + in dataSource.streamingProperty!.entries) + _streamingPropertyType[entry.key]!: entry.value + }; break; case DataSourceType.file: message.uri = dataSource.uri; @@ -197,6 +201,16 @@ class VideoPlayerTizen extends VideoPlayerPlatform { return Duration(milliseconds: response.position); } + @override + Future getStreamingProperty( + int playerId, StreamingPropertyType type) async { + final StreamingPropertyMessage streamingPropertyMessage = + await _api.getStreamingProperty(StreamingPropertyTypeMessage( + playerId: playerId, + streamingPropertyType: _streamingPropertyType[type]!)); + return streamingPropertyMessage.streamingProperty; + } + @override Stream videoEventsFor(int playerId) { return _eventChannelFor(playerId) @@ -286,4 +300,22 @@ class VideoPlayerTizen extends VideoPlayerPlatform { 2: AudioTrackChannelType.stereo, 3: AudioTrackChannelType.surround, }; + + static const Map _streamingPropertyType = + { + 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', + }; } diff --git a/packages/video_player_avplay/lib/video_player.dart b/packages/video_player_avplay/lib/video_player.dart index d440cc258..2e84e1ad5 100644 --- a/packages/video_player_avplay/lib/video_player.dart +++ b/packages/video_player_avplay/lib/video_player.dart @@ -315,7 +315,7 @@ class VideoPlayerController extends ValueNotifier { /// 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? streamingProperty; + final Map? streamingProperty; /// **Android only**. Will override the platform's generic file format /// detection with whatever is set here. @@ -714,6 +714,14 @@ class VideoPlayerController extends ValueNotifier { await _applyVolume(); } + /// Retrieves a specific property value obtained by the streaming engine (Smooth Streaming, HLS, DASH, or Widevine). + Future 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 diff --git a/packages/video_player_avplay/lib/video_player_platform_interface.dart b/packages/video_player_avplay/lib/video_player_platform_interface.dart index f298c43a2..8f202ebda 100644 --- a/packages/video_player_avplay/lib/video_player_platform_interface.dart +++ b/packages/video_player_avplay/lib/video_player_platform_interface.dart @@ -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 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.'); @@ -217,7 +224,7 @@ class DataSource { Map? playerOptions; /// Sets specific feature values for HTTP, MMS, or specific streaming engine - Map? streamingProperty; + Map? streamingProperty; } /// The way in which the video was originally loaded. @@ -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 { diff --git a/packages/video_player_avplay/pigeons/messages.dart b/packages/video_player_avplay/pigeons/messages.dart index 6e4315298..ad4e35b58 100644 --- a/packages/video_player_avplay/pigeons/messages.dart +++ b/packages/video_player_avplay/pigeons/messages.dart @@ -89,6 +89,18 @@ class DurationMessage { List? 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(); @@ -109,4 +121,6 @@ abstract class VideoPlayerAvplayApi { void pause(PlayerMessage msg); void setMixWithOthers(MixWithOthersMessage msg); void setDisplayGeometry(GeometryMessage msg); + StreamingPropertyMessage getStreamingProperty( + StreamingPropertyTypeMessage msg); } diff --git a/packages/video_player_avplay/pubspec.yaml b/packages/video_player_avplay/pubspec.yaml index 097102c85..414b08131 100644 --- a/packages/video_player_avplay/pubspec.yaml +++ b/packages/video_player_avplay/pubspec.yaml @@ -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" diff --git a/packages/video_player_avplay/tizen/src/media_player.cc b/packages/video_player_avplay/tizen/src/media_player.cc index e07d1b5ec..69d0608fb 100644 --- a/packages/video_player_avplay/tizen/src/media_player.cc +++ b/packages/video_player_avplay/tizen/src/media_player.cc @@ -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()); @@ -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()); diff --git a/packages/video_player_avplay/tizen/src/messages.cc b/packages/video_player_avplay/tizen/src/messages.cc index a8e743436..9da8f8e8d 100644 --- a/packages/video_player_avplay/tizen/src/messages.cc +++ b/packages/video_player_avplay/tizen/src/messages.cc @@ -560,6 +560,80 @@ DurationMessage DurationMessage::FromEncodableList(const EncodableList& list) { return decoded; } +// StreamingPropertyMessage + +StreamingPropertyMessage::StreamingPropertyMessage( + int64_t player_id, const std::string& streaming_property) + : player_id_(player_id), streaming_property_(streaming_property) {} + +int64_t StreamingPropertyMessage::player_id() const { return player_id_; } + +void StreamingPropertyMessage::set_player_id(int64_t value_arg) { + player_id_ = value_arg; +} + +const std::string& StreamingPropertyMessage::streaming_property() const { + return streaming_property_; +} + +void StreamingPropertyMessage::set_streaming_property( + std::string_view value_arg) { + streaming_property_ = value_arg; +} + +EncodableList StreamingPropertyMessage::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(player_id_)); + list.push_back(EncodableValue(streaming_property_)); + return list; +} + +StreamingPropertyMessage StreamingPropertyMessage::FromEncodableList( + const EncodableList& list) { + StreamingPropertyMessage decoded(list[0].LongValue(), + std::get(list[1])); + return decoded; +} + +// StreamingPropertyTypeMessage + +StreamingPropertyTypeMessage::StreamingPropertyTypeMessage( + int64_t player_id, const std::string& streaming_property_type) + : player_id_(player_id), + streaming_property_type_(streaming_property_type) {} + +int64_t StreamingPropertyTypeMessage::player_id() const { return player_id_; } + +void StreamingPropertyTypeMessage::set_player_id(int64_t value_arg) { + player_id_ = value_arg; +} + +const std::string& StreamingPropertyTypeMessage::streaming_property_type() + const { + return streaming_property_type_; +} + +void StreamingPropertyTypeMessage::set_streaming_property_type( + std::string_view value_arg) { + streaming_property_type_ = value_arg; +} + +EncodableList StreamingPropertyTypeMessage::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(player_id_)); + list.push_back(EncodableValue(streaming_property_type_)); + return list; +} + +StreamingPropertyTypeMessage StreamingPropertyTypeMessage::FromEncodableList( + const EncodableList& list) { + StreamingPropertyTypeMessage decoded(list[0].LongValue(), + std::get(list[1])); + return decoded; +} + VideoPlayerAvplayApiCodecSerializer::VideoPlayerAvplayApiCodecSerializer() {} EncodableValue VideoPlayerAvplayApiCodecSerializer::ReadValueOfType( @@ -593,12 +667,19 @@ EncodableValue VideoPlayerAvplayApiCodecSerializer::ReadValueOfType( return CustomEncodableValue(SelectedTracksMessage::FromEncodableList( std::get(ReadValue(stream)))); case 137: - return CustomEncodableValue(TrackMessage::FromEncodableList( + return CustomEncodableValue(StreamingPropertyMessage::FromEncodableList( std::get(ReadValue(stream)))); case 138: + return CustomEncodableValue( + StreamingPropertyTypeMessage::FromEncodableList( + std::get(ReadValue(stream)))); + case 139: + return CustomEncodableValue(TrackMessage::FromEncodableList( + std::get(ReadValue(stream)))); + case 140: return CustomEncodableValue(TrackTypeMessage::FromEncodableList( std::get(ReadValue(stream)))); - case 139: + case 141: return CustomEncodableValue(VolumeMessage::FromEncodableList( std::get(ReadValue(stream)))); default: @@ -682,8 +763,24 @@ void VideoPlayerAvplayApiCodecSerializer::WriteValue( stream); return; } - if (custom_value->type() == typeid(TrackMessage)) { + if (custom_value->type() == typeid(StreamingPropertyMessage)) { stream->WriteByte(137); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(StreamingPropertyTypeMessage)) { + stream->WriteByte(138); + WriteValue(EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(TrackMessage)) { + stream->WriteByte(139); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -691,7 +788,7 @@ void VideoPlayerAvplayApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(TrackTypeMessage)) { - stream->WriteByte(138); + stream->WriteByte(140); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -699,7 +796,7 @@ void VideoPlayerAvplayApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(VolumeMessage)) { - stream->WriteByte(139); + stream->WriteByte(141); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -1307,6 +1404,44 @@ void VideoPlayerAvplayApi::SetUp(flutter::BinaryMessenger* binary_messenger, channel->SetMessageHandler(nullptr); } } + { + auto channel = std::make_unique>( + binary_messenger, + "dev.flutter.pigeon.video_player_avplay.VideoPlayerAvplayApi." + "getStreamingProperty", + &GetCodec()); + if (api != nullptr) { + channel->SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_msg_arg = args.at(0); + if (encodable_msg_arg.IsNull()) { + reply(WrapError("msg_arg unexpectedly null.")); + return; + } + const auto& msg_arg = + std::any_cast( + std::get(encodable_msg_arg)); + ErrorOr output = + api->GetStreamingProperty(msg_arg); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel->SetMessageHandler(nullptr); + } + } } EncodableValue VideoPlayerAvplayApi::WrapError(std::string_view error_message) { diff --git a/packages/video_player_avplay/tizen/src/messages.h b/packages/video_player_avplay/tizen/src/messages.h index fd52f5f70..0d066bbca 100644 --- a/packages/video_player_avplay/tizen/src/messages.h +++ b/packages/video_player_avplay/tizen/src/messages.h @@ -365,6 +365,52 @@ class DurationMessage { std::optional duration_range_; }; +// Generated class from Pigeon that represents data sent in messages. +class StreamingPropertyMessage { + public: + // Constructs an object setting all fields. + explicit StreamingPropertyMessage(int64_t player_id, + const std::string& streaming_property); + + int64_t player_id() const; + void set_player_id(int64_t value_arg); + + const std::string& streaming_property() const; + void set_streaming_property(std::string_view value_arg); + + private: + static StreamingPropertyMessage FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class VideoPlayerAvplayApi; + friend class VideoPlayerAvplayApiCodecSerializer; + int64_t player_id_; + std::string streaming_property_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class StreamingPropertyTypeMessage { + public: + // Constructs an object setting all fields. + explicit StreamingPropertyTypeMessage( + int64_t player_id, const std::string& streaming_property_type); + + int64_t player_id() const; + void set_player_id(int64_t value_arg); + + const std::string& streaming_property_type() const; + void set_streaming_property_type(std::string_view value_arg); + + private: + static StreamingPropertyTypeMessage FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class VideoPlayerAvplayApi; + friend class VideoPlayerAvplayApiCodecSerializer; + int64_t player_id_; + std::string streaming_property_type_; +}; + class VideoPlayerAvplayApiCodecSerializer : public flutter::StandardCodecSerializer { public: @@ -411,6 +457,8 @@ class VideoPlayerAvplayApi { const MixWithOthersMessage& msg) = 0; virtual std::optional SetDisplayGeometry( const GeometryMessage& msg) = 0; + virtual ErrorOr GetStreamingProperty( + const StreamingPropertyTypeMessage& msg) = 0; // The codec used by VideoPlayerAvplayApi. static const flutter::StandardMessageCodec& GetCodec(); diff --git a/packages/video_player_avplay/tizen/src/plus_player.cc b/packages/video_player_avplay/tizen/src/plus_player.cc index 3be99ebed..ebc6cced6 100644 --- a/packages/video_player_avplay/tizen/src/plus_player.cc +++ b/packages/video_player_avplay/tizen/src/plus_player.cc @@ -87,20 +87,12 @@ int64_t PlusPlayer::Create(const std::string &uri, return -1; } - std::string cookie = flutter_common::GetValue(create_message.http_headers(), - "Cookie", std::string()); - if (!cookie.empty()) { - SetStreamingProperty(player_, "COOKIE", cookie); - } - std::string user_agent = flutter_common::GetValue( - create_message.http_headers(), "User-Agent", std::string()); - if (!user_agent.empty()) { - SetStreamingProperty(player_, "USER_AGENT", user_agent); - } - std::string adaptive_info = flutter_common::GetValue( - create_message.streaming_property(), "ADAPTIVE_INFO", std::string()); - if (!adaptive_info.empty()) { - SetStreamingProperty(player_, "ADAPTIVE_INFO", adaptive_info); + if (create_message.streaming_property() != nullptr && + !create_message.streaming_property()->empty()) { + for (const auto &[key, value] : *create_message.streaming_property()) { + SetStreamingProperty(player_, std::get(key), + std::get(value)); + } } if (!Open(player_, uri)) { @@ -334,7 +326,7 @@ bool PlusPlayer::IsLive() { std::pair PlusPlayer::GetLiveDuration() { std::string live_duration_str = - GetStreamingProperty(player_, "GET_LIVE_DURATION"); + ::GetStreamingProperty(player_, "GET_LIVE_DURATION"); if (live_duration_str.empty()) { LOG_ERROR("[PlusPlayer] Player fail to get live duration."); return std::make_pair(0, 0); @@ -577,6 +569,20 @@ bool PlusPlayer::SetDrm(const std::string &uri, int drm_type, return true; } +std::string PlusPlayer::GetStreamingProperty( + const std::string &streaming_property_type) { + if (!player_) { + LOG_ERROR("[PlusPlayer] Player not created."); + return ""; + } + plusplayer::State state = GetState(player_); + if (state == plusplayer::State::kNone || state == plusplayer::State::kIdle) { + LOG_ERROR("[PlusPlayer]:Player is in invalid state[%d]", state); + return ""; + } + return ::GetStreamingProperty(player_, streaming_property_type); +} + bool PlusPlayer::OnLicenseAcquired(int *drm_handle, unsigned int length, unsigned char *pssh_data, void *user_data) { LOG_INFO("[PlusPlayer] License acquired."); diff --git a/packages/video_player_avplay/tizen/src/plus_player.h b/packages/video_player_avplay/tizen/src/plus_player.h index 4d4d89b41..61632457e 100644 --- a/packages/video_player_avplay/tizen/src/plus_player.h +++ b/packages/video_player_avplay/tizen/src/plus_player.h @@ -41,6 +41,8 @@ class PlusPlayer : public VideoPlayer { bool IsReady() override; flutter::EncodableList GetTrackInfo(std::string track_type) override; bool SetTrackSelection(int32_t track_id, std::string track_type) override; + std::string GetStreamingProperty( + const std::string &streaming_property_type) override; private: bool IsLive(); diff --git a/packages/video_player_avplay/tizen/src/video_player.h b/packages/video_player_avplay/tizen/src/video_player.h index 0c160d838..c5f02f809 100644 --- a/packages/video_player_avplay/tizen/src/video_player.h +++ b/packages/video_player_avplay/tizen/src/video_player.h @@ -48,6 +48,10 @@ class VideoPlayer { virtual bool IsReady() = 0; virtual flutter::EncodableList GetTrackInfo(std::string track_type) = 0; virtual bool SetTrackSelection(int32_t track_id, std::string track_type) = 0; + virtual std::string GetStreamingProperty( + const std::string &streaming_property_type) { + return ""; + }; protected: virtual void GetVideoSize(int32_t *width, int32_t *height) = 0; diff --git a/packages/video_player_avplay/tizen/src/video_player_tizen_plugin.cc b/packages/video_player_avplay/tizen/src/video_player_tizen_plugin.cc index 0175c5ffb..38c39f56f 100644 --- a/packages/video_player_avplay/tizen/src/video_player_tizen_plugin.cc +++ b/packages/video_player_avplay/tizen/src/video_player_tizen_plugin.cc @@ -55,6 +55,8 @@ class VideoPlayerTizenPlugin : public flutter::Plugin, const MixWithOthersMessage &msg) override; std::optional SetDisplayGeometry( const GeometryMessage &msg) override; + ErrorOr GetStreamingProperty( + const StreamingPropertyTypeMessage &msg) override; static VideoPlayer *FindPlayerById(int64_t player_id) { auto iter = players_.find(player_id); @@ -299,6 +301,18 @@ std::optional VideoPlayerTizenPlugin::SetDisplayGeometry( return std::nullopt; } +ErrorOr VideoPlayerTizenPlugin::GetStreamingProperty( + const StreamingPropertyTypeMessage &msg) { + VideoPlayer *player = FindPlayerById(msg.player_id()); + if (!player) { + return FlutterError("Invalid argument", "Player not found"); + } + StreamingPropertyMessage result( + msg.player_id(), + player->GetStreamingProperty(msg.streaming_property_type())); + return result; +} + std::optional VideoPlayerTizenPlugin::SetMixWithOthers( const MixWithOthersMessage &msg) { options_.SetMixWithOthers(msg.mix_with_others());