2011-01-16 18:03:08 +00:00
|
|
|
/*
|
2015-04-13 07:36:54 +00:00
|
|
|
* This file is part of mpv.
|
2011-01-16 18:03:08 +00:00
|
|
|
*
|
2015-04-13 07:36:54 +00:00
|
|
|
* mpv is free software; you can redistribute it and/or modify
|
2011-01-16 18:03:08 +00:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
2015-04-13 07:36:54 +00:00
|
|
|
* mpv is distributed in the hope that it will be useful,
|
2011-01-16 18:03:08 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
2015-04-13 07:36:54 +00:00
|
|
|
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
2011-01-16 18:03:08 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdbool.h>
|
sub: add subtitle charset conversion
This code was once part of subreader.c, then traveled to libass, and now
made its way back to the fork of the fork of the original code, MPlayer.
It works pretty much the same as subreader.c, except that we have to
concatenate some packets to do auto-detection. This is rather annoying,
but for all we know the actual source file could be a binary format.
Unlike subreader.c, the iconv context is reopened on each packet. This
is simpler, and with respect to multibyte encodings, more robust.
Reopening is probably not a very fast, but I suspect subtitle charset
conversion is not an operation that happens often or has to be fast.
Also, this auto-detection is disabled for microdvd - this is the only
format we know that has binary data in its packets, but is actually
decoded to text. FFmpeg doesn't really allow us to solve this properly,
because a) the input packets can be binary, and b) the output will be
checked whether it's UTF-8, and if it's not, the output is thrown away
and an error message is printed. We could just recode the decoded
subtitles before sd_ass if it weren't for that.
2013-06-23 20:15:04 +00:00
|
|
|
#include <string.h>
|
2013-07-07 21:54:11 +00:00
|
|
|
#include <math.h>
|
2011-01-16 18:03:08 +00:00
|
|
|
#include <assert.h>
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
#include <pthread.h>
|
2011-01-16 18:03:08 +00:00
|
|
|
|
|
|
|
#include "config.h"
|
2013-06-11 19:39:54 +00:00
|
|
|
#include "demux/demux.h"
|
2013-06-01 17:54:18 +00:00
|
|
|
#include "sd.h"
|
|
|
|
#include "dec_sub.h"
|
2013-12-17 01:02:25 +00:00
|
|
|
#include "options/options.h"
|
2013-12-21 18:06:37 +00:00
|
|
|
#include "common/global.h"
|
2013-12-17 01:39:45 +00:00
|
|
|
#include "common/msg.h"
|
|
|
|
#include "misc/charset_conv.h"
|
2014-01-31 18:50:25 +00:00
|
|
|
#include "osdep/threads.h"
|
2011-01-16 18:03:08 +00:00
|
|
|
|
|
|
|
extern const struct sd_functions sd_ass;
|
2012-08-16 15:21:21 +00:00
|
|
|
extern const struct sd_functions sd_lavc;
|
sub: add sd_spu.c to wrap spudec, cleanup mplayer.c
This unifies the subtitle rendering path. Now all subtitle rendering
goes through sd_ass.c/sd_lavc.c/sd_spu.c.
Before that commit, the spudec.h functions were used directly in
mplayer.c, which introduced many special cases. Add sd_spu.c, which is
just a small wrapper connecting the new subtitle render API with the
dusty old vobsub decoder in spudec.c.
One detail that changes is that we always pass the palette as extra
data, instead of passing the libdvdread palette as pointer to spudec
directly. This is a bit roundabout, but actually makes the code simpler
and more elegant: the difference between DVD and non-DVD dvdsubs is
reduced.
Ideally, we would just delete spudec.c and use libavcodec's DVD sub
decoder. However, DVD playback with demux_mpg produces packets
incompatible to lavc. There are incompatibilities the other way around
as well: packets from libavformat's vobsub demuxer are incompatible to
spudec.c. So we define a new subtitle codec name for demux_mpg subs,
"dvd_subtitle_mpg", which only sd_spu can decode.
There is actually code in spudec.c to "assemble" fragments into complete
packets, but using the whole spudec.c is easier than trying to move this
code into demux_mpg to fix subtitle packets.
As additional complication, Libav 9.x can't decode DVD subs correctly,
so use sd_spu in that case as well.
2013-04-28 23:13:22 +00:00
|
|
|
|
2014-06-10 21:56:05 +00:00
|
|
|
static const struct sd_functions *const sd_list[] = {
|
2015-12-18 00:54:14 +00:00
|
|
|
&sd_lavc,
|
2013-07-16 11:28:28 +00:00
|
|
|
#if HAVE_LIBASS
|
sub: add sd_spu.c to wrap spudec, cleanup mplayer.c
This unifies the subtitle rendering path. Now all subtitle rendering
goes through sd_ass.c/sd_lavc.c/sd_spu.c.
Before that commit, the spudec.h functions were used directly in
mplayer.c, which introduced many special cases. Add sd_spu.c, which is
just a small wrapper connecting the new subtitle render API with the
dusty old vobsub decoder in spudec.c.
One detail that changes is that we always pass the palette as extra
data, instead of passing the libdvdread palette as pointer to spudec
directly. This is a bit roundabout, but actually makes the code simpler
and more elegant: the difference between DVD and non-DVD dvdsubs is
reduced.
Ideally, we would just delete spudec.c and use libavcodec's DVD sub
decoder. However, DVD playback with demux_mpg produces packets
incompatible to lavc. There are incompatibilities the other way around
as well: packets from libavformat's vobsub demuxer are incompatible to
spudec.c. So we define a new subtitle codec name for demux_mpg subs,
"dvd_subtitle_mpg", which only sd_spu can decode.
There is actually code in spudec.c to "assemble" fragments into complete
packets, but using the whole spudec.c is easier than trying to move this
code into demux_mpg to fix subtitle packets.
As additional complication, Libav 9.x can't decode DVD subs correctly,
so use sd_spu in that case as well.
2013-04-28 23:13:22 +00:00
|
|
|
&sd_ass,
|
|
|
|
#endif
|
|
|
|
NULL
|
|
|
|
};
|
2011-01-16 18:03:08 +00:00
|
|
|
|
2013-06-01 17:44:12 +00:00
|
|
|
struct dec_sub {
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_t lock;
|
|
|
|
|
2013-12-21 18:06:37 +00:00
|
|
|
struct mp_log *log;
|
2013-06-01 17:44:12 +00:00
|
|
|
struct MPOpts *opts;
|
|
|
|
struct sd init_sd;
|
|
|
|
|
2015-12-16 22:54:25 +00:00
|
|
|
struct sh_stream *sh;
|
2013-06-11 19:39:54 +00:00
|
|
|
|
2015-12-18 00:54:14 +00:00
|
|
|
struct sd *sd;
|
2013-06-01 17:44:12 +00:00
|
|
|
};
|
|
|
|
|
2013-06-11 19:39:54 +00:00
|
|
|
struct packet_list {
|
|
|
|
struct demux_packet **packets;
|
|
|
|
int num_packets;
|
|
|
|
};
|
|
|
|
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
|
|
|
|
void sub_lock(struct dec_sub *sub)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&sub->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void sub_unlock(struct dec_sub *sub)
|
|
|
|
{
|
|
|
|
pthread_mutex_unlock(&sub->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Thread-safety of the returned object: all functions are thread-safe,
|
|
|
|
// except sub_get_bitmaps() and sub_get_text(). Decoder backends (sd_*)
|
|
|
|
// do not need to acquire locks.
|
2013-12-21 18:06:37 +00:00
|
|
|
struct dec_sub *sub_create(struct mpv_global *global)
|
2013-06-01 17:44:12 +00:00
|
|
|
{
|
|
|
|
struct dec_sub *sub = talloc_zero(NULL, struct dec_sub);
|
2013-12-21 18:06:37 +00:00
|
|
|
sub->log = mp_log_new(sub, global->log, "sub");
|
|
|
|
sub->opts = global->opts;
|
2015-12-18 00:54:14 +00:00
|
|
|
sub->init_sd.opts = sub->opts;
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
|
2014-01-31 18:50:25 +00:00
|
|
|
mpthread_mutex_init_recursive(&sub->lock);
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
|
2013-06-01 17:44:12 +00:00
|
|
|
return sub;
|
|
|
|
}
|
|
|
|
|
2013-06-01 17:44:55 +00:00
|
|
|
static void sub_uninit(struct dec_sub *sub)
|
|
|
|
{
|
|
|
|
sub_reset(sub);
|
2015-12-18 00:54:14 +00:00
|
|
|
if (sub->sd)
|
|
|
|
sub->sd->driver->uninit(sub->sd);
|
|
|
|
talloc_free(sub->sd);
|
|
|
|
sub->sd = NULL;
|
2013-06-01 17:44:55 +00:00
|
|
|
}
|
|
|
|
|
2013-06-01 17:44:12 +00:00
|
|
|
void sub_destroy(struct dec_sub *sub)
|
|
|
|
{
|
|
|
|
if (!sub)
|
|
|
|
return;
|
2013-06-01 17:44:55 +00:00
|
|
|
sub_uninit(sub);
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_destroy(&sub->lock);
|
2013-06-01 17:44:12 +00:00
|
|
|
talloc_free(sub);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool sub_is_initialized(struct dec_sub *sub)
|
|
|
|
{
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_lock(&sub->lock);
|
2015-12-18 00:54:14 +00:00
|
|
|
bool r = !!sub->sd;
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
|
|
|
return r;
|
2013-06-01 17:44:12 +00:00
|
|
|
}
|
|
|
|
|
2013-06-11 19:39:54 +00:00
|
|
|
void sub_set_video_fps(struct dec_sub *sub, double fps)
|
|
|
|
{
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_lock(&sub->lock);
|
2015-12-05 22:56:28 +00:00
|
|
|
sub->init_sd.video_fps = fps;
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2013-06-11 19:39:54 +00:00
|
|
|
}
|
|
|
|
|
2013-06-01 17:44:12 +00:00
|
|
|
void sub_set_ass_renderer(struct dec_sub *sub, struct ass_library *ass_library,
|
2015-07-06 19:55:37 +00:00
|
|
|
struct ass_renderer *ass_renderer,
|
|
|
|
pthread_mutex_t *ass_lock)
|
2013-06-01 17:44:12 +00:00
|
|
|
{
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_lock(&sub->lock);
|
2013-06-01 17:44:12 +00:00
|
|
|
sub->init_sd.ass_library = ass_library;
|
|
|
|
sub->init_sd.ass_renderer = ass_renderer;
|
2015-07-06 19:55:37 +00:00
|
|
|
sub->init_sd.ass_lock = ass_lock;
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2013-06-01 17:44:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int sub_init_decoder(struct dec_sub *sub, struct sd *sd)
|
2011-01-16 18:03:08 +00:00
|
|
|
{
|
2013-06-01 17:44:12 +00:00
|
|
|
sd->driver = NULL;
|
sub: add sd_spu.c to wrap spudec, cleanup mplayer.c
This unifies the subtitle rendering path. Now all subtitle rendering
goes through sd_ass.c/sd_lavc.c/sd_spu.c.
Before that commit, the spudec.h functions were used directly in
mplayer.c, which introduced many special cases. Add sd_spu.c, which is
just a small wrapper connecting the new subtitle render API with the
dusty old vobsub decoder in spudec.c.
One detail that changes is that we always pass the palette as extra
data, instead of passing the libdvdread palette as pointer to spudec
directly. This is a bit roundabout, but actually makes the code simpler
and more elegant: the difference between DVD and non-DVD dvdsubs is
reduced.
Ideally, we would just delete spudec.c and use libavcodec's DVD sub
decoder. However, DVD playback with demux_mpg produces packets
incompatible to lavc. There are incompatibilities the other way around
as well: packets from libavformat's vobsub demuxer are incompatible to
spudec.c. So we define a new subtitle codec name for demux_mpg subs,
"dvd_subtitle_mpg", which only sd_spu can decode.
There is actually code in spudec.c to "assemble" fragments into complete
packets, but using the whole spudec.c is easier than trying to move this
code into demux_mpg to fix subtitle packets.
As additional complication, Libav 9.x can't decode DVD subs correctly,
so use sd_spu in that case as well.
2013-04-28 23:13:22 +00:00
|
|
|
for (int n = 0; sd_list[n]; n++) {
|
2015-12-18 00:54:14 +00:00
|
|
|
if (sd->sh->codec && sd_list[n]->supports_format(sd->sh->codec)) {
|
2013-06-01 17:44:12 +00:00
|
|
|
sd->driver = sd_list[n];
|
sub: add sd_spu.c to wrap spudec, cleanup mplayer.c
This unifies the subtitle rendering path. Now all subtitle rendering
goes through sd_ass.c/sd_lavc.c/sd_spu.c.
Before that commit, the spudec.h functions were used directly in
mplayer.c, which introduced many special cases. Add sd_spu.c, which is
just a small wrapper connecting the new subtitle render API with the
dusty old vobsub decoder in spudec.c.
One detail that changes is that we always pass the palette as extra
data, instead of passing the libdvdread palette as pointer to spudec
directly. This is a bit roundabout, but actually makes the code simpler
and more elegant: the difference between DVD and non-DVD dvdsubs is
reduced.
Ideally, we would just delete spudec.c and use libavcodec's DVD sub
decoder. However, DVD playback with demux_mpg produces packets
incompatible to lavc. There are incompatibilities the other way around
as well: packets from libavformat's vobsub demuxer are incompatible to
spudec.c. So we define a new subtitle codec name for demux_mpg subs,
"dvd_subtitle_mpg", which only sd_spu can decode.
There is actually code in spudec.c to "assemble" fragments into complete
packets, but using the whole spudec.c is easier than trying to move this
code into demux_mpg to fix subtitle packets.
As additional complication, Libav 9.x can't decode DVD subs correctly,
so use sd_spu in that case as well.
2013-04-28 23:13:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-01-16 18:03:08 +00:00
|
|
|
|
2013-06-01 17:44:12 +00:00
|
|
|
if (!sd->driver)
|
|
|
|
return -1;
|
|
|
|
|
2013-12-21 18:06:37 +00:00
|
|
|
sd->log = mp_log_new(sd, sub->log, sd->driver->name);
|
2013-06-01 17:44:12 +00:00
|
|
|
if (sd->driver->init(sd) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-23 20:37:15 +00:00
|
|
|
void sub_init_from_sh(struct dec_sub *sub, struct sh_stream *sh)
|
2013-06-01 17:44:12 +00:00
|
|
|
{
|
2015-12-18 00:54:14 +00:00
|
|
|
assert(!sub->sd);
|
2013-11-23 20:37:15 +00:00
|
|
|
assert(sh && sh->sub);
|
2013-06-01 17:44:55 +00:00
|
|
|
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_lock(&sub->lock);
|
|
|
|
|
2015-12-16 22:54:25 +00:00
|
|
|
sub->sh = sh;
|
|
|
|
|
2013-06-01 17:44:55 +00:00
|
|
|
struct sd init_sd = sub->init_sd;
|
2015-12-05 22:56:28 +00:00
|
|
|
init_sd.sh = sh;
|
2013-06-01 17:44:55 +00:00
|
|
|
|
2015-12-18 00:54:14 +00:00
|
|
|
struct sd *sd = talloc(NULL, struct sd);
|
|
|
|
*sd = init_sd;
|
2013-06-01 17:44:55 +00:00
|
|
|
|
2015-12-18 00:54:14 +00:00
|
|
|
if (sub_init_decoder(sub, sd) < 0) {
|
2015-12-22 01:16:14 +00:00
|
|
|
if (sd->driver && sd->driver->uninit)
|
|
|
|
sd->driver->uninit(sd);
|
2015-12-18 00:54:14 +00:00
|
|
|
talloc_free(sd);
|
|
|
|
MP_ERR(sub, "Could not find subtitle decoder for format '%s'.\n",
|
|
|
|
sh->codec ? sh->codec : "<unknown>");
|
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2013-06-23 22:47:08 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-12-18 00:54:14 +00:00
|
|
|
|
|
|
|
sub->sd = sd;
|
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2013-06-23 22:47:08 +00:00
|
|
|
}
|
|
|
|
|
2013-12-21 18:06:37 +00:00
|
|
|
static struct demux_packet *recode_packet(struct mp_log *log,
|
|
|
|
struct demux_packet *in,
|
2013-06-23 22:47:08 +00:00
|
|
|
const char *charset)
|
|
|
|
{
|
|
|
|
struct demux_packet *pkt = NULL;
|
|
|
|
bstr in_buf = {in->buffer, in->len};
|
2013-12-21 19:37:16 +00:00
|
|
|
bstr conv = mp_iconv_to_utf8(log, in_buf, charset, MP_ICONV_VERBOSE);
|
2013-06-23 22:47:08 +00:00
|
|
|
if (conv.start && conv.start != in_buf.start) {
|
|
|
|
pkt = talloc_ptrtype(NULL, pkt);
|
|
|
|
talloc_steal(pkt, conv.start);
|
|
|
|
*pkt = (struct demux_packet) {
|
|
|
|
.buffer = conv.start,
|
|
|
|
.len = conv.len,
|
|
|
|
.pts = in->pts,
|
sub: do not clear subtitle list on seeking
This affects non-ASS text subtitles (those which go through libavcodec's
subtitle converter), which are muxed with video/audio. (Typically srt
subs in mkv.)
The problem is that seeking in the file can send a subtitle packet to
the decoder multiple times. These packets are interlaved with video,
and thus can't be all read when opening the file. Rather, subtitle
packets can essentially be randomly skipped or repeated (by seeking).
Until recently, this was solved by scanning the libass event list for
duplicates. Then our builtin srt-to-ass converter was removed, and
the problem was handled by fully clearing the subtitle list on each
seek.
This resulted in sub-seek not working properly for this type of file.
Since the subtitle list was cleared on seek, it was not possible to
do e.g. sub-seeks to subtitles before the current playback position.
Fix this by not clearing the list, and intead explicitly rejecting
duplicate packets. We use the packet file position was unique ID for
subtitles; this is confirmed working for most file formats (although
it is slightly risky - new demuxers may not necessarily set the file
position to something unique, or at all).
The list of seen packets is sorted, and the lookup uses binary search.
This is to avoid quadratic complexity when subtitles are added in
bulks, such as when opening a text subtitle file.
In some places, the code has to be adjusted to pass through the packet
file position correctly.
2015-12-17 23:51:57 +00:00
|
|
|
.pos = in->pos,
|
2013-06-23 22:47:08 +00:00
|
|
|
.duration = in->duration,
|
|
|
|
.avpacket = in->avpacket, // questionable, but gives us sidedata
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return pkt;
|
|
|
|
}
|
|
|
|
|
2015-12-06 17:17:14 +00:00
|
|
|
static void decode_chain_recode(struct dec_sub *sub, struct demux_packet *packet)
|
2013-06-23 22:47:08 +00:00
|
|
|
{
|
2015-12-18 00:54:14 +00:00
|
|
|
if (sub->sd) {
|
2013-06-23 22:47:08 +00:00
|
|
|
struct demux_packet *recoded = NULL;
|
2015-12-16 22:54:25 +00:00
|
|
|
if (sub->sh && sub->sh->sub->charset)
|
|
|
|
recoded = recode_packet(sub->log, packet, sub->sh->sub->charset);
|
2015-12-18 00:54:14 +00:00
|
|
|
sub->sd->driver->decode(sub->sd, recoded ? recoded : packet);
|
2013-06-28 12:22:53 +00:00
|
|
|
talloc_free(recoded);
|
2013-06-23 22:47:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-23 23:04:17 +00:00
|
|
|
void sub_decode(struct dec_sub *sub, struct demux_packet *packet)
|
|
|
|
{
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_lock(&sub->lock);
|
2015-12-06 17:17:14 +00:00
|
|
|
decode_chain_recode(sub, packet);
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2013-06-23 23:04:17 +00:00
|
|
|
}
|
|
|
|
|
2015-12-05 22:56:53 +00:00
|
|
|
static void add_sub_list(struct dec_sub *sub, struct packet_list *subs)
|
2013-06-11 19:39:54 +00:00
|
|
|
{
|
|
|
|
for (int n = 0; n < subs->num_packets; n++)
|
2015-12-06 17:17:14 +00:00
|
|
|
decode_chain_recode(sub, subs->packets[n]);
|
2013-06-11 19:39:54 +00:00
|
|
|
}
|
|
|
|
|
2013-06-23 23:04:17 +00:00
|
|
|
static void add_packet(struct packet_list *subs, struct demux_packet *pkt)
|
|
|
|
{
|
|
|
|
pkt = demux_copy_packet(pkt);
|
2014-09-16 16:11:00 +00:00
|
|
|
if (pkt) {
|
|
|
|
talloc_steal(subs, pkt);
|
|
|
|
MP_TARRAY_APPEND(subs, subs->packets, subs->num_packets, pkt);
|
|
|
|
}
|
2013-06-23 23:04:17 +00:00
|
|
|
}
|
|
|
|
|
2013-06-11 19:39:54 +00:00
|
|
|
// Read all packets from the demuxer and decode/add them. Returns false if
|
|
|
|
// there are circumstances which makes this not possible.
|
2013-11-23 20:37:15 +00:00
|
|
|
bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh)
|
2013-06-11 19:39:54 +00:00
|
|
|
{
|
2013-11-23 20:37:15 +00:00
|
|
|
assert(sh && sh->sub);
|
2013-06-11 19:41:50 +00:00
|
|
|
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_lock(&sub->lock);
|
|
|
|
|
2015-12-05 22:54:00 +00:00
|
|
|
// Converters are assumed to always accept packets in advance
|
2015-12-18 00:54:14 +00:00
|
|
|
if (!(sub->sd && sub->sd->driver->accept_packets_in_advance)) {
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2013-06-11 19:39:54 +00:00
|
|
|
return false;
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
}
|
2013-06-11 19:39:54 +00:00
|
|
|
|
2013-06-23 22:58:10 +00:00
|
|
|
struct packet_list *subs = talloc_zero(NULL, struct packet_list);
|
2013-06-11 19:39:54 +00:00
|
|
|
|
|
|
|
for (;;) {
|
2013-11-23 20:37:15 +00:00
|
|
|
struct demux_packet *pkt = demux_read_packet(sh);
|
2013-06-11 19:39:54 +00:00
|
|
|
if (!pkt)
|
|
|
|
break;
|
2015-12-05 22:56:53 +00:00
|
|
|
add_packet(subs, pkt);
|
|
|
|
talloc_free(pkt);
|
2013-06-11 19:39:54 +00:00
|
|
|
}
|
|
|
|
|
2015-12-05 22:56:53 +00:00
|
|
|
add_sub_list(sub, subs);
|
2013-06-11 19:39:54 +00:00
|
|
|
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2013-06-23 22:58:10 +00:00
|
|
|
talloc_free(subs);
|
2013-06-11 19:39:54 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-12-05 22:54:00 +00:00
|
|
|
bool sub_accepts_packet_in_advance(struct dec_sub *sub)
|
2013-04-28 19:12:11 +00:00
|
|
|
{
|
2015-12-05 22:54:00 +00:00
|
|
|
bool res = true;
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_lock(&sub->lock);
|
2015-12-18 00:54:14 +00:00
|
|
|
if (sub->sd && sub->sd->driver->accepts_packet)
|
|
|
|
res &= sub->sd->driver->accepts_packet(sub->sd);
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2015-12-05 22:54:00 +00:00
|
|
|
return res;
|
2013-06-01 17:44:55 +00:00
|
|
|
}
|
|
|
|
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
// You must call sub_lock/sub_unlock if more than 1 thread access sub.
|
|
|
|
// The issue is that *res will contain decoder allocated data, which might
|
|
|
|
// be deallocated on the next decoder access.
|
2013-06-01 17:44:12 +00:00
|
|
|
void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, double pts,
|
2012-10-04 15:16:36 +00:00
|
|
|
struct sub_bitmaps *res)
|
2012-08-25 18:22:39 +00:00
|
|
|
{
|
2013-06-01 17:44:12 +00:00
|
|
|
struct MPOpts *opts = sub->opts;
|
2012-08-25 18:22:39 +00:00
|
|
|
|
2012-10-04 15:16:36 +00:00
|
|
|
*res = (struct sub_bitmaps) {0};
|
2015-12-18 00:54:14 +00:00
|
|
|
if (sub->sd && opts->sub_visibility && sub->sd->driver->get_bitmaps)
|
|
|
|
sub->sd->driver->get_bitmaps(sub->sd, dim, pts, res);
|
2013-04-28 19:12:11 +00:00
|
|
|
}
|
|
|
|
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
// See sub_get_bitmaps() for locking requirements.
|
2014-09-05 22:16:15 +00:00
|
|
|
// It can be called unlocked too, but then only 1 thread must call this function
|
|
|
|
// at a time (unless exclusive access is guaranteed).
|
2013-06-01 17:44:12 +00:00
|
|
|
char *sub_get_text(struct dec_sub *sub, double pts)
|
2011-01-16 18:03:08 +00:00
|
|
|
{
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_lock(&sub->lock);
|
2013-06-01 17:44:12 +00:00
|
|
|
struct MPOpts *opts = sub->opts;
|
|
|
|
char *text = NULL;
|
2015-12-18 00:54:14 +00:00
|
|
|
if (sub->sd && opts->sub_visibility && sub->sd->driver->get_text)
|
|
|
|
text = sub->sd->driver->get_text(sub->sd, pts);
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2013-06-01 17:44:12 +00:00
|
|
|
return text;
|
2011-01-16 18:03:08 +00:00
|
|
|
}
|
|
|
|
|
2013-06-01 17:44:12 +00:00
|
|
|
void sub_reset(struct dec_sub *sub)
|
2011-01-16 18:03:08 +00:00
|
|
|
{
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_lock(&sub->lock);
|
2015-12-18 00:54:14 +00:00
|
|
|
if (sub->sd && sub->sd->driver->reset)
|
|
|
|
sub->sd->driver->reset(sub->sd);
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
2013-06-01 17:44:55 +00:00
|
|
|
}
|
|
|
|
|
2013-06-28 23:34:11 +00:00
|
|
|
int sub_control(struct dec_sub *sub, enum sd_ctrl cmd, void *arg)
|
|
|
|
{
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
int r = CONTROL_UNKNOWN;
|
|
|
|
pthread_mutex_lock(&sub->lock);
|
2015-12-18 00:54:14 +00:00
|
|
|
if (sub->sd && sub->sd->driver->control)
|
|
|
|
r = sub->sd->driver->control(sub->sd, cmd, arg);
|
sub: uglify sub decoder with locking
The plan is to make the whole OSD thread-safe, and we start with this.
We just put locks on all entry points (fortunately, dec_sub.c and all
sd_*.c decoders are very closed off, and only the entry points in
dec_sub.h let you access it). I think this is pretty ugly, but at least
it's very simple.
There's a special case with sub_get_bitmaps(): this function returns
pointers to decoder data (specifically, libass images). There's no way
to synchronize this internally, so expose sub_lock/sub_unlock functions.
To make things simpler, and especially because the lock is sort-of
exposed to the outside world, make the locks recursive. Although the
only case where this is actually needed (although trivial) is
sub_set_extradata().
One corner case are ASS subtitles: for some reason, we keep a single
ASS_Renderer instance for subtitles around (probably to avoid rescanning
fonts with ordered chapters), and this ASS_Renderer instance is not
synchronized. Also, demux_libass.c loads ASS_Track objects, which are
directly passed to sd_ass.c. These things are not synchronized (and
would be hard to synchronize), and basically we're out of luck. But I
think for now, accesses happen reasonably serialized, so there is no
actual problem yet, even if we start to access OSD from other threads.
2014-01-17 22:13:09 +00:00
|
|
|
pthread_mutex_unlock(&sub->lock);
|
|
|
|
return r;
|
2013-06-28 23:34:11 +00:00
|
|
|
}
|