Skip to content

Commit 4052926

Browse files
committed
Add seek
1 parent 52a3217 commit 4052926

File tree

3 files changed

+85
-20
lines changed

3 files changed

+85
-20
lines changed

thirdparty/pl_mpeg.h

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,15 @@ typedef void(*plm_audio_decode_callback)
247247
typedef void(*plm_buffer_load_callback)(plm_buffer_t *self, void *user);
248248

249249

250+
// Callback function for plm_buffer when it needs to seek
251+
252+
typedef void(*plm_buffer_seek_callback)(plm_buffer_t *self, size_t offset, void *user);
253+
254+
255+
// Callback function for plm_buffer when it needs to tell the position
256+
257+
typedef size_t(*plm_buffer_tell_callback)(plm_buffer_t *self, void *user);
258+
250259

251260
// -----------------------------------------------------------------------------
252261
// plm_* public API
@@ -477,6 +486,20 @@ plm_buffer_t *plm_buffer_create_with_filename(const char *filename);
477486
plm_buffer_t *plm_buffer_create_with_file(FILE *fh, int close_when_done);
478487

479488

489+
// Create a buffer instance with custom callbacks for loading, seeking and
490+
// telling the position. This behaves like a file handle, but with user-defined
491+
// callbacks, useful for file handles that don't use the standard FILE API.
492+
// Setting the length and closing/freeing has to be done manually.
493+
494+
plm_buffer_t *plm_buffer_create_with_callbacks(
495+
plm_buffer_load_callback load_callback,
496+
plm_buffer_seek_callback seek_callback,
497+
plm_buffer_tell_callback tell_callback,
498+
size_t length,
499+
void *user
500+
);
501+
502+
480503
// Create a buffer instance with a pointer to memory as source. This assumes
481504
// the whole file is in memory. The bytes are not copied. Pass 1 to
482505
// free_when_done to let plmpeg call free() on the pointer when plm_destroy()
@@ -1357,6 +1380,8 @@ struct plm_buffer_t {
13571380
int close_when_done;
13581381
FILE *fh;
13591382
plm_buffer_load_callback load_callback;
1383+
plm_buffer_seek_callback seek_callback;
1384+
plm_buffer_tell_callback tell_callback;
13601385
void *load_callback_user_data;
13611386
uint8_t *bytes;
13621387
enum plm_buffer_mode mode;
@@ -1377,6 +1402,8 @@ void plm_buffer_seek(plm_buffer_t *self, size_t pos);
13771402
size_t plm_buffer_tell(plm_buffer_t *self);
13781403
void plm_buffer_discard_read_bytes(plm_buffer_t *self);
13791404
void plm_buffer_load_file_callback(plm_buffer_t *self, void *user);
1405+
void plm_buffer_seek_file_callback(plm_buffer_t *self, size_t offset, void *user);
1406+
size_t plm_buffer_tell_file_callback(plm_buffer_t *self, void *user);
13801407

13811408
int plm_buffer_has(plm_buffer_t *self, size_t count);
13821409
int plm_buffer_read(plm_buffer_t *self, int count);
@@ -1408,7 +1435,26 @@ plm_buffer_t *plm_buffer_create_with_file(FILE *fh, int close_when_done) {
14081435
self->total_size = ftell(self->fh);
14091436
fseek(self->fh, 0, SEEK_SET);
14101437

1411-
plm_buffer_set_load_callback(self, plm_buffer_load_file_callback, NULL);
1438+
self->load_callback = plm_buffer_load_file_callback;
1439+
self->seek_callback = plm_buffer_seek_file_callback;
1440+
self->tell_callback = plm_buffer_tell_file_callback;
1441+
return self;
1442+
}
1443+
1444+
plm_buffer_t *plm_buffer_create_with_callbacks(
1445+
plm_buffer_load_callback load_callback,
1446+
plm_buffer_seek_callback seek_callback,
1447+
plm_buffer_tell_callback tell_callback,
1448+
size_t length,
1449+
void *user
1450+
) {
1451+
plm_buffer_t *self = plm_buffer_create_with_capacity(PLM_BUFFER_DEFAULT_SIZE);
1452+
self->mode = PLM_BUFFER_MODE_FILE;
1453+
self->total_size = length;
1454+
self->load_callback = load_callback;
1455+
self->seek_callback = seek_callback;
1456+
self->tell_callback = tell_callback;
1457+
self->load_callback_user_data = user;
14121458
return self;
14131459
}
14141460

@@ -1512,8 +1558,8 @@ void plm_buffer_rewind(plm_buffer_t *self) {
15121558
void plm_buffer_seek(plm_buffer_t *self, size_t pos) {
15131559
self->has_ended = FALSE;
15141560

1515-
if (self->mode == PLM_BUFFER_MODE_FILE) {
1516-
fseek(self->fh, pos, SEEK_SET);
1561+
if (self->seek_callback) {
1562+
self->seek_callback(self, pos, self->load_callback_user_data);
15171563
self->bit_index = 0;
15181564
self->length = 0;
15191565
}
@@ -1532,8 +1578,8 @@ void plm_buffer_seek(plm_buffer_t *self, size_t pos) {
15321578
}
15331579

15341580
size_t plm_buffer_tell(plm_buffer_t *self) {
1535-
return self->mode == PLM_BUFFER_MODE_FILE
1536-
? ftell(self->fh) + (self->bit_index >> 3) - self->length
1581+
return self->tell_callback
1582+
? self->tell_callback(self, self->load_callback_user_data) + (self->bit_index >> 3) - self->length
15371583
: self->bit_index >> 3;
15381584
}
15391585

@@ -1566,6 +1612,16 @@ void plm_buffer_load_file_callback(plm_buffer_t *self, void *user) {
15661612
}
15671613
}
15681614

1615+
void plm_buffer_seek_file_callback(plm_buffer_t *self, size_t offset, void *user) {
1616+
PLM_UNUSED(user);
1617+
fseek(self->fh, offset, SEEK_SET);
1618+
}
1619+
1620+
size_t plm_buffer_tell_file_callback(plm_buffer_t *self, void *user) {
1621+
PLM_UNUSED(user);
1622+
return ftell(self->fh);
1623+
}
1624+
15691625
int plm_buffer_has_ended(plm_buffer_t *self) {
15701626
return self->has_ended;
15711627
}

video_stream_mpg.cpp

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@
1111

1212
#include "thirdparty/misc/yuv2rgb.h"
1313

14-
void VideoStreamPlaybackMPG::dummy_yuv2rgb() {
15-
// MPEG-1 only supports 4:2:0, these are here to prevent werror from yelling
16-
yuv444_2_rgb8888(nullptr, nullptr, nullptr, nullptr, 0, 0, 0, 0, 0);
17-
yuv422_2_rgb8888(nullptr, nullptr, nullptr, nullptr, 0, 0, 0, 0, 0);
18-
}
19-
2014
void VideoStreamPlaybackMPG::load_callback(plm_buffer_t *buf, void *user) {
2115
Ref<FileAccess> fa = *(Ref<FileAccess> *)user;
2216

@@ -31,6 +25,16 @@ void VideoStreamPlaybackMPG::load_callback(plm_buffer_t *buf, void *user) {
3125
}
3226
}
3327

28+
void VideoStreamPlaybackMPG::seek_callback(plm_buffer_t *buf, size_t pos, void *user) {
29+
Ref<FileAccess> fa = *(Ref<FileAccess> *)user;
30+
fa->seek(pos);
31+
}
32+
33+
size_t VideoStreamPlaybackMPG::tell_callback(plm_buffer_t *buf, void *user) {
34+
Ref<FileAccess> fa = *(Ref<FileAccess> *)user;
35+
return fa->get_position();
36+
}
37+
3438
void VideoStreamPlaybackMPG::video_callback(plm_t *self, plm_frame_t *frame, void *user) {
3539
VideoStreamPlaybackMPG *ps = (VideoStreamPlaybackMPG *)user;
3640
ps->frame_current = frame;
@@ -51,8 +55,7 @@ void VideoStreamPlaybackMPG::set_file(const String &p_file) {
5155
file = FileAccess::open(p_file, FileAccess::READ);
5256
ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file: " + p_file);
5357

54-
plm_buffer_t *buffer = plm_buffer_create_with_capacity(PLM_BUFFER_DEFAULT_SIZE);
55-
plm_buffer_set_load_callback(buffer, load_callback, &file);
58+
plm_buffer_t *buffer = plm_buffer_create_with_callbacks(load_callback, seek_callback, tell_callback, file->get_length(), &file);
5659
mpeg = plm_create_with_buffer(buffer, TRUE);
5760

5861
plm_set_video_decode_callback(mpeg, video_callback, this);
@@ -119,11 +122,7 @@ double VideoStreamPlaybackMPG::get_playback_position() const {
119122

120123
void VideoStreamPlaybackMPG::seek(double p_time) {
121124
if (mpeg != nullptr) {
122-
if (p_time != 0.0) {
123-
WARN_PRINT_ONCE("VideoStreamMPG only supports seeking to 0.0.");
124-
}
125-
file->seek(0);
126-
plm_rewind(mpeg);
125+
seek_pos = p_time;
127126
}
128127
}
129128

@@ -141,7 +140,12 @@ void VideoStreamPlaybackMPG::update(double p_delta) {
141140
return;
142141
}
143142

144-
plm_decode(mpeg, p_delta);
143+
if (seek_pos != -1.0) {
144+
plm_seek(mpeg, seek_pos, FALSE);
145+
seek_pos = -1.0;
146+
} else {
147+
plm_decode(mpeg, p_delta);
148+
}
145149

146150
if (frame_pending) {
147151
int x = frame_current->width;
@@ -171,6 +175,8 @@ void VideoStreamPlaybackMPG::set_audio_track(int p_track) {
171175

172176
VideoStreamPlaybackMPG::VideoStreamPlaybackMPG() {
173177
texture.instantiate();
178+
PLM_UNUSED(yuv444_2_rgb8888);
179+
PLM_UNUSED(yuv422_2_rgb8888);
174180
}
175181

176182
VideoStreamPlaybackMPG::~VideoStreamPlaybackMPG() {

video_stream_mpg.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@ class VideoStreamPlaybackMPG : public VideoStreamPlayback {
1515
plm_t *mpeg = nullptr;
1616

1717
Ref<FileAccess> file;
18+
LocalVector<uint8_t> file_buffer;
1819
String file_name;
1920
Ref<ImageTexture> texture;
2021
Vector<uint8_t> frame_data; // Image creation has a big overhead converting from LocalVector
2122

2223
plm_frame_t *frame_current = nullptr;
2324
bool frame_pending = false;
25+
double seek_pos = -1.0;
2426

25-
static void dummy_yuv2rgb();
2627
static void load_callback(plm_buffer_t *buf, void *user);
28+
static void seek_callback(plm_buffer_t *buf, size_t pos, void *user);
29+
static size_t tell_callback(plm_buffer_t *buf, void *user);
2730
static void video_callback(plm_t *self, plm_frame_t *frame, void *user);
2831
static void audio_callback(plm_t *self, plm_samples_t *samples, void *user);
2932

0 commit comments

Comments
 (0)