sub: remove only user of demux_read_packet()

There are 3 packet reading functions in the demux API, which all
function completely differently. One of them, demux_read_packet(), has
only 1 caller, which is in dec_sub.c. Change this caller to use
demux_read_packet_async() instead. Since it really wants to do a
blocking call, setup some proper waiting. This uses mp_dispatch_queue,
because even though it's overkill, it needs the least code.

In practice, waiting actually never happens. This code is only called on
code paths where everything is already read into memory (libavformat's
subtitle demuxers simply behave this way). It's still a bit of a
"coincidence", so implement it properly anyway.

If suubtitle decoder init fails, we still need to unset the demuxer
wakeup callback. Add a sub_destroy() call to the failure path. This also
happens to fix a missed pthread_mutex_destroy() call (in practice this
was a nop, or a memory leak on BSDs).
This commit is contained in:
wm4 2019-05-17 18:52:22 +02:00
parent d9cc13f311
commit 287166b02e
3 changed files with 25 additions and 6 deletions

View File

@ -1930,7 +1930,7 @@ static struct demux_packet *dequeue_packet(struct demux_stream *ds)
// Read a packet from the given stream. The returned packet belongs to the
// caller, who has to free it with talloc_free(). Might block. Returns NULL
// on EOF.
struct demux_packet *demux_read_packet(struct sh_stream *sh)
static struct demux_packet *demux_read_packet(struct sh_stream *sh)
{
struct demux_stream *ds = sh ? sh->ds : NULL;
if (!ds)

View File

@ -238,7 +238,6 @@ bool demux_free_async_finish(struct demux_free_async_state *state);
void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp);
struct demux_packet *demux_read_packet(struct sh_stream *sh);
int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt);
bool demux_stream_is_selected(struct sh_stream *stream);
void demux_set_stream_wakeup_cb(struct sh_stream *sh,

View File

@ -31,6 +31,7 @@
#include "common/global.h"
#include "common/msg.h"
#include "common/recorder.h"
#include "misc/dispatch.h"
#include "osdep/threads.h"
extern const struct sd_functions sd_ass;
@ -69,6 +70,8 @@ struct dec_sub {
struct sd *sd;
struct demux_packet *new_segment;
struct mp_dispatch_queue *demux_waiter;
};
static void update_subtitle_speed(struct dec_sub *sub)
@ -119,12 +122,21 @@ void sub_unlock(struct dec_sub *sub)
pthread_mutex_unlock(&sub->lock);
}
static void wakeup_demux(void *ctx)
{
struct mp_dispatch_queue *q = ctx;
mp_dispatch_interrupt(q);
}
void sub_destroy(struct dec_sub *sub)
{
if (!sub)
return;
sub_reset(sub);
sub->sd->driver->uninit(sub->sd);
demux_set_stream_wakeup_cb(sub->sh, NULL, NULL);
if (sub->sd) {
sub_reset(sub);
sub->sd->driver->uninit(sub->sd);
}
talloc_free(sub->sd);
pthread_mutex_destroy(&sub->lock);
talloc_free(sub);
@ -178,17 +190,20 @@ struct dec_sub *sub_create(struct mpv_global *global, struct sh_stream *sh,
.last_vo_pts = MP_NOPTS_VALUE,
.start = MP_NOPTS_VALUE,
.end = MP_NOPTS_VALUE,
.demux_waiter = mp_dispatch_create(sub),
};
sub->opts = sub->opts_cache->opts;
mpthread_mutex_init_recursive(&sub->lock);
demux_set_stream_wakeup_cb(sub->sh, wakeup_demux, sub->demux_waiter);
sub->sd = init_decoder(sub);
if (sub->sd) {
update_subtitle_speed(sub);
return sub;
}
talloc_free(sub);
sub_destroy(sub);
return NULL;
}
@ -237,7 +252,12 @@ void sub_preload(struct dec_sub *sub)
sub->preload_attempted = true;
for (;;) {
struct demux_packet *pkt = demux_read_packet(sub->sh);
struct demux_packet *pkt = NULL;
int r = demux_read_packet_async(sub->sh, &pkt);
if (r == 0) {
mp_dispatch_queue_process(sub->demux_waiter, INFINITY);
continue;
}
if (!pkt)
break;
sub->sd->driver->decode(sub->sd, pkt);