From 59dd77e1beac215abf2a6ee49d2f74120aa312c2 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Wed, 2 Aug 2023 18:17:45 +0800 Subject: [PATCH 01/15] Add function:get and set video track selections --- .../lib/src/messages.g.dart | 83 ++++++- .../lib/src/video_player_tizen.dart | 78 +++++++ .../lib/video_player.dart | 23 ++ .../lib/video_player_platform_interface.dart | 97 ++++++++ .../pigeons/messages.dart | 8 + .../tizen/src/messages.cc | 121 +++++++++- .../tizen/src/messages.h | 27 +++ .../tizen/src/video_player.cc | 211 ++++++++++++++++++ .../tizen/src/video_player.h | 50 +++++ .../tizen/src/video_player_tizen_plugin.cc | 26 +++ 10 files changed, 722 insertions(+), 2 deletions(-) diff --git a/packages/video_player_videohole/lib/src/messages.g.dart b/packages/video_player_videohole/lib/src/messages.g.dart index 1dcbd4698..a6da6782d 100644 --- a/packages/video_player_videohole/lib/src/messages.g.dart +++ b/packages/video_player_videohole/lib/src/messages.g.dart @@ -107,6 +107,33 @@ class PlaybackSpeedMessage { } } +class TrackSelectionsMessage { + TrackSelectionsMessage({ + required this.playerId, + required this.trackSelections, + }); + + int playerId; + + List?> trackSelections; + + Object encode() { + return [ + playerId, + trackSelections, + ]; + } + + static TrackSelectionsMessage decode(Object result) { + result as List; + return TrackSelectionsMessage( + playerId: result[0]! as int, + trackSelections: + (result[1] as List?)!.cast?>(), + ); + } +} + class PositionMessage { PositionMessage({ required this.playerId, @@ -268,9 +295,12 @@ class _VideoPlayerVideoholeApiCodec extends StandardMessageCodec { } else if (value is PositionMessage) { buffer.putUint8(134); writeValue(buffer, value.encode()); - } else if (value is VolumeMessage) { + } else if (value is TrackSelectionsMessage) { buffer.putUint8(135); writeValue(buffer, value.encode()); + } else if (value is VolumeMessage) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -294,6 +324,8 @@ class _VideoPlayerVideoholeApiCodec extends StandardMessageCodec { case 134: return PositionMessage.decode(readValue(buffer)!); case 135: + return TrackSelectionsMessage.decode(readValue(buffer)!); + case 136: return VolumeMessage.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -518,6 +550,55 @@ class VideoPlayerVideoholeApi { } } + Future trackSelections(PlayerMessage arg_msg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.VideoPlayerVideoholeApi.trackSelections', 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 TrackSelectionsMessage?)!; + } + } + + Future setTrackSelection(TrackSelectionsMessage arg_msg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.VideoPlayerVideoholeApi.setTrackSelection', 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 { + return; + } + } + Future pause(PlayerMessage arg_msg) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.VideoPlayerVideoholeApi.pause', codec, diff --git a/packages/video_player_videohole/lib/src/video_player_tizen.dart b/packages/video_player_videohole/lib/src/video_player_tizen.dart index 2e5427472..455dda35d 100644 --- a/packages/video_player_videohole/lib/src/video_player_tizen.dart +++ b/packages/video_player_videohole/lib/src/video_player_tizen.dart @@ -88,6 +88,77 @@ class VideoPlayerTizen extends VideoPlayerPlatform { PositionMessage(playerId: playerId, position: position.inMilliseconds)); } + @override + Future> getTrackSelections(int playerId) async { + final TrackSelectionsMessage response = + await _api.trackSelections(PlayerMessage(playerId: playerId)); + + final List trackSelections = []; + + for (final Map? trackSelectionMap + in response.trackSelections) { + final TrackSelectionType trackSelectionType = + _intTrackSelectionTypeMap[trackSelectionMap!['trackType']]!; + final bool isUnknown = trackSelectionMap['isUnknown']! as bool; + final int trackId = trackSelectionMap['trackId']! as int; + + if (isUnknown) { + trackSelections.add(TrackSelection( + trackId: trackId, + trackType: trackSelectionType, + )); + } else { + switch (trackSelectionType) { + case TrackSelectionType.video: + { + final int bitrate = trackSelectionMap['bitrate']! as int; + final int width = trackSelectionMap['width']! as int; + final int height = trackSelectionMap['height']! as int; + + trackSelections.add(TrackSelection( + trackId: trackId, + trackType: trackSelectionType, + width: width, + height: height, + bitrate: bitrate == 0 ? null : bitrate, + )); + break; + } + case TrackSelectionType.audio: + { + // TODO:implement get audio track. + break; + } + case TrackSelectionType.text: + { + // TODO:implement get text track. + break; + } + } + } + } + + return trackSelections; + } + + @override + Future setTrackSelection(int playerId, TrackSelection trackSelection) { + final List?> list = ?>[ + { + 'trackId': trackSelection.trackId, + 'trackType': _intTrackSelectionTypeMap.keys.firstWhere( + (int key) => + _intTrackSelectionTypeMap[key] == trackSelection.trackType, + orElse: () => -1), + } + ]; + + return _api.setTrackSelection(TrackSelectionsMessage( + playerId: playerId, + trackSelections: list, + )); + } + @override Future getPosition(int playerId) async { final PositionMessage response = @@ -174,4 +245,11 @@ class VideoPlayerTizen extends VideoPlayerPlatform { VideoFormat.dash: 'dash', VideoFormat.other: 'other', }; + + static const Map _intTrackSelectionTypeMap = + { + 1: TrackSelectionType.audio, + 2: TrackSelectionType.video, + 3: TrackSelectionType.text, + }; } diff --git a/packages/video_player_videohole/lib/video_player.dart b/packages/video_player_videohole/lib/video_player.dart index d510253f3..0538ba79c 100644 --- a/packages/video_player_videohole/lib/video_player.dart +++ b/packages/video_player_videohole/lib/video_player.dart @@ -44,6 +44,7 @@ class VideoPlayerValue { this.position = Duration.zero, this.caption = Caption.none, this.captionOffset = Duration.zero, + this.trackSelections = const [], this.buffered = 0, this.isInitialized = false, this.isPlaying = false, @@ -106,6 +107,9 @@ class VideoPlayerValue { /// The current speed of the playback. final double playbackSpeed; + /// The current playback track selections. + final List trackSelections; + /// A description of the error if present. /// /// If [hasError] is false this is `null`. @@ -146,6 +150,7 @@ class VideoPlayerValue { Duration? position, Caption? caption, Duration? captionOffset, + List? trackSelections, int? buffered, bool? isInitialized, bool? isPlaying, @@ -161,6 +166,7 @@ class VideoPlayerValue { position: position ?? this.position, caption: caption ?? this.caption, captionOffset: captionOffset ?? this.captionOffset, + trackSelections: trackSelections ?? this.trackSelections, buffered: buffered ?? this.buffered, isInitialized: isInitialized ?? this.isInitialized, isPlaying: isPlaying ?? this.isPlaying, @@ -182,6 +188,7 @@ class VideoPlayerValue { 'position: $position, ' 'caption: $caption, ' 'captionOffset: $captionOffset, ' + 'trackSelections: $trackSelections, ' 'buffered: $buffered, ' 'isInitialized: $isInitialized, ' 'isPlaying: $isPlaying, ' @@ -577,6 +584,22 @@ class VideoPlayerController extends ValueNotifier { _updatePosition(position); } + /// The track selections in the current video. + Future?> get trackSelections async { + if (!value.isInitialized || _isDisposed) { + return null; + } + return _videoPlayerPlatform.getTrackSelections(_playerId); + } + + /// Sets the selected video track selection. + Future setTrackSelection(TrackSelection trackSelection) async { + if (!value.isInitialized || _isDisposed) { + return; + } + await _videoPlayerPlatform.setTrackSelection(_playerId, trackSelection); + } + /// Sets the audio volume of [this]. /// /// [volume] indicates a value between 0.0 (silent) and 1.0 (full volume) on a diff --git a/packages/video_player_videohole/lib/video_player_platform_interface.dart b/packages/video_player_videohole/lib/video_player_platform_interface.dart index 6d87887fa..56b6a5b4a 100644 --- a/packages/video_player_videohole/lib/video_player_platform_interface.dart +++ b/packages/video_player_videohole/lib/video_player_platform_interface.dart @@ -86,6 +86,18 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('seekTo() has not been implemented.'); } + /// Gets the video [TrackSelection]s. For convenience if the video file has at + /// least one [TrackSelection] for a specific type, the auto track selection will + /// be added to this list with that type. + Future> getTrackSelections(int playerId) { + throw UnimplementedError('getTrackSelection() has not been implemented.'); + } + + /// Sets the selected video track selection. + Future setTrackSelection(int playerId, TrackSelection trackSelection) { + throw UnimplementedError('setTrackSelection() has not been implemented.'); + } + /// Sets the playback speed to a [speed] value indicating the playback rate. Future setPlaybackSpeed(int playerId, double speed) { throw UnimplementedError('setPlaybackSpeed() has not been implemented.'); @@ -390,3 +402,88 @@ class VideoPlayerOptions { /// currently no way to implement this feature in this platform). final bool mixWithOthers; } + +/// A representation of a single track selection. +/// +/// A typical video file will include several [TrackSelection]s. For convenience +/// the auto track selection will be added to this list of [getTrackSelections]. +@immutable +class TrackSelection { + /// Creates an instance of [VideoEvent]. + /// + /// The [trackId] and [trackType] argument is required. + /// + const TrackSelection({ + required this.trackId, + required this.trackType, + this.width, + this.height, + this.bitrate, + }); + + /// The track id of track selection that uses to determine track selection. + final int trackId; + + /// The type of the track selection. + final TrackSelectionType trackType; + + /// The width of video track selection. This will be null if the [trackType] + /// is not [TrackSelectionType.video] or an unknowntrack selection. + /// + /// If the track selection doesn't specify the width this may be null. + final int? width; + + /// The height of video track selection. This will be null if the [trackType] + /// is not [TrackSelectionType.video] or an unknown track selection. + /// + /// If the track selection doesn't specify the height this may be null. + final int? height; + + /// The label of track selection. This will be null if the [trackType] + /// is not [TrackSelectionType.video] and [TrackSelectionType.audio] or an unknown + /// track selection. + /// + /// If the track selection doesn't specify the bitrate this may be null. + final int? bitrate; + + @override + String toString() { + return '${objectRuntimeType(this, 'TrackSelection')}(' + 'trackId: $trackId, ' + 'trackType: $trackType, ' + 'width: $width, ' + 'height: $height, ' + 'bitrate: $bitrate)'; + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is TrackSelection && + runtimeType == other.runtimeType && + trackId == other.trackId && + trackType == other.trackType && + width == other.width && + height == other.height && + bitrate == other.bitrate; + + @override + int get hashCode => + trackId.hashCode ^ + trackType.hashCode ^ + width.hashCode ^ + height.hashCode ^ + bitrate.hashCode; +} + +/// Type of the track selection. +enum TrackSelectionType { + /// The video track selection. + video, + + /// The audio track selection. + audio, + + /// The text track selection. + text, +} diff --git a/packages/video_player_videohole/pigeons/messages.dart b/packages/video_player_videohole/pigeons/messages.dart index 1a7e946f9..317dc1046 100644 --- a/packages/video_player_videohole/pigeons/messages.dart +++ b/packages/video_player_videohole/pigeons/messages.dart @@ -32,6 +32,12 @@ class PlaybackSpeedMessage { double speed; } +class TrackSelectionsMessage { + TrackSelectionsMessage(this.playerId, this.trackSelections); + int playerId; + List?> trackSelections; +} + class PositionMessage { PositionMessage(this.playerId, this.position); int playerId; @@ -74,6 +80,8 @@ abstract class VideoPlayerVideoholeApi { PositionMessage position(PlayerMessage msg); @async void seekTo(PositionMessage msg); + TrackSelectionsMessage trackSelections(PlayerMessage msg); + void setTrackSelection(TrackSelectionsMessage msg); void pause(PlayerMessage msg); void setMixWithOthers(MixWithOthersMessage msg); void setDisplayGeometry(GeometryMessage msg); diff --git a/packages/video_player_videohole/tizen/src/messages.cc b/packages/video_player_videohole/tizen/src/messages.cc index 80ddfce8e..a85d5705b 100644 --- a/packages/video_player_videohole/tizen/src/messages.cc +++ b/packages/video_player_videohole/tizen/src/messages.cc @@ -123,6 +123,42 @@ PlaybackSpeedMessage PlaybackSpeedMessage::FromEncodableList( return decoded; } +// TrackSelectionsMessage + +TrackSelectionsMessage::TrackSelectionsMessage( + int64_t player_id, const EncodableList& track_selections) + : player_id_(player_id), track_selections_(track_selections) {} + +int64_t TrackSelectionsMessage::player_id() const { return player_id_; } + +void TrackSelectionsMessage::set_player_id(int64_t value_arg) { + player_id_ = value_arg; +} + +const EncodableList& TrackSelectionsMessage::track_selections() const { + return track_selections_; +} + +void TrackSelectionsMessage::set_track_selections( + const EncodableList& value_arg) { + track_selections_ = value_arg; +} + +EncodableList TrackSelectionsMessage::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(player_id_)); + list.push_back(EncodableValue(track_selections_)); + return list; +} + +TrackSelectionsMessage TrackSelectionsMessage::FromEncodableList( + const EncodableList& list) { + TrackSelectionsMessage decoded(list[0].LongValue(), + std::get(list[1])); + return decoded; +} + // PositionMessage PositionMessage::PositionMessage(int64_t player_id, int64_t position) @@ -388,6 +424,9 @@ EncodableValue VideoPlayerVideoholeApiCodecSerializer::ReadValueOfType( return CustomEncodableValue(PositionMessage::FromEncodableList( std::get(ReadValue(stream)))); case 135: + return CustomEncodableValue(TrackSelectionsMessage::FromEncodableList( + std::get(ReadValue(stream)))); + case 136: return CustomEncodableValue(VolumeMessage::FromEncodableList( std::get(ReadValue(stream)))); default: @@ -455,8 +494,16 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( stream); return; } - if (custom_value->type() == typeid(VolumeMessage)) { + if (custom_value->type() == typeid(TrackSelectionsMessage)) { stream->WriteByte(135); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(VolumeMessage)) { + stream->WriteByte(136); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -772,6 +819,78 @@ void VideoPlayerVideoholeApi::SetUp(flutter::BinaryMessenger* binary_messenger, channel->SetMessageHandler(nullptr); } } + { + auto channel = std::make_unique>( + binary_messenger, + "dev.flutter.pigeon.VideoPlayerVideoholeApi.trackSelections", + &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->TrackSelections(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); + } + } + { + auto channel = std::make_unique>( + binary_messenger, + "dev.flutter.pigeon.VideoPlayerVideoholeApi.setTrackSelection", + &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)); + std::optional output = + api->SetTrackSelection(msg_arg); + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel->SetMessageHandler(nullptr); + } + } { auto channel = std::make_unique>( binary_messenger, "dev.flutter.pigeon.VideoPlayerVideoholeApi.pause", diff --git a/packages/video_player_videohole/tizen/src/messages.h b/packages/video_player_videohole/tizen/src/messages.h index 6effb80c4..7dc64c00e 100644 --- a/packages/video_player_videohole/tizen/src/messages.h +++ b/packages/video_player_videohole/tizen/src/messages.h @@ -134,6 +134,29 @@ class PlaybackSpeedMessage { double speed_; }; +// Generated class from Pigeon that represents data sent in messages. +class TrackSelectionsMessage { + public: + // Constructs an object setting all fields. + explicit TrackSelectionsMessage( + int64_t player_id, const flutter::EncodableList& track_selections); + + int64_t player_id() const; + void set_player_id(int64_t value_arg); + + const flutter::EncodableList& track_selections() const; + void set_track_selections(const flutter::EncodableList& value_arg); + + private: + static TrackSelectionsMessage FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class VideoPlayerVideoholeApi; + friend class VideoPlayerVideoholeApiCodecSerializer; + int64_t player_id_; + flutter::EncodableList track_selections_; +}; + // Generated class from Pigeon that represents data sent in messages. class PositionMessage { public: @@ -293,6 +316,10 @@ class VideoPlayerVideoholeApi { virtual void SeekTo( const PositionMessage& msg, std::function reply)> result) = 0; + virtual ErrorOr TrackSelections( + const PlayerMessage& msg) = 0; + virtual std::optional SetTrackSelection( + const TrackSelectionsMessage& msg) = 0; virtual std::optional Pause(const PlayerMessage& msg) = 0; virtual std::optional SetMixWithOthers( const MixWithOthersMessage& msg) = 0; diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index 7c2f12e16..b9e0ae42e 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -265,6 +265,217 @@ void VideoPlayer::SetPlaybackSpeed(double speed) { } } +flutter::EncodableList VideoPlayer::getTotalTrackInfo() { + player_state_e state = PLAYER_STATE_NONE; + int ret = player_get_state(player_, &state); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_state failed: %s", + get_error_message(ret)); + } + if (state == PLAYER_STATE_NONE || state == PLAYER_STATE_IDLE) { + LOG_ERROR("[VideoPlayer] Player not ready."); + return {}; + } + + int video_count = 0; + int audio_count = 0; + int subtitle_count = 0; + int stream_counter = 0; + int total_count = 0; + + player_video_track_info_v2 *video_track_info = NULL; + player_audio_track_info_v2 *audio_track_info = NULL; + player_subtitle_track_info_v2 *sub_track_info = NULL; + StreamInformation *streamInfo = NULL; + + void *player_lib_handle = dlopen("libcapi-media-player.so.0", RTLD_LAZY); + if (player_lib_handle) { + FuncPlayerGetTrackCountV2 player_get_track_count_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_track_count_v2")); + FuncPlayerGetVideoTrackInfoV2 player_get_video_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_video_track_info_v2")); + FuncPlayerGetAudioTrackInfoV2 player_get_audio_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_audio_track_info_v2")); + FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_subtitle_track_info_v2")); + + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_VIDEO, + &video_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_video_track_count failed: %s", + get_error_message(ret)); + } + + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_AUDIO, + &audio_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_audio_track_count failed: %s", + get_error_message(ret)); + } + + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_TEXT, + &subtitle_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_subtitle_track_count failed: %s", + get_error_message(ret)); + } + + total_count = video_count + audio_count + subtitle_count; + LOG_INFO( + "[VideoPlayer] video_count: %d, audio_count: %d, subtitle_count:%d, " + "total_count: %d", + video_count, audio_count, subtitle_count, total_count); + streamInfo = new StreamInformation[total_count]; + + if (player_get_video_track_info_v2 || player_get_audio_track_info_v2 || + player_get_subtitle_track_info_v2) { + if (video_count > 0) { + for (int video_index = 0; video_index < video_count; video_index++) { + ret = player_get_video_track_info_v2(player_, video_index, + &video_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_video_track_info_v2 failed: %s", + get_error_message(ret)); + } + LOG_INFO( + "[VideoPlayer] video track info: width[%d], height[%d], " + "bitrate[%d]", + video_track_info->width, video_track_info->height, + video_track_info->bit_rate); + + streamInfo[stream_counter].track = video_index; + streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_VIDEO; + streamInfo[stream_counter].videoInfo.width = video_track_info->width; + streamInfo[stream_counter].videoInfo.height = + video_track_info->height; + streamInfo[stream_counter].videoInfo.bit_rate = + video_track_info->bit_rate; + stream_counter++; + } + } + + if (audio_count > 0) { + for (int audio_index = 0; audio_index < audio_count; audio_index++) { + ret = player_get_audio_track_info_v2(player_, audio_index, + &audio_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_audio_track_info_v2 failed: %s", + get_error_message(ret)); + } + LOG_INFO( + "[VideoPlayer] audio track info: language[%s], channel[%d], " + "sample_rate[%d], bitrate[%d]", + audio_track_info->language, audio_track_info->channel, + audio_track_info->sample_rate, audio_track_info->bit_rate); + + // TODO:implement audio info + } + } + + if (subtitle_count > 0) { + for (int sub_index = 0; sub_index < subtitle_count; sub_index++) { + ret = player_get_subtitle_track_info_v2(player_, sub_index, + &sub_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR( + "[VideoPlayer] player_get_subtitle_track_info_v2 failed: %s", + get_error_message(ret)); + } + LOG_INFO( + "[VideoPlayer] subtitle track info: track_lang[%s], " + "subtitle_type[%d]", + sub_track_info->language, sub_track_info->subtitle_type); + + // TODO:implement subtitle info + } + } + } else { + LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); + dlclose(player_lib_handle); + return {}; + } + dlclose(player_lib_handle); + } else { + LOG_ERROR("[VideoPlayer] dlopen failed: %s", dlerror()); + return {}; + } + + flutter::EncodableList trackSelections; + for (int index = 0; index < stream_counter; index++) { + flutter::EncodableMap trackSelection; + + trackSelection.insert( + {flutter::EncodableValue("isUnknown"), flutter::EncodableValue(false)}); + trackSelection.insert( + {flutter::EncodableValue("trackType"), + flutter::EncodableValue(streamInfo[index].trackType)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(streamInfo[index].track)}); + + switch (streamInfo[index].trackType) { + case PLAYER_STREAM_TYPE_VIDEO: + trackSelection.insert( + {flutter::EncodableValue("width"), + flutter::EncodableValue(streamInfo[index].videoInfo.width)}); + trackSelection.insert( + {flutter::EncodableValue("height"), + flutter::EncodableValue(streamInfo[index].videoInfo.height)}); + trackSelection.insert( + {flutter::EncodableValue("bitrate"), + flutter::EncodableValue(streamInfo[index].videoInfo.bit_rate)}); + break; + case PLAYER_STREAM_TYPE_AUDIO: + // TODO:implement audio info + break; + case PLAYER_STREAM_TYPE_TEXT: + // TODO:implement subtitle info + break; + default: + trackSelection.insert({flutter::EncodableValue("isUnknown"), + flutter::EncodableValue(true)}); + } + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); + } + return trackSelections; +} + +void VideoPlayer::SetTrackSelection(const flutter::EncodableList &list) { + player_state_e state = PLAYER_STATE_NONE; + int ret = player_get_state(player_, &state); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_state failed: %s", + get_error_message(ret)); + } + if (state == PLAYER_STATE_NONE || state == PLAYER_STATE_IDLE) { + LOG_ERROR("[VideoPlayer] Player not ready."); + return; + } + + flutter::EncodableMap track_map; + if (!list.empty()) { + for (auto &map : list) { + track_map = std::get(map); + } + } + + int track_id = std::get(track_map[flutter::EncodableValue("trackId")]); + int track_type = + std::get(track_map[flutter::EncodableValue("trackType")]); + LOG_INFO("[VideoPlayer] track_id: %d,track_type: %d", track_id, track_type); + + ret = + player_select_track(player_, (player_stream_type_e)track_type, track_id); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_select_track failed: %s", + get_error_message(ret)); + } +} + void VideoPlayer::SeekTo(int32_t position, SeekCompletedCallback callback) { LOG_INFO("[VideoPlayer] position: %d", position); diff --git a/packages/video_player_videohole/tizen/src/video_player.h b/packages/video_player_videohole/tizen/src/video_player.h index 077559c99..b48f5630b 100644 --- a/packages/video_player_videohole/tizen/src/video_player.h +++ b/packages/video_player_videohole/tizen/src/video_player.h @@ -18,12 +18,60 @@ #include "drm_manager.h" #include "video_player_options.h" +#define MAX_STRING_NAME_LEN 255 +#define MMPLAYER_FOUR_CC_LEN 14 +#define PLAYER_LANG_NAME_SIZE 10 + +typedef struct { + char fourCC[MMPLAYER_FOUR_CC_LEN + 1]; /**< codec fourcc */ + char name[MAX_STRING_NAME_LEN]; /**< name: video/audio, it maybe not exit in + some track*/ + /*dynamic infos in hls,ss,dash streams*/ + int width; /**< resolution width */ + int height; /**< resolution height */ + int bit_rate; /**< bitrate in bps */ +} player_video_track_info_v2; + +typedef struct { + char fourCC[MMPLAYER_FOUR_CC_LEN + 1]; /**< codec fourcc */ + char language[PLAYER_LANG_NAME_SIZE]; /**< language info*/ + /*dynamic infos in hls,ss,dash streams*/ + int sample_rate; /**< sample rate in this track*/ + int channel; /**< channel in this track*/ + int bit_rate; /**< bitrate in this track*/ +} player_audio_track_info_v2; + +typedef struct { + char fourCC[MMPLAYER_FOUR_CC_LEN + 1]; /**< codec fourcc */ + char language[PLAYER_LANG_NAME_SIZE]; /**< language info*/ + int subtitle_type; /**< text subtitle = 0, picture subtitle = 1 */ +} player_subtitle_track_info_v2; + +typedef struct { + int track; + int adaptation_index; + int alternate_index; + player_stream_type_e trackType; + player_video_track_info_v2 videoInfo; + player_audio_track_info_v2 audioInfo; + player_subtitle_track_info_v2 textInfo; +} StreamInformation; + typedef void (*FuncEcoreWl2WindowGeometryGet)(void *window, int *x, int *y, int *width, int *height); typedef int (*FuncPlayerSetEcoreWlDisplay)(player_h player, player_display_type_e type, void *ecore_wl_window, int x, int y, int width, int height); +typedef int (*FuncPlayerGetTrackCountV2)(player_h player, + player_stream_type_e type, + int *pcount); +typedef int (*FuncPlayerGetVideoTrackInfoV2)( + player_h player, int index, player_video_track_info_v2 **track_info); +typedef int (*FuncPlayerGetAudioTrackInfoV2)( + player_h player, int index, player_audio_track_info_v2 **track_info); +typedef int (*FuncPlayerGetSubtitleTrackInfoV2)( + player_h player, int index, player_subtitle_track_info_v2 **track_info); class VideoPlayer { public: @@ -45,6 +93,8 @@ class VideoPlayer { void SetPlaybackSpeed(double speed); void SeekTo(int32_t position, SeekCompletedCallback callback); int32_t GetPosition(); + flutter::EncodableList getTotalTrackInfo(); + void SetTrackSelection(const flutter::EncodableList &list); void RegisterSendPort(Dart_Port send_port) { send_port_ = send_port; } diff --git a/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc b/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc index b72ae520a..2a1a94d1b 100644 --- a/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc +++ b/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc @@ -44,6 +44,10 @@ class VideoPlayerTizenPlugin : public flutter::Plugin, void SeekTo( const PositionMessage &msg, std::function reply)> result) override; + ErrorOr TrackSelections( + const PlayerMessage &msg) override; + std::optional SetTrackSelection( + const TrackSelectionsMessage &msg) override; std::optional Pause(const PlayerMessage &msg) override; std::optional SetMixWithOthers( const MixWithOthersMessage &msg) override; @@ -243,6 +247,28 @@ void VideoPlayerTizenPlugin::SeekTo( player->SeekTo(msg.position(), [result]() -> void { result(std::nullopt); }); } +ErrorOr VideoPlayerTizenPlugin::TrackSelections( + const PlayerMessage &msg) { + VideoPlayer *player = FindPlayerById(msg.player_id()); + + if (!player) { + return FlutterError("Invalid argument", "Player not found."); + } + TrackSelectionsMessage result(msg.player_id(), player->getTotalTrackInfo()); + return result; +} + +std::optional VideoPlayerTizenPlugin::SetTrackSelection( + const TrackSelectionsMessage &msg) { + VideoPlayer *player = FindPlayerById(msg.player_id()); + if (!player) { + return FlutterError("Invalid argument", "Player not found."); + } + player->SetTrackSelection(msg.track_selections()); + + return std::nullopt; +} + std::optional VideoPlayerTizenPlugin::SetDisplayGeometry( const GeometryMessage &msg) { VideoPlayer *player = FindPlayerById(msg.player_id()); From e0a55db9b03644383312a63c49486eb487d95a49 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Thu, 3 Aug 2023 10:42:53 +0800 Subject: [PATCH 02/15] implement audio track selections --- .../lib/src/video_player_tizen.dart | 19 ++++++++++- .../lib/video_player_platform_interface.dart | 33 +++++++++++++++++++ .../tizen/src/video_player.cc | 20 +++++++++-- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/packages/video_player_videohole/lib/src/video_player_tizen.dart b/packages/video_player_videohole/lib/src/video_player_tizen.dart index 455dda35d..c5cf6fcc1 100644 --- a/packages/video_player_videohole/lib/src/video_player_tizen.dart +++ b/packages/video_player_videohole/lib/src/video_player_tizen.dart @@ -126,7 +126,17 @@ class VideoPlayerTizen extends VideoPlayerPlatform { } case TrackSelectionType.audio: { - // TODO:implement get audio track. + final String language = trackSelectionMap['language']! as String; + final TrackSelectionChannelType channelType = + _intChannelTypeMap[trackSelectionMap['channel']]!; + final int bitrate = trackSelectionMap['bitrate']! as int; + trackSelections.add(TrackSelection( + trackId: trackId, + trackType: trackSelectionType, + language: language.isEmpty ? null : language, + channel: channelType, + bitrate: bitrate == 0 ? null : bitrate, + )); break; } case TrackSelectionType.text: @@ -252,4 +262,11 @@ class VideoPlayerTizen extends VideoPlayerPlatform { 2: TrackSelectionType.video, 3: TrackSelectionType.text, }; + + static const Map _intChannelTypeMap = + { + 1: TrackSelectionChannelType.mono, + 2: TrackSelectionChannelType.stereo, + 3: TrackSelectionChannelType.surround, + }; } diff --git a/packages/video_player_videohole/lib/video_player_platform_interface.dart b/packages/video_player_videohole/lib/video_player_platform_interface.dart index 56b6a5b4a..ff9659e41 100644 --- a/packages/video_player_videohole/lib/video_player_platform_interface.dart +++ b/packages/video_player_videohole/lib/video_player_platform_interface.dart @@ -419,6 +419,8 @@ class TrackSelection { this.width, this.height, this.bitrate, + this.language, + this.channel, }); /// The track id of track selection that uses to determine track selection. @@ -446,6 +448,19 @@ class TrackSelection { /// If the track selection doesn't specify the bitrate this may be null. final int? bitrate; + /// The language of track selection. This will be null if the [trackType] + /// is not [TrackSelectionType.audio] and [TrackSelectionType.text] or an unknown + /// track selection. + /// + /// If the track selection doesn't specify the language this may be null. + final String? language; + + /// The channelCount of track selection. This will be null if the [trackType] + /// is not [TrackSelectionType.audio] or an unknown track selection. + /// + /// If the track selection doesn't specify the channelCount this may be null. + final TrackSelectionChannelType? channel; + @override String toString() { return '${objectRuntimeType(this, 'TrackSelection')}(' @@ -453,6 +468,8 @@ class TrackSelection { 'trackType: $trackType, ' 'width: $width, ' 'height: $height, ' + 'language: $language, ' + 'channel: $channel, ' 'bitrate: $bitrate)'; } @@ -465,6 +482,8 @@ class TrackSelection { trackType == other.trackType && width == other.width && height == other.height && + language == other.language && + channel == other.channel && bitrate == other.bitrate; @override @@ -473,6 +492,8 @@ class TrackSelection { trackType.hashCode ^ width.hashCode ^ height.hashCode ^ + language.hashCode ^ + channel.hashCode ^ bitrate.hashCode; } @@ -487,3 +508,15 @@ enum TrackSelectionType { /// The text track selection. text, } + +/// Type of the track selection channel for [TrackSelectionType.audio]. +enum TrackSelectionChannelType { + /// The mono channel. + mono, + + /// The stereo channel. + stereo, + + /// The surround channel. + surround, +} diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index b9e0ae42e..94063f1d6 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -372,7 +372,15 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { audio_track_info->language, audio_track_info->channel, audio_track_info->sample_rate, audio_track_info->bit_rate); - // TODO:implement audio info + streamInfo[stream_counter].track = audio_index; + streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_AUDIO; + strcpy(streamInfo[stream_counter].audioInfo.language, + audio_track_info->language); + streamInfo[stream_counter].audioInfo.channel = + audio_track_info->channel; + streamInfo[stream_counter].audioInfo.bit_rate = + audio_track_info->bit_rate; + stream_counter++; } } @@ -429,7 +437,15 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { flutter::EncodableValue(streamInfo[index].videoInfo.bit_rate)}); break; case PLAYER_STREAM_TYPE_AUDIO: - // TODO:implement audio info + trackSelection.insert( + {flutter::EncodableValue("language"), + flutter::EncodableValue(std::string(streamInfo[index].audioInfo.language))}); + trackSelection.insert( + {flutter::EncodableValue("channel"), + flutter::EncodableValue(streamInfo[index].audioInfo.channel)}); + trackSelection.insert( + {flutter::EncodableValue("bitrate"), + flutter::EncodableValue(streamInfo[index].audioInfo.bit_rate)}); break; case PLAYER_STREAM_TYPE_TEXT: // TODO:implement subtitle info From 617a23becc2e2d165ecac526ae91216fe4994301 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Thu, 3 Aug 2023 11:14:07 +0800 Subject: [PATCH 03/15] Implement text track selections --- .../lib/src/video_player_tizen.dart | 16 ++++++++++++- .../lib/video_player_platform_interface.dart | 19 +++++++++++++++ .../tizen/src/video_player.cc | 23 ++++++++++++++----- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/packages/video_player_videohole/lib/src/video_player_tizen.dart b/packages/video_player_videohole/lib/src/video_player_tizen.dart index c5cf6fcc1..08c75e81e 100644 --- a/packages/video_player_videohole/lib/src/video_player_tizen.dart +++ b/packages/video_player_videohole/lib/src/video_player_tizen.dart @@ -141,7 +141,15 @@ class VideoPlayerTizen extends VideoPlayerPlatform { } case TrackSelectionType.text: { - // TODO:implement get text track. + final String language = trackSelectionMap['language']! as String; + final TrackSelectionSubtitleType subtitleType = + _intSubtitleTypeMap[trackSelectionMap['subtitleType']]!; + trackSelections.add(TrackSelection( + trackId: trackId, + trackType: trackSelectionType, + language: language.isEmpty ? null : language, + subtitleType: subtitleType, + )); break; } } @@ -269,4 +277,10 @@ class VideoPlayerTizen extends VideoPlayerPlatform { 2: TrackSelectionChannelType.stereo, 3: TrackSelectionChannelType.surround, }; + + static const Map _intSubtitleTypeMap = + { + 0: TrackSelectionSubtitleType.text, + 1: TrackSelectionSubtitleType.picture, + }; } diff --git a/packages/video_player_videohole/lib/video_player_platform_interface.dart b/packages/video_player_videohole/lib/video_player_platform_interface.dart index ff9659e41..e278c75e7 100644 --- a/packages/video_player_videohole/lib/video_player_platform_interface.dart +++ b/packages/video_player_videohole/lib/video_player_platform_interface.dart @@ -421,6 +421,7 @@ class TrackSelection { this.bitrate, this.language, this.channel, + this.subtitleType, }); /// The track id of track selection that uses to determine track selection. @@ -461,6 +462,12 @@ class TrackSelection { /// If the track selection doesn't specify the channelCount this may be null. final TrackSelectionChannelType? channel; + /// The subtitle type of track selection. This will be null if the [trackType] + /// is not [TrackSelectionType.text] or an unknown track selection. + /// + /// If the track selection doesn't specify the subtitle type this may be null. + final TrackSelectionSubtitleType? subtitleType; + @override String toString() { return '${objectRuntimeType(this, 'TrackSelection')}(' @@ -470,6 +477,7 @@ class TrackSelection { 'height: $height, ' 'language: $language, ' 'channel: $channel, ' + 'subtitleType: $subtitleType, ' 'bitrate: $bitrate)'; } @@ -484,6 +492,7 @@ class TrackSelection { height == other.height && language == other.language && channel == other.channel && + subtitleType == other.subtitleType && bitrate == other.bitrate; @override @@ -494,6 +503,7 @@ class TrackSelection { height.hashCode ^ language.hashCode ^ channel.hashCode ^ + subtitleType.hashCode ^ bitrate.hashCode; } @@ -520,3 +530,12 @@ enum TrackSelectionChannelType { /// The surround channel. surround, } + +/// Type of the track selection channel for [TrackSelectionType.text]. +enum TrackSelectionSubtitleType { + /// The text subtitle. + text, + + /// The picture subtitle. + picture, +} diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index 94063f1d6..d88563251 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -394,11 +394,17 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { get_error_message(ret)); } LOG_INFO( - "[VideoPlayer] subtitle track info: track_lang[%s], " + "[VideoPlayer] subtitle track info: language[%s], " "subtitle_type[%d]", sub_track_info->language, sub_track_info->subtitle_type); - // TODO:implement subtitle info + streamInfo[stream_counter].track = sub_index; + streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_TEXT; + strcpy(streamInfo[stream_counter].textInfo.language, + sub_track_info->language); + streamInfo[stream_counter].textInfo.subtitle_type = + sub_track_info->subtitle_type; + stream_counter++; } } } else { @@ -437,9 +443,9 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { flutter::EncodableValue(streamInfo[index].videoInfo.bit_rate)}); break; case PLAYER_STREAM_TYPE_AUDIO: - trackSelection.insert( - {flutter::EncodableValue("language"), - flutter::EncodableValue(std::string(streamInfo[index].audioInfo.language))}); + trackSelection.insert({flutter::EncodableValue("language"), + flutter::EncodableValue(std::string( + streamInfo[index].audioInfo.language))}); trackSelection.insert( {flutter::EncodableValue("channel"), flutter::EncodableValue(streamInfo[index].audioInfo.channel)}); @@ -448,7 +454,12 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { flutter::EncodableValue(streamInfo[index].audioInfo.bit_rate)}); break; case PLAYER_STREAM_TYPE_TEXT: - // TODO:implement subtitle info + trackSelection.insert({flutter::EncodableValue("language"), + flutter::EncodableValue(std::string( + streamInfo[index].textInfo.language))}); + trackSelection.insert({flutter::EncodableValue("subtitleType"), + flutter::EncodableValue( + streamInfo[index].textInfo.subtitle_type)}); break; default: trackSelection.insert({flutter::EncodableValue("isUnknown"), From 0824e3f1355463391dd7a5985c398a62c6a51679 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Thu, 3 Aug 2023 11:59:47 +0800 Subject: [PATCH 04/15] Update example --- .../example/lib/main.dart | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/packages/video_player_videohole/example/lib/main.dart b/packages/video_player_videohole/example/lib/main.dart index 24f6a7c90..9c1e46c12 100644 --- a/packages/video_player_videohole/example/lib/main.dart +++ b/packages/video_player_videohole/example/lib/main.dart @@ -11,6 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; import 'package:video_player_videohole/video_player.dart'; +import 'package:video_player_videohole/video_player_platform_interface.dart'; void main() { runApp( @@ -37,6 +38,7 @@ class _App extends StatelessWidget { Tab(icon: Icon(Icons.cloud), text: 'Dash'), Tab(icon: Icon(Icons.cloud), text: 'DRM Widevine'), Tab(icon: Icon(Icons.cloud), text: 'DRM PlayReady'), + Tab(icon: Icon(Icons.cloud), text: 'Track Selections'), ], ), ), @@ -47,6 +49,7 @@ class _App extends StatelessWidget { _DashRomoteVideo(), _DrmRemoteVideo(), _DrmRemoteVideo2(), + _TrackSelectionTest(), ], ), ), @@ -370,6 +373,67 @@ class _DrmRemoteVideoState2 extends State<_DrmRemoteVideo2> { } } +class _TrackSelectionTest extends StatefulWidget { + @override + State<_TrackSelectionTest> createState() => _TrackSelectionTestState2(); +} + +class _TrackSelectionTestState2 extends State<_TrackSelectionTest> { + late VideoPlayerController _controller; + + @override + void initState() { + super.initState(); + + _controller = VideoPlayerController.network( + 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8'); + + _controller.addListener(() { + if (_controller.value.hasError) { + print(_controller.value.errorDescription); + } + setState(() {}); + }); + _controller.setLooping(true); + _controller.initialize().then((_) => setState(() {})); + _controller.play(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Column( + children: [ + Container(padding: const EdgeInsets.only(top: 20.0)), + const Text('track selections test'), + Container( + padding: const EdgeInsets.all(20), + child: AspectRatio( + aspectRatio: _controller.value.aspectRatio, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + VideoPlayer(_controller), + ClosedCaption(text: _controller.value.caption.text), + _ControlsOverlay(controller: _controller), + VideoProgressIndicator(_controller, allowScrubbing: true), + ], + ), + ), + ), + _GetTrackSelectionButton(controller: _controller), + ], + ), + ); + } +} + class _ControlsOverlay extends StatelessWidget { const _ControlsOverlay({required this.controller}); @@ -485,3 +549,124 @@ class _ControlsOverlay extends StatelessWidget { ); } } + +class _GetTrackSelectionButton extends StatelessWidget { + const _GetTrackSelectionButton({required this.controller}); + + final VideoPlayerController controller; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 20.0), + child: MaterialButton( + child: const Text('Get Track Selection'), + onPressed: () async { + final List? tracks = + await controller.trackSelections; + if (tracks == null) { + return; + } + // ignore: use_build_context_synchronously + await showDialog( + context: context, + builder: (_) => _TrackSelectionDialog( + controller: controller, + videoTrackSelections: tracks + .where((TrackSelection track) => + track.trackType == TrackSelectionType.video) + .toList(), + audioTrackSelections: tracks + .where((TrackSelection track) => + track.trackType == TrackSelectionType.audio) + .toList(), + textTrackSelections: tracks + .where((TrackSelection track) => + track.trackType == TrackSelectionType.text) + .toList(), + ), + ); + }), + ); + } +} + +class _TrackSelectionDialog extends StatelessWidget { + const _TrackSelectionDialog({ + required this.controller, + required this.videoTrackSelections, + required this.audioTrackSelections, + required this.textTrackSelections, + }); + + final VideoPlayerController controller; + final List videoTrackSelections; + final List audioTrackSelections; + final List textTrackSelections; + + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 3, + child: AlertDialog( + titlePadding: EdgeInsets.zero, + contentPadding: EdgeInsets.zero, + title: TabBar( + labelColor: Colors.black, + tabs: [ + if (videoTrackSelections.isNotEmpty) const Tab(text: 'Video'), + if (audioTrackSelections.isNotEmpty) const Tab(text: 'Audio'), + if (textTrackSelections.isNotEmpty) const Tab(text: 'Text'), + ], + ), + content: SizedBox( + height: 200, + width: 200, + child: TabBarView( + children: [ + if (videoTrackSelections.isNotEmpty) + ListView.builder( + itemCount: videoTrackSelections.length, + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text( + '${videoTrackSelections[index].width}x${videoTrackSelections[index].height},${(videoTrackSelections[index].bitrate! / 1000000).toStringAsFixed(2)}Mbps'), + onTap: () { + controller + .setTrackSelection(videoTrackSelections[index]); + }, + ); + }), + if (audioTrackSelections.isNotEmpty) + ListView.builder( + itemCount: audioTrackSelections.length, + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text( + 'language:${audioTrackSelections[index].language}'), + onTap: () { + controller + .setTrackSelection(audioTrackSelections[index]); + }, + ); + }), + if (textTrackSelections.isNotEmpty) + ListView.builder( + itemCount: textTrackSelections.length, + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text( + 'language:${textTrackSelections[index].language}'), + onTap: () { + controller + .setTrackSelection(textTrackSelections[index]); + }, + ); + }), + ], + ), + ), + ), + ); + } +} From e918614978b9126d8af37cacaa8fd9b3421288d9 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Tue, 8 Aug 2023 14:30:26 +0800 Subject: [PATCH 05/15] Mino code cleanups --- .../tizen/src/video_player.cc | 261 +++++++++--------- 1 file changed, 134 insertions(+), 127 deletions(-) diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index d88563251..6ae6c3371 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -271,152 +271,153 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { if (ret != PLAYER_ERROR_NONE) { LOG_ERROR("[VideoPlayer] player_get_state failed: %s", get_error_message(ret)); + return {}; } if (state == PLAYER_STATE_NONE || state == PLAYER_STATE_IDLE) { LOG_ERROR("[VideoPlayer] Player not ready."); return {}; } + void *player_lib_handle = dlopen("libcapi-media-player.so.0", RTLD_LAZY); + if (!player_lib_handle) { + LOG_ERROR("[VideoPlayer] dlopen failed: %s", dlerror()); + return {}; + } + + FuncPlayerGetTrackCountV2 player_get_track_count_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_track_count_v2")); + FuncPlayerGetVideoTrackInfoV2 player_get_video_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_video_track_info_v2")); + FuncPlayerGetAudioTrackInfoV2 player_get_audio_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_audio_track_info_v2")); + FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_subtitle_track_info_v2")); + if (!player_get_track_count_v2 || !player_get_video_track_info_v2 || + !player_get_audio_track_info_v2 || !player_get_subtitle_track_info_v2) { + LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); + dlclose(player_lib_handle); + return {}; + } + int video_count = 0; - int audio_count = 0; - int subtitle_count = 0; - int stream_counter = 0; - int total_count = 0; + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_VIDEO, + &video_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_video_track_count failed: %s", + get_error_message(ret)); + return {}; + } - player_video_track_info_v2 *video_track_info = NULL; - player_audio_track_info_v2 *audio_track_info = NULL; - player_subtitle_track_info_v2 *sub_track_info = NULL; - StreamInformation *streamInfo = NULL; + int audio_count = 0; + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_AUDIO, + &audio_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_audio_track_count failed: %s", + get_error_message(ret)); + return {}; + } - void *player_lib_handle = dlopen("libcapi-media-player.so.0", RTLD_LAZY); - if (player_lib_handle) { - FuncPlayerGetTrackCountV2 player_get_track_count_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_track_count_v2")); - FuncPlayerGetVideoTrackInfoV2 player_get_video_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_video_track_info_v2")); - FuncPlayerGetAudioTrackInfoV2 player_get_audio_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_audio_track_info_v2")); - FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_subtitle_track_info_v2")); - - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_VIDEO, - &video_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_video_track_count failed: %s", - get_error_message(ret)); - } + int subtitle_count = 0; + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_TEXT, + &subtitle_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_subtitle_track_count failed: %s", + get_error_message(ret)); + return {}; + } - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_AUDIO, - &audio_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_audio_track_count failed: %s", - get_error_message(ret)); - } + int total_count = video_count + audio_count + subtitle_count; + LOG_INFO( + "[VideoPlayer] video_count: %d, audio_count: %d, subtitle_count:%d, " + "total_count: %d", + video_count, audio_count, subtitle_count, total_count); - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_TEXT, - &subtitle_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_subtitle_track_count failed: %s", - get_error_message(ret)); - } + int stream_counter = 0; + StreamInformation *streamInfo = NULL; + streamInfo = new StreamInformation[total_count]; - total_count = video_count + audio_count + subtitle_count; - LOG_INFO( - "[VideoPlayer] video_count: %d, audio_count: %d, subtitle_count:%d, " - "total_count: %d", - video_count, audio_count, subtitle_count, total_count); - streamInfo = new StreamInformation[total_count]; - - if (player_get_video_track_info_v2 || player_get_audio_track_info_v2 || - player_get_subtitle_track_info_v2) { - if (video_count > 0) { - for (int video_index = 0; video_index < video_count; video_index++) { - ret = player_get_video_track_info_v2(player_, video_index, - &video_track_info); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_video_track_info_v2 failed: %s", - get_error_message(ret)); - } - LOG_INFO( - "[VideoPlayer] video track info: width[%d], height[%d], " - "bitrate[%d]", - video_track_info->width, video_track_info->height, - video_track_info->bit_rate); - - streamInfo[stream_counter].track = video_index; - streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_VIDEO; - streamInfo[stream_counter].videoInfo.width = video_track_info->width; - streamInfo[stream_counter].videoInfo.height = - video_track_info->height; - streamInfo[stream_counter].videoInfo.bit_rate = - video_track_info->bit_rate; - stream_counter++; - } + player_video_track_info_v2 *video_track_info = NULL; + if (video_count > 0) { + for (int video_index = 0; video_index < video_count; video_index++) { + ret = player_get_video_track_info_v2(player_, video_index, + &video_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_video_track_info_v2 failed: %s", + get_error_message(ret)); + return {}; } + LOG_INFO( + "[VideoPlayer] video track info: width[%d], height[%d], " + "bitrate[%d]", + video_track_info->width, video_track_info->height, + video_track_info->bit_rate); + + streamInfo[stream_counter].track = video_index; + streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_VIDEO; + streamInfo[stream_counter].videoInfo.width = video_track_info->width; + streamInfo[stream_counter].videoInfo.height = video_track_info->height; + streamInfo[stream_counter].videoInfo.bit_rate = + video_track_info->bit_rate; + stream_counter++; + } + } - if (audio_count > 0) { - for (int audio_index = 0; audio_index < audio_count; audio_index++) { - ret = player_get_audio_track_info_v2(player_, audio_index, - &audio_track_info); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_audio_track_info_v2 failed: %s", - get_error_message(ret)); - } - LOG_INFO( - "[VideoPlayer] audio track info: language[%s], channel[%d], " - "sample_rate[%d], bitrate[%d]", - audio_track_info->language, audio_track_info->channel, - audio_track_info->sample_rate, audio_track_info->bit_rate); - - streamInfo[stream_counter].track = audio_index; - streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_AUDIO; - strcpy(streamInfo[stream_counter].audioInfo.language, - audio_track_info->language); - streamInfo[stream_counter].audioInfo.channel = - audio_track_info->channel; - streamInfo[stream_counter].audioInfo.bit_rate = - audio_track_info->bit_rate; - stream_counter++; - } + player_audio_track_info_v2 *audio_track_info = NULL; + if (audio_count > 0) { + for (int audio_index = 0; audio_index < audio_count; audio_index++) { + ret = player_get_audio_track_info_v2(player_, audio_index, + &audio_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_audio_track_info_v2 failed: %s", + get_error_message(ret)); + return {}; } + LOG_INFO( + "[VideoPlayer] audio track info: language[%s], channel[%d], " + "sample_rate[%d], bitrate[%d]", + audio_track_info->language, audio_track_info->channel, + audio_track_info->sample_rate, audio_track_info->bit_rate); + + streamInfo[stream_counter].track = audio_index; + streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_AUDIO; + strcpy(streamInfo[stream_counter].audioInfo.language, + audio_track_info->language); + streamInfo[stream_counter].audioInfo.channel = audio_track_info->channel; + streamInfo[stream_counter].audioInfo.bit_rate = + audio_track_info->bit_rate; + stream_counter++; + } + } - if (subtitle_count > 0) { - for (int sub_index = 0; sub_index < subtitle_count; sub_index++) { - ret = player_get_subtitle_track_info_v2(player_, sub_index, - &sub_track_info); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR( - "[VideoPlayer] player_get_subtitle_track_info_v2 failed: %s", - get_error_message(ret)); - } - LOG_INFO( - "[VideoPlayer] subtitle track info: language[%s], " - "subtitle_type[%d]", - sub_track_info->language, sub_track_info->subtitle_type); - - streamInfo[stream_counter].track = sub_index; - streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_TEXT; - strcpy(streamInfo[stream_counter].textInfo.language, - sub_track_info->language); - streamInfo[stream_counter].textInfo.subtitle_type = - sub_track_info->subtitle_type; - stream_counter++; - } + player_subtitle_track_info_v2 *sub_track_info = NULL; + if (subtitle_count > 0) { + for (int sub_index = 0; sub_index < subtitle_count; sub_index++) { + ret = player_get_subtitle_track_info_v2(player_, sub_index, + &sub_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_subtitle_track_info_v2 failed: %s", + get_error_message(ret)); + return {}; } - } else { - LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); - dlclose(player_lib_handle); - return {}; + LOG_INFO( + "[VideoPlayer] subtitle track info: language[%s], " + "subtitle_type[%d]", + sub_track_info->language, sub_track_info->subtitle_type); + + streamInfo[stream_counter].track = sub_index; + streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_TEXT; + strcpy(streamInfo[stream_counter].textInfo.language, + sub_track_info->language); + streamInfo[stream_counter].textInfo.subtitle_type = + sub_track_info->subtitle_type; + stream_counter++; } - dlclose(player_lib_handle); - } else { - LOG_ERROR("[VideoPlayer] dlopen failed: %s", dlerror()); - return {}; } + dlclose(player_lib_handle); flutter::EncodableList trackSelections; for (int index = 0; index < stream_counter; index++) { @@ -468,6 +469,12 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { trackSelections.push_back(flutter::EncodableValue(trackSelection)); } + + if (streamInfo) { + free(streamInfo); + streamInfo = nullptr; + } + return trackSelections; } From 4424bd4ef2bf5250d0cec9aeb2534ea46db9de70 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Tue, 8 Aug 2023 15:45:00 +0800 Subject: [PATCH 06/15] Define SelectedTracksMessage class as input --- .../lib/src/messages.g.dart | 56 ++++++++++-- .../lib/src/video_player_tizen.dart | 20 ++-- .../pigeons/messages.dart | 15 ++- .../tizen/src/messages.cc | 91 ++++++++++++++----- .../tizen/src/messages.h | 41 +++++++-- .../tizen/src/video_player.cc | 17 +--- .../tizen/src/video_player.h | 2 +- .../tizen/src/video_player_tizen_plugin.cc | 13 ++- 8 files changed, 176 insertions(+), 79 deletions(-) diff --git a/packages/video_player_videohole/lib/src/messages.g.dart b/packages/video_player_videohole/lib/src/messages.g.dart index a6da6782d..d06d99a2b 100644 --- a/packages/video_player_videohole/lib/src/messages.g.dart +++ b/packages/video_player_videohole/lib/src/messages.g.dart @@ -107,8 +107,8 @@ class PlaybackSpeedMessage { } } -class TrackSelectionsMessage { - TrackSelectionsMessage({ +class TrackMessage { + TrackMessage({ required this.playerId, required this.trackSelections, }); @@ -124,9 +124,9 @@ class TrackSelectionsMessage { ]; } - static TrackSelectionsMessage decode(Object result) { + static TrackMessage decode(Object result) { result as List; - return TrackSelectionsMessage( + return TrackMessage( playerId: result[0]! as int, trackSelections: (result[1] as List?)!.cast?>(), @@ -134,6 +134,37 @@ class TrackSelectionsMessage { } } +class SelectedTracksMessage { + SelectedTracksMessage({ + required this.playerId, + required this.trackId, + required this.trackType, + }); + + int playerId; + + int trackId; + + int trackType; + + Object encode() { + return [ + playerId, + trackId, + trackType, + ]; + } + + static SelectedTracksMessage decode(Object result) { + result as List; + return SelectedTracksMessage( + playerId: result[0]! as int, + trackId: result[1]! as int, + trackType: result[2]! as int, + ); + } +} + class PositionMessage { PositionMessage({ required this.playerId, @@ -295,12 +326,15 @@ class _VideoPlayerVideoholeApiCodec extends StandardMessageCodec { } else if (value is PositionMessage) { buffer.putUint8(134); writeValue(buffer, value.encode()); - } else if (value is TrackSelectionsMessage) { + } else if (value is SelectedTracksMessage) { buffer.putUint8(135); writeValue(buffer, value.encode()); - } else if (value is VolumeMessage) { + } else if (value is TrackMessage) { buffer.putUint8(136); writeValue(buffer, value.encode()); + } else if (value is VolumeMessage) { + buffer.putUint8(137); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -324,8 +358,10 @@ class _VideoPlayerVideoholeApiCodec extends StandardMessageCodec { case 134: return PositionMessage.decode(readValue(buffer)!); case 135: - return TrackSelectionsMessage.decode(readValue(buffer)!); + return SelectedTracksMessage.decode(readValue(buffer)!); case 136: + return TrackMessage.decode(readValue(buffer)!); + case 137: return VolumeMessage.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -550,7 +586,7 @@ class VideoPlayerVideoholeApi { } } - Future trackSelections(PlayerMessage arg_msg) async { + Future trackSelections(PlayerMessage arg_msg) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.VideoPlayerVideoholeApi.trackSelections', codec, binaryMessenger: _binaryMessenger); @@ -573,11 +609,11 @@ class VideoPlayerVideoholeApi { message: 'Host platform returned null value for non-null return value.', ); } else { - return (replyList[0] as TrackSelectionsMessage?)!; + return (replyList[0] as TrackMessage?)!; } } - Future setTrackSelection(TrackSelectionsMessage arg_msg) async { + Future setTrackSelection(SelectedTracksMessage arg_msg) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.VideoPlayerVideoholeApi.setTrackSelection', codec, binaryMessenger: _binaryMessenger); diff --git a/packages/video_player_videohole/lib/src/video_player_tizen.dart b/packages/video_player_videohole/lib/src/video_player_tizen.dart index 08c75e81e..eabbb62fe 100644 --- a/packages/video_player_videohole/lib/src/video_player_tizen.dart +++ b/packages/video_player_videohole/lib/src/video_player_tizen.dart @@ -90,7 +90,7 @@ class VideoPlayerTizen extends VideoPlayerPlatform { @override Future> getTrackSelections(int playerId) async { - final TrackSelectionsMessage response = + final TrackMessage response = await _api.trackSelections(PlayerMessage(playerId: playerId)); final List trackSelections = []; @@ -161,19 +161,13 @@ class VideoPlayerTizen extends VideoPlayerPlatform { @override Future setTrackSelection(int playerId, TrackSelection trackSelection) { - final List?> list = ?>[ - { - 'trackId': trackSelection.trackId, - 'trackType': _intTrackSelectionTypeMap.keys.firstWhere( - (int key) => - _intTrackSelectionTypeMap[key] == trackSelection.trackType, - orElse: () => -1), - } - ]; - - return _api.setTrackSelection(TrackSelectionsMessage( + return _api.setTrackSelection(SelectedTracksMessage( playerId: playerId, - trackSelections: list, + trackId: trackSelection.trackId, + trackType: _intTrackSelectionTypeMap.keys.firstWhere( + (int key) => + _intTrackSelectionTypeMap[key] == trackSelection.trackType, + orElse: () => -1), )); } diff --git a/packages/video_player_videohole/pigeons/messages.dart b/packages/video_player_videohole/pigeons/messages.dart index 317dc1046..812b7a9ba 100644 --- a/packages/video_player_videohole/pigeons/messages.dart +++ b/packages/video_player_videohole/pigeons/messages.dart @@ -32,12 +32,19 @@ class PlaybackSpeedMessage { double speed; } -class TrackSelectionsMessage { - TrackSelectionsMessage(this.playerId, this.trackSelections); +class TrackMessage { + TrackMessage(this.playerId, this.trackSelections); int playerId; List?> trackSelections; } +class SelectedTracksMessage { + SelectedTracksMessage(this.playerId, this.trackId, this.trackType); + int playerId; + int trackId; + int trackType; +} + class PositionMessage { PositionMessage(this.playerId, this.position); int playerId; @@ -80,8 +87,8 @@ abstract class VideoPlayerVideoholeApi { PositionMessage position(PlayerMessage msg); @async void seekTo(PositionMessage msg); - TrackSelectionsMessage trackSelections(PlayerMessage msg); - void setTrackSelection(TrackSelectionsMessage msg); + TrackMessage trackSelections(PlayerMessage msg); + void setTrackSelection(SelectedTracksMessage msg); void pause(PlayerMessage msg); void setMixWithOthers(MixWithOthersMessage msg); void setDisplayGeometry(GeometryMessage msg); diff --git a/packages/video_player_videohole/tizen/src/messages.cc b/packages/video_player_videohole/tizen/src/messages.cc index a85d5705b..b4ac2d4cd 100644 --- a/packages/video_player_videohole/tizen/src/messages.cc +++ b/packages/video_player_videohole/tizen/src/messages.cc @@ -123,28 +123,25 @@ PlaybackSpeedMessage PlaybackSpeedMessage::FromEncodableList( return decoded; } -// TrackSelectionsMessage +// TrackMessage -TrackSelectionsMessage::TrackSelectionsMessage( - int64_t player_id, const EncodableList& track_selections) +TrackMessage::TrackMessage(int64_t player_id, + const EncodableList& track_selections) : player_id_(player_id), track_selections_(track_selections) {} -int64_t TrackSelectionsMessage::player_id() const { return player_id_; } +int64_t TrackMessage::player_id() const { return player_id_; } -void TrackSelectionsMessage::set_player_id(int64_t value_arg) { - player_id_ = value_arg; -} +void TrackMessage::set_player_id(int64_t value_arg) { player_id_ = value_arg; } -const EncodableList& TrackSelectionsMessage::track_selections() const { +const EncodableList& TrackMessage::track_selections() const { return track_selections_; } -void TrackSelectionsMessage::set_track_selections( - const EncodableList& value_arg) { +void TrackMessage::set_track_selections(const EncodableList& value_arg) { track_selections_ = value_arg; } -EncodableList TrackSelectionsMessage::ToEncodableList() const { +EncodableList TrackMessage::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(EncodableValue(player_id_)); @@ -152,10 +149,49 @@ EncodableList TrackSelectionsMessage::ToEncodableList() const { return list; } -TrackSelectionsMessage TrackSelectionsMessage::FromEncodableList( +TrackMessage TrackMessage::FromEncodableList(const EncodableList& list) { + TrackMessage decoded(list[0].LongValue(), std::get(list[1])); + return decoded; +} + +// SelectedTracksMessage + +SelectedTracksMessage::SelectedTracksMessage(int64_t player_id, + int64_t track_id, + int64_t track_type) + : player_id_(player_id), track_id_(track_id), track_type_(track_type) {} + +int64_t SelectedTracksMessage::player_id() const { return player_id_; } + +void SelectedTracksMessage::set_player_id(int64_t value_arg) { + player_id_ = value_arg; +} + +int64_t SelectedTracksMessage::track_id() const { return track_id_; } + +void SelectedTracksMessage::set_track_id(int64_t value_arg) { + track_id_ = value_arg; +} + +int64_t SelectedTracksMessage::track_type() const { return track_type_; } + +void SelectedTracksMessage::set_track_type(int64_t value_arg) { + track_type_ = value_arg; +} + +EncodableList SelectedTracksMessage::ToEncodableList() const { + EncodableList list; + list.reserve(3); + list.push_back(EncodableValue(player_id_)); + list.push_back(EncodableValue(track_id_)); + list.push_back(EncodableValue(track_type_)); + return list; +} + +SelectedTracksMessage SelectedTracksMessage::FromEncodableList( const EncodableList& list) { - TrackSelectionsMessage decoded(list[0].LongValue(), - std::get(list[1])); + SelectedTracksMessage decoded(list[0].LongValue(), list[1].LongValue(), + list[2].LongValue()); return decoded; } @@ -424,9 +460,12 @@ EncodableValue VideoPlayerVideoholeApiCodecSerializer::ReadValueOfType( return CustomEncodableValue(PositionMessage::FromEncodableList( std::get(ReadValue(stream)))); case 135: - return CustomEncodableValue(TrackSelectionsMessage::FromEncodableList( + return CustomEncodableValue(SelectedTracksMessage::FromEncodableList( std::get(ReadValue(stream)))); case 136: + return CustomEncodableValue(TrackMessage::FromEncodableList( + std::get(ReadValue(stream)))); + case 137: return CustomEncodableValue(VolumeMessage::FromEncodableList( std::get(ReadValue(stream)))); default: @@ -494,16 +533,24 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( stream); return; } - if (custom_value->type() == typeid(TrackSelectionsMessage)) { + if (custom_value->type() == typeid(SelectedTracksMessage)) { stream->WriteByte(135); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(VolumeMessage)) { + if (custom_value->type() == typeid(TrackMessage)) { stream->WriteByte(136); + WriteValue( + EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(VolumeMessage)) { + stream->WriteByte(137); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -837,8 +884,7 @@ void VideoPlayerVideoholeApi::SetUp(flutter::BinaryMessenger* binary_messenger, } const auto& msg_arg = std::any_cast( std::get(encodable_msg_arg)); - ErrorOr output = - api->TrackSelections(msg_arg); + ErrorOr output = api->TrackSelections(msg_arg); if (output.has_error()) { reply(WrapError(output.error())); return; @@ -871,9 +917,8 @@ void VideoPlayerVideoholeApi::SetUp(flutter::BinaryMessenger* binary_messenger, reply(WrapError("msg_arg unexpectedly null.")); return; } - const auto& msg_arg = - std::any_cast( - std::get(encodable_msg_arg)); + const auto& msg_arg = std::any_cast( + std::get(encodable_msg_arg)); std::optional output = api->SetTrackSelection(msg_arg); if (output.has_value()) { diff --git a/packages/video_player_videohole/tizen/src/messages.h b/packages/video_player_videohole/tizen/src/messages.h index 7dc64c00e..7f2285457 100644 --- a/packages/video_player_videohole/tizen/src/messages.h +++ b/packages/video_player_videohole/tizen/src/messages.h @@ -135,11 +135,11 @@ class PlaybackSpeedMessage { }; // Generated class from Pigeon that represents data sent in messages. -class TrackSelectionsMessage { +class TrackMessage { public: // Constructs an object setting all fields. - explicit TrackSelectionsMessage( - int64_t player_id, const flutter::EncodableList& track_selections); + explicit TrackMessage(int64_t player_id, + const flutter::EncodableList& track_selections); int64_t player_id() const; void set_player_id(int64_t value_arg); @@ -148,8 +148,7 @@ class TrackSelectionsMessage { void set_track_selections(const flutter::EncodableList& value_arg); private: - static TrackSelectionsMessage FromEncodableList( - const flutter::EncodableList& list); + static TrackMessage FromEncodableList(const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; friend class VideoPlayerVideoholeApi; friend class VideoPlayerVideoholeApiCodecSerializer; @@ -157,6 +156,33 @@ class TrackSelectionsMessage { flutter::EncodableList track_selections_; }; +// Generated class from Pigeon that represents data sent in messages. +class SelectedTracksMessage { + public: + // Constructs an object setting all fields. + explicit SelectedTracksMessage(int64_t player_id, int64_t track_id, + int64_t track_type); + + int64_t player_id() const; + void set_player_id(int64_t value_arg); + + int64_t track_id() const; + void set_track_id(int64_t value_arg); + + int64_t track_type() const; + void set_track_type(int64_t value_arg); + + private: + static SelectedTracksMessage FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class VideoPlayerVideoholeApi; + friend class VideoPlayerVideoholeApiCodecSerializer; + int64_t player_id_; + int64_t track_id_; + int64_t track_type_; +}; + // Generated class from Pigeon that represents data sent in messages. class PositionMessage { public: @@ -316,10 +342,9 @@ class VideoPlayerVideoholeApi { virtual void SeekTo( const PositionMessage& msg, std::function reply)> result) = 0; - virtual ErrorOr TrackSelections( - const PlayerMessage& msg) = 0; + virtual ErrorOr TrackSelections(const PlayerMessage& msg) = 0; virtual std::optional SetTrackSelection( - const TrackSelectionsMessage& msg) = 0; + const SelectedTracksMessage& msg) = 0; virtual std::optional Pause(const PlayerMessage& msg) = 0; virtual std::optional SetMixWithOthers( const MixWithOthersMessage& msg) = 0; diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index 6ae6c3371..43226c149 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -478,30 +478,21 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { return trackSelections; } -void VideoPlayer::SetTrackSelection(const flutter::EncodableList &list) { +void VideoPlayer::SetTrackSelection(int32_t track_id, int32_t track_type) { + LOG_INFO("[VideoPlayer] track_id: %d,track_type: %d", track_id, track_type); + player_state_e state = PLAYER_STATE_NONE; int ret = player_get_state(player_, &state); if (ret != PLAYER_ERROR_NONE) { LOG_ERROR("[VideoPlayer] player_get_state failed: %s", get_error_message(ret)); + return; } if (state == PLAYER_STATE_NONE || state == PLAYER_STATE_IDLE) { LOG_ERROR("[VideoPlayer] Player not ready."); return; } - flutter::EncodableMap track_map; - if (!list.empty()) { - for (auto &map : list) { - track_map = std::get(map); - } - } - - int track_id = std::get(track_map[flutter::EncodableValue("trackId")]); - int track_type = - std::get(track_map[flutter::EncodableValue("trackType")]); - LOG_INFO("[VideoPlayer] track_id: %d,track_type: %d", track_id, track_type); - ret = player_select_track(player_, (player_stream_type_e)track_type, track_id); if (ret != PLAYER_ERROR_NONE) { diff --git a/packages/video_player_videohole/tizen/src/video_player.h b/packages/video_player_videohole/tizen/src/video_player.h index b48f5630b..975367b56 100644 --- a/packages/video_player_videohole/tizen/src/video_player.h +++ b/packages/video_player_videohole/tizen/src/video_player.h @@ -94,7 +94,7 @@ class VideoPlayer { void SeekTo(int32_t position, SeekCompletedCallback callback); int32_t GetPosition(); flutter::EncodableList getTotalTrackInfo(); - void SetTrackSelection(const flutter::EncodableList &list); + void SetTrackSelection(int32_t track_id, int32_t track_type); void RegisterSendPort(Dart_Port send_port) { send_port_ = send_port; } diff --git a/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc b/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc index 2a1a94d1b..e59bc3cec 100644 --- a/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc +++ b/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc @@ -44,10 +44,9 @@ class VideoPlayerTizenPlugin : public flutter::Plugin, void SeekTo( const PositionMessage &msg, std::function reply)> result) override; - ErrorOr TrackSelections( - const PlayerMessage &msg) override; + ErrorOr TrackSelections(const PlayerMessage &msg) override; std::optional SetTrackSelection( - const TrackSelectionsMessage &msg) override; + const SelectedTracksMessage &msg) override; std::optional Pause(const PlayerMessage &msg) override; std::optional SetMixWithOthers( const MixWithOthersMessage &msg) override; @@ -247,24 +246,24 @@ void VideoPlayerTizenPlugin::SeekTo( player->SeekTo(msg.position(), [result]() -> void { result(std::nullopt); }); } -ErrorOr VideoPlayerTizenPlugin::TrackSelections( +ErrorOr VideoPlayerTizenPlugin::TrackSelections( const PlayerMessage &msg) { VideoPlayer *player = FindPlayerById(msg.player_id()); if (!player) { return FlutterError("Invalid argument", "Player not found."); } - TrackSelectionsMessage result(msg.player_id(), player->getTotalTrackInfo()); + TrackMessage result(msg.player_id(), player->getTotalTrackInfo()); return result; } std::optional VideoPlayerTizenPlugin::SetTrackSelection( - const TrackSelectionsMessage &msg) { + const SelectedTracksMessage &msg) { VideoPlayer *player = FindPlayerById(msg.player_id()); if (!player) { return FlutterError("Invalid argument", "Player not found."); } - player->SetTrackSelection(msg.track_selections()); + player->SetTrackSelection(msg.track_id(), msg.track_type()); return std::nullopt; } From e63ef2d4f8d75c1b929614ea88432722ad02bd3d Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Wed, 16 Aug 2023 16:24:23 +0800 Subject: [PATCH 07/15] Use VideoTrack,AudioTrack,TextTrack extend Track class --- .../example/lib/main.dart | 216 +++++++------- .../lib/src/messages.g.dart | 177 ++++++++++-- .../lib/src/video_player_tizen.dart | 165 ++++++----- .../lib/video_player.dart | 40 ++- .../lib/video_player_platform_interface.dart | 229 ++++++++------- .../pigeons/messages.dart | 22 +- .../tizen/src/messages.cc | 237 +++++++++++++--- .../tizen/src/messages.h | 64 ++++- .../tizen/src/video_player.cc | 263 ++++++++++-------- .../tizen/src/video_player.h | 14 +- .../tizen/src/video_player_tizen_plugin.cc | 33 ++- 11 files changed, 934 insertions(+), 526 deletions(-) diff --git a/packages/video_player_videohole/example/lib/main.dart b/packages/video_player_videohole/example/lib/main.dart index 9c1e46c12..ed3216ccf 100644 --- a/packages/video_player_videohole/example/lib/main.dart +++ b/packages/video_player_videohole/example/lib/main.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// ignore_for_file: public_member_api_docs, avoid_print +// ignore_for_file: public_member_api_docs, avoid_print, use_build_context_synchronously /// An example of using the plugin, controlling lifecycle and playback of the /// video. @@ -38,7 +38,7 @@ class _App extends StatelessWidget { Tab(icon: Icon(Icons.cloud), text: 'Dash'), Tab(icon: Icon(Icons.cloud), text: 'DRM Widevine'), Tab(icon: Icon(Icons.cloud), text: 'DRM PlayReady'), - Tab(icon: Icon(Icons.cloud), text: 'Track Selections'), + Tab(icon: Icon(Icons.cloud), text: 'Track'), ], ), ), @@ -49,7 +49,7 @@ class _App extends StatelessWidget { _DashRomoteVideo(), _DrmRemoteVideo(), _DrmRemoteVideo2(), - _TrackSelectionTest(), + _TrackTest(), ], ), ), @@ -373,12 +373,12 @@ class _DrmRemoteVideoState2 extends State<_DrmRemoteVideo2> { } } -class _TrackSelectionTest extends StatefulWidget { +class _TrackTest extends StatefulWidget { @override - State<_TrackSelectionTest> createState() => _TrackSelectionTestState2(); + State<_TrackTest> createState() => _TrackTestState(); } -class _TrackSelectionTestState2 extends State<_TrackSelectionTest> { +class _TrackTestState extends State<_TrackTest> { late VideoPlayerController _controller; @override @@ -427,7 +427,9 @@ class _TrackSelectionTestState2 extends State<_TrackSelectionTest> { ), ), ), - _GetTrackSelectionButton(controller: _controller), + _GetVideoTrackButton(controller: _controller), + _GetAudioTrackButton(controller: _controller), + _GetTextTrackButton(controller: _controller), ], ), ); @@ -550,8 +552,8 @@ class _ControlsOverlay extends StatelessWidget { } } -class _GetTrackSelectionButton extends StatelessWidget { - const _GetTrackSelectionButton({required this.controller}); +class _GetVideoTrackButton extends StatelessWidget { + const _GetVideoTrackButton({required this.controller}); final VideoPlayerController controller; @@ -560,113 +562,123 @@ class _GetTrackSelectionButton extends StatelessWidget { return Padding( padding: const EdgeInsets.only(top: 20.0), child: MaterialButton( - child: const Text('Get Track Selection'), + child: const Text('Get Video Track'), onPressed: () async { - final List? tracks = - await controller.trackSelections; - if (tracks == null) { + final List? videotracks = await controller.videoTracks; + if (videotracks == null) { return; } - // ignore: use_build_context_synchronously await showDialog( - context: context, - builder: (_) => _TrackSelectionDialog( - controller: controller, - videoTrackSelections: tracks - .where((TrackSelection track) => - track.trackType == TrackSelectionType.video) - .toList(), - audioTrackSelections: tracks - .where((TrackSelection track) => - track.trackType == TrackSelectionType.audio) - .toList(), - textTrackSelections: tracks - .where((TrackSelection track) => - track.trackType == TrackSelectionType.text) - .toList(), - ), - ); + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Video'), + content: SizedBox( + height: 200, + width: 200, + child: ListView.builder( + itemCount: videotracks.length, + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text( + '${videotracks[index].width}x${videotracks[index].height},${(videotracks[index].bitrate / 1000000).toStringAsFixed(2)}Mbps'), + onTap: () { + controller + .setTrackSelection(videotracks[index]); + }, + ); + }, + )), + ); + }); }), ); } } -class _TrackSelectionDialog extends StatelessWidget { - const _TrackSelectionDialog({ - required this.controller, - required this.videoTrackSelections, - required this.audioTrackSelections, - required this.textTrackSelections, - }); +class _GetAudioTrackButton extends StatelessWidget { + const _GetAudioTrackButton({required this.controller}); final VideoPlayerController controller; - final List videoTrackSelections; - final List audioTrackSelections; - final List textTrackSelections; @override Widget build(BuildContext context) { - return DefaultTabController( - length: 3, - child: AlertDialog( - titlePadding: EdgeInsets.zero, - contentPadding: EdgeInsets.zero, - title: TabBar( - labelColor: Colors.black, - tabs: [ - if (videoTrackSelections.isNotEmpty) const Tab(text: 'Video'), - if (audioTrackSelections.isNotEmpty) const Tab(text: 'Audio'), - if (textTrackSelections.isNotEmpty) const Tab(text: 'Text'), - ], - ), - content: SizedBox( - height: 200, - width: 200, - child: TabBarView( - children: [ - if (videoTrackSelections.isNotEmpty) - ListView.builder( - itemCount: videoTrackSelections.length, - itemBuilder: (BuildContext context, int index) { - return ListTile( - title: Text( - '${videoTrackSelections[index].width}x${videoTrackSelections[index].height},${(videoTrackSelections[index].bitrate! / 1000000).toStringAsFixed(2)}Mbps'), - onTap: () { - controller - .setTrackSelection(videoTrackSelections[index]); - }, - ); - }), - if (audioTrackSelections.isNotEmpty) - ListView.builder( - itemCount: audioTrackSelections.length, - itemBuilder: (BuildContext context, int index) { - return ListTile( - title: Text( - 'language:${audioTrackSelections[index].language}'), - onTap: () { - controller - .setTrackSelection(audioTrackSelections[index]); - }, - ); - }), - if (textTrackSelections.isNotEmpty) - ListView.builder( - itemCount: textTrackSelections.length, - itemBuilder: (BuildContext context, int index) { - return ListTile( - title: Text( - 'language:${textTrackSelections[index].language}'), - onTap: () { - controller - .setTrackSelection(textTrackSelections[index]); - }, - ); - }), - ], - ), - ), - ), + return Padding( + padding: const EdgeInsets.only(top: 20.0), + child: MaterialButton( + child: const Text('Get Audio Track'), + onPressed: () async { + final List? audioTracks = await controller.audioTracks; + if (audioTracks == null) { + return; + } + await showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Audio'), + content: SizedBox( + height: 200, + width: 200, + child: ListView.builder( + itemCount: audioTracks.length, + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text( + 'language:${audioTracks[index].language}'), + onTap: () { + controller + .setTrackSelection(audioTracks[index]); + }, + ); + }, + )), + ); + }); + }), + ); + } +} + +class _GetTextTrackButton extends StatelessWidget { + const _GetTextTrackButton({required this.controller}); + + final VideoPlayerController controller; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 20.0), + child: MaterialButton( + child: const Text('Get Text Track'), + onPressed: () async { + final List? textTracks = await controller.textTracks; + if (textTracks == null) { + return; + } + await showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Text'), + content: SizedBox( + height: 200, + width: 200, + child: ListView.builder( + itemCount: textTracks.length, + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text( + 'language:${textTracks[index].language}'), + onTap: () { + controller.setTrackSelection(textTracks[index]); + }, + ); + }, + )), + ); + }); + }), ); } } diff --git a/packages/video_player_videohole/lib/src/messages.g.dart b/packages/video_player_videohole/lib/src/messages.g.dart index d06d99a2b..1c4e5acc3 100644 --- a/packages/video_player_videohole/lib/src/messages.g.dart +++ b/packages/video_player_videohole/lib/src/messages.g.dart @@ -107,33 +107,86 @@ class PlaybackSpeedMessage { } } -class TrackMessage { - TrackMessage({ +class VideoTrackMessage { + VideoTrackMessage({ required this.playerId, - required this.trackSelections, + required this.videoTracks, }); int playerId; - List?> trackSelections; + List?> videoTracks; Object encode() { return [ playerId, - trackSelections, + videoTracks, ]; } - static TrackMessage decode(Object result) { + static VideoTrackMessage decode(Object result) { result as List; - return TrackMessage( + return VideoTrackMessage( playerId: result[0]! as int, - trackSelections: + videoTracks: (result[1] as List?)!.cast?>(), ); } } +class AudioTrackMessage { + AudioTrackMessage({ + required this.playerId, + required this.audioTracks, + }); + + int playerId; + + List?> audioTracks; + + Object encode() { + return [ + playerId, + audioTracks, + ]; + } + + static AudioTrackMessage decode(Object result) { + result as List; + return AudioTrackMessage( + playerId: result[0]! as int, + audioTracks: + (result[1] as List?)!.cast?>(), + ); + } +} + +class TextTrackMessage { + TextTrackMessage({ + required this.playerId, + required this.textTracks, + }); + + int playerId; + + List?> textTracks; + + Object encode() { + return [ + playerId, + textTracks, + ]; + } + + static TextTrackMessage decode(Object result) { + result as List; + return TextTrackMessage( + playerId: result[0]! as int, + textTracks: (result[1] as List?)!.cast?>(), + ); + } +} + class SelectedTracksMessage { SelectedTracksMessage({ required this.playerId, @@ -305,36 +358,42 @@ class _VideoPlayerVideoholeApiCodec extends StandardMessageCodec { const _VideoPlayerVideoholeApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is CreateMessage) { + if (value is AudioTrackMessage) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is GeometryMessage) { + } else if (value is CreateMessage) { buffer.putUint8(129); writeValue(buffer, value.encode()); - } else if (value is LoopingMessage) { + } else if (value is GeometryMessage) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is MixWithOthersMessage) { + } else if (value is LoopingMessage) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is PlaybackSpeedMessage) { + } else if (value is MixWithOthersMessage) { buffer.putUint8(132); writeValue(buffer, value.encode()); - } else if (value is PlayerMessage) { + } else if (value is PlaybackSpeedMessage) { buffer.putUint8(133); writeValue(buffer, value.encode()); - } else if (value is PositionMessage) { + } else if (value is PlayerMessage) { buffer.putUint8(134); writeValue(buffer, value.encode()); - } else if (value is SelectedTracksMessage) { + } else if (value is PositionMessage) { buffer.putUint8(135); writeValue(buffer, value.encode()); - } else if (value is TrackMessage) { + } else if (value is SelectedTracksMessage) { buffer.putUint8(136); writeValue(buffer, value.encode()); - } else if (value is VolumeMessage) { + } else if (value is TextTrackMessage) { buffer.putUint8(137); writeValue(buffer, value.encode()); + } else if (value is VideoTrackMessage) { + buffer.putUint8(138); + writeValue(buffer, value.encode()); + } else if (value is VolumeMessage) { + buffer.putUint8(139); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -344,24 +403,28 @@ class _VideoPlayerVideoholeApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: - return CreateMessage.decode(readValue(buffer)!); + return AudioTrackMessage.decode(readValue(buffer)!); case 129: - return GeometryMessage.decode(readValue(buffer)!); + return CreateMessage.decode(readValue(buffer)!); case 130: - return LoopingMessage.decode(readValue(buffer)!); + return GeometryMessage.decode(readValue(buffer)!); case 131: - return MixWithOthersMessage.decode(readValue(buffer)!); + return LoopingMessage.decode(readValue(buffer)!); case 132: - return PlaybackSpeedMessage.decode(readValue(buffer)!); + return MixWithOthersMessage.decode(readValue(buffer)!); case 133: - return PlayerMessage.decode(readValue(buffer)!); + return PlaybackSpeedMessage.decode(readValue(buffer)!); case 134: - return PositionMessage.decode(readValue(buffer)!); + return PlayerMessage.decode(readValue(buffer)!); case 135: - return SelectedTracksMessage.decode(readValue(buffer)!); + return PositionMessage.decode(readValue(buffer)!); case 136: - return TrackMessage.decode(readValue(buffer)!); + return SelectedTracksMessage.decode(readValue(buffer)!); case 137: + return TextTrackMessage.decode(readValue(buffer)!); + case 138: + return VideoTrackMessage.decode(readValue(buffer)!); + case 139: return VolumeMessage.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -586,9 +649,63 @@ class VideoPlayerVideoholeApi { } } - Future trackSelections(PlayerMessage arg_msg) async { + Future videoTrack(PlayerMessage arg_msg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.VideoPlayerVideoholeApi.videoTrack', 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 VideoTrackMessage?)!; + } + } + + Future audioTrack(PlayerMessage arg_msg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.VideoPlayerVideoholeApi.audioTrack', 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 AudioTrackMessage?)!; + } + } + + Future textTrack(PlayerMessage arg_msg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.VideoPlayerVideoholeApi.trackSelections', codec, + 'dev.flutter.pigeon.VideoPlayerVideoholeApi.textTrack', codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_msg]) as List?; @@ -609,7 +726,7 @@ class VideoPlayerVideoholeApi { message: 'Host platform returned null value for non-null return value.', ); } else { - return (replyList[0] as TrackMessage?)!; + return (replyList[0] as TextTrackMessage?)!; } } diff --git a/packages/video_player_videohole/lib/src/video_player_tizen.dart b/packages/video_player_videohole/lib/src/video_player_tizen.dart index eabbb62fe..6cad29e55 100644 --- a/packages/video_player_videohole/lib/src/video_player_tizen.dart +++ b/packages/video_player_videohole/lib/src/video_player_tizen.dart @@ -89,84 +89,80 @@ class VideoPlayerTizen extends VideoPlayerPlatform { } @override - Future> getTrackSelections(int playerId) async { - final TrackMessage response = - await _api.trackSelections(PlayerMessage(playerId: playerId)); - - final List trackSelections = []; - - for (final Map? trackSelectionMap - in response.trackSelections) { - final TrackSelectionType trackSelectionType = - _intTrackSelectionTypeMap[trackSelectionMap!['trackType']]!; - final bool isUnknown = trackSelectionMap['isUnknown']! as bool; - final int trackId = trackSelectionMap['trackId']! as int; - - if (isUnknown) { - trackSelections.add(TrackSelection( - trackId: trackId, - trackType: trackSelectionType, - )); - } else { - switch (trackSelectionType) { - case TrackSelectionType.video: - { - final int bitrate = trackSelectionMap['bitrate']! as int; - final int width = trackSelectionMap['width']! as int; - final int height = trackSelectionMap['height']! as int; - - trackSelections.add(TrackSelection( - trackId: trackId, - trackType: trackSelectionType, - width: width, - height: height, - bitrate: bitrate == 0 ? null : bitrate, - )); - break; - } - case TrackSelectionType.audio: - { - final String language = trackSelectionMap['language']! as String; - final TrackSelectionChannelType channelType = - _intChannelTypeMap[trackSelectionMap['channel']]!; - final int bitrate = trackSelectionMap['bitrate']! as int; - trackSelections.add(TrackSelection( - trackId: trackId, - trackType: trackSelectionType, - language: language.isEmpty ? null : language, - channel: channelType, - bitrate: bitrate == 0 ? null : bitrate, - )); - break; - } - case TrackSelectionType.text: - { - final String language = trackSelectionMap['language']! as String; - final TrackSelectionSubtitleType subtitleType = - _intSubtitleTypeMap[trackSelectionMap['subtitleType']]!; - trackSelections.add(TrackSelection( - trackId: trackId, - trackType: trackSelectionType, - language: language.isEmpty ? null : language, - subtitleType: subtitleType, - )); - break; - } - } - } + Future> getVideoTracks(int playerId) async { + final VideoTrackMessage response = + await _api.videoTrack(PlayerMessage(playerId: playerId)); + + final List videoTracks = []; + for (final Map? trackMap in response.videoTracks) { + final int trackId = trackMap!['trackId']! as int; + final int bitrate = trackMap['bitrate']! as int; + final int width = trackMap['width']! as int; + final int height = trackMap['height']! as int; + + videoTracks.add(VideoTrack( + trackId: trackId, + width: width, + height: height, + bitrate: bitrate, + )); + } + + return videoTracks; + } + + @override + Future> getAudioTracks(int playerId) async { + final AudioTrackMessage response = + await _api.audioTrack(PlayerMessage(playerId: playerId)); + + final List audioTracks = []; + for (final Map? trackMap in response.audioTracks) { + final int trackId = trackMap!['trackId']! as int; + final String language = trackMap['language']! as String; + final AudioTrackChannelType channelType = + _intChannelTypeMap[trackMap['channel']]!; + final int bitrate = trackMap['bitrate']! as int; + audioTracks.add(AudioTrack( + trackId: trackId, + language: language, + channel: channelType, + bitrate: bitrate, + )); + } + + return audioTracks; + } + + @override + Future> getTextTracks(int playerId) async { + final TextTrackMessage response = + await _api.textTrack(PlayerMessage(playerId: playerId)); + + final List textTracks = []; + for (final Map? trackMap in response.textTracks) { + final int trackId = trackMap!['trackId']! as int; + final String language = trackMap['language']! as String; + final TextTrackSubtitleType subtitleType = + _intSubtitleTypeMap[trackMap['subtitleType']]!; + + textTracks.add(TextTrack( + trackId: trackId, + language: language, + subtitleType: subtitleType, + )); } - return trackSelections; + return textTracks; } @override - Future setTrackSelection(int playerId, TrackSelection trackSelection) { + Future setTrackSelection(int playerId, Track track) { return _api.setTrackSelection(SelectedTracksMessage( playerId: playerId, - trackId: trackSelection.trackId, - trackType: _intTrackSelectionTypeMap.keys.firstWhere( - (int key) => - _intTrackSelectionTypeMap[key] == trackSelection.trackType, + trackId: track.trackId, + trackType: _intTrackTypeMap.keys.firstWhere( + (int key) => _intTrackTypeMap[key] == track.trackType, orElse: () => -1), )); } @@ -258,23 +254,22 @@ class VideoPlayerTizen extends VideoPlayerPlatform { VideoFormat.other: 'other', }; - static const Map _intTrackSelectionTypeMap = - { - 1: TrackSelectionType.audio, - 2: TrackSelectionType.video, - 3: TrackSelectionType.text, + static const Map _intTrackTypeMap = { + 1: TrackType.audio, + 2: TrackType.video, + 3: TrackType.text, }; - static const Map _intChannelTypeMap = - { - 1: TrackSelectionChannelType.mono, - 2: TrackSelectionChannelType.stereo, - 3: TrackSelectionChannelType.surround, + static const Map _intChannelTypeMap = + { + 1: AudioTrackChannelType.mono, + 2: AudioTrackChannelType.stereo, + 3: AudioTrackChannelType.surround, }; - static const Map _intSubtitleTypeMap = - { - 0: TrackSelectionSubtitleType.text, - 1: TrackSelectionSubtitleType.picture, + static const Map _intSubtitleTypeMap = + { + 0: TextTrackSubtitleType.text, + 1: TextTrackSubtitleType.picture, }; } diff --git a/packages/video_player_videohole/lib/video_player.dart b/packages/video_player_videohole/lib/video_player.dart index 0538ba79c..62dea954f 100644 --- a/packages/video_player_videohole/lib/video_player.dart +++ b/packages/video_player_videohole/lib/video_player.dart @@ -44,7 +44,7 @@ class VideoPlayerValue { this.position = Duration.zero, this.caption = Caption.none, this.captionOffset = Duration.zero, - this.trackSelections = const [], + this.tracks = const [], this.buffered = 0, this.isInitialized = false, this.isPlaying = false, @@ -107,8 +107,8 @@ class VideoPlayerValue { /// The current speed of the playback. final double playbackSpeed; - /// The current playback track selections. - final List trackSelections; + /// The current playback tracks. + final List tracks; /// A description of the error if present. /// @@ -150,7 +150,7 @@ class VideoPlayerValue { Duration? position, Caption? caption, Duration? captionOffset, - List? trackSelections, + List? tracks, int? buffered, bool? isInitialized, bool? isPlaying, @@ -166,7 +166,7 @@ class VideoPlayerValue { position: position ?? this.position, caption: caption ?? this.caption, captionOffset: captionOffset ?? this.captionOffset, - trackSelections: trackSelections ?? this.trackSelections, + tracks: tracks ?? this.tracks, buffered: buffered ?? this.buffered, isInitialized: isInitialized ?? this.isInitialized, isPlaying: isPlaying ?? this.isPlaying, @@ -188,7 +188,7 @@ class VideoPlayerValue { 'position: $position, ' 'caption: $caption, ' 'captionOffset: $captionOffset, ' - 'trackSelections: $trackSelections, ' + 'tracks: $tracks, ' 'buffered: $buffered, ' 'isInitialized: $isInitialized, ' 'isPlaying: $isPlaying, ' @@ -584,20 +584,36 @@ class VideoPlayerController extends ValueNotifier { _updatePosition(position); } - /// The track selections in the current video. - Future?> get trackSelections async { + /// The video tracks in the current video. + Future?> get videoTracks async { if (!value.isInitialized || _isDisposed) { return null; } - return _videoPlayerPlatform.getTrackSelections(_playerId); + return _videoPlayerPlatform.getVideoTracks(_playerId); } - /// Sets the selected video track selection. - Future setTrackSelection(TrackSelection trackSelection) async { + /// The audio tracks in the current video. + Future?> get audioTracks async { + if (!value.isInitialized || _isDisposed) { + return null; + } + return _videoPlayerPlatform.getAudioTracks(_playerId); + } + + /// The text tracks in the current video. + Future?> get textTracks async { + if (!value.isInitialized || _isDisposed) { + return null; + } + return _videoPlayerPlatform.getTextTracks(_playerId); + } + + /// Sets the selected tracks. + Future setTrackSelection(Track track) async { if (!value.isInitialized || _isDisposed) { return; } - await _videoPlayerPlatform.setTrackSelection(_playerId, trackSelection); + await _videoPlayerPlatform.setTrackSelection(_playerId, track); } /// Sets the audio volume of [this]. diff --git a/packages/video_player_videohole/lib/video_player_platform_interface.dart b/packages/video_player_videohole/lib/video_player_platform_interface.dart index e278c75e7..d8b069908 100644 --- a/packages/video_player_videohole/lib/video_player_platform_interface.dart +++ b/packages/video_player_videohole/lib/video_player_platform_interface.dart @@ -86,15 +86,23 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('seekTo() has not been implemented.'); } - /// Gets the video [TrackSelection]s. For convenience if the video file has at - /// least one [TrackSelection] for a specific type, the auto track selection will - /// be added to this list with that type. - Future> getTrackSelections(int playerId) { - throw UnimplementedError('getTrackSelection() has not been implemented.'); + /// Gets the video tracks as a list of [VideoTrack]. + Future> getVideoTracks(int playerId) { + throw UnimplementedError('getVideoTracks() has not been implemented.'); + } + + /// Gets the video tracks as a list of [AudioTrack]. + Future> getAudioTracks(int playerId) { + throw UnimplementedError('getAudioTracks() has not been implemented.'); + } + + /// Gets the video tracks as a list of [TextTrack]. + Future> getTextTracks(int playerId) { + throw UnimplementedError('getTextTracks() has not been implemented.'); } /// Sets the selected video track selection. - Future setTrackSelection(int playerId, TrackSelection trackSelection) { + Future setTrackSelection(int playerId, Track track) { throw UnimplementedError('setTrackSelection() has not been implemented.'); } @@ -403,139 +411,126 @@ class VideoPlayerOptions { final bool mixWithOthers; } -/// A representation of a single track selection. +/// Type of the track. +enum TrackType { + /// The video track. + video, + + /// The audio track. + audio, + + /// The text track. + text, +} + +/// Type of the track audio channel for [TrackType.audio]. +enum AudioTrackChannelType { + /// The mono channel. + mono, + + /// The stereo channel. + stereo, + + /// The surround channel. + surround, +} + +/// Type of the track subtitle type for [TrackType.text]. +enum TextTrackSubtitleType { + /// The text subtitle. + text, + + /// The picture subtitle. + picture, +} + +/// A representation of a single track. /// -/// A typical video file will include several [TrackSelection]s. For convenience -/// the auto track selection will be added to this list of [getTrackSelections]. -@immutable -class TrackSelection { - /// Creates an instance of [VideoEvent]. +/// A typical video file will include several [Track]s.Such as [VideoTrack]s, [AudioTrack]s, [TextTrack]s. +class Track { + /// Creates an instance of [Track]. /// - /// The [trackId] and [trackType] argument is required. + /// The [trackId] argument is required. /// - const TrackSelection({ + const Track({ required this.trackId, required this.trackType, - this.width, - this.height, - this.bitrate, - this.language, - this.channel, - this.subtitleType, }); - /// The track id of track selection that uses to determine track selection. + /// The track id of track that uses to determine track. final int trackId; - /// The type of the track selection. - final TrackSelectionType trackType; + /// The type of the track. + final TrackType trackType; +} - /// The width of video track selection. This will be null if the [trackType] - /// is not [TrackSelectionType.video] or an unknowntrack selection. +/// A representation of a video track. +class VideoTrack extends Track { + /// Creates an instance of [VideoTrack]. /// - /// If the track selection doesn't specify the width this may be null. - final int? width; - - /// The height of video track selection. This will be null if the [trackType] - /// is not [TrackSelectionType.video] or an unknown track selection. + /// The [width], [height] and [bitrate] argument is required. /// - /// If the track selection doesn't specify the height this may be null. - final int? height; + /// [trackType] is [TrackType.video]. + VideoTrack({ + required super.trackId, + super.trackType = TrackType.video, + required this.width, + required this.height, + required this.bitrate, + }); - /// The label of track selection. This will be null if the [trackType] - /// is not [TrackSelectionType.video] and [TrackSelectionType.audio] or an unknown - /// track selection. - /// - /// If the track selection doesn't specify the bitrate this may be null. - final int? bitrate; + /// The width of video track. + final int width; - /// The language of track selection. This will be null if the [trackType] - /// is not [TrackSelectionType.audio] and [TrackSelectionType.text] or an unknown - /// track selection. - /// - /// If the track selection doesn't specify the language this may be null. - final String? language; + /// The height of video track. + final int height; - /// The channelCount of track selection. This will be null if the [trackType] - /// is not [TrackSelectionType.audio] or an unknown track selection. - /// - /// If the track selection doesn't specify the channelCount this may be null. - final TrackSelectionChannelType? channel; + /// The bitrate of video track. + final int bitrate; +} - /// The subtitle type of track selection. This will be null if the [trackType] - /// is not [TrackSelectionType.text] or an unknown track selection. +/// A representation of a audio track. +class AudioTrack extends Track { + /// Creates an instance of [AudioTrack]. + /// + /// The [language], [channel] argument is required. /// - /// If the track selection doesn't specify the subtitle type this may be null. - final TrackSelectionSubtitleType? subtitleType; + /// [trackType] is [TrackType.audio]. + AudioTrack({ + required super.trackId, + super.trackType = TrackType.audio, + required this.language, + required this.channel, + required this.bitrate, + }); - @override - String toString() { - return '${objectRuntimeType(this, 'TrackSelection')}(' - 'trackId: $trackId, ' - 'trackType: $trackType, ' - 'width: $width, ' - 'height: $height, ' - 'language: $language, ' - 'channel: $channel, ' - 'subtitleType: $subtitleType, ' - 'bitrate: $bitrate)'; - } + /// The language of audio track. + final String language; - @override - bool operator ==(Object other) => - identical(this, other) || - other is TrackSelection && - runtimeType == other.runtimeType && - trackId == other.trackId && - trackType == other.trackType && - width == other.width && - height == other.height && - language == other.language && - channel == other.channel && - subtitleType == other.subtitleType && - bitrate == other.bitrate; + /// The channel of audio track. + final AudioTrackChannelType channel; - @override - int get hashCode => - trackId.hashCode ^ - trackType.hashCode ^ - width.hashCode ^ - height.hashCode ^ - language.hashCode ^ - channel.hashCode ^ - subtitleType.hashCode ^ - bitrate.hashCode; + /// The bitrate of audio track. + final int bitrate; } -/// Type of the track selection. -enum TrackSelectionType { - /// The video track selection. - video, - - /// The audio track selection. - audio, - - /// The text track selection. - text, -} - -/// Type of the track selection channel for [TrackSelectionType.audio]. -enum TrackSelectionChannelType { - /// The mono channel. - mono, - - /// The stereo channel. - stereo, - - /// The surround channel. - surround, -} +/// A representation of a text track. +class TextTrack extends Track { + /// Creates an instance of [TextTrack]. + /// + /// The [language] argument is required. + /// + /// [trackType] is [TrackType.text]. + TextTrack({ + required super.trackId, + super.trackType = TrackType.text, + required this.language, + required this.subtitleType, + }); -/// Type of the track selection channel for [TrackSelectionType.text]. -enum TrackSelectionSubtitleType { - /// The text subtitle. - text, + /// The language of text track. + final String language; - /// The picture subtitle. - picture, + /// The subtitle type of track. + final TextTrackSubtitleType subtitleType; } diff --git a/packages/video_player_videohole/pigeons/messages.dart b/packages/video_player_videohole/pigeons/messages.dart index 812b7a9ba..cd8701a0a 100644 --- a/packages/video_player_videohole/pigeons/messages.dart +++ b/packages/video_player_videohole/pigeons/messages.dart @@ -32,10 +32,22 @@ class PlaybackSpeedMessage { double speed; } -class TrackMessage { - TrackMessage(this.playerId, this.trackSelections); +class VideoTrackMessage { + VideoTrackMessage(this.playerId, this.videoTracks); int playerId; - List?> trackSelections; + List?> videoTracks; +} + +class AudioTrackMessage { + AudioTrackMessage(this.playerId, this.audioTracks); + int playerId; + List?> audioTracks; +} + +class TextTrackMessage { + TextTrackMessage(this.playerId, this.textTracks); + int playerId; + List?> textTracks; } class SelectedTracksMessage { @@ -87,7 +99,9 @@ abstract class VideoPlayerVideoholeApi { PositionMessage position(PlayerMessage msg); @async void seekTo(PositionMessage msg); - TrackMessage trackSelections(PlayerMessage msg); + VideoTrackMessage videoTrack(PlayerMessage msg); + AudioTrackMessage audioTrack(PlayerMessage msg); + TextTrackMessage textTrack(PlayerMessage msg); void setTrackSelection(SelectedTracksMessage msg); void pause(PlayerMessage msg); void setMixWithOthers(MixWithOthersMessage msg); diff --git a/packages/video_player_videohole/tizen/src/messages.cc b/packages/video_player_videohole/tizen/src/messages.cc index b4ac2d4cd..83cab2bb8 100644 --- a/packages/video_player_videohole/tizen/src/messages.cc +++ b/packages/video_player_videohole/tizen/src/messages.cc @@ -123,34 +123,108 @@ PlaybackSpeedMessage PlaybackSpeedMessage::FromEncodableList( return decoded; } -// TrackMessage +// VideoTrackMessage -TrackMessage::TrackMessage(int64_t player_id, - const EncodableList& track_selections) - : player_id_(player_id), track_selections_(track_selections) {} +VideoTrackMessage::VideoTrackMessage(int64_t player_id, + const EncodableList& video_tracks) + : player_id_(player_id), video_tracks_(video_tracks) {} -int64_t TrackMessage::player_id() const { return player_id_; } +int64_t VideoTrackMessage::player_id() const { return player_id_; } -void TrackMessage::set_player_id(int64_t value_arg) { player_id_ = value_arg; } +void VideoTrackMessage::set_player_id(int64_t value_arg) { + player_id_ = value_arg; +} + +const EncodableList& VideoTrackMessage::video_tracks() const { + return video_tracks_; +} + +void VideoTrackMessage::set_video_tracks(const EncodableList& value_arg) { + video_tracks_ = value_arg; +} + +EncodableList VideoTrackMessage::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(player_id_)); + list.push_back(EncodableValue(video_tracks_)); + return list; +} + +VideoTrackMessage VideoTrackMessage::FromEncodableList( + const EncodableList& list) { + VideoTrackMessage decoded(list[0].LongValue(), + std::get(list[1])); + return decoded; +} + +// AudioTrackMessage + +AudioTrackMessage::AudioTrackMessage(int64_t player_id, + const EncodableList& audio_tracks) + : player_id_(player_id), audio_tracks_(audio_tracks) {} + +int64_t AudioTrackMessage::player_id() const { return player_id_; } -const EncodableList& TrackMessage::track_selections() const { - return track_selections_; +void AudioTrackMessage::set_player_id(int64_t value_arg) { + player_id_ = value_arg; +} + +const EncodableList& AudioTrackMessage::audio_tracks() const { + return audio_tracks_; } -void TrackMessage::set_track_selections(const EncodableList& value_arg) { - track_selections_ = value_arg; +void AudioTrackMessage::set_audio_tracks(const EncodableList& value_arg) { + audio_tracks_ = value_arg; } -EncodableList TrackMessage::ToEncodableList() const { +EncodableList AudioTrackMessage::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(EncodableValue(player_id_)); - list.push_back(EncodableValue(track_selections_)); + list.push_back(EncodableValue(audio_tracks_)); return list; } -TrackMessage TrackMessage::FromEncodableList(const EncodableList& list) { - TrackMessage decoded(list[0].LongValue(), std::get(list[1])); +AudioTrackMessage AudioTrackMessage::FromEncodableList( + const EncodableList& list) { + AudioTrackMessage decoded(list[0].LongValue(), + std::get(list[1])); + return decoded; +} + +// TextTrackMessage + +TextTrackMessage::TextTrackMessage(int64_t player_id, + const EncodableList& text_tracks) + : player_id_(player_id), text_tracks_(text_tracks) {} + +int64_t TextTrackMessage::player_id() const { return player_id_; } + +void TextTrackMessage::set_player_id(int64_t value_arg) { + player_id_ = value_arg; +} + +const EncodableList& TextTrackMessage::text_tracks() const { + return text_tracks_; +} + +void TextTrackMessage::set_text_tracks(const EncodableList& value_arg) { + text_tracks_ = value_arg; +} + +EncodableList TextTrackMessage::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(player_id_)); + list.push_back(EncodableValue(text_tracks_)); + return list; +} + +TextTrackMessage TextTrackMessage::FromEncodableList( + const EncodableList& list) { + TextTrackMessage decoded(list[0].LongValue(), + std::get(list[1])); return decoded; } @@ -439,33 +513,39 @@ EncodableValue VideoPlayerVideoholeApiCodecSerializer::ReadValueOfType( uint8_t type, flutter::ByteStreamReader* stream) const { switch (type) { case 128: - return CustomEncodableValue(CreateMessage::FromEncodableList( + return CustomEncodableValue(AudioTrackMessage::FromEncodableList( std::get(ReadValue(stream)))); case 129: - return CustomEncodableValue(GeometryMessage::FromEncodableList( + return CustomEncodableValue(CreateMessage::FromEncodableList( std::get(ReadValue(stream)))); case 130: - return CustomEncodableValue(LoopingMessage::FromEncodableList( + return CustomEncodableValue(GeometryMessage::FromEncodableList( std::get(ReadValue(stream)))); case 131: - return CustomEncodableValue(MixWithOthersMessage::FromEncodableList( + return CustomEncodableValue(LoopingMessage::FromEncodableList( std::get(ReadValue(stream)))); case 132: - return CustomEncodableValue(PlaybackSpeedMessage::FromEncodableList( + return CustomEncodableValue(MixWithOthersMessage::FromEncodableList( std::get(ReadValue(stream)))); case 133: - return CustomEncodableValue(PlayerMessage::FromEncodableList( + return CustomEncodableValue(PlaybackSpeedMessage::FromEncodableList( std::get(ReadValue(stream)))); case 134: - return CustomEncodableValue(PositionMessage::FromEncodableList( + return CustomEncodableValue(PlayerMessage::FromEncodableList( std::get(ReadValue(stream)))); case 135: - return CustomEncodableValue(SelectedTracksMessage::FromEncodableList( + return CustomEncodableValue(PositionMessage::FromEncodableList( std::get(ReadValue(stream)))); case 136: - return CustomEncodableValue(TrackMessage::FromEncodableList( + return CustomEncodableValue(SelectedTracksMessage::FromEncodableList( std::get(ReadValue(stream)))); case 137: + return CustomEncodableValue(TextTrackMessage::FromEncodableList( + std::get(ReadValue(stream)))); + case 138: + return CustomEncodableValue(VideoTrackMessage::FromEncodableList( + std::get(ReadValue(stream)))); + case 139: return CustomEncodableValue(VolumeMessage::FromEncodableList( std::get(ReadValue(stream)))); default: @@ -477,8 +557,15 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( const EncodableValue& value, flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { - if (custom_value->type() == typeid(CreateMessage)) { + if (custom_value->type() == typeid(AudioTrackMessage)) { stream->WriteByte(128); + WriteValue(EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(CreateMessage)) { + stream->WriteByte(129); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -486,7 +573,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(GeometryMessage)) { - stream->WriteByte(129); + stream->WriteByte(130); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -494,7 +581,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(LoopingMessage)) { - stream->WriteByte(130); + stream->WriteByte(131); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -502,7 +589,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(MixWithOthersMessage)) { - stream->WriteByte(131); + stream->WriteByte(132); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), @@ -510,7 +597,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(PlaybackSpeedMessage)) { - stream->WriteByte(132); + stream->WriteByte(133); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), @@ -518,7 +605,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(PlayerMessage)) { - stream->WriteByte(133); + stream->WriteByte(134); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -526,7 +613,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(PositionMessage)) { - stream->WriteByte(134); + stream->WriteByte(135); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -534,23 +621,30 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(SelectedTracksMessage)) { - stream->WriteByte(135); + stream->WriteByte(136); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(TrackMessage)) { - stream->WriteByte(136); + if (custom_value->type() == typeid(TextTrackMessage)) { + stream->WriteByte(137); WriteValue( EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), + std::any_cast(*custom_value).ToEncodableList()), stream); return; } + if (custom_value->type() == typeid(VideoTrackMessage)) { + stream->WriteByte(138); + WriteValue(EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } if (custom_value->type() == typeid(VolumeMessage)) { - stream->WriteByte(137); + stream->WriteByte(139); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -869,8 +963,75 @@ void VideoPlayerVideoholeApi::SetUp(flutter::BinaryMessenger* binary_messenger, { auto channel = std::make_unique>( binary_messenger, - "dev.flutter.pigeon.VideoPlayerVideoholeApi.trackSelections", - &GetCodec()); + "dev.flutter.pigeon.VideoPlayerVideoholeApi.videoTrack", &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->VideoTrack(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); + } + } + { + auto channel = std::make_unique>( + binary_messenger, + "dev.flutter.pigeon.VideoPlayerVideoholeApi.audioTrack", &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->AudioTrack(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); + } + } + { + auto channel = std::make_unique>( + binary_messenger, + "dev.flutter.pigeon.VideoPlayerVideoholeApi.textTrack", &GetCodec()); if (api != nullptr) { channel->SetMessageHandler( [api](const EncodableValue& message, @@ -884,7 +1045,7 @@ void VideoPlayerVideoholeApi::SetUp(flutter::BinaryMessenger* binary_messenger, } const auto& msg_arg = std::any_cast( std::get(encodable_msg_arg)); - ErrorOr output = api->TrackSelections(msg_arg); + ErrorOr output = api->TextTrack(msg_arg); if (output.has_error()) { reply(WrapError(output.error())); return; diff --git a/packages/video_player_videohole/tizen/src/messages.h b/packages/video_player_videohole/tizen/src/messages.h index 7f2285457..194b4ff30 100644 --- a/packages/video_player_videohole/tizen/src/messages.h +++ b/packages/video_player_videohole/tizen/src/messages.h @@ -135,25 +135,71 @@ class PlaybackSpeedMessage { }; // Generated class from Pigeon that represents data sent in messages. -class TrackMessage { +class VideoTrackMessage { public: // Constructs an object setting all fields. - explicit TrackMessage(int64_t player_id, - const flutter::EncodableList& track_selections); + explicit VideoTrackMessage(int64_t player_id, + const flutter::EncodableList& video_tracks); int64_t player_id() const; void set_player_id(int64_t value_arg); - const flutter::EncodableList& track_selections() const; - void set_track_selections(const flutter::EncodableList& value_arg); + const flutter::EncodableList& video_tracks() const; + void set_video_tracks(const flutter::EncodableList& value_arg); private: - static TrackMessage FromEncodableList(const flutter::EncodableList& list); + static VideoTrackMessage FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class VideoPlayerVideoholeApi; + friend class VideoPlayerVideoholeApiCodecSerializer; + int64_t player_id_; + flutter::EncodableList video_tracks_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class AudioTrackMessage { + public: + // Constructs an object setting all fields. + explicit AudioTrackMessage(int64_t player_id, + const flutter::EncodableList& audio_tracks); + + int64_t player_id() const; + void set_player_id(int64_t value_arg); + + const flutter::EncodableList& audio_tracks() const; + void set_audio_tracks(const flutter::EncodableList& value_arg); + + private: + static AudioTrackMessage FromEncodableList( + const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class VideoPlayerVideoholeApi; + friend class VideoPlayerVideoholeApiCodecSerializer; + int64_t player_id_; + flutter::EncodableList audio_tracks_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class TextTrackMessage { + public: + // Constructs an object setting all fields. + explicit TextTrackMessage(int64_t player_id, + const flutter::EncodableList& text_tracks); + + int64_t player_id() const; + void set_player_id(int64_t value_arg); + + const flutter::EncodableList& text_tracks() const; + void set_text_tracks(const flutter::EncodableList& value_arg); + + private: + static TextTrackMessage FromEncodableList(const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; friend class VideoPlayerVideoholeApi; friend class VideoPlayerVideoholeApiCodecSerializer; int64_t player_id_; - flutter::EncodableList track_selections_; + flutter::EncodableList text_tracks_; }; // Generated class from Pigeon that represents data sent in messages. @@ -342,7 +388,9 @@ class VideoPlayerVideoholeApi { virtual void SeekTo( const PositionMessage& msg, std::function reply)> result) = 0; - virtual ErrorOr TrackSelections(const PlayerMessage& msg) = 0; + virtual ErrorOr VideoTrack(const PlayerMessage& msg) = 0; + virtual ErrorOr AudioTrack(const PlayerMessage& msg) = 0; + virtual ErrorOr TextTrack(const PlayerMessage& msg) = 0; virtual std::optional SetTrackSelection( const SelectedTracksMessage& msg) = 0; virtual std::optional Pause(const PlayerMessage& msg) = 0; diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index 43226c149..99ead05ae 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -265,7 +265,7 @@ void VideoPlayer::SetPlaybackSpeed(double speed) { } } -flutter::EncodableList VideoPlayer::getTotalTrackInfo() { +flutter::EncodableList VideoPlayer::getVideoTrackInfo() { player_state_e state = PLAYER_STATE_NONE; int ret = player_get_state(player_, &state); if (ret != PLAYER_ERROR_NONE) { @@ -290,14 +290,8 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { FuncPlayerGetVideoTrackInfoV2 player_get_video_track_info_v2 = reinterpret_cast( dlsym(player_lib_handle, "player_get_video_track_info_v2")); - FuncPlayerGetAudioTrackInfoV2 player_get_audio_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_audio_track_info_v2")); - FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_subtitle_track_info_v2")); - if (!player_get_track_count_v2 || !player_get_video_track_info_v2 || - !player_get_audio_track_info_v2 || !player_get_subtitle_track_info_v2) { + + if (!player_get_track_count_v2 || !player_get_video_track_info_v2) { LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); dlclose(player_lib_handle); return {}; @@ -311,38 +305,14 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { get_error_message(ret)); return {}; } - - int audio_count = 0; - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_AUDIO, - &audio_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_audio_track_count failed: %s", - get_error_message(ret)); - return {}; - } - - int subtitle_count = 0; - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_TEXT, - &subtitle_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_subtitle_track_count failed: %s", - get_error_message(ret)); - return {}; - } - - int total_count = video_count + audio_count + subtitle_count; - LOG_INFO( - "[VideoPlayer] video_count: %d, audio_count: %d, subtitle_count:%d, " - "total_count: %d", - video_count, audio_count, subtitle_count, total_count); - - int stream_counter = 0; - StreamInformation *streamInfo = NULL; - streamInfo = new StreamInformation[total_count]; + LOG_INFO("[VideoPlayer] video_count: %d", video_count); player_video_track_info_v2 *video_track_info = NULL; + flutter::EncodableList trackSelections; + if (video_count > 0) { for (int video_index = 0; video_index < video_count; video_index++) { + flutter::EncodableMap trackSelection = {}; ret = player_get_video_track_info_v2(player_, video_index, &video_track_info); if (ret != PLAYER_ERROR_NONE) { @@ -356,19 +326,76 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { video_track_info->width, video_track_info->height, video_track_info->bit_rate); - streamInfo[stream_counter].track = video_index; - streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_VIDEO; - streamInfo[stream_counter].videoInfo.width = video_track_info->width; - streamInfo[stream_counter].videoInfo.height = video_track_info->height; - streamInfo[stream_counter].videoInfo.bit_rate = - video_track_info->bit_rate; - stream_counter++; + trackSelection.insert( + {flutter::EncodableValue("trackType"), + flutter::EncodableValue(PLAYER_STREAM_TYPE_VIDEO)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(video_index)}); + + trackSelection.insert({flutter::EncodableValue("width"), + flutter::EncodableValue(video_track_info->width)}); + trackSelection.insert( + {flutter::EncodableValue("height"), + flutter::EncodableValue(video_track_info->height)}); + trackSelection.insert( + {flutter::EncodableValue("bitrate"), + flutter::EncodableValue(video_track_info->bit_rate)}); + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); } } + dlclose(player_lib_handle); + return trackSelections; +} + +flutter::EncodableList VideoPlayer::getAudioTrackInfo() { + player_state_e state = PLAYER_STATE_NONE; + int ret = player_get_state(player_, &state); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_state failed: %s", + get_error_message(ret)); + return {}; + } + if (state == PLAYER_STATE_NONE || state == PLAYER_STATE_IDLE) { + LOG_ERROR("[VideoPlayer] Player not ready."); + return {}; + } + + void *player_lib_handle = dlopen("libcapi-media-player.so.0", RTLD_LAZY); + if (!player_lib_handle) { + LOG_ERROR("[VideoPlayer] dlopen failed: %s", dlerror()); + return {}; + } + + FuncPlayerGetTrackCountV2 player_get_track_count_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_track_count_v2")); + FuncPlayerGetAudioTrackInfoV2 player_get_audio_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_audio_track_info_v2")); + + if (!player_get_track_count_v2 || !player_get_audio_track_info_v2) { + LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); + dlclose(player_lib_handle); + return {}; + } + + int audio_count = 0; + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_AUDIO, + &audio_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_audio_track_count failed: %s", + get_error_message(ret)); + return {}; + } + LOG_INFO("[VideoPlayer] audio_count: %d", audio_count); player_audio_track_info_v2 *audio_track_info = NULL; + flutter::EncodableList trackSelections; + if (audio_count > 0) { for (int audio_index = 0; audio_index < audio_count; audio_index++) { + flutter::EncodableMap trackSelection = {}; ret = player_get_audio_track_info_v2(player_, audio_index, &audio_track_info); if (ret != PLAYER_ERROR_NONE) { @@ -382,20 +409,76 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { audio_track_info->language, audio_track_info->channel, audio_track_info->sample_rate, audio_track_info->bit_rate); - streamInfo[stream_counter].track = audio_index; - streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_AUDIO; - strcpy(streamInfo[stream_counter].audioInfo.language, - audio_track_info->language); - streamInfo[stream_counter].audioInfo.channel = audio_track_info->channel; - streamInfo[stream_counter].audioInfo.bit_rate = - audio_track_info->bit_rate; - stream_counter++; + trackSelection.insert( + {flutter::EncodableValue("trackType"), + flutter::EncodableValue(PLAYER_STREAM_TYPE_AUDIO)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(audio_index)}); + trackSelection.insert( + {flutter::EncodableValue("language"), + flutter::EncodableValue(std::string(audio_track_info->language))}); + trackSelection.insert( + {flutter::EncodableValue("channel"), + flutter::EncodableValue(audio_track_info->channel)}); + trackSelection.insert( + {flutter::EncodableValue("bitrate"), + flutter::EncodableValue(audio_track_info->bit_rate)}); + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); } } + dlclose(player_lib_handle); + return trackSelections; +} + +flutter::EncodableList VideoPlayer::getTextTrackInfo() { + player_state_e state = PLAYER_STATE_NONE; + int ret = player_get_state(player_, &state); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_state failed: %s", + get_error_message(ret)); + return {}; + } + if (state == PLAYER_STATE_NONE || state == PLAYER_STATE_IDLE) { + LOG_ERROR("[VideoPlayer] Player not ready."); + return {}; + } + + void *player_lib_handle = dlopen("libcapi-media-player.so.0", RTLD_LAZY); + if (!player_lib_handle) { + LOG_ERROR("[VideoPlayer] dlopen failed: %s", dlerror()); + return {}; + } + + FuncPlayerGetTrackCountV2 player_get_track_count_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_track_count_v2")); + FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_subtitle_track_info_v2")); + + if (!player_get_track_count_v2 || !player_get_subtitle_track_info_v2) { + LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); + dlclose(player_lib_handle); + return {}; + } + + int subtitle_count = 0; + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_TEXT, + &subtitle_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_subtitle_track_count failed: %s", + get_error_message(ret)); + return {}; + } + LOG_INFO("[VideoPlayer] subtitle_count: %d", subtitle_count); player_subtitle_track_info_v2 *sub_track_info = NULL; + flutter::EncodableList trackSelections; + if (subtitle_count > 0) { for (int sub_index = 0; sub_index < subtitle_count; sub_index++) { + flutter::EncodableMap trackSelection = {}; ret = player_get_subtitle_track_info_v2(player_, sub_index, &sub_track_info); if (ret != PLAYER_ERROR_NONE) { @@ -408,73 +491,21 @@ flutter::EncodableList VideoPlayer::getTotalTrackInfo() { "subtitle_type[%d]", sub_track_info->language, sub_track_info->subtitle_type); - streamInfo[stream_counter].track = sub_index; - streamInfo[stream_counter].trackType = PLAYER_STREAM_TYPE_TEXT; - strcpy(streamInfo[stream_counter].textInfo.language, - sub_track_info->language); - streamInfo[stream_counter].textInfo.subtitle_type = - sub_track_info->subtitle_type; - stream_counter++; + trackSelection.insert({flutter::EncodableValue("trackType"), + flutter::EncodableValue(PLAYER_STREAM_TYPE_TEXT)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(sub_index)}); + trackSelection.insert( + {flutter::EncodableValue("language"), + flutter::EncodableValue(std::string(sub_track_info->language))}); + trackSelection.insert( + {flutter::EncodableValue("subtitleType"), + flutter::EncodableValue(sub_track_info->subtitle_type)}); + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); } } dlclose(player_lib_handle); - - flutter::EncodableList trackSelections; - for (int index = 0; index < stream_counter; index++) { - flutter::EncodableMap trackSelection; - - trackSelection.insert( - {flutter::EncodableValue("isUnknown"), flutter::EncodableValue(false)}); - trackSelection.insert( - {flutter::EncodableValue("trackType"), - flutter::EncodableValue(streamInfo[index].trackType)}); - trackSelection.insert({flutter::EncodableValue("trackId"), - flutter::EncodableValue(streamInfo[index].track)}); - - switch (streamInfo[index].trackType) { - case PLAYER_STREAM_TYPE_VIDEO: - trackSelection.insert( - {flutter::EncodableValue("width"), - flutter::EncodableValue(streamInfo[index].videoInfo.width)}); - trackSelection.insert( - {flutter::EncodableValue("height"), - flutter::EncodableValue(streamInfo[index].videoInfo.height)}); - trackSelection.insert( - {flutter::EncodableValue("bitrate"), - flutter::EncodableValue(streamInfo[index].videoInfo.bit_rate)}); - break; - case PLAYER_STREAM_TYPE_AUDIO: - trackSelection.insert({flutter::EncodableValue("language"), - flutter::EncodableValue(std::string( - streamInfo[index].audioInfo.language))}); - trackSelection.insert( - {flutter::EncodableValue("channel"), - flutter::EncodableValue(streamInfo[index].audioInfo.channel)}); - trackSelection.insert( - {flutter::EncodableValue("bitrate"), - flutter::EncodableValue(streamInfo[index].audioInfo.bit_rate)}); - break; - case PLAYER_STREAM_TYPE_TEXT: - trackSelection.insert({flutter::EncodableValue("language"), - flutter::EncodableValue(std::string( - streamInfo[index].textInfo.language))}); - trackSelection.insert({flutter::EncodableValue("subtitleType"), - flutter::EncodableValue( - streamInfo[index].textInfo.subtitle_type)}); - break; - default: - trackSelection.insert({flutter::EncodableValue("isUnknown"), - flutter::EncodableValue(true)}); - } - - trackSelections.push_back(flutter::EncodableValue(trackSelection)); - } - - if (streamInfo) { - free(streamInfo); - streamInfo = nullptr; - } - return trackSelections; } diff --git a/packages/video_player_videohole/tizen/src/video_player.h b/packages/video_player_videohole/tizen/src/video_player.h index 975367b56..300e50a0b 100644 --- a/packages/video_player_videohole/tizen/src/video_player.h +++ b/packages/video_player_videohole/tizen/src/video_player.h @@ -47,16 +47,6 @@ typedef struct { int subtitle_type; /**< text subtitle = 0, picture subtitle = 1 */ } player_subtitle_track_info_v2; -typedef struct { - int track; - int adaptation_index; - int alternate_index; - player_stream_type_e trackType; - player_video_track_info_v2 videoInfo; - player_audio_track_info_v2 audioInfo; - player_subtitle_track_info_v2 textInfo; -} StreamInformation; - typedef void (*FuncEcoreWl2WindowGeometryGet)(void *window, int *x, int *y, int *width, int *height); typedef int (*FuncPlayerSetEcoreWlDisplay)(player_h player, @@ -93,7 +83,9 @@ class VideoPlayer { void SetPlaybackSpeed(double speed); void SeekTo(int32_t position, SeekCompletedCallback callback); int32_t GetPosition(); - flutter::EncodableList getTotalTrackInfo(); + flutter::EncodableList getVideoTrackInfo(); + flutter::EncodableList getAudioTrackInfo(); + flutter::EncodableList getTextTrackInfo(); void SetTrackSelection(int32_t track_id, int32_t track_type); void RegisterSendPort(Dart_Port send_port) { send_port_ = send_port; } diff --git a/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc b/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc index e59bc3cec..6b7341a5a 100644 --- a/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc +++ b/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc @@ -44,7 +44,12 @@ class VideoPlayerTizenPlugin : public flutter::Plugin, void SeekTo( const PositionMessage &msg, std::function reply)> result) override; - ErrorOr TrackSelections(const PlayerMessage &msg) override; + virtual ErrorOr VideoTrack( + const PlayerMessage &msg) override; + virtual ErrorOr AudioTrack( + const PlayerMessage &msg) override; + virtual ErrorOr TextTrack( + const PlayerMessage &msg) override; std::optional SetTrackSelection( const SelectedTracksMessage &msg) override; std::optional Pause(const PlayerMessage &msg) override; @@ -246,14 +251,36 @@ void VideoPlayerTizenPlugin::SeekTo( player->SeekTo(msg.position(), [result]() -> void { result(std::nullopt); }); } -ErrorOr VideoPlayerTizenPlugin::TrackSelections( +ErrorOr VideoPlayerTizenPlugin::VideoTrack( const PlayerMessage &msg) { VideoPlayer *player = FindPlayerById(msg.player_id()); if (!player) { return FlutterError("Invalid argument", "Player not found."); } - TrackMessage result(msg.player_id(), player->getTotalTrackInfo()); + VideoTrackMessage result(msg.player_id(), player->getVideoTrackInfo()); + return result; +} + +ErrorOr VideoPlayerTizenPlugin::AudioTrack( + const PlayerMessage &msg) { + VideoPlayer *player = FindPlayerById(msg.player_id()); + + if (!player) { + return FlutterError("Invalid argument", "Player not found."); + } + AudioTrackMessage result(msg.player_id(), player->getAudioTrackInfo()); + return result; +} + +ErrorOr VideoPlayerTizenPlugin::TextTrack( + const PlayerMessage &msg) { + VideoPlayer *player = FindPlayerById(msg.player_id()); + + if (!player) { + return FlutterError("Invalid argument", "Player not found."); + } + TextTrackMessage result(msg.player_id(), player->getTextTrackInfo()); return result; } From 3e9515c020363e2dffa3c0ca930e56be6920c589 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Thu, 17 Aug 2023 10:21:05 +0800 Subject: [PATCH 08/15] Export video_player_platform_interface.dart in video_player.dart --- packages/video_player_videohole/example/lib/main.dart | 1 - packages/video_player_videohole/lib/video_player.dart | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player_videohole/example/lib/main.dart b/packages/video_player_videohole/example/lib/main.dart index ed3216ccf..873360c4d 100644 --- a/packages/video_player_videohole/example/lib/main.dart +++ b/packages/video_player_videohole/example/lib/main.dart @@ -11,7 +11,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; import 'package:video_player_videohole/video_player.dart'; -import 'package:video_player_videohole/video_player_platform_interface.dart'; void main() { runApp( diff --git a/packages/video_player_videohole/lib/video_player.dart b/packages/video_player_videohole/lib/video_player.dart index 62dea954f..f5313b414 100644 --- a/packages/video_player_videohole/lib/video_player.dart +++ b/packages/video_player_videohole/lib/video_player.dart @@ -19,6 +19,7 @@ import 'video_player_platform_interface.dart'; export 'src/closed_caption_file.dart'; export 'src/drm_configs.dart'; +export 'video_player_platform_interface.dart'; VideoPlayerPlatform? _lastVideoPlayerPlatform; From b1a38edcaf2517ede40822abffb251eaae6ff728 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Fri, 18 Aug 2023 14:31:07 +0800 Subject: [PATCH 09/15] Move track related code to tracks.dart --- .../lib/src/tracks.dart | 127 ++++++++++++++++++ .../lib/src/video_player_tizen.dart | 1 + .../lib/video_player.dart | 3 +- .../lib/video_player_platform_interface.dart | 125 +---------------- 4 files changed, 131 insertions(+), 125 deletions(-) create mode 100644 packages/video_player_videohole/lib/src/tracks.dart diff --git a/packages/video_player_videohole/lib/src/tracks.dart b/packages/video_player_videohole/lib/src/tracks.dart new file mode 100644 index 000000000..5b4508914 --- /dev/null +++ b/packages/video_player_videohole/lib/src/tracks.dart @@ -0,0 +1,127 @@ +// Copyright 2023 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Type of the track. +enum TrackType { + /// The video track. + video, + + /// The audio track. + audio, + + /// The text track. + text, +} + +/// Type of the track audio channel for [TrackType.audio]. +enum AudioTrackChannelType { + /// The mono channel. + mono, + + /// The stereo channel. + stereo, + + /// The surround channel. + surround, +} + +/// Type of the track subtitle type for [TrackType.text]. +enum TextTrackSubtitleType { + /// The text subtitle. + text, + + /// The picture subtitle. + picture, +} + +/// A representation of a single track. +/// +/// A typical video file will include several [Track]s.Such as [VideoTrack]s, [AudioTrack]s, [TextTrack]s. +class Track { + /// Creates an instance of [Track]. + /// + /// The [trackId] argument is required. + /// + const Track({ + required this.trackId, + required this.trackType, + }); + + /// The track id of track that uses to determine track. + final int trackId; + + /// The type of the track. + final TrackType trackType; +} + +/// A representation of a video track. +class VideoTrack extends Track { + /// Creates an instance of [VideoTrack]. + /// + /// The [width], [height] and [bitrate] argument is required. + /// + /// [trackType] is [TrackType.video]. + VideoTrack({ + required super.trackId, + super.trackType = TrackType.video, + required this.width, + required this.height, + required this.bitrate, + }); + + /// The width of video track. + final int width; + + /// The height of video track. + final int height; + + /// The bitrate of video track. + final int bitrate; +} + +/// A representation of a audio track. +class AudioTrack extends Track { + /// Creates an instance of [AudioTrack]. + /// + /// The [language], [channel] argument is required. + /// + /// [trackType] is [TrackType.audio]. + AudioTrack({ + required super.trackId, + super.trackType = TrackType.audio, + required this.language, + required this.channel, + required this.bitrate, + }); + + /// The language of audio track. + final String language; + + /// The channel of audio track. + final AudioTrackChannelType channel; + + /// The bitrate of audio track. + final int bitrate; +} + +/// A representation of a text track. +class TextTrack extends Track { + /// Creates an instance of [TextTrack]. + /// + /// The [language] argument is required. + /// + /// [trackType] is [TrackType.text]. + TextTrack({ + required super.trackId, + super.trackType = TrackType.text, + required this.language, + required this.subtitleType, + }); + + /// The language of text track. + final String language; + + /// The subtitle type of track. + final TextTrackSubtitleType subtitleType; +} diff --git a/packages/video_player_videohole/lib/src/video_player_tizen.dart b/packages/video_player_videohole/lib/src/video_player_tizen.dart index 6cad29e55..eb310bbdd 100644 --- a/packages/video_player_videohole/lib/src/video_player_tizen.dart +++ b/packages/video_player_videohole/lib/src/video_player_tizen.dart @@ -10,6 +10,7 @@ import 'package:flutter/widgets.dart'; import '../video_player_platform_interface.dart'; import 'messages.g.dart'; +import 'tracks.dart'; /// An implementation of [VideoPlayerPlatform] that uses the /// Pigeon-generated [TizenVideoPlayerApi]. diff --git a/packages/video_player_videohole/lib/video_player.dart b/packages/video_player_videohole/lib/video_player.dart index f5313b414..5f8d7beaf 100644 --- a/packages/video_player_videohole/lib/video_player.dart +++ b/packages/video_player_videohole/lib/video_player.dart @@ -15,11 +15,12 @@ import 'src/drm_configs.dart'; import 'src/hole.dart'; import 'src/register_drm_callback_stub.dart' if (dart.library.ffi) 'src/register_drm_callback_real.dart'; +import 'src/tracks.dart'; import 'video_player_platform_interface.dart'; export 'src/closed_caption_file.dart'; export 'src/drm_configs.dart'; -export 'video_player_platform_interface.dart'; +export 'src/tracks.dart'; VideoPlayerPlatform? _lastVideoPlayerPlatform; diff --git a/packages/video_player_videohole/lib/video_player_platform_interface.dart b/packages/video_player_videohole/lib/video_player_platform_interface.dart index d8b069908..878e2d4b0 100644 --- a/packages/video_player_videohole/lib/video_player_platform_interface.dart +++ b/packages/video_player_videohole/lib/video_player_platform_interface.dart @@ -8,6 +8,7 @@ import 'package:flutter/widgets.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; import 'src/drm_configs.dart'; +import 'src/tracks.dart'; import 'src/video_player_tizen.dart'; /// The interface that implementations of video_player must implement. @@ -410,127 +411,3 @@ class VideoPlayerOptions { /// currently no way to implement this feature in this platform). final bool mixWithOthers; } - -/// Type of the track. -enum TrackType { - /// The video track. - video, - - /// The audio track. - audio, - - /// The text track. - text, -} - -/// Type of the track audio channel for [TrackType.audio]. -enum AudioTrackChannelType { - /// The mono channel. - mono, - - /// The stereo channel. - stereo, - - /// The surround channel. - surround, -} - -/// Type of the track subtitle type for [TrackType.text]. -enum TextTrackSubtitleType { - /// The text subtitle. - text, - - /// The picture subtitle. - picture, -} - -/// A representation of a single track. -/// -/// A typical video file will include several [Track]s.Such as [VideoTrack]s, [AudioTrack]s, [TextTrack]s. -class Track { - /// Creates an instance of [Track]. - /// - /// The [trackId] argument is required. - /// - const Track({ - required this.trackId, - required this.trackType, - }); - - /// The track id of track that uses to determine track. - final int trackId; - - /// The type of the track. - final TrackType trackType; -} - -/// A representation of a video track. -class VideoTrack extends Track { - /// Creates an instance of [VideoTrack]. - /// - /// The [width], [height] and [bitrate] argument is required. - /// - /// [trackType] is [TrackType.video]. - VideoTrack({ - required super.trackId, - super.trackType = TrackType.video, - required this.width, - required this.height, - required this.bitrate, - }); - - /// The width of video track. - final int width; - - /// The height of video track. - final int height; - - /// The bitrate of video track. - final int bitrate; -} - -/// A representation of a audio track. -class AudioTrack extends Track { - /// Creates an instance of [AudioTrack]. - /// - /// The [language], [channel] argument is required. - /// - /// [trackType] is [TrackType.audio]. - AudioTrack({ - required super.trackId, - super.trackType = TrackType.audio, - required this.language, - required this.channel, - required this.bitrate, - }); - - /// The language of audio track. - final String language; - - /// The channel of audio track. - final AudioTrackChannelType channel; - - /// The bitrate of audio track. - final int bitrate; -} - -/// A representation of a text track. -class TextTrack extends Track { - /// Creates an instance of [TextTrack]. - /// - /// The [language] argument is required. - /// - /// [trackType] is [TrackType.text]. - TextTrack({ - required super.trackId, - super.trackType = TrackType.text, - required this.language, - required this.subtitleType, - }); - - /// The language of text track. - final String language; - - /// The subtitle type of track. - final TextTrackSubtitleType subtitleType; -} From 21c88fcb41ac6e42e78761a907a153229d6f1747 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Fri, 18 Aug 2023 14:43:13 +0800 Subject: [PATCH 10/15] Update CHANGELOG.md --- packages/video_player_videohole/CHANGELOG.md | 4 ++++ packages/video_player_videohole/README.md | 2 +- packages/video_player_videohole/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/video_player_videohole/CHANGELOG.md b/packages/video_player_videohole/CHANGELOG.md index a9563e341..ca63690ab 100644 --- a/packages/video_player_videohole/CHANGELOG.md +++ b/packages/video_player_videohole/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.3 + +* Implement function of selecting video, audio and text traks. + ## 0.1.2 * Increase the minimum Flutter version to 3.3. diff --git a/packages/video_player_videohole/README.md b/packages/video_player_videohole/README.md index 15bda9318..c2bb54393 100644 --- a/packages/video_player_videohole/README.md +++ b/packages/video_player_videohole/README.md @@ -12,7 +12,7 @@ To use this package, add `video_player_videohole` as a dependency in your `pubsp ```yaml dependencies: - video_player_videohole: ^0.1.1 + video_player_videohole: ^0.1.3 ``` Then you can import `video_player_videohole` in your Dart code: diff --git a/packages/video_player_videohole/pubspec.yaml b/packages/video_player_videohole/pubspec.yaml index 09bf84847..881e4da35 100644 --- a/packages/video_player_videohole/pubspec.yaml +++ b/packages/video_player_videohole/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_videohole 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_videohole -version: 0.1.2 +version: 0.1.3 environment: sdk: ">=2.18.0 <4.0.0" From 36bb30c53e70d54e96b1bbd16ae5e5a2ef3b8fb7 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Mon, 21 Aug 2023 11:12:17 +0800 Subject: [PATCH 11/15] Move duplicate codes to a new function to get track info --- .../tizen/src/video_player.cc | 358 ++++++++---------- .../tizen/src/video_player.h | 1 + 2 files changed, 164 insertions(+), 195 deletions(-) diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index 99ead05ae..b21b7c6fc 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -266,89 +266,19 @@ void VideoPlayer::SetPlaybackSpeed(double speed) { } flutter::EncodableList VideoPlayer::getVideoTrackInfo() { - player_state_e state = PLAYER_STATE_NONE; - int ret = player_get_state(player_, &state); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_state failed: %s", - get_error_message(ret)); - return {}; - } - if (state == PLAYER_STATE_NONE || state == PLAYER_STATE_IDLE) { - LOG_ERROR("[VideoPlayer] Player not ready."); - return {}; - } - - void *player_lib_handle = dlopen("libcapi-media-player.so.0", RTLD_LAZY); - if (!player_lib_handle) { - LOG_ERROR("[VideoPlayer] dlopen failed: %s", dlerror()); - return {}; - } - - FuncPlayerGetTrackCountV2 player_get_track_count_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_track_count_v2")); - FuncPlayerGetVideoTrackInfoV2 player_get_video_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_video_track_info_v2")); - - if (!player_get_track_count_v2 || !player_get_video_track_info_v2) { - LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); - dlclose(player_lib_handle); - return {}; - } - - int video_count = 0; - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_VIDEO, - &video_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_video_track_count failed: %s", - get_error_message(ret)); - return {}; - } - LOG_INFO("[VideoPlayer] video_count: %d", video_count); + return getTrackInfo(PLAYER_STREAM_TYPE_VIDEO); +} - player_video_track_info_v2 *video_track_info = NULL; - flutter::EncodableList trackSelections; +flutter::EncodableList VideoPlayer::getAudioTrackInfo() { + return getTrackInfo(PLAYER_STREAM_TYPE_AUDIO); +} - if (video_count > 0) { - for (int video_index = 0; video_index < video_count; video_index++) { - flutter::EncodableMap trackSelection = {}; - ret = player_get_video_track_info_v2(player_, video_index, - &video_track_info); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_video_track_info_v2 failed: %s", - get_error_message(ret)); - return {}; - } - LOG_INFO( - "[VideoPlayer] video track info: width[%d], height[%d], " - "bitrate[%d]", - video_track_info->width, video_track_info->height, - video_track_info->bit_rate); - - trackSelection.insert( - {flutter::EncodableValue("trackType"), - flutter::EncodableValue(PLAYER_STREAM_TYPE_VIDEO)}); - trackSelection.insert({flutter::EncodableValue("trackId"), - flutter::EncodableValue(video_index)}); - - trackSelection.insert({flutter::EncodableValue("width"), - flutter::EncodableValue(video_track_info->width)}); - trackSelection.insert( - {flutter::EncodableValue("height"), - flutter::EncodableValue(video_track_info->height)}); - trackSelection.insert( - {flutter::EncodableValue("bitrate"), - flutter::EncodableValue(video_track_info->bit_rate)}); - - trackSelections.push_back(flutter::EncodableValue(trackSelection)); - } - } - dlclose(player_lib_handle); - return trackSelections; +flutter::EncodableList VideoPlayer::getTextTrackInfo() { + return getTrackInfo(PLAYER_STREAM_TYPE_TEXT); } -flutter::EncodableList VideoPlayer::getAudioTrackInfo() { +flutter::EncodableList VideoPlayer::getTrackInfo( + player_stream_type_e track_type) { player_state_e state = PLAYER_STATE_NONE; int ret = player_get_state(player_, &state); if (ret != PLAYER_ERROR_NONE) { @@ -370,141 +300,179 @@ flutter::EncodableList VideoPlayer::getAudioTrackInfo() { FuncPlayerGetTrackCountV2 player_get_track_count_v2 = reinterpret_cast( dlsym(player_lib_handle, "player_get_track_count_v2")); + FuncPlayerGetVideoTrackInfoV2 player_get_video_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_video_track_info_v2")); FuncPlayerGetAudioTrackInfoV2 player_get_audio_track_info_v2 = reinterpret_cast( dlsym(player_lib_handle, "player_get_audio_track_info_v2")); + FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_subtitle_track_info_v2")); - if (!player_get_track_count_v2 || !player_get_audio_track_info_v2) { + if (!player_get_track_count_v2) { LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); dlclose(player_lib_handle); return {}; } - int audio_count = 0; - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_AUDIO, - &audio_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_audio_track_count failed: %s", - get_error_message(ret)); - return {}; - } - LOG_INFO("[VideoPlayer] audio_count: %d", audio_count); - - player_audio_track_info_v2 *audio_track_info = NULL; flutter::EncodableList trackSelections; + if (track_type == PLAYER_STREAM_TYPE_VIDEO) { + int video_count = 0; + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_VIDEO, + &video_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_video_track_count failed: %s", + get_error_message(ret)); + return {}; + } + LOG_INFO("[VideoPlayer] video_count: %d", video_count); - if (audio_count > 0) { - for (int audio_index = 0; audio_index < audio_count; audio_index++) { - flutter::EncodableMap trackSelection = {}; - ret = player_get_audio_track_info_v2(player_, audio_index, - &audio_track_info); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_audio_track_info_v2 failed: %s", - get_error_message(ret)); - return {}; + if (!player_get_video_track_info_v2) { + LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); + dlclose(player_lib_handle); + return {}; + } + player_video_track_info_v2 *video_track_info = NULL; + + if (video_count > 0) { + for (int video_index = 0; video_index < video_count; video_index++) { + flutter::EncodableMap trackSelection = {}; + ret = player_get_video_track_info_v2(player_, video_index, + &video_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_video_track_info_v2 failed: %s", + get_error_message(ret)); + return {}; + } + LOG_INFO( + "[VideoPlayer] video track info: width[%d], height[%d], " + "bitrate[%d]", + video_track_info->width, video_track_info->height, + video_track_info->bit_rate); + + trackSelection.insert( + {flutter::EncodableValue("trackType"), + flutter::EncodableValue(PLAYER_STREAM_TYPE_VIDEO)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(video_index)}); + + trackSelection.insert( + {flutter::EncodableValue("width"), + flutter::EncodableValue(video_track_info->width)}); + trackSelection.insert( + {flutter::EncodableValue("height"), + flutter::EncodableValue(video_track_info->height)}); + trackSelection.insert( + {flutter::EncodableValue("bitrate"), + flutter::EncodableValue(video_track_info->bit_rate)}); + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); } - LOG_INFO( - "[VideoPlayer] audio track info: language[%s], channel[%d], " - "sample_rate[%d], bitrate[%d]", - audio_track_info->language, audio_track_info->channel, - audio_track_info->sample_rate, audio_track_info->bit_rate); - - trackSelection.insert( - {flutter::EncodableValue("trackType"), - flutter::EncodableValue(PLAYER_STREAM_TYPE_AUDIO)}); - trackSelection.insert({flutter::EncodableValue("trackId"), - flutter::EncodableValue(audio_index)}); - trackSelection.insert( - {flutter::EncodableValue("language"), - flutter::EncodableValue(std::string(audio_track_info->language))}); - trackSelection.insert( - {flutter::EncodableValue("channel"), - flutter::EncodableValue(audio_track_info->channel)}); - trackSelection.insert( - {flutter::EncodableValue("bitrate"), - flutter::EncodableValue(audio_track_info->bit_rate)}); - - trackSelections.push_back(flutter::EncodableValue(trackSelection)); } - } - dlclose(player_lib_handle); - return trackSelections; -} - -flutter::EncodableList VideoPlayer::getTextTrackInfo() { - player_state_e state = PLAYER_STATE_NONE; - int ret = player_get_state(player_, &state); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_state failed: %s", - get_error_message(ret)); - return {}; - } - if (state == PLAYER_STATE_NONE || state == PLAYER_STATE_IDLE) { - LOG_ERROR("[VideoPlayer] Player not ready."); - return {}; - } - - void *player_lib_handle = dlopen("libcapi-media-player.so.0", RTLD_LAZY); - if (!player_lib_handle) { - LOG_ERROR("[VideoPlayer] dlopen failed: %s", dlerror()); - return {}; - } - - FuncPlayerGetTrackCountV2 player_get_track_count_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_track_count_v2")); - FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_subtitle_track_info_v2")); + } else if (track_type == PLAYER_STREAM_TYPE_AUDIO) { + int audio_count = 0; + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_AUDIO, + &audio_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_audio_track_count failed: %s", + get_error_message(ret)); + return {}; + } + LOG_INFO("[VideoPlayer] audio_count: %d", audio_count); - if (!player_get_track_count_v2 || !player_get_subtitle_track_info_v2) { - LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); - dlclose(player_lib_handle); - return {}; - } + if (!player_get_audio_track_info_v2) { + LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); + dlclose(player_lib_handle); + return {}; + } + player_audio_track_info_v2 *audio_track_info = NULL; + + if (audio_count > 0) { + for (int audio_index = 0; audio_index < audio_count; audio_index++) { + flutter::EncodableMap trackSelection = {}; + ret = player_get_audio_track_info_v2(player_, audio_index, + &audio_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_audio_track_info_v2 failed: %s", + get_error_message(ret)); + return {}; + } + LOG_INFO( + "[VideoPlayer] audio track info: language[%s], channel[%d], " + "sample_rate[%d], bitrate[%d]", + audio_track_info->language, audio_track_info->channel, + audio_track_info->sample_rate, audio_track_info->bit_rate); + + trackSelection.insert( + {flutter::EncodableValue("trackType"), + flutter::EncodableValue(PLAYER_STREAM_TYPE_AUDIO)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(audio_index)}); + trackSelection.insert( + {flutter::EncodableValue("language"), + flutter::EncodableValue(std::string(audio_track_info->language))}); + trackSelection.insert( + {flutter::EncodableValue("channel"), + flutter::EncodableValue(audio_track_info->channel)}); + trackSelection.insert( + {flutter::EncodableValue("bitrate"), + flutter::EncodableValue(audio_track_info->bit_rate)}); + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); + } + } + } else if (track_type == PLAYER_STREAM_TYPE_TEXT) { + int subtitle_count = 0; + ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_TEXT, + &subtitle_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_subtitle_track_count failed: %s", + get_error_message(ret)); + return {}; + } + LOG_INFO("[VideoPlayer] subtitle_count: %d", subtitle_count); - int subtitle_count = 0; - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_TEXT, - &subtitle_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_subtitle_track_count failed: %s", + if (!player_get_subtitle_track_info_v2) { + LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); + dlclose(player_lib_handle); + return {}; + } + player_subtitle_track_info_v2 *sub_track_info = NULL; + + if (subtitle_count > 0) { + for (int sub_index = 0; sub_index < subtitle_count; sub_index++) { + flutter::EncodableMap trackSelection = {}; + ret = player_get_subtitle_track_info_v2(player_, sub_index, + &sub_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR( + "[VideoPlayer] player_get_subtitle_track_info_v2 failed: %s", get_error_message(ret)); - return {}; - } - LOG_INFO("[VideoPlayer] subtitle_count: %d", subtitle_count); - - player_subtitle_track_info_v2 *sub_track_info = NULL; - flutter::EncodableList trackSelections; - - if (subtitle_count > 0) { - for (int sub_index = 0; sub_index < subtitle_count; sub_index++) { - flutter::EncodableMap trackSelection = {}; - ret = player_get_subtitle_track_info_v2(player_, sub_index, - &sub_track_info); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_subtitle_track_info_v2 failed: %s", - get_error_message(ret)); - return {}; + return {}; + } + LOG_INFO( + "[VideoPlayer] subtitle track info: language[%s], " + "subtitle_type[%d]", + sub_track_info->language, sub_track_info->subtitle_type); + + trackSelection.insert( + {flutter::EncodableValue("trackType"), + flutter::EncodableValue(PLAYER_STREAM_TYPE_TEXT)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(sub_index)}); + trackSelection.insert( + {flutter::EncodableValue("language"), + flutter::EncodableValue(std::string(sub_track_info->language))}); + trackSelection.insert( + {flutter::EncodableValue("subtitleType"), + flutter::EncodableValue(sub_track_info->subtitle_type)}); + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); } - LOG_INFO( - "[VideoPlayer] subtitle track info: language[%s], " - "subtitle_type[%d]", - sub_track_info->language, sub_track_info->subtitle_type); - - trackSelection.insert({flutter::EncodableValue("trackType"), - flutter::EncodableValue(PLAYER_STREAM_TYPE_TEXT)}); - trackSelection.insert({flutter::EncodableValue("trackId"), - flutter::EncodableValue(sub_index)}); - trackSelection.insert( - {flutter::EncodableValue("language"), - flutter::EncodableValue(std::string(sub_track_info->language))}); - trackSelection.insert( - {flutter::EncodableValue("subtitleType"), - flutter::EncodableValue(sub_track_info->subtitle_type)}); - - trackSelections.push_back(flutter::EncodableValue(trackSelection)); } } + dlclose(player_lib_handle); return trackSelections; } diff --git a/packages/video_player_videohole/tizen/src/video_player.h b/packages/video_player_videohole/tizen/src/video_player.h index 300e50a0b..183e564f3 100644 --- a/packages/video_player_videohole/tizen/src/video_player.h +++ b/packages/video_player_videohole/tizen/src/video_player.h @@ -86,6 +86,7 @@ class VideoPlayer { flutter::EncodableList getVideoTrackInfo(); flutter::EncodableList getAudioTrackInfo(); flutter::EncodableList getTextTrackInfo(); + flutter::EncodableList getTrackInfo(player_stream_type_e track_type); void SetTrackSelection(int32_t track_id, int32_t track_type); void RegisterSendPort(Dart_Port send_port) { send_port_ = send_port; } From e9fba847f4d972df7eed9e369b6107b37ff48130 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Mon, 21 Aug 2023 11:13:26 +0800 Subject: [PATCH 12/15] Update CHANGELOG.md --- packages/video_player_videohole/CHANGELOG.md | 4 ++-- packages/video_player_videohole/README.md | 2 +- packages/video_player_videohole/pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/video_player_videohole/CHANGELOG.md b/packages/video_player_videohole/CHANGELOG.md index ca63690ab..a66050f24 100644 --- a/packages/video_player_videohole/CHANGELOG.md +++ b/packages/video_player_videohole/CHANGELOG.md @@ -1,6 +1,6 @@ -## 0.1.3 +## 0.2.0 -* Implement function of selecting video, audio and text traks. +* Implement functionality of selecting video, audio and text tracks. ## 0.1.2 diff --git a/packages/video_player_videohole/README.md b/packages/video_player_videohole/README.md index c2bb54393..252c1cd97 100644 --- a/packages/video_player_videohole/README.md +++ b/packages/video_player_videohole/README.md @@ -12,7 +12,7 @@ To use this package, add `video_player_videohole` as a dependency in your `pubsp ```yaml dependencies: - video_player_videohole: ^0.1.3 + video_player_videohole: ^0.2.0 ``` Then you can import `video_player_videohole` in your Dart code: diff --git a/packages/video_player_videohole/pubspec.yaml b/packages/video_player_videohole/pubspec.yaml index 881e4da35..876ebac9d 100644 --- a/packages/video_player_videohole/pubspec.yaml +++ b/packages/video_player_videohole/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_videohole 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_videohole -version: 0.1.3 +version: 0.2.0 environment: sdk: ">=2.18.0 <4.0.0" From 3fe64ba12c14a42a44f6474fc39445236bfccacc Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Fri, 25 Aug 2023 11:29:59 +0800 Subject: [PATCH 13/15] Code cleanups --- .../lib/src/tracks.dart | 6 ++-- .../lib/src/video_player_tizen.dart | 1 + .../lib/video_player_platform_interface.dart | 6 ++-- .../tizen/src/video_player.cc | 35 +++++++++++-------- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/packages/video_player_videohole/lib/src/tracks.dart b/packages/video_player_videohole/lib/src/tracks.dart index 5b4508914..fe68ab1df 100644 --- a/packages/video_player_videohole/lib/src/tracks.dart +++ b/packages/video_player_videohole/lib/src/tracks.dart @@ -41,7 +41,7 @@ enum TextTrackSubtitleType { class Track { /// Creates an instance of [Track]. /// - /// The [trackId] argument is required. + /// The [trackId] and [trackType] arguments are required. /// const Track({ required this.trackId, @@ -84,7 +84,7 @@ class VideoTrack extends Track { class AudioTrack extends Track { /// Creates an instance of [AudioTrack]. /// - /// The [language], [channel] argument is required. + /// The [language], [channel] and [bitrate] arguments are required. /// /// [trackType] is [TrackType.audio]. AudioTrack({ @@ -109,7 +109,7 @@ class AudioTrack extends Track { class TextTrack extends Track { /// Creates an instance of [TextTrack]. /// - /// The [language] argument is required. + /// The [language] and [subtitleType] arguments are required. /// /// [trackType] is [TrackType.text]. TextTrack({ diff --git a/packages/video_player_videohole/lib/src/video_player_tizen.dart b/packages/video_player_videohole/lib/src/video_player_tizen.dart index eb310bbdd..4f9e48c9f 100644 --- a/packages/video_player_videohole/lib/src/video_player_tizen.dart +++ b/packages/video_player_videohole/lib/src/video_player_tizen.dart @@ -124,6 +124,7 @@ class VideoPlayerTizen extends VideoPlayerPlatform { final AudioTrackChannelType channelType = _intChannelTypeMap[trackMap['channel']]!; final int bitrate = trackMap['bitrate']! as int; + audioTracks.add(AudioTrack( trackId: trackId, language: language, diff --git a/packages/video_player_videohole/lib/video_player_platform_interface.dart b/packages/video_player_videohole/lib/video_player_platform_interface.dart index 878e2d4b0..e8e63ce21 100644 --- a/packages/video_player_videohole/lib/video_player_platform_interface.dart +++ b/packages/video_player_videohole/lib/video_player_platform_interface.dart @@ -92,17 +92,17 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('getVideoTracks() has not been implemented.'); } - /// Gets the video tracks as a list of [AudioTrack]. + /// Gets the audio tracks as a list of [AudioTrack]. Future> getAudioTracks(int playerId) { throw UnimplementedError('getAudioTracks() has not been implemented.'); } - /// Gets the video tracks as a list of [TextTrack]. + /// Gets the text tracks as a list of [TextTrack]. Future> getTextTracks(int playerId) { throw UnimplementedError('getTextTracks() has not been implemented.'); } - /// Sets the selected video track selection. + /// Sets the selected track. Future setTrackSelection(int playerId, Track track) { throw UnimplementedError('setTrackSelection() has not been implemented.'); } diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index b21b7c6fc..e1ee9f0d9 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -300,23 +300,13 @@ flutter::EncodableList VideoPlayer::getTrackInfo( FuncPlayerGetTrackCountV2 player_get_track_count_v2 = reinterpret_cast( dlsym(player_lib_handle, "player_get_track_count_v2")); - FuncPlayerGetVideoTrackInfoV2 player_get_video_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_video_track_info_v2")); - FuncPlayerGetAudioTrackInfoV2 player_get_audio_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_audio_track_info_v2")); - FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = - reinterpret_cast( - dlsym(player_lib_handle, "player_get_subtitle_track_info_v2")); - if (!player_get_track_count_v2) { LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); dlclose(player_lib_handle); return {}; } - flutter::EncodableList trackSelections; + flutter::EncodableList trackSelections = {}; if (track_type == PLAYER_STREAM_TYPE_VIDEO) { int video_count = 0; ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_VIDEO, @@ -324,20 +314,25 @@ flutter::EncodableList VideoPlayer::getTrackInfo( if (ret != PLAYER_ERROR_NONE) { LOG_ERROR("[VideoPlayer] player_get_video_track_count failed: %s", get_error_message(ret)); + dlclose(player_lib_handle); return {}; } LOG_INFO("[VideoPlayer] video_count: %d", video_count); + FuncPlayerGetVideoTrackInfoV2 player_get_video_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_video_track_info_v2")); if (!player_get_video_track_info_v2) { LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); dlclose(player_lib_handle); return {}; } - player_video_track_info_v2 *video_track_info = NULL; if (video_count > 0) { for (int video_index = 0; video_index < video_count; video_index++) { flutter::EncodableMap trackSelection = {}; + player_video_track_info_v2 *video_track_info = nullptr; + ret = player_get_video_track_info_v2(player_, video_index, &video_track_info); if (ret != PLAYER_ERROR_NONE) { @@ -377,25 +372,31 @@ flutter::EncodableList VideoPlayer::getTrackInfo( if (ret != PLAYER_ERROR_NONE) { LOG_ERROR("[VideoPlayer] player_get_audio_track_count failed: %s", get_error_message(ret)); + dlclose(player_lib_handle); return {}; } LOG_INFO("[VideoPlayer] audio_count: %d", audio_count); + FuncPlayerGetAudioTrackInfoV2 player_get_audio_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_audio_track_info_v2")); if (!player_get_audio_track_info_v2) { LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); dlclose(player_lib_handle); return {}; } - player_audio_track_info_v2 *audio_track_info = NULL; if (audio_count > 0) { for (int audio_index = 0; audio_index < audio_count; audio_index++) { flutter::EncodableMap trackSelection = {}; + player_audio_track_info_v2 *audio_track_info = nullptr; + ret = player_get_audio_track_info_v2(player_, audio_index, &audio_track_info); if (ret != PLAYER_ERROR_NONE) { LOG_ERROR("[VideoPlayer] player_get_audio_track_info_v2 failed: %s", get_error_message(ret)); + dlclose(player_lib_handle); return {}; } LOG_INFO( @@ -429,26 +430,32 @@ flutter::EncodableList VideoPlayer::getTrackInfo( if (ret != PLAYER_ERROR_NONE) { LOG_ERROR("[VideoPlayer] player_get_subtitle_track_count failed: %s", get_error_message(ret)); + dlclose(player_lib_handle); return {}; } LOG_INFO("[VideoPlayer] subtitle_count: %d", subtitle_count); + FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = + reinterpret_cast( + dlsym(player_lib_handle, "player_get_subtitle_track_info_v2")); if (!player_get_subtitle_track_info_v2) { LOG_ERROR("[VideoPlayer] Symbol not found: %s", dlerror()); dlclose(player_lib_handle); return {}; } - player_subtitle_track_info_v2 *sub_track_info = NULL; if (subtitle_count > 0) { for (int sub_index = 0; sub_index < subtitle_count; sub_index++) { flutter::EncodableMap trackSelection = {}; + player_subtitle_track_info_v2 *sub_track_info = nullptr; + ret = player_get_subtitle_track_info_v2(player_, sub_index, &sub_track_info); if (ret != PLAYER_ERROR_NONE) { LOG_ERROR( "[VideoPlayer] player_get_subtitle_track_info_v2 failed: %s", get_error_message(ret)); + dlclose(player_lib_handle); return {}; } LOG_INFO( From 3bf7b6b061ed055d24ac03cab9742b2c0e960834 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Fri, 25 Aug 2023 13:37:07 +0800 Subject: [PATCH 14/15] Pass trackType through trackTypeMessage --- .../lib/src/messages.g.dart | 167 +++---------- .../lib/src/video_player_tizen.dart | 30 ++- .../pigeons/messages.dart | 22 +- .../tizen/src/messages.cc | 235 +++++------------- .../tizen/src/messages.h | 55 ++-- .../tizen/src/video_player.cc | 15 +- .../tizen/src/video_player.h | 5 +- .../tizen/src/video_player_tizen_plugin.cc | 34 +-- 8 files changed, 144 insertions(+), 419 deletions(-) diff --git a/packages/video_player_videohole/lib/src/messages.g.dart b/packages/video_player_videohole/lib/src/messages.g.dart index 1c4e5acc3..ea6b377ce 100644 --- a/packages/video_player_videohole/lib/src/messages.g.dart +++ b/packages/video_player_videohole/lib/src/messages.g.dart @@ -107,82 +107,54 @@ class PlaybackSpeedMessage { } } -class VideoTrackMessage { - VideoTrackMessage({ +class TrackMessage { + TrackMessage({ required this.playerId, - required this.videoTracks, + required this.tracks, }); int playerId; - List?> videoTracks; + List?> tracks; Object encode() { return [ playerId, - videoTracks, + tracks, ]; } - static VideoTrackMessage decode(Object result) { + static TrackMessage decode(Object result) { result as List; - return VideoTrackMessage( + return TrackMessage( playerId: result[0]! as int, - videoTracks: - (result[1] as List?)!.cast?>(), + tracks: (result[1] as List?)!.cast?>(), ); } } -class AudioTrackMessage { - AudioTrackMessage({ +class TrackTypeMessage { + TrackTypeMessage({ required this.playerId, - required this.audioTracks, - }); - - int playerId; - - List?> audioTracks; - - Object encode() { - return [ - playerId, - audioTracks, - ]; - } - - static AudioTrackMessage decode(Object result) { - result as List; - return AudioTrackMessage( - playerId: result[0]! as int, - audioTracks: - (result[1] as List?)!.cast?>(), - ); - } -} - -class TextTrackMessage { - TextTrackMessage({ - required this.playerId, - required this.textTracks, + required this.trackType, }); int playerId; - List?> textTracks; + int trackType; Object encode() { return [ playerId, - textTracks, + trackType, ]; } - static TextTrackMessage decode(Object result) { + static TrackTypeMessage decode(Object result) { result as List; - return TextTrackMessage( + return TrackTypeMessage( playerId: result[0]! as int, - textTracks: (result[1] as List?)!.cast?>(), + trackType: result[1]! as int, ); } } @@ -358,41 +330,38 @@ class _VideoPlayerVideoholeApiCodec extends StandardMessageCodec { const _VideoPlayerVideoholeApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is AudioTrackMessage) { + if (value is CreateMessage) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is CreateMessage) { + } else if (value is GeometryMessage) { buffer.putUint8(129); writeValue(buffer, value.encode()); - } else if (value is GeometryMessage) { + } else if (value is LoopingMessage) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is LoopingMessage) { + } else if (value is MixWithOthersMessage) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is MixWithOthersMessage) { + } else if (value is PlaybackSpeedMessage) { buffer.putUint8(132); writeValue(buffer, value.encode()); - } else if (value is PlaybackSpeedMessage) { + } else if (value is PlayerMessage) { buffer.putUint8(133); writeValue(buffer, value.encode()); - } else if (value is PlayerMessage) { + } else if (value is PositionMessage) { buffer.putUint8(134); writeValue(buffer, value.encode()); - } else if (value is PositionMessage) { + } else if (value is SelectedTracksMessage) { buffer.putUint8(135); writeValue(buffer, value.encode()); - } else if (value is SelectedTracksMessage) { + } else if (value is TrackMessage) { buffer.putUint8(136); writeValue(buffer, value.encode()); - } else if (value is TextTrackMessage) { + } else if (value is TrackTypeMessage) { buffer.putUint8(137); writeValue(buffer, value.encode()); - } else if (value is VideoTrackMessage) { - buffer.putUint8(138); - writeValue(buffer, value.encode()); } else if (value is VolumeMessage) { - buffer.putUint8(139); + buffer.putUint8(138); writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); @@ -403,28 +372,26 @@ class _VideoPlayerVideoholeApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: - return AudioTrackMessage.decode(readValue(buffer)!); - case 129: return CreateMessage.decode(readValue(buffer)!); - case 130: + case 129: return GeometryMessage.decode(readValue(buffer)!); - case 131: + case 130: return LoopingMessage.decode(readValue(buffer)!); - case 132: + case 131: return MixWithOthersMessage.decode(readValue(buffer)!); - case 133: + case 132: return PlaybackSpeedMessage.decode(readValue(buffer)!); - case 134: + case 133: return PlayerMessage.decode(readValue(buffer)!); - case 135: + case 134: return PositionMessage.decode(readValue(buffer)!); - case 136: + case 135: return SelectedTracksMessage.decode(readValue(buffer)!); + case 136: + return TrackMessage.decode(readValue(buffer)!); case 137: - return TextTrackMessage.decode(readValue(buffer)!); + return TrackTypeMessage.decode(readValue(buffer)!); case 138: - return VideoTrackMessage.decode(readValue(buffer)!); - case 139: return VolumeMessage.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -649,63 +616,9 @@ class VideoPlayerVideoholeApi { } } - Future videoTrack(PlayerMessage arg_msg) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.VideoPlayerVideoholeApi.videoTrack', 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 VideoTrackMessage?)!; - } - } - - Future audioTrack(PlayerMessage arg_msg) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.VideoPlayerVideoholeApi.audioTrack', 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 AudioTrackMessage?)!; - } - } - - Future textTrack(PlayerMessage arg_msg) async { + Future track(TrackTypeMessage arg_msg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.VideoPlayerVideoholeApi.textTrack', codec, + 'dev.flutter.pigeon.VideoPlayerVideoholeApi.track', codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_msg]) as List?; @@ -726,7 +639,7 @@ class VideoPlayerVideoholeApi { message: 'Host platform returned null value for non-null return value.', ); } else { - return (replyList[0] as TextTrackMessage?)!; + return (replyList[0] as TrackMessage?)!; } } diff --git a/packages/video_player_videohole/lib/src/video_player_tizen.dart b/packages/video_player_videohole/lib/src/video_player_tizen.dart index 4f9e48c9f..94dc871af 100644 --- a/packages/video_player_videohole/lib/src/video_player_tizen.dart +++ b/packages/video_player_videohole/lib/src/video_player_tizen.dart @@ -91,11 +91,15 @@ class VideoPlayerTizen extends VideoPlayerPlatform { @override Future> getVideoTracks(int playerId) async { - final VideoTrackMessage response = - await _api.videoTrack(PlayerMessage(playerId: playerId)); + final TrackMessage response = await _api.track(TrackTypeMessage( + playerId: playerId, + trackType: _intTrackTypeMap.keys.firstWhere( + (int key) => _intTrackTypeMap[key] == TrackType.video, + orElse: () => -1), + )); final List videoTracks = []; - for (final Map? trackMap in response.videoTracks) { + for (final Map? trackMap in response.tracks) { final int trackId = trackMap!['trackId']! as int; final int bitrate = trackMap['bitrate']! as int; final int width = trackMap['width']! as int; @@ -114,11 +118,15 @@ class VideoPlayerTizen extends VideoPlayerPlatform { @override Future> getAudioTracks(int playerId) async { - final AudioTrackMessage response = - await _api.audioTrack(PlayerMessage(playerId: playerId)); + final TrackMessage response = await _api.track(TrackTypeMessage( + playerId: playerId, + trackType: _intTrackTypeMap.keys.firstWhere( + (int key) => _intTrackTypeMap[key] == TrackType.audio, + orElse: () => -1), + )); final List audioTracks = []; - for (final Map? trackMap in response.audioTracks) { + for (final Map? trackMap in response.tracks) { final int trackId = trackMap!['trackId']! as int; final String language = trackMap['language']! as String; final AudioTrackChannelType channelType = @@ -138,11 +146,15 @@ class VideoPlayerTizen extends VideoPlayerPlatform { @override Future> getTextTracks(int playerId) async { - final TextTrackMessage response = - await _api.textTrack(PlayerMessage(playerId: playerId)); + final TrackMessage response = await _api.track(TrackTypeMessage( + playerId: playerId, + trackType: _intTrackTypeMap.keys.firstWhere( + (int key) => _intTrackTypeMap[key] == TrackType.text, + orElse: () => -1), + )); final List textTracks = []; - for (final Map? trackMap in response.textTracks) { + for (final Map? trackMap in response.tracks) { final int trackId = trackMap!['trackId']! as int; final String language = trackMap['language']! as String; final TextTrackSubtitleType subtitleType = diff --git a/packages/video_player_videohole/pigeons/messages.dart b/packages/video_player_videohole/pigeons/messages.dart index cd8701a0a..25bf8173b 100644 --- a/packages/video_player_videohole/pigeons/messages.dart +++ b/packages/video_player_videohole/pigeons/messages.dart @@ -32,22 +32,16 @@ class PlaybackSpeedMessage { double speed; } -class VideoTrackMessage { - VideoTrackMessage(this.playerId, this.videoTracks); +class TrackMessage { + TrackMessage(this.playerId, this.tracks); int playerId; - List?> videoTracks; + List?> tracks; } -class AudioTrackMessage { - AudioTrackMessage(this.playerId, this.audioTracks); +class TrackTypeMessage { + TrackTypeMessage(this.playerId, this.trackType); int playerId; - List?> audioTracks; -} - -class TextTrackMessage { - TextTrackMessage(this.playerId, this.textTracks); - int playerId; - List?> textTracks; + int trackType; } class SelectedTracksMessage { @@ -99,9 +93,7 @@ abstract class VideoPlayerVideoholeApi { PositionMessage position(PlayerMessage msg); @async void seekTo(PositionMessage msg); - VideoTrackMessage videoTrack(PlayerMessage msg); - AudioTrackMessage audioTrack(PlayerMessage msg); - TextTrackMessage textTrack(PlayerMessage msg); + TrackMessage track(TrackTypeMessage msg); void setTrackSelection(SelectedTracksMessage msg); void pause(PlayerMessage msg); void setMixWithOthers(MixWithOthersMessage msg); diff --git a/packages/video_player_videohole/tizen/src/messages.cc b/packages/video_player_videohole/tizen/src/messages.cc index 83cab2bb8..090d888ff 100644 --- a/packages/video_player_videohole/tizen/src/messages.cc +++ b/packages/video_player_videohole/tizen/src/messages.cc @@ -123,108 +123,62 @@ PlaybackSpeedMessage PlaybackSpeedMessage::FromEncodableList( return decoded; } -// VideoTrackMessage +// TrackMessage -VideoTrackMessage::VideoTrackMessage(int64_t player_id, - const EncodableList& video_tracks) - : player_id_(player_id), video_tracks_(video_tracks) {} +TrackMessage::TrackMessage(int64_t player_id, const EncodableList& tracks) + : player_id_(player_id), tracks_(tracks) {} -int64_t VideoTrackMessage::player_id() const { return player_id_; } +int64_t TrackMessage::player_id() const { return player_id_; } -void VideoTrackMessage::set_player_id(int64_t value_arg) { - player_id_ = value_arg; -} +void TrackMessage::set_player_id(int64_t value_arg) { player_id_ = value_arg; } -const EncodableList& VideoTrackMessage::video_tracks() const { - return video_tracks_; -} +const EncodableList& TrackMessage::tracks() const { return tracks_; } -void VideoTrackMessage::set_video_tracks(const EncodableList& value_arg) { - video_tracks_ = value_arg; +void TrackMessage::set_tracks(const EncodableList& value_arg) { + tracks_ = value_arg; } -EncodableList VideoTrackMessage::ToEncodableList() const { +EncodableList TrackMessage::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(EncodableValue(player_id_)); - list.push_back(EncodableValue(video_tracks_)); + list.push_back(EncodableValue(tracks_)); return list; } -VideoTrackMessage VideoTrackMessage::FromEncodableList( - const EncodableList& list) { - VideoTrackMessage decoded(list[0].LongValue(), - std::get(list[1])); +TrackMessage TrackMessage::FromEncodableList(const EncodableList& list) { + TrackMessage decoded(list[0].LongValue(), std::get(list[1])); return decoded; } -// AudioTrackMessage +// TrackTypeMessage -AudioTrackMessage::AudioTrackMessage(int64_t player_id, - const EncodableList& audio_tracks) - : player_id_(player_id), audio_tracks_(audio_tracks) {} +TrackTypeMessage::TrackTypeMessage(int64_t player_id, int64_t track_type) + : player_id_(player_id), track_type_(track_type) {} -int64_t AudioTrackMessage::player_id() const { return player_id_; } +int64_t TrackTypeMessage::player_id() const { return player_id_; } -void AudioTrackMessage::set_player_id(int64_t value_arg) { +void TrackTypeMessage::set_player_id(int64_t value_arg) { player_id_ = value_arg; } -const EncodableList& AudioTrackMessage::audio_tracks() const { - return audio_tracks_; -} - -void AudioTrackMessage::set_audio_tracks(const EncodableList& value_arg) { - audio_tracks_ = value_arg; -} - -EncodableList AudioTrackMessage::ToEncodableList() const { - EncodableList list; - list.reserve(2); - list.push_back(EncodableValue(player_id_)); - list.push_back(EncodableValue(audio_tracks_)); - return list; -} - -AudioTrackMessage AudioTrackMessage::FromEncodableList( - const EncodableList& list) { - AudioTrackMessage decoded(list[0].LongValue(), - std::get(list[1])); - return decoded; -} - -// TextTrackMessage +int64_t TrackTypeMessage::track_type() const { return track_type_; } -TextTrackMessage::TextTrackMessage(int64_t player_id, - const EncodableList& text_tracks) - : player_id_(player_id), text_tracks_(text_tracks) {} - -int64_t TextTrackMessage::player_id() const { return player_id_; } - -void TextTrackMessage::set_player_id(int64_t value_arg) { - player_id_ = value_arg; -} - -const EncodableList& TextTrackMessage::text_tracks() const { - return text_tracks_; -} - -void TextTrackMessage::set_text_tracks(const EncodableList& value_arg) { - text_tracks_ = value_arg; +void TrackTypeMessage::set_track_type(int64_t value_arg) { + track_type_ = value_arg; } -EncodableList TextTrackMessage::ToEncodableList() const { +EncodableList TrackTypeMessage::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(EncodableValue(player_id_)); - list.push_back(EncodableValue(text_tracks_)); + list.push_back(EncodableValue(track_type_)); return list; } -TextTrackMessage TextTrackMessage::FromEncodableList( +TrackTypeMessage TrackTypeMessage::FromEncodableList( const EncodableList& list) { - TextTrackMessage decoded(list[0].LongValue(), - std::get(list[1])); + TrackTypeMessage decoded(list[0].LongValue(), list[1].LongValue()); return decoded; } @@ -513,39 +467,36 @@ EncodableValue VideoPlayerVideoholeApiCodecSerializer::ReadValueOfType( uint8_t type, flutter::ByteStreamReader* stream) const { switch (type) { case 128: - return CustomEncodableValue(AudioTrackMessage::FromEncodableList( + return CustomEncodableValue(CreateMessage::FromEncodableList( std::get(ReadValue(stream)))); case 129: - return CustomEncodableValue(CreateMessage::FromEncodableList( + return CustomEncodableValue(GeometryMessage::FromEncodableList( std::get(ReadValue(stream)))); case 130: - return CustomEncodableValue(GeometryMessage::FromEncodableList( + return CustomEncodableValue(LoopingMessage::FromEncodableList( std::get(ReadValue(stream)))); case 131: - return CustomEncodableValue(LoopingMessage::FromEncodableList( + return CustomEncodableValue(MixWithOthersMessage::FromEncodableList( std::get(ReadValue(stream)))); case 132: - return CustomEncodableValue(MixWithOthersMessage::FromEncodableList( + return CustomEncodableValue(PlaybackSpeedMessage::FromEncodableList( std::get(ReadValue(stream)))); case 133: - return CustomEncodableValue(PlaybackSpeedMessage::FromEncodableList( + return CustomEncodableValue(PlayerMessage::FromEncodableList( std::get(ReadValue(stream)))); case 134: - return CustomEncodableValue(PlayerMessage::FromEncodableList( + return CustomEncodableValue(PositionMessage::FromEncodableList( std::get(ReadValue(stream)))); case 135: - return CustomEncodableValue(PositionMessage::FromEncodableList( + return CustomEncodableValue(SelectedTracksMessage::FromEncodableList( std::get(ReadValue(stream)))); case 136: - return CustomEncodableValue(SelectedTracksMessage::FromEncodableList( + return CustomEncodableValue(TrackMessage::FromEncodableList( std::get(ReadValue(stream)))); case 137: - return CustomEncodableValue(TextTrackMessage::FromEncodableList( + return CustomEncodableValue(TrackTypeMessage::FromEncodableList( std::get(ReadValue(stream)))); case 138: - return CustomEncodableValue(VideoTrackMessage::FromEncodableList( - std::get(ReadValue(stream)))); - case 139: return CustomEncodableValue(VolumeMessage::FromEncodableList( std::get(ReadValue(stream)))); default: @@ -557,15 +508,8 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( const EncodableValue& value, flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { - if (custom_value->type() == typeid(AudioTrackMessage)) { - stream->WriteByte(128); - WriteValue(EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } if (custom_value->type() == typeid(CreateMessage)) { - stream->WriteByte(129); + stream->WriteByte(128); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -573,7 +517,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(GeometryMessage)) { - stream->WriteByte(130); + stream->WriteByte(129); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -581,7 +525,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(LoopingMessage)) { - stream->WriteByte(131); + stream->WriteByte(130); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -589,7 +533,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(MixWithOthersMessage)) { - stream->WriteByte(132); + stream->WriteByte(131); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), @@ -597,7 +541,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(PlaybackSpeedMessage)) { - stream->WriteByte(133); + stream->WriteByte(132); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), @@ -605,7 +549,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(PlayerMessage)) { - stream->WriteByte(134); + stream->WriteByte(133); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -613,7 +557,7 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(PositionMessage)) { - stream->WriteByte(135); + stream->WriteByte(134); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -621,30 +565,31 @@ void VideoPlayerVideoholeApiCodecSerializer::WriteValue( return; } if (custom_value->type() == typeid(SelectedTracksMessage)) { - stream->WriteByte(136); + stream->WriteByte(135); WriteValue( EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(TextTrackMessage)) { - stream->WriteByte(137); + if (custom_value->type() == typeid(TrackMessage)) { + stream->WriteByte(136); WriteValue( EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), + std::any_cast(*custom_value).ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(VideoTrackMessage)) { - stream->WriteByte(138); - WriteValue(EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); + if (custom_value->type() == typeid(TrackTypeMessage)) { + stream->WriteByte(137); + WriteValue( + EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); return; } if (custom_value->type() == typeid(VolumeMessage)) { - stream->WriteByte(139); + stream->WriteByte(138); WriteValue( EncodableValue( std::any_cast(*custom_value).ToEncodableList()), @@ -962,76 +907,8 @@ void VideoPlayerVideoholeApi::SetUp(flutter::BinaryMessenger* binary_messenger, } { auto channel = std::make_unique>( - binary_messenger, - "dev.flutter.pigeon.VideoPlayerVideoholeApi.videoTrack", &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->VideoTrack(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); - } - } - { - auto channel = std::make_unique>( - binary_messenger, - "dev.flutter.pigeon.VideoPlayerVideoholeApi.audioTrack", &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->AudioTrack(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); - } - } - { - auto channel = std::make_unique>( - binary_messenger, - "dev.flutter.pigeon.VideoPlayerVideoholeApi.textTrack", &GetCodec()); + binary_messenger, "dev.flutter.pigeon.VideoPlayerVideoholeApi.track", + &GetCodec()); if (api != nullptr) { channel->SetMessageHandler( [api](const EncodableValue& message, @@ -1043,9 +920,9 @@ void VideoPlayerVideoholeApi::SetUp(flutter::BinaryMessenger* binary_messenger, reply(WrapError("msg_arg unexpectedly null.")); return; } - const auto& msg_arg = std::any_cast( + const auto& msg_arg = std::any_cast( std::get(encodable_msg_arg)); - ErrorOr output = api->TextTrack(msg_arg); + ErrorOr output = api->Track(msg_arg); if (output.has_error()) { reply(WrapError(output.error())); return; diff --git a/packages/video_player_videohole/tizen/src/messages.h b/packages/video_player_videohole/tizen/src/messages.h index 194b4ff30..3a40ddbb3 100644 --- a/packages/video_player_videohole/tizen/src/messages.h +++ b/packages/video_player_videohole/tizen/src/messages.h @@ -135,71 +135,46 @@ class PlaybackSpeedMessage { }; // Generated class from Pigeon that represents data sent in messages. -class VideoTrackMessage { +class TrackMessage { public: // Constructs an object setting all fields. - explicit VideoTrackMessage(int64_t player_id, - const flutter::EncodableList& video_tracks); + explicit TrackMessage(int64_t player_id, + const flutter::EncodableList& tracks); int64_t player_id() const; void set_player_id(int64_t value_arg); - const flutter::EncodableList& video_tracks() const; - void set_video_tracks(const flutter::EncodableList& value_arg); + const flutter::EncodableList& tracks() const; + void set_tracks(const flutter::EncodableList& value_arg); private: - static VideoTrackMessage FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class VideoPlayerVideoholeApi; - friend class VideoPlayerVideoholeApiCodecSerializer; - int64_t player_id_; - flutter::EncodableList video_tracks_; -}; - -// Generated class from Pigeon that represents data sent in messages. -class AudioTrackMessage { - public: - // Constructs an object setting all fields. - explicit AudioTrackMessage(int64_t player_id, - const flutter::EncodableList& audio_tracks); - - int64_t player_id() const; - void set_player_id(int64_t value_arg); - - const flutter::EncodableList& audio_tracks() const; - void set_audio_tracks(const flutter::EncodableList& value_arg); - - private: - static AudioTrackMessage FromEncodableList( - const flutter::EncodableList& list); + static TrackMessage FromEncodableList(const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; friend class VideoPlayerVideoholeApi; friend class VideoPlayerVideoholeApiCodecSerializer; int64_t player_id_; - flutter::EncodableList audio_tracks_; + flutter::EncodableList tracks_; }; // Generated class from Pigeon that represents data sent in messages. -class TextTrackMessage { +class TrackTypeMessage { public: // Constructs an object setting all fields. - explicit TextTrackMessage(int64_t player_id, - const flutter::EncodableList& text_tracks); + explicit TrackTypeMessage(int64_t player_id, int64_t track_type); int64_t player_id() const; void set_player_id(int64_t value_arg); - const flutter::EncodableList& text_tracks() const; - void set_text_tracks(const flutter::EncodableList& value_arg); + int64_t track_type() const; + void set_track_type(int64_t value_arg); private: - static TextTrackMessage FromEncodableList(const flutter::EncodableList& list); + static TrackTypeMessage FromEncodableList(const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; friend class VideoPlayerVideoholeApi; friend class VideoPlayerVideoholeApiCodecSerializer; int64_t player_id_; - flutter::EncodableList text_tracks_; + int64_t track_type_; }; // Generated class from Pigeon that represents data sent in messages. @@ -388,9 +363,7 @@ class VideoPlayerVideoholeApi { virtual void SeekTo( const PositionMessage& msg, std::function reply)> result) = 0; - virtual ErrorOr VideoTrack(const PlayerMessage& msg) = 0; - virtual ErrorOr AudioTrack(const PlayerMessage& msg) = 0; - virtual ErrorOr TextTrack(const PlayerMessage& msg) = 0; + virtual ErrorOr Track(const TrackTypeMessage& msg) = 0; virtual std::optional SetTrackSelection( const SelectedTracksMessage& msg) = 0; virtual std::optional Pause(const PlayerMessage& msg) = 0; diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index e1ee9f0d9..faf182a32 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -265,20 +265,7 @@ void VideoPlayer::SetPlaybackSpeed(double speed) { } } -flutter::EncodableList VideoPlayer::getVideoTrackInfo() { - return getTrackInfo(PLAYER_STREAM_TYPE_VIDEO); -} - -flutter::EncodableList VideoPlayer::getAudioTrackInfo() { - return getTrackInfo(PLAYER_STREAM_TYPE_AUDIO); -} - -flutter::EncodableList VideoPlayer::getTextTrackInfo() { - return getTrackInfo(PLAYER_STREAM_TYPE_TEXT); -} - -flutter::EncodableList VideoPlayer::getTrackInfo( - player_stream_type_e track_type) { +flutter::EncodableList VideoPlayer::getTrackInfo(int32_t track_type) { player_state_e state = PLAYER_STATE_NONE; int ret = player_get_state(player_, &state); if (ret != PLAYER_ERROR_NONE) { diff --git a/packages/video_player_videohole/tizen/src/video_player.h b/packages/video_player_videohole/tizen/src/video_player.h index 183e564f3..6474695b7 100644 --- a/packages/video_player_videohole/tizen/src/video_player.h +++ b/packages/video_player_videohole/tizen/src/video_player.h @@ -83,10 +83,7 @@ class VideoPlayer { void SetPlaybackSpeed(double speed); void SeekTo(int32_t position, SeekCompletedCallback callback); int32_t GetPosition(); - flutter::EncodableList getVideoTrackInfo(); - flutter::EncodableList getAudioTrackInfo(); - flutter::EncodableList getTextTrackInfo(); - flutter::EncodableList getTrackInfo(player_stream_type_e track_type); + flutter::EncodableList getTrackInfo(int32_t track_type); void SetTrackSelection(int32_t track_id, int32_t track_type); void RegisterSendPort(Dart_Port send_port) { send_port_ = send_port; } diff --git a/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc b/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc index 6b7341a5a..11a2962a3 100644 --- a/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc +++ b/packages/video_player_videohole/tizen/src/video_player_tizen_plugin.cc @@ -44,12 +44,7 @@ class VideoPlayerTizenPlugin : public flutter::Plugin, void SeekTo( const PositionMessage &msg, std::function reply)> result) override; - virtual ErrorOr VideoTrack( - const PlayerMessage &msg) override; - virtual ErrorOr AudioTrack( - const PlayerMessage &msg) override; - virtual ErrorOr TextTrack( - const PlayerMessage &msg) override; + virtual ErrorOr Track(const TrackTypeMessage &msg) override; std::optional SetTrackSelection( const SelectedTracksMessage &msg) override; std::optional Pause(const PlayerMessage &msg) override; @@ -251,36 +246,15 @@ void VideoPlayerTizenPlugin::SeekTo( player->SeekTo(msg.position(), [result]() -> void { result(std::nullopt); }); } -ErrorOr VideoPlayerTizenPlugin::VideoTrack( - const PlayerMessage &msg) { - VideoPlayer *player = FindPlayerById(msg.player_id()); - - if (!player) { - return FlutterError("Invalid argument", "Player not found."); - } - VideoTrackMessage result(msg.player_id(), player->getVideoTrackInfo()); - return result; -} - -ErrorOr VideoPlayerTizenPlugin::AudioTrack( - const PlayerMessage &msg) { +ErrorOr VideoPlayerTizenPlugin::Track( + const TrackTypeMessage &msg) { VideoPlayer *player = FindPlayerById(msg.player_id()); if (!player) { return FlutterError("Invalid argument", "Player not found."); } - AudioTrackMessage result(msg.player_id(), player->getAudioTrackInfo()); - return result; -} -ErrorOr VideoPlayerTizenPlugin::TextTrack( - const PlayerMessage &msg) { - VideoPlayer *player = FindPlayerById(msg.player_id()); - - if (!player) { - return FlutterError("Invalid argument", "Player not found."); - } - TextTrackMessage result(msg.player_id(), player->getTextTrackInfo()); + TrackMessage result(msg.player_id(), player->getTrackInfo(msg.track_type())); return result; } From a32368ebb6ebb384146f554ee340ff41a5525234 Mon Sep 17 00:00:00 2001 From: "yue7.huang" Date: Fri, 25 Aug 2023 17:06:34 +0800 Subject: [PATCH 15/15] Remove duplicated codes --- .../tizen/src/video_player.cc | 241 ++++++++---------- 1 file changed, 110 insertions(+), 131 deletions(-) diff --git a/packages/video_player_videohole/tizen/src/video_player.cc b/packages/video_player_videohole/tizen/src/video_player.cc index faf182a32..00a05ce5a 100644 --- a/packages/video_player_videohole/tizen/src/video_player.cc +++ b/packages/video_player_videohole/tizen/src/video_player.cc @@ -293,18 +293,22 @@ flutter::EncodableList VideoPlayer::getTrackInfo(int32_t track_type) { return {}; } + int track_count = 0; + ret = player_get_track_count_v2(player_, (player_stream_type_e)track_type, + &track_count); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_track_count_v2 failed: %s", + get_error_message(ret)); + dlclose(player_lib_handle); + return {}; + } + if (track_count <= 0) { + return {}; + } + flutter::EncodableList trackSelections = {}; if (track_type == PLAYER_STREAM_TYPE_VIDEO) { - int video_count = 0; - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_VIDEO, - &video_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_video_track_count failed: %s", - get_error_message(ret)); - dlclose(player_lib_handle); - return {}; - } - LOG_INFO("[VideoPlayer] video_count: %d", video_count); + LOG_INFO("[VideoPlayer] video_count: %d", track_count); FuncPlayerGetVideoTrackInfoV2 player_get_video_track_info_v2 = reinterpret_cast( @@ -315,54 +319,43 @@ flutter::EncodableList VideoPlayer::getTrackInfo(int32_t track_type) { return {}; } - if (video_count > 0) { - for (int video_index = 0; video_index < video_count; video_index++) { - flutter::EncodableMap trackSelection = {}; - player_video_track_info_v2 *video_track_info = nullptr; - - ret = player_get_video_track_info_v2(player_, video_index, - &video_track_info); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_video_track_info_v2 failed: %s", - get_error_message(ret)); - return {}; - } - LOG_INFO( - "[VideoPlayer] video track info: width[%d], height[%d], " - "bitrate[%d]", - video_track_info->width, video_track_info->height, - video_track_info->bit_rate); - - trackSelection.insert( - {flutter::EncodableValue("trackType"), - flutter::EncodableValue(PLAYER_STREAM_TYPE_VIDEO)}); - trackSelection.insert({flutter::EncodableValue("trackId"), - flutter::EncodableValue(video_index)}); - - trackSelection.insert( - {flutter::EncodableValue("width"), - flutter::EncodableValue(video_track_info->width)}); - trackSelection.insert( - {flutter::EncodableValue("height"), - flutter::EncodableValue(video_track_info->height)}); - trackSelection.insert( - {flutter::EncodableValue("bitrate"), - flutter::EncodableValue(video_track_info->bit_rate)}); - - trackSelections.push_back(flutter::EncodableValue(trackSelection)); + for (int video_index = 0; video_index < track_count; video_index++) { + flutter::EncodableMap trackSelection = {}; + player_video_track_info_v2 *video_track_info = nullptr; + + ret = player_get_video_track_info_v2(player_, video_index, + &video_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_video_track_info_v2 failed: %s", + get_error_message(ret)); + dlclose(player_lib_handle); + return {}; } + LOG_INFO( + "[VideoPlayer] video track info: width[%d], height[%d], " + "bitrate[%d]", + video_track_info->width, video_track_info->height, + video_track_info->bit_rate); + + trackSelection.insert( + {flutter::EncodableValue("trackType"), + flutter::EncodableValue(PLAYER_STREAM_TYPE_VIDEO)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(video_index)}); + trackSelection.insert({flutter::EncodableValue("width"), + flutter::EncodableValue(video_track_info->width)}); + trackSelection.insert( + {flutter::EncodableValue("height"), + flutter::EncodableValue(video_track_info->height)}); + trackSelection.insert( + {flutter::EncodableValue("bitrate"), + flutter::EncodableValue(video_track_info->bit_rate)}); + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); } + } else if (track_type == PLAYER_STREAM_TYPE_AUDIO) { - int audio_count = 0; - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_AUDIO, - &audio_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_audio_track_count failed: %s", - get_error_message(ret)); - dlclose(player_lib_handle); - return {}; - } - LOG_INFO("[VideoPlayer] audio_count: %d", audio_count); + LOG_INFO("[VideoPlayer] audio_count: %d", track_count); FuncPlayerGetAudioTrackInfoV2 player_get_audio_track_info_v2 = reinterpret_cast( @@ -373,54 +366,44 @@ flutter::EncodableList VideoPlayer::getTrackInfo(int32_t track_type) { return {}; } - if (audio_count > 0) { - for (int audio_index = 0; audio_index < audio_count; audio_index++) { - flutter::EncodableMap trackSelection = {}; - player_audio_track_info_v2 *audio_track_info = nullptr; - - ret = player_get_audio_track_info_v2(player_, audio_index, - &audio_track_info); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_audio_track_info_v2 failed: %s", - get_error_message(ret)); - dlclose(player_lib_handle); - return {}; - } - LOG_INFO( - "[VideoPlayer] audio track info: language[%s], channel[%d], " - "sample_rate[%d], bitrate[%d]", - audio_track_info->language, audio_track_info->channel, - audio_track_info->sample_rate, audio_track_info->bit_rate); - - trackSelection.insert( - {flutter::EncodableValue("trackType"), - flutter::EncodableValue(PLAYER_STREAM_TYPE_AUDIO)}); - trackSelection.insert({flutter::EncodableValue("trackId"), - flutter::EncodableValue(audio_index)}); - trackSelection.insert( - {flutter::EncodableValue("language"), - flutter::EncodableValue(std::string(audio_track_info->language))}); - trackSelection.insert( - {flutter::EncodableValue("channel"), - flutter::EncodableValue(audio_track_info->channel)}); - trackSelection.insert( - {flutter::EncodableValue("bitrate"), - flutter::EncodableValue(audio_track_info->bit_rate)}); - - trackSelections.push_back(flutter::EncodableValue(trackSelection)); + for (int audio_index = 0; audio_index < track_count; audio_index++) { + flutter::EncodableMap trackSelection = {}; + player_audio_track_info_v2 *audio_track_info = nullptr; + + ret = player_get_audio_track_info_v2(player_, audio_index, + &audio_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_audio_track_info_v2 failed: %s", + get_error_message(ret)); + dlclose(player_lib_handle); + return {}; } + LOG_INFO( + "[VideoPlayer] audio track info: language[%s], channel[%d], " + "sample_rate[%d], bitrate[%d]", + audio_track_info->language, audio_track_info->channel, + audio_track_info->sample_rate, audio_track_info->bit_rate); + + trackSelection.insert( + {flutter::EncodableValue("trackType"), + flutter::EncodableValue(PLAYER_STREAM_TYPE_AUDIO)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(audio_index)}); + trackSelection.insert( + {flutter::EncodableValue("language"), + flutter::EncodableValue(std::string(audio_track_info->language))}); + trackSelection.insert( + {flutter::EncodableValue("channel"), + flutter::EncodableValue(audio_track_info->channel)}); + trackSelection.insert( + {flutter::EncodableValue("bitrate"), + flutter::EncodableValue(audio_track_info->bit_rate)}); + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); } + } else if (track_type == PLAYER_STREAM_TYPE_TEXT) { - int subtitle_count = 0; - ret = player_get_track_count_v2(player_, PLAYER_STREAM_TYPE_TEXT, - &subtitle_count); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR("[VideoPlayer] player_get_subtitle_track_count failed: %s", - get_error_message(ret)); - dlclose(player_lib_handle); - return {}; - } - LOG_INFO("[VideoPlayer] subtitle_count: %d", subtitle_count); + LOG_INFO("[VideoPlayer] subtitle_count: %d", track_count); FuncPlayerGetSubtitleTrackInfoV2 player_get_subtitle_track_info_v2 = reinterpret_cast( @@ -431,39 +414,35 @@ flutter::EncodableList VideoPlayer::getTrackInfo(int32_t track_type) { return {}; } - if (subtitle_count > 0) { - for (int sub_index = 0; sub_index < subtitle_count; sub_index++) { - flutter::EncodableMap trackSelection = {}; - player_subtitle_track_info_v2 *sub_track_info = nullptr; + for (int sub_index = 0; sub_index < track_count; sub_index++) { + flutter::EncodableMap trackSelection = {}; + player_subtitle_track_info_v2 *sub_track_info = nullptr; - ret = player_get_subtitle_track_info_v2(player_, sub_index, - &sub_track_info); - if (ret != PLAYER_ERROR_NONE) { - LOG_ERROR( - "[VideoPlayer] player_get_subtitle_track_info_v2 failed: %s", - get_error_message(ret)); - dlclose(player_lib_handle); - return {}; - } - LOG_INFO( - "[VideoPlayer] subtitle track info: language[%s], " - "subtitle_type[%d]", - sub_track_info->language, sub_track_info->subtitle_type); - - trackSelection.insert( - {flutter::EncodableValue("trackType"), - flutter::EncodableValue(PLAYER_STREAM_TYPE_TEXT)}); - trackSelection.insert({flutter::EncodableValue("trackId"), - flutter::EncodableValue(sub_index)}); - trackSelection.insert( - {flutter::EncodableValue("language"), - flutter::EncodableValue(std::string(sub_track_info->language))}); - trackSelection.insert( - {flutter::EncodableValue("subtitleType"), - flutter::EncodableValue(sub_track_info->subtitle_type)}); - - trackSelections.push_back(flutter::EncodableValue(trackSelection)); + ret = player_get_subtitle_track_info_v2(player_, sub_index, + &sub_track_info); + if (ret != PLAYER_ERROR_NONE) { + LOG_ERROR("[VideoPlayer] player_get_subtitle_track_info_v2 failed: %s", + get_error_message(ret)); + dlclose(player_lib_handle); + return {}; } + LOG_INFO( + "[VideoPlayer] subtitle track info: language[%s], " + "subtitle_type[%d]", + sub_track_info->language, sub_track_info->subtitle_type); + + trackSelection.insert({flutter::EncodableValue("trackType"), + flutter::EncodableValue(PLAYER_STREAM_TYPE_TEXT)}); + trackSelection.insert({flutter::EncodableValue("trackId"), + flutter::EncodableValue(sub_index)}); + trackSelection.insert( + {flutter::EncodableValue("language"), + flutter::EncodableValue(std::string(sub_track_info->language))}); + trackSelection.insert( + {flutter::EncodableValue("subtitleType"), + flutter::EncodableValue(sub_track_info->subtitle_type)}); + + trackSelections.push_back(flutter::EncodableValue(trackSelection)); } }