diff options
Diffstat (limited to 'libmpdemux')
-rw-r--r-- | libmpdemux/demux_lavf.c | 3 | ||||
-rw-r--r-- | libmpdemux/demuxer.c | 179 | ||||
-rw-r--r-- | libmpdemux/demuxer.h | 28 | ||||
-rw-r--r-- | libmpdemux/stheader.h | 7 |
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; \ |