summaryrefslogtreecommitdiffstats
path: root/libmpdemux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-08-30 16:43:31 +0200
committerwm4 <wm4@nowhere>2012-09-18 21:04:45 +0200
commitd21b109bf7d3f36c13298d794c856eff834946c3 (patch)
tree86e8bfcdcc61aa75af10402e6b921bc5ad21224a /libmpdemux
parentfbc424ef35d4c76235feb3aa8295bcb8a3ce9443 (diff)
downloadmpv-d21b109bf7d3f36c13298d794c856eff834946c3.tar.bz2
mpv-d21b109bf7d3f36c13298d794c856eff834946c3.tar.xz
core: fix DVD subtitle selection
Add all subtitle tracks as reported by libdvdread at playback start. Display language for subtitle and audio tracks. This commit restores these features to the state when demux_mpg was default for DVD playback, and makes them work with demux_lavf and the recent changes to subtitle selection in the frontend. demux_mpg, which was the default demuxer for DVD playback, reordered the subtitle streams according to the "logical" subtitle track number, which conforms to the track layout reported by libdvdread, and is what stream_dvd expects for the STREAM_CTRL_GET_LANG call. demux_lavf, on the other hand, adds the streams in the order it encounters them in the MPEG stream. It seems this order is essentially random, and can't be mapped easily to what stream_dvd expects. Solve this by making demux_lavf hand out the MPEG stream IDs (using the demuxer_id field). The MPEG IDs are mapped by mplayer.c by special casing DVD playback (map_id_from/to_demuxer() functions). This mapping is essentially the same what demux_mpg did. Making demux_lavf reorder the streams is out of the question, because its stream handling is already messy enough. (Note that demux_lavf doesn't export stream IDs for other formats, because most time libavformat demuxers do not set AVStream.id, and we don't know which demuxers do. But we know that MPEG is safe.) Another major complication is that subtitle tracks are added lazily, as soon as the demuxer encounters the first subtitle packet for a given subtitle stream. Add the streams in advance. If a yet non-existent stream is selected, demux_lavf must be made to auto-select that subtitle stream as soon as it is added. Otherwise, the first subtitle packet would be lost. This is done by DEMUXER_CTRL_PRESELECT_SUBTITLE. demux_mpg didn't need this: the frontend code could just set ds->id to the desired stream number. But demux_lavf's stream IDs don't map directly to the stream number as used by libdvdread, which is why this hack is needed.
Diffstat (limited to 'libmpdemux')
-rw-r--r--libmpdemux/demux_lavf.c25
-rw-r--r--libmpdemux/demuxer.c13
-rw-r--r--libmpdemux/demuxer.h3
3 files changed, 26 insertions, 15 deletions
diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c
index 4dd9938d07..69cb0f02fc 100644
--- a/libmpdemux/demux_lavf.c
+++ b/libmpdemux/demux_lavf.c
@@ -24,6 +24,7 @@
#include <limits.h>
#include <stdbool.h>
#include <string.h>
+#include <assert.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
@@ -70,6 +71,7 @@ typedef struct lavf_priv {
int audio_streams;
int video_streams;
int sub_streams;
+ int autoselect_sub;
int64_t last_pts;
int astreams[MAX_A_STREAMS];
int vstreams[MAX_V_STREAMS];
@@ -164,6 +166,7 @@ static int lavf_check_file(demuxer_t *demuxer)
if (!demuxer->priv)
demuxer->priv = calloc(sizeof(lavf_priv_t), 1);
priv = demuxer->priv;
+ priv->autoselect_sub = -1;
char *format = lavfdopts->format;
if (!format)
@@ -302,6 +305,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
AVCodec *avc = avcodec_find_decoder(codec->codec_id);
const char *codec_name = avc ? avc->name : "unknown";
+ bool set_demuxer_id = matches_avinputformat_name(priv, "mpeg");
+
switch (codec->codec_type) {
case AVMEDIA_TYPE_AUDIO: {
WAVEFORMATEX *wf;
@@ -310,6 +315,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
if (!sh_audio)
break;
sh_audio->demuxer_codecname = codec_name;
+ if (set_demuxer_id)
+ sh_audio->gsh->demuxer_id = st->id;
stream_type = "audio";
priv->astreams[priv->audio_streams] = i;
sh_audio->libav_codec_id = codec->codec_id;
@@ -391,6 +398,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
if (!sh_video)
break;
sh_video->demuxer_codecname = codec_name;
+ if (set_demuxer_id)
+ sh_video->gsh->demuxer_id = st->id;
stream_type = "video";
priv->vstreams[priv->video_streams] = i;
sh_video->libav_codec_id = codec->codec_id;
@@ -503,6 +512,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
if (!sh_sub)
break;
sh_sub->demuxer_codecname = codec_name;
+ if (set_demuxer_id)
+ sh_sub->gsh->demuxer_id = st->id;
stream_type = "subtitle";
priv->sstreams[priv->sub_streams] = i;
sh_sub->libav_codec_id = codec->codec_id;
@@ -774,6 +785,14 @@ static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds)
id = pkt->stream_index;
+ assert(id >= 0 && id < MAX_S_STREAMS);
+ if (demux->s_streams[id] && demux->sub->id == -1 &&
+ demux->s_streams[id]->gsh->demuxer_id == priv->autoselect_sub)
+ {
+ priv->autoselect_sub = -1;
+ demux->sub->id = id;
+ }
+
if (id == demux->audio->id || priv->internet_radio_hack) {
// audio
ds = demux->audio;
@@ -943,6 +962,12 @@ static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg)
return DEMUXER_CTRL_OK;
}
}
+ case DEMUXER_CTRL_AUTOSELECT_SUBTITLE:
+ {
+ demuxer->sub->id = -1;
+ priv->autoselect_sub = *((int *)arg);
+ return DEMUXER_CTRL_OK;
+ }
case DEMUXER_CTRL_IDENTIFY_PROGRAM:
{
demux_program_t *prog = arg;
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index 798f701305..ce425751f9 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -1369,16 +1369,3 @@ int demuxer_set_angle(demuxer_t *demuxer, int angle)
return angle;
}
-
-char *demuxer_stream_lang(demuxer_t *d, struct sh_stream *sh)
-{
- struct stream_lang_req req = { .id = sh->tid }; // assume 1:1 mapping
- switch (sh->type) {
- case STREAM_AUDIO: req.type = stream_ctrl_audio; break;
- case STREAM_SUB: req.type = stream_ctrl_sub; break;
- default: return NULL;
- }
- if (stream_control(d->stream, STREAM_CTRL_GET_LANG, &req) == STREAM_OK)
- return req.name;
- return NULL;
-}
diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h
index f2236c6016..2dd2c5a35a 100644
--- a/libmpdemux/demuxer.h
+++ b/libmpdemux/demuxer.h
@@ -93,6 +93,7 @@ enum timestamp_type {
#define DEMUXER_CTRL_SWITCH_VIDEO 14
#define DEMUXER_CTRL_IDENTIFY_PROGRAM 15
#define DEMUXER_CTRL_CORRECT_PTS 16
+#define DEMUXER_CTRL_AUTOSELECT_SUBTITLE 17
#define SEEK_ABSOLUTE (1 << 0)
#define SEEK_FACTOR (1 << 1)
@@ -406,6 +407,4 @@ int demuxer_angles_count(struct demuxer *demuxer);
struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
enum stream_type t, int id);
-char *demuxer_stream_lang(demuxer_t *d, struct sh_stream *s);
-
#endif /* MPLAYER_DEMUXER_H */