Skip to content

Commit 348641e

Browse files
Merge pull request #108 from alexmercerind/dynamic-frame-size-video
Remove videoWidth & videoHeight from Player in favor of automatic Texture/Buffer resize (#101)
2 parents 2ce934b + be55665 commit 348641e

File tree

16 files changed

+327
-296
lines changed

16 files changed

+327
-296
lines changed

dartvlc/internal/events.hpp

Lines changed: 71 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,25 @@ class PlayerEvents : public PlayerGetters {
1919
std::bind(&PlayerEvents::OnOpenCallback, this, std::placeholders::_1));
2020
}
2121

22-
void OnPlay(std::function<void(void)> callback) {
22+
void OnPlay(std::function<void()> callback) {
2323
play_callback_ = callback;
2424
vlc_media_player_.eventManager().onPlaying(
2525
std::bind(&PlayerEvents::OnPlayCallback, this));
2626
}
2727

28-
void OnPause(std::function<void(void)> callback) {
28+
void OnVideoDimensions(std::function<void(int32_t, int32_t)> callback) {
29+
video_dimension_callback_ = callback;
30+
vlc_media_player_.eventManager().onPlaying(
31+
std::bind(&PlayerEvents::OnVideoDimensionsCallback, this));
32+
}
33+
34+
void OnPause(std::function<void()> callback) {
2935
pause_callback_ = callback;
3036
vlc_media_player_.eventManager().onPaused(
3137
std::bind(&PlayerEvents::OnPauseCallback, this));
3238
}
3339

34-
void OnStop(std::function<void(void)> callback) {
40+
void OnStop(std::function<void()> callback) {
3541
stop_callback_ = callback;
3642
vlc_media_player_.eventManager().onStopped(
3743
std::bind(&PlayerEvents::OnStopCallback, this));
@@ -49,7 +55,7 @@ class PlayerEvents : public PlayerGetters {
4955
&PlayerEvents::OnSeekableCallback, this, std::placeholders::_1));
5056
}
5157

52-
void OnComplete(std::function<void(void)> callback) {
58+
void OnComplete(std::function<void()> callback) {
5359
complete_callback_ = callback;
5460
vlc_media_player_.eventManager().onEndReached(
5561
std::bind(&PlayerEvents::OnCompleteCallback, this));
@@ -63,37 +69,18 @@ class PlayerEvents : public PlayerGetters {
6369
rate_callback_ = callback;
6470
}
6571

66-
void OnPlaylist(std::function<void(void)> callback) {
72+
void OnPlaylist(std::function<void()> callback) {
6773
playlist_callback_ = callback;
6874
}
6975

70-
void OnVideo(std::function<void(uint8_t* frame)> callback) {
76+
void OnVideo(
77+
std::function<void(uint8_t* frame, int32_t width, int32_t height)>
78+
callback) {
7179
video_callback_ = callback;
72-
int32_t pitch = video_width_ * 4;
73-
int32_t size = video_height_ * pitch;
74-
video_frame_buffer_.reset(new uint8_t[size]);
75-
vlc_media_player_.setVideoCallbacks(
76-
std::bind(&PlayerEvents::OnVideoLockCallback, this,
77-
std::placeholders::_1),
78-
nullptr, std::bind(&PlayerEvents::OnVideoPictureCallback, this,
79-
std::placeholders::_1));
80-
vlc_media_player_.setVideoFormatCallbacks(
81-
[=](char* chroma, uint32_t* w, uint32_t* h, uint32_t* p,
82-
uint32_t* l) -> int32_t {
83-
strcpy(chroma, "RGBA");
84-
*w = video_width_;
85-
*h = video_height_;
86-
*p = pitch;
87-
*l = video_height_;
88-
return 1;
89-
},
90-
nullptr);
91-
vlc_media_player_.setVideoFormat("RGBA", video_width_, video_height_,
92-
pitch);
9380
}
9481

9582
protected:
96-
std::function<void(void)> playlist_callback_ = [=]() -> void {};
83+
std::function<void()> playlist_callback_ = [=]() -> void {};
9784

9885
void OnPlaylistCallback() {
9986
if (is_playlist_modified_) {
@@ -110,10 +97,9 @@ class PlayerEvents : public PlayerGetters {
11097
};
11198
}
11299

113-
std::function<void(VLC::Media)> open_callback_ = [=](
114-
VLC::Media media) -> void {};
100+
std::function<void(VLC::Media)> open_callback_ = [=](VLC::Media) -> void {};
115101

116-
void OnOpenCallback(VLC::MediaPtr media_ptr) {
102+
void OnOpenCallback(VLC::MediaPtr vlc_media_ptr) {
117103
state()->is_playing_ = vlc_media_player_.isPlaying();
118104
state()->is_valid_ = vlc_media_player_.isValid();
119105
if (duration() > 0) {
@@ -125,11 +111,51 @@ class PlayerEvents : public PlayerGetters {
125111
state()->position_ = 0;
126112
state()->duration_ = 0;
127113
}
128-
state()->index_ = vlc_media_list_.indexOfItem(*media_ptr.get());
129-
open_callback_(*media_ptr.get());
114+
state()->index_ = vlc_media_list_.indexOfItem(*vlc_media_ptr.get());
115+
open_callback_(*vlc_media_ptr.get());
116+
}
117+
118+
std::function<void(int32_t, int32_t)> video_dimension_callback_ =
119+
[=](int32_t, int32_t) -> void {};
120+
121+
void OnVideoDimensionsCallback() {
122+
int32_t video_width = preferred_video_width_.has_value()
123+
? preferred_video_width_.value()
124+
: libvlc_video_get_width(vlc_media_player_.get());
125+
int32_t video_height =
126+
preferred_video_height_.has_value()
127+
? preferred_video_height_.value()
128+
: libvlc_video_get_height(vlc_media_player_.get());
129+
video_dimension_callback_(video_width, video_height);
130+
if (video_width_ != video_width || video_height_ != video_height) {
131+
video_width_ = video_width;
132+
video_height_ = video_height;
133+
int32_t pitch = video_width * 4;
134+
int32_t size = video_height * pitch;
135+
video_frame_buffer_.reset(new uint8_t[size]);
136+
vlc_media_player_.setVideoCallbacks(
137+
std::bind(&PlayerEvents::OnVideoLockCallback, this,
138+
std::placeholders::_1),
139+
nullptr,
140+
std::bind(&PlayerEvents::OnVideoPictureCallback, this,
141+
std::placeholders::_1));
142+
vlc_media_player_.setVideoFormatCallbacks(
143+
[=](char* chroma, uint32_t* w, uint32_t* h, uint32_t* p,
144+
uint32_t* l) -> int32_t {
145+
strcpy(chroma, "RGBA");
146+
*w = video_width;
147+
*h = video_height;
148+
*p = pitch;
149+
*l = video_height;
150+
return 1;
151+
},
152+
nullptr);
153+
vlc_media_player_.setVideoFormat("RGBA", video_width, video_height,
154+
pitch);
155+
}
130156
}
131157

132-
std::function<void(void)> play_callback_ = [=]() -> void {};
158+
std::function<void()> play_callback_ = [=]() -> void {};
133159

134160
void OnPlayCallback() {
135161
state()->is_playing_ = vlc_media_player_.isPlaying();
@@ -142,7 +168,7 @@ class PlayerEvents : public PlayerGetters {
142168
play_callback_();
143169
}
144170

145-
std::function<void(void)> pause_callback_ = [=]() -> void {};
171+
std::function<void()> pause_callback_ = [=]() -> void {};
146172

147173
void OnPauseCallback() {
148174
state()->is_playing_ = vlc_media_player_.isPlaying();
@@ -154,7 +180,7 @@ class PlayerEvents : public PlayerGetters {
154180
pause_callback_();
155181
}
156182

157-
std::function<void(void)> stop_callback_ = [=]() -> void {};
183+
std::function<void()> stop_callback_ = [=]() -> void {};
158184

159185
void OnStopCallback() {
160186
state()->is_playing_ = vlc_media_player_.isPlaying();
@@ -164,8 +190,8 @@ class PlayerEvents : public PlayerGetters {
164190
stop_callback_();
165191
}
166192

167-
std::function<void(int32_t)> position_callback_ = [=](
168-
int32_t position) -> void {};
193+
std::function<void(int32_t)> position_callback_ =
194+
[=](int32_t position) -> void {};
169195

170196
void OnPositionCallback(float relative_position) {
171197
state()->is_playing_ = vlc_media_player_.isPlaying();
@@ -178,8 +204,7 @@ class PlayerEvents : public PlayerGetters {
178204
static_cast<int32_t>(relative_position * vlc_media_player_.length()));
179205
}
180206

181-
std::function<void(bool)> seekable_callback_ = [=](bool isSeekable) -> void {
182-
};
207+
std::function<void(bool)> seekable_callback_ = [=](bool) -> void {};
183208

184209
void OnSeekableCallback(bool isSeekable) {
185210
if (duration() > 0) {
@@ -188,7 +213,7 @@ class PlayerEvents : public PlayerGetters {
188213
}
189214
}
190215

191-
std::function<void(void)> complete_callback_ = [=]() -> void {};
216+
std::function<void()> complete_callback_ = [=]() -> void {};
192217

193218
void OnCompleteCallback() {
194219
state()->is_playing_ = vlc_media_player_.isPlaying();
@@ -205,19 +230,19 @@ class PlayerEvents : public PlayerGetters {
205230
}
206231
}
207232

208-
std::function<void(float)> volume_callback_ = [=](float volume) -> void {};
233+
std::function<void(float)> volume_callback_ = [=](float) -> void {};
209234

210-
std::function<void(float)> rate_callback_ = [=](float rate) -> void {};
235+
std::function<void(float)> rate_callback_ = [=](float) -> void {};
211236

212-
std::function<void(uint8_t* frame)> video_callback_ = [=](
213-
uint8_t* frame) -> void {};
237+
std::function<void(uint8_t*, int32_t, int32_t)> video_callback_ =
238+
[=](uint8_t*, int32_t width, int32_t height) -> void {};
214239

215240
void* OnVideoLockCallback(void** planes) {
216241
planes[0] = static_cast<void*>(video_frame_buffer_.get());
217242
return nullptr;
218243
}
219244

220245
void OnVideoPictureCallback(void* picture) {
221-
video_callback_(static_cast<uint8_t*>(video_frame_buffer_.get()));
246+
video_callback_(video_frame_buffer_.get(), video_width_, video_height_);
222247
}
223248
};

dartvlc/internal/internal.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* GNU Lesser General Public License v2.1
1010
*/
1111

12+
#include <optional>
13+
1214
#include <vlcpp/vlc.hpp>
1315

1416
#include "state.hpp"
@@ -23,5 +25,7 @@ class PlayerInternal {
2325
std::unique_ptr<uint8_t> video_frame_buffer_ = nullptr;
2426
int32_t video_width_ = 0;
2527
int32_t video_height_ = 0;
28+
std::optional<int32_t> preferred_video_width_ = std::nullopt;
29+
std::optional<int32_t> preferred_video_height_ = std::nullopt;
2630
bool is_playlist_modified_ = false;
2731
};

dartvlc/internal/setters.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,11 @@ class PlayerSetters : public PlayerEvents {
197197
OnPlaylistCallback();
198198
}
199199

200-
void SetVideoWidth(int32_t video_width) { video_width_ = video_width; }
200+
void SetVideoWidth(int32_t video_width) {
201+
preferred_video_width_ = video_width;
202+
}
201203

202-
void SetVideoHeight(int32_t video_height) { video_height_ = video_height; }
204+
void SetVideoHeight(int32_t video_height) {
205+
preferred_video_height_ = video_height;
206+
}
203207
};

dartvlc/player.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
#ifndef Player_HEADER
1515
#define Player_HEADER
1616

17-
auto TO_CHARARRAY = [](std::vector<std::string>* vector) -> char** {
18-
size_t size = vector->size();
17+
auto TO_CHARARRAY = [](std::vector<std::string>& vector) -> char** {
18+
size_t size = vector.size();
1919
char** array = new char*[size];
20-
for (int32_t i = 0; i < size; i++) array[i] = (*vector)[i].data();
20+
for (int32_t i = 0; i < size; i++) array[i] = vector[i].data();
2121
return array;
2222
};
2323

@@ -27,7 +27,7 @@ class Player : public PlayerSetters {
2727
if (cmd_arguments.empty()) {
2828
vlc_instance_ = VLC::Instance(0, nullptr);
2929
} else {
30-
char** args = TO_CHARARRAY(&cmd_arguments);
30+
char** args = TO_CHARARRAY(cmd_arguments);
3131
vlc_instance_ =
3232
VLC::Instance(static_cast<int32_t>(cmd_arguments.size()), args);
3333
delete[] args;

example/lib/main.dart

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,13 @@ class DartVLCExample extends StatefulWidget {
1414
}
1515

1616
class DartVLCExampleState extends State<DartVLCExample> {
17-
Player player = Player(
18-
id: 0,
19-
videoWidth: 480,
20-
videoHeight: 360,
21-
);
17+
Player player = Player(id: 0);
2218
MediaType mediaType = MediaType.file;
2319
CurrentState current = new CurrentState();
2420
PositionState position = new PositionState();
2521
PlaybackState playback = new PlaybackState();
2622
GeneralState general = new GeneralState();
23+
VideoDimensions videoDimensions = new VideoDimensions(0, 0);
2724
List<Media> medias = <Media>[];
2825
List<Device> devices = <Device>[];
2926
TextEditingController controller = new TextEditingController();
@@ -46,6 +43,11 @@ class DartVLCExampleState extends State<DartVLCExample> {
4643
this.player.generalStream.listen((general) {
4744
this.setState(() => this.general = general);
4845
});
46+
this.player.videoDimensionsStream.listen((videoDimensions) {
47+
this.setState(() {
48+
this.videoDimensions = videoDimensions;
49+
});
50+
});
4951
}
5052
}
5153

@@ -128,8 +130,7 @@ class DartVLCExampleState extends State<DartVLCExample> {
128130
hintStyle: TextStyle(
129131
fontSize: 14.0,
130132
),
131-
hintText:
132-
'Enter Media path.',
133+
hintText: 'Enter Media path.',
133134
),
134135
),
135136
),
@@ -179,7 +180,9 @@ class DartVLCExampleState extends State<DartVLCExample> {
179180
MediaType.file) {
180181
this.medias.add(
181182
Media.file(new File(
182-
controller.text.replaceAll('"', ''))),
183+
controller.text
184+
.replaceAll(
185+
'"', ''))),
183186
);
184187
} else if (this.mediaType ==
185188
MediaType.network) {
@@ -355,6 +358,10 @@ class DartVLCExampleState extends State<DartVLCExample> {
355358
Text('player.current.medias'),
356359
Text('${this.current.medias}')
357360
]),
361+
TableRow(children: [
362+
Text('player.videoDimensions'),
363+
Text('${this.videoDimensions}')
364+
]),
358365
],
359366
),
360367
],

ffi/lib/src/internal/ffi.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,16 @@ final ReceivePort receiver = new ReceivePort()
289289
.add(players[playerId]!.general);
290290
break;
291291
}
292+
case 'videoDimensionsEvent':
293+
{
294+
players[playerId]!.videoDimensions =
295+
VideoDimensions(int.parse(event[2]), int.parse(event[3]));
296+
if (!players[playerId]!.videoDimensionsController.isClosed)
297+
players[playerId]!
298+
.videoDimensionsController
299+
.add(players[playerId]!.videoDimensions);
300+
break;
301+
}
292302
}
293303
} else {
294304
videoFrameCallback(event[0], event[1]);

0 commit comments

Comments
 (0)