summaryrefslogtreecommitdiffstats
path: root/libmpdemux
diff options
context:
space:
mode:
Diffstat (limited to 'libmpdemux')
-rw-r--r--libmpdemux/demux_lavf.c3
-rw-r--r--libmpdemux/demuxer.c179
-rw-r--r--libmpdemux/demuxer.h28
-rw-r--r--libmpdemux/stheader.h7
4 files changed, 78 insertions, 139 deletions
diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c
index baf013a8ef..4dd9938d07 100644
--- a/libmpdemux/demux_lavf.c
+++ b/libmpdemux/demux_lavf.c
@@ -309,7 +309,6 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
sh_audio = new_sh_audio_aid(demuxer, i, priv->audio_streams);
if (!sh_audio)
break;
- sh_audio->gsh->demuxer_id = i;
sh_audio->demuxer_codecname = codec_name;
stream_type = "audio";
priv->astreams[priv->audio_streams] = i;
@@ -391,7 +390,6 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
sh_video = new_sh_video_vid(demuxer, i, priv->video_streams);
if (!sh_video)
break;
- sh_video->gsh->demuxer_id = i;
sh_video->demuxer_codecname = codec_name;
stream_type = "video";
priv->vstreams[priv->video_streams] = i;
@@ -504,7 +502,6 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams);
if (!sh_sub)
break;
- sh_sub->gsh->demuxer_id = i;
sh_sub->demuxer_codecname = codec_name;
stream_type = "subtitle";
priv->sstreams[priv->sub_streams] = i;
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index bc2e132c60..13f5fab268 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -189,10 +189,12 @@ static void free_demuxer_stream(struct demux_stream *ds)
free(ds);
}
-static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer, int id)
+static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer,
+ enum stream_type type, int id)
{
demux_stream_t *ds = malloc(sizeof(demux_stream_t));
- *ds = (demux_stream_t){
+ *ds = (demux_stream_t) {
+ .stream_type = type,
.id = id,
.demuxer = demuxer,
.asf_seq = -1,
@@ -200,6 +202,19 @@ static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer, int id)
return ds;
}
+struct sh_stream *ds_gsh(struct demux_stream *ds)
+{
+ // Ideally ds would have a gsh field, but since all the old demuxers set
+ // ds->sh themselves and we don't want to change them, enjoy this hack.
+ if (!ds->sh)
+ return NULL;
+ switch (ds->stream_type) {
+ case STREAM_VIDEO: return ((struct sh_video *)ds->sh)->gsh;
+ case STREAM_AUDIO: return ((struct sh_audio *)ds->sh)->gsh;
+ case STREAM_SUB: return ((struct sh_sub *)ds->sh)->gsh;
+ }
+ assert(false);
+}
/**
* Get demuxer description structure for a given demuxer type
@@ -231,9 +246,12 @@ demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type,
d->seekable = 1;
d->synced = 0;
d->filepos = -1;
- d->audio = new_demuxer_stream(d, a_id);
- d->video = new_demuxer_stream(d, v_id);
- d->sub = new_demuxer_stream(d, s_id);
+ d->audio = new_demuxer_stream(d, STREAM_VIDEO, a_id);
+ d->video = new_demuxer_stream(d, STREAM_AUDIO, v_id);
+ d->sub = new_demuxer_stream(d, STREAM_SUB, s_id);
+ d->ds[STREAM_VIDEO] = d->video;
+ d->ds[STREAM_AUDIO] = d->audio;
+ d->ds[STREAM_SUB] = d->sub;
d->type = type;
d->opts = opts;
if (type)
@@ -269,8 +287,9 @@ static struct sh_stream *new_sh_stream(demuxer_t *demuxer,
{
struct sh_stream *sh = talloc_struct(demuxer, struct sh_stream, {
.type = type,
+ .demuxer = demuxer,
.index = demuxer->num_streams,
- .demuxer_id = demuxer->new_stream_id++, // possibly temporary value only
+ .demuxer_id = tid, // may be overwritten by demuxer
.tid = tid,
.stream_index = stream_index,
.opts = demuxer->opts,
@@ -308,7 +327,6 @@ static struct sh_stream *new_sh_stream(demuxer_t *demuxer,
}
default: assert(false);
}
- sh->common_header->id = sh->tid;
sh->common_header->opts = sh->opts;
sh->common_header->gsh = sh;
return sh;
@@ -1235,37 +1253,42 @@ int demux_control(demuxer_t *demuxer, int cmd, void *arg)
return DEMUXER_CTRL_NOTIMPL;
}
-int demuxer_switch_audio(demuxer_t *demuxer, int index)
+struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
+ enum stream_type t, int id)
{
- int res = demux_control(demuxer, DEMUXER_CTRL_SWITCH_AUDIO, &index);
- if (res == DEMUXER_CTRL_NOTIMPL) {
- struct sh_audio *sh_audio = demuxer->audio->sh;
- return sh_audio ? sh_audio->aid : -2;
+ for (int n = 0; n < d->num_streams; n++) {
+ struct sh_stream *s = d->streams[n];
+ if (s->type == t && s->demuxer_id == id)
+ return d->streams[n];
}
- if (demuxer->audio->id >= 0) {
- struct sh_audio *sh_audio = demuxer->a_streams[demuxer->audio->id];
- demuxer->audio->sh = sh_audio;
- index = sh_audio->aid; // internal MPEG demuxers don't set it right
- }
- else
- demuxer->audio->sh = NULL;
- return index;
+ return NULL;
}
-int demuxer_switch_video(demuxer_t *demuxer, int index)
-{
- int res = demux_control(demuxer, DEMUXER_CTRL_SWITCH_VIDEO, &index);
- if (res == DEMUXER_CTRL_NOTIMPL) {
- struct sh_video *sh_video = demuxer->video->sh;
- return sh_video ? sh_video->vid : -2;
+void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type,
+ struct sh_stream *stream)
+{
+ assert(!stream || stream->type == type);
+ int index = stream ? stream->tid : -2;
+ if (type == STREAM_AUDIO) {
+ demux_control(demuxer, DEMUXER_CTRL_SWITCH_AUDIO, &index);
+ } else if (type == STREAM_VIDEO) {
+ demux_control(demuxer, DEMUXER_CTRL_SWITCH_VIDEO, &index);
+ } else if (type == STREAM_SUB) {
+ int index2 = stream ? stream->stream_index : -2;
+ if (demuxer->ds[type]->id != index2)
+ ds_free_packs(demuxer->ds[type]);
+ demuxer->ds[type]->id = index2;
}
- if (demuxer->video->id >= 0) {
- struct sh_video *sh_video = demuxer->v_streams[demuxer->video->id];
- demuxer->video->sh = sh_video;
- index = sh_video->vid; // internal MPEG demuxers don't set it right
- } else
- demuxer->video->sh = NULL;
- return index;
+ int new_id = demuxer->ds[type]->id;
+ void *new = NULL;
+ if (new_id >= 0) {
+ switch (type) {
+ case STREAM_VIDEO: new = demuxer->v_streams[new_id]; break;
+ case STREAM_AUDIO: new = demuxer->a_streams[new_id]; break;
+ case STREAM_SUB: new = demuxer->s_streams[new_id]; break;
+ }
+ }
+ demuxer->ds[type]->sh = new;
}
int demuxer_add_attachment(demuxer_t *demuxer, struct bstr name,
@@ -1456,91 +1479,15 @@ int demuxer_set_angle(demuxer_t *demuxer, int angle)
return angle;
}
-static char *demuxer_audio_lang(demuxer_t *d, int id)
-{
- struct stream_lang_req req;
- sh_audio_t *sh;
- if (id < 0 || id >= MAX_A_STREAMS)
- return NULL;
- sh = d->a_streams[id];
- if (!sh)
- return NULL;
- if (sh->lang)
- return talloc_strdup(NULL, sh->lang);
- req.type = stream_ctrl_audio;
- req.id = sh->aid;
- if (stream_control(d->stream, STREAM_CTRL_GET_LANG, &req) == STREAM_OK)
- return req.name;
- return NULL;
-}
-
-static char *demuxer_sub_lang(demuxer_t *d, int id)
+char *demuxer_stream_lang(demuxer_t *d, struct sh_stream *sh)
{
- struct stream_lang_req req;
- sh_sub_t *sh;
- if (id < 0 || id >= MAX_S_STREAMS)
- return NULL;
- sh = d->s_streams[id];
- if (sh && sh->lang)
- return talloc_strdup(NULL, sh->lang);
- req.type = stream_ctrl_sub;
- // assume 1:1 mapping so we can show the language of
- // DVD subs even when we have not yet created the stream.
- req.id = sh ? sh->sid : id;
+ 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;
}
-
-char *demuxer_stream_lang(demuxer_t *d, struct sh_stream *s)
-{
- switch (s->type) {
- case STREAM_AUDIO: return demuxer_audio_lang(d, s->stream_index);
- case STREAM_SUB: return demuxer_sub_lang(d, s->stream_index);
- default: return NULL;
- }
-}
-
-int demuxer_audio_track_by_lang_and_default(struct demuxer *d, char **langt)
-{
- int n = 0;
- while (1) {
- char *lang = langt ? langt[n++] : NULL;
- int id = -1;
- for (int i = 0; i < MAX_A_STREAMS; i++) {
- struct sh_audio *sh = d->a_streams[i];
- if (sh && (!lang || sh->lang && !strcmp(lang, sh->lang))) {
- if (sh->gsh->default_track)
- return sh->aid;
- if (id < 0)
- id = sh->aid;
- }
- }
- if (id >= 0)
- return id;
- if (!lang)
- return -1;
- }
-}
-
-int demuxer_sub_track_by_lang_and_default(struct demuxer *d, char **langt)
-{
- int n = 0;
- while (1) {
- char *lang = langt ? langt[n++] : NULL;
- int id = -1;
- for (int i = 0; i < MAX_S_STREAMS; i++) {
- struct sh_sub *sh = d->s_streams[i];
- if (sh && (!lang || sh->lang && !strcmp(lang, sh->lang))) {
- if (sh->gsh->default_track)
- return sh->sid;
- if (id < 0)
- id = sh->sid;
- }
- }
- if (!lang)
- return -1;
- if (id >= 0)
- return id;
- }
-}
diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h
index 63910240bc..50ab0525c4 100644
--- a/libmpdemux/demuxer.h
+++ b/libmpdemux/demuxer.h
@@ -28,6 +28,7 @@
#include "bstr.h"
#include "mpcommon.h"
#include "demux_packet.h"
+#include "stheader.h"
struct MPOpts;
@@ -103,6 +104,7 @@ enum timestamp_type {
#define MP_INPUT_BUFFER_PADDING_SIZE 16
typedef struct demux_stream {
+ enum stream_type stream_type;
int buffer_pos; // current buffer position
int buffer_size; // current buffer size
unsigned char *buffer; // current buffer, never free() it, always use free_demux_packet(buffer_ref);
@@ -233,6 +235,9 @@ typedef struct demuxer {
bool accurate_seek;
enum timestamp_type timestamp_type;
+ struct demux_stream *ds[STREAM_TYPE_COUNT]; // video/audio/sub buffers
+
+ // These correspond to ds[], e.g.: audio == ds[STREAM_AUDIO]
struct demux_stream *audio; // audio buffer/demuxer
struct demux_stream *video; // video buffer/demuxer
struct demux_stream *sub; // dvd subtitle buffer/demuxer
@@ -261,8 +266,6 @@ typedef struct demuxer {
char **info; // metadata
struct MPOpts *opts;
struct demuxer_params *params;
-
- int new_stream_id;
} demuxer_t;
typedef struct {
@@ -295,6 +298,8 @@ struct demuxer *new_demuxer(struct MPOpts *opts, struct stream *stream,
char *filename);
void free_demuxer(struct demuxer *demuxer);
+struct sh_stream *ds_gsh(struct demux_stream *ds);
+
void ds_add_packet(struct demux_stream *ds, struct demux_packet *dp);
void ds_read_packet(struct demux_stream *ds, struct stream *stream, int len,
double pts, off_t pos, bool keyframe);
@@ -369,8 +374,8 @@ char *demux_info_get(struct demuxer *demuxer, const char *opt);
int demux_info_print(struct demuxer *demuxer);
int demux_control(struct demuxer *demuxer, int cmd, void *arg);
-int demuxer_switch_audio(struct demuxer *demuxer, int index);
-int demuxer_switch_video(struct demuxer *demuxer, int index);
+void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type,
+ struct sh_stream *stream);
int demuxer_type_by_filename(char *filename);
@@ -398,19 +403,8 @@ int demuxer_set_angle(struct demuxer *demuxer, int angle);
/// Get number of angles.
int demuxer_angles_count(struct demuxer *demuxer);
-/* Get the index of a track.
- * lang is a string list, NULL is same as empty list
- * Sort tracks based on the following criteria:
- * 1) earlier match in lang list, or last no match
- * 2) track is marked default (default wins)
- * 3) track number (lower wins)
- * For audio, select best track according to these criteria; only return -1
- * if there are no tracks at all.
- * For subs, select best track according to the same criteria, but return -1
- * if all tracks are no-lang-match, not-default.
- */
-int demuxer_audio_track_by_lang_and_default(struct demuxer *d, char **langt);
-int demuxer_sub_track_by_lang_and_default(struct demuxer *d, char **langt);
+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);
diff --git a/libmpdemux/stheader.h b/libmpdemux/stheader.h
index f36ac8c347..90d06f96d5 100644
--- a/libmpdemux/stheader.h
+++ b/libmpdemux/stheader.h
@@ -27,22 +27,24 @@ struct MPOpts;
struct demuxer;
enum stream_type {
- STREAM_VIDEO = 1,
+ STREAM_VIDEO,
STREAM_AUDIO,
STREAM_SUB,
+ STREAM_TYPE_COUNT,
};
// Stream headers:
struct sh_stream {
enum stream_type type;
+ struct demuxer *demuxer;
// Index into demuxer->streams.
int index;
// The (possibly) type specific id, e.g. aid or sid.
int tid;
// Index into stream array (currently one array per type, e.g. a_streams).
int stream_index;
- // Demuxer specific ID (-1 if unknown, otherwise >= 0).
+ // Demuxer specific ID (always set, defaults to tid).
int demuxer_id;
// Abomination.
struct sh_common *common_header;
@@ -61,7 +63,6 @@ struct sh_stream {
#define SH_COMMON \
- int id; \
struct sh_stream *gsh; \
const char *demuxer_codecname; \
struct MPOpts *opts; \