diff options
author | Martin Herkt <lachs0r@srsfckn.biz> | 2016-01-18 07:27:03 +0100 |
---|---|---|
committer | Martin Herkt <lachs0r@srsfckn.biz> | 2016-01-18 07:27:03 +0100 |
commit | ba9b2f1e49732d597009ba514b0132a50562cd10 (patch) | |
tree | fa05f5feb181823ac9d3b5682a835ff825de6914 /demux | |
parent | e1993d5ad2bdf3dd4c26474aaa2370cbc9c1cd1b (diff) | |
parent | 7b4ccb3e9f58a0745b58e473ee6e60b381242813 (diff) | |
download | mpv-ba9b2f1e49732d597009ba514b0132a50562cd10.tar.bz2 mpv-ba9b2f1e49732d597009ba514b0132a50562cd10.tar.xz |
Merge branch 'master' into release/current
Diffstat (limited to 'demux')
-rw-r--r-- | demux/codec_tags.c | 16 | ||||
-rw-r--r-- | demux/codec_tags.h | 8 | ||||
-rw-r--r-- | demux/cue.c | 17 | ||||
-rw-r--r-- | demux/cue.h | 1 | ||||
-rw-r--r-- | demux/demux.c | 251 | ||||
-rw-r--r-- | demux/demux.h | 12 | ||||
-rw-r--r-- | demux/demux_cue.c | 16 | ||||
-rw-r--r-- | demux/demux_disc.c | 45 | ||||
-rw-r--r-- | demux/demux_edl.c | 2 | ||||
-rw-r--r-- | demux/demux_lavf.c | 189 | ||||
-rw-r--r-- | demux/demux_mf.c | 29 | ||||
-rw-r--r-- | demux/demux_mkv.c | 152 | ||||
-rw-r--r-- | demux/demux_mkv_timeline.c | 14 | ||||
-rw-r--r-- | demux/demux_raw.c | 48 | ||||
-rw-r--r-- | demux/demux_tv.c | 45 | ||||
-rw-r--r-- | demux/ebml.c | 2 | ||||
-rw-r--r-- | demux/stheader.h | 57 |
17 files changed, 518 insertions, 386 deletions
diff --git a/demux/codec_tags.c b/demux/codec_tags.c index c7b48f6038..7e91291e9e 100644 --- a/demux/codec_tags.c +++ b/demux/codec_tags.c @@ -70,20 +70,20 @@ static const char *map_audio_pcm_tag(uint32_t tag, int bits) } } -void mp_set_codec_from_tag(struct sh_stream *sh) +void mp_set_codec_from_tag(struct mp_codec_params *c) { - sh->codec = lookup_tag(sh->type, sh->codec_tag); + c->codec = lookup_tag(c->type, c->codec_tag); - if (sh->audio && sh->audio->bits_per_coded_sample) { + if (c->type == STREAM_AUDIO && c->bits_per_coded_sample) { const char *codec = - map_audio_pcm_tag(sh->codec_tag, sh->audio->bits_per_coded_sample); + map_audio_pcm_tag(c->codec_tag, c->bits_per_coded_sample); if (codec) - sh->codec = codec; + c->codec = codec; } } -void mp_set_pcm_codec(struct sh_stream *sh, bool sign, bool is_float, int bits, - bool is_be) +void mp_set_pcm_codec(struct mp_codec_params *c, bool sign, bool is_float, + int bits, bool is_be) { // This uses libavcodec pcm codec names, e.g. "pcm_u16le". char codec[64] = "pcm_"; @@ -95,7 +95,7 @@ void mp_set_pcm_codec(struct sh_stream *sh, bool sign, bool is_float, int bits, mp_snprintf_cat(codec, sizeof(codec), "%d", bits); if (bits != 8) mp_snprintf_cat(codec, sizeof(codec), is_be ? "be" : "le"); - sh->codec = talloc_strdup(sh->audio, codec); + c->codec = talloc_strdup(c, codec); } static const char *const mimetype_to_codec[][2] = { diff --git a/demux/codec_tags.h b/demux/codec_tags.h index 3489f0da5c..294759a299 100644 --- a/demux/codec_tags.h +++ b/demux/codec_tags.h @@ -21,12 +21,12 @@ #include <stdint.h> #include <stdbool.h> -struct sh_stream; +struct mp_codec_params; -void mp_set_codec_from_tag(struct sh_stream *sh); +void mp_set_codec_from_tag(struct mp_codec_params *c); -void mp_set_pcm_codec(struct sh_stream *sh, bool sign, bool is_float, int bits, - bool is_be); +void mp_set_pcm_codec(struct mp_codec_params *c, bool sign, bool is_float, + int bits, bool is_be); const char *mp_map_mimetype_to_video_codec(const char *mimetype); diff --git a/demux/cue.c b/demux/cue.c index d72e84249b..4a84107db7 100644 --- a/demux/cue.c +++ b/demux/cue.c @@ -20,7 +20,7 @@ #include <string.h> #include <inttypes.h> -#include "talloc.h" +#include "mpv_talloc.h" #include "misc/bstr.h" #include "common/common.h" @@ -218,3 +218,18 @@ struct cue_file *mp_parse_cue(struct bstr data) return f; } + +int mp_check_embedded_cue(struct cue_file *f) +{ + char *fn0 = f->tracks[0].filename; + for (int n = 1; n < f->num_tracks; n++) { + char *fn = f->tracks[n].filename; + // both filenames have the same address (including NULL) + if (fn0 == fn) + continue; + // only one filename is NULL, or the strings don't match + if (!fn0 || !fn || strcmp(fn0, fn) != 0) + return -1; + } + return 0; +} diff --git a/demux/cue.h b/demux/cue.h index cf4b4c1a08..1ae5f0a203 100644 --- a/demux/cue.h +++ b/demux/cue.h @@ -38,5 +38,6 @@ struct cue_track { bool mp_probe_cue(struct bstr data); struct cue_file *mp_parse_cue(struct bstr data); +int mp_check_embedded_cue(struct cue_file *f); #endif diff --git a/demux/demux.c b/demux/demux.c index dcad692be5..19ad6970b0 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -29,7 +29,7 @@ #include "config.h" #include "options/options.h" -#include "talloc.h" +#include "mpv_talloc.h" #include "common/msg.h" #include "common/global.h" #include "osdep/threads.h" @@ -103,6 +103,11 @@ struct demux_internal { void (*wakeup_cb)(void *ctx); void *wakeup_cb_ctx; + struct sh_stream **streams; + int num_streams; + + int events; + bool warned_queue_overflow; bool last_eof; // last actual global EOF status bool eof; // whether we're in EOF state (reset for retry) @@ -198,42 +203,84 @@ void demux_set_ts_offset(struct demuxer *demuxer, double offset) pthread_mutex_unlock(&in->lock); } -struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) +// Allocate a new sh_stream of the given type. It either has to be released +// with talloc_free(), or added to a demuxer with demux_add_sh_stream(). You +// cannot add or read packets from the stream before it has been added. +struct sh_stream *demux_alloc_sh_stream(enum stream_type type) { - assert(demuxer == demuxer->in->d_thread); - - if (demuxer->num_streams > MAX_SH_STREAMS) { - MP_WARN(demuxer, "Too many streams.\n"); - return NULL; - } - - int demuxer_id = 0; - for (int n = 0; n < demuxer->num_streams; n++) { - if (demuxer->streams[n]->type == type) - demuxer_id++; - } - - struct sh_stream *sh = talloc_ptrtype(demuxer, sh); + struct sh_stream *sh = talloc_ptrtype(NULL, sh); *sh = (struct sh_stream) { .type = type, - .index = demuxer->num_streams, - .ff_index = demuxer->num_streams, - .demuxer_id = demuxer_id, // may be overwritten by demuxer - .ds = talloc(sh, struct demux_stream), + .index = -1, + .ff_index = -1, // may be overwritten by demuxer + .demuxer_id = -1, // ... same + .codec = talloc_zero(sh, struct mp_codec_params), }; + sh->codec->type = type; + return sh; +} + +// Add a new sh_stream to the demuxer. Note that as soon as the stream has been +// added, it must be immutable, and must not be released (this will happen when +// the demuxer is destroyed). +void demux_add_sh_stream(struct demuxer *demuxer, struct sh_stream *sh) +{ + struct demux_internal *in = demuxer->in; + pthread_mutex_lock(&in->lock); + + assert(!sh->ds); // must not be added yet + + sh->ds = talloc(sh, struct demux_stream); *sh->ds = (struct demux_stream) { - .in = demuxer->in, + .in = in, .type = sh->type, - .selected = demuxer->in->autoselect, + .selected = in->autoselect, }; - MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh); - switch (sh->type) { - case STREAM_VIDEO: sh->video = talloc_zero(demuxer, struct sh_video); break; - case STREAM_AUDIO: sh->audio = talloc_zero(demuxer, struct sh_audio); break; - case STREAM_SUB: sh->sub = talloc_zero(demuxer, struct sh_sub); break; + + if (!sh->codec->codec) + sh->codec->codec = ""; + + sh->index = in->num_streams; + if (sh->ff_index < 0) + sh->ff_index = sh->index; + if (sh->demuxer_id < 0) { + sh->demuxer_id = 0; + for (int n = 0; n < in->num_streams; n++) { + if (in->streams[n]->type == sh->type) + sh->demuxer_id += 1; + } } - return sh; + MP_TARRAY_APPEND(in, in->streams, in->num_streams, sh); + + in->events |= DEMUX_EVENT_STREAMS; + if (in->wakeup_cb) + in->wakeup_cb(in->wakeup_cb_ctx); + pthread_mutex_unlock(&in->lock); +} + +// Return a stream with the given index. Since streams can only be added during +// the lifetime of the demuxer, it is guaranteed that an index within the valid +// range [0, demux_get_num_stream()) always returns a valid sh_stream pointer, +// which will be valid until the demuxer is destroyed. +struct sh_stream *demux_get_stream(struct demuxer *demuxer, int index) +{ + struct demux_internal *in = demuxer->in; + pthread_mutex_lock(&in->lock); + assert(index >= 0 && index < in->num_streams); + struct sh_stream *r = in->streams[index]; + pthread_mutex_unlock(&in->lock); + return r; +} + +// See demux_get_stream(). +int demux_get_num_stream(struct demuxer *demuxer) +{ + struct demux_internal *in = demuxer->in; + pthread_mutex_lock(&in->lock); + int r = in->num_streams; + pthread_mutex_unlock(&in->lock); + return r; } void free_demuxer(demuxer_t *demuxer) @@ -247,8 +294,10 @@ void free_demuxer(demuxer_t *demuxer) if (demuxer->desc->close) demuxer->desc->close(in->d_thread); - for (int n = 0; n < demuxer->num_streams; n++) - ds_flush(demuxer->streams[n]->ds); + for (int n = in->num_streams - 1; n >= 0; n--) { + ds_flush(in->streams[n]->ds); + talloc_free(in->streams[n]); + } pthread_mutex_destroy(&in->lock); pthread_cond_destroy(&in->wakeup); talloc_free(demuxer); @@ -388,8 +437,8 @@ static bool read_packet(struct demux_internal *in) // safe-guards against packet queue overflow. bool active = false, read_more = false; size_t packs = 0, bytes = 0; - for (int n = 0; n < in->d_buffer->num_streams; n++) { - struct demux_stream *ds = in->d_buffer->streams[n]->ds; + for (int n = 0; n < in->num_streams; n++) { + struct demux_stream *ds = in->streams[n]->ds; active |= ds->active; read_more |= ds->active && !ds->head; packs += ds->packs; @@ -404,16 +453,16 @@ static bool read_packet(struct demux_internal *in) if (!in->warned_queue_overflow) { in->warned_queue_overflow = true; MP_ERR(in, "Too many packets in the demuxer packet queues:\n"); - for (int n = 0; n < in->d_buffer->num_streams; n++) { - struct demux_stream *ds = in->d_buffer->streams[n]->ds; + for (int n = 0; n < in->num_streams; n++) { + struct demux_stream *ds = in->streams[n]->ds; if (ds->selected) { MP_ERR(in, " %s/%d: %zd packets, %zd bytes\n", stream_type_name(ds->type), n, ds->packs, ds->bytes); } } } - for (int n = 0; n < in->d_buffer->num_streams; n++) { - struct demux_stream *ds = in->d_buffer->streams[n]->ds; + for (int n = 0; n < in->num_streams; n++) { + struct demux_stream *ds = in->streams[n]->ds; ds->eof |= !ds->head; } pthread_cond_signal(&in->wakeup); @@ -433,8 +482,8 @@ static bool read_packet(struct demux_internal *in) pthread_mutex_lock(&in->lock); if (eof) { - for (int n = 0; n < in->d_buffer->num_streams; n++) - in->d_buffer->streams[n]->ds->eof = true; + for (int n = 0; n < in->num_streams; n++) + in->streams[n]->ds->eof = true; // If we had EOF previously, then don't wakeup (avoids wakeup loop) if (!in->last_eof) { if (in->wakeup_cb) @@ -478,8 +527,8 @@ static void start_refreshing(struct demux_internal *in) in->start_refresh_seek = false; double start_ts = MP_NOPTS_VALUE; - for (int n = 0; n < demux->num_streams; n++) { - struct demux_stream *ds = demux->streams[n]->ds; + for (int n = 0; n < in->num_streams; n++) { + struct demux_stream *ds = in->streams[n]->ds; if (ds->type == STREAM_VIDEO || ds->type == STREAM_AUDIO) start_ts = MP_PTS_MIN(start_ts, ds->base_ts); } @@ -488,8 +537,8 @@ static void start_refreshing(struct demux_internal *in) demux->partially_seekable || !demux->allow_refresh_seeks) return; - for (int n = 0; n < demux->num_streams; n++) { - struct demux_stream *ds = demux->streams[n]->ds; + for (int n = 0; n < in->num_streams; n++) { + struct demux_stream *ds = in->streams[n]->ds; // Streams which didn't read any packets yet can return all packets, // or they'd be stuck forever; affects newly selected streams too. if (ds->last_pos != -1) @@ -635,15 +684,33 @@ struct demux_packet *demux_read_packet(struct sh_stream *sh) return pkt; } +// Sparse packets (Subtitles) interleaved with other non-sparse packets (video, +// audio) should never be read actively, meaning the demuxer thread does not +// try to exceed default readahead in order to find a new packet. +static bool use_lazy_subtitle_reading(struct demux_stream *ds) +{ + if (ds->type != STREAM_SUB) + return false; + for (int n = 0; n < ds->in->num_streams; n++) { + struct demux_stream *s = ds->in->streams[n]->ds; + if (s->type != STREAM_SUB && s->selected && !s->eof) + return true; + } + return false; +} + // Poll the demuxer queue, and if there's a packet, return it. Otherwise, just // make the demuxer thread read packets for this stream, and if there's at // least one packet, call the wakeup callback. -// Unlike demux_read_packet(), this always enables readahead (which means you -// must not use it on interleaved subtitle streams). +// Unlike demux_read_packet(), this always enables readahead (except for +// interleaved subtitles). // Returns: // < 0: EOF was reached, *out_pkt=NULL // == 0: no new packet yet, but maybe later, *out_pkt=NULL // > 0: new packet read, *out_pkt is set +// Note: when reading interleaved subtitles, the demuxer won't try to forcibly +// read ahead to get the next subtitle packet (as the next packet could be +// minutes away). In this situation, this function will just return -1. int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt) { struct demux_stream *ds = sh ? sh->ds : NULL; @@ -653,10 +720,14 @@ int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt) if (ds->in->threading) { pthread_mutex_lock(&ds->in->lock); *out_pkt = dequeue_packet(ds); - r = *out_pkt ? 1 : ((ds->eof || !ds->selected) ? -1 : 0); - ds->active = ds->selected; // enable readahead - ds->in->eof = false; // force retry - pthread_cond_signal(&ds->in->wakeup); // possibly read more + if (use_lazy_subtitle_reading(ds)) { + r = *out_pkt ? 1 : -1; + } else { + r = *out_pkt ? 1 : ((ds->eof || !ds->selected) ? -1 : 0); + ds->active = ds->selected; // enable readahead + ds->in->eof = false; // force retry + pthread_cond_signal(&ds->in->wakeup); // possibly read more + } pthread_mutex_unlock(&ds->in->lock); } else { *out_pkt = demux_read_packet(sh); @@ -666,22 +737,6 @@ int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt) return r; } -// Return the pts of the next packet that demux_read_packet() would return. -// Might block. Sometimes used to force a packet read, without removing any -// packets from the queue. -double demux_get_next_pts(struct sh_stream *sh) -{ - double res = MP_NOPTS_VALUE; - if (sh) { - pthread_mutex_lock(&sh->ds->in->lock); - ds_get_packets(sh->ds); - if (sh->ds->head) - res = MP_ADD_PTS(sh->ds->head->pts, sh->ds->in->ts_offset); - pthread_mutex_unlock(&sh->ds->in->lock); - } - return res; -} - // Return whether a packet is queued. Never blocks, never forces any reads. bool demux_has_packet(struct sh_stream *sh) { @@ -697,21 +752,22 @@ bool demux_has_packet(struct sh_stream *sh) // Read and return any packet we find. struct demux_packet *demux_read_any_packet(struct demuxer *demuxer) { - assert(!demuxer->in->threading); // doesn't work with threading + struct demux_internal *in = demuxer->in; + assert(!in->threading); // doesn't work with threading bool read_more = true; while (read_more) { - for (int n = 0; n < demuxer->num_streams; n++) { - struct sh_stream *sh = demuxer->streams[n]; + for (int n = 0; n < in->num_streams; n++) { + struct sh_stream *sh = in->streams[n]; sh->ds->active = sh->ds->selected; // force read_packet() to read struct demux_packet *pkt = dequeue_packet(sh->ds); if (pkt) return pkt; } // retry after calling this - pthread_mutex_lock(&demuxer->in->lock); - read_more = read_packet(demuxer->in); - read_more &= !demuxer->in->eof; - pthread_mutex_unlock(&demuxer->in->lock); + pthread_mutex_lock(&in->lock); // lock only because read_packet unlocks + read_more = read_packet(in); + read_more &= !in->eof; + pthread_mutex_unlock(&in->lock); } return NULL; } @@ -795,13 +851,14 @@ static int decode_peak(demuxer_t *demuxer, const char *tag, float *out) static void apply_replaygain(demuxer_t *demuxer, struct replaygain_data *rg) { - for (int n = 0; n < demuxer->num_streams; n++) { - struct sh_stream *sh = demuxer->streams[n]; - if (sh->audio && !sh->audio->replaygain_data) { + struct demux_internal *in = demuxer->in; + for (int n = 0; n < in->num_streams; n++) { + struct sh_stream *sh = in->streams[n]; + if (sh->type == STREAM_AUDIO && !sh->codec->replaygain_data) { MP_VERBOSE(demuxer, "Replaygain: Track=%f/%f Album=%f/%f\n", rg->track_gain, rg->track_peak, rg->album_gain, rg->album_peak); - sh->audio->replaygain_data = talloc_memdup(demuxer, rg, sizeof(*rg)); + sh->codec->replaygain_data = talloc_memdup(in, rg, sizeof(*rg)); } } } @@ -853,11 +910,6 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src) dst->start_time = src->start_time; dst->priv = src->priv; } - if (src->events & DEMUX_EVENT_STREAMS) { - // The stream structs themselves are immutable. - for (int n = dst->num_streams; n < src->num_streams; n++) - MP_TARRAY_APPEND(dst, dst->streams, dst->num_streams, src->streams[n]); - } if (src->events & DEMUX_EVENT_METADATA) { talloc_free(dst->metadata); dst->metadata = mp_tags_dup(dst, src->metadata); @@ -905,6 +957,8 @@ void demux_update(demuxer_t *demuxer) pthread_mutex_lock(&in->lock); demux_copy(demuxer, in->d_buffer); + demuxer->events |= in->events; + in->events = 0; if (in->stream_metadata && (demuxer->events & DEMUX_EVENT_METADATA)) mp_tags_merge(demuxer->metadata, in->stream_metadata); pthread_mutex_unlock(&in->lock); @@ -926,10 +980,15 @@ static void demux_init_cuesheet(struct demuxer *demuxer) if (cue && !demuxer->num_chapters) { struct cue_file *f = mp_parse_cue(bstr0(cue)); if (f) { - for (int n = 0; n < f->num_tracks; n++) { - struct cue_track *t = &f->tracks[n]; - int idx = demuxer_add_chapter(demuxer, "", t->start, -1); - mp_tags_merge(demuxer->chapters[idx].metadata, t->tags); + if (mp_check_embedded_cue(f) < 0) { + MP_WARN(demuxer, "Embedded cue sheet references more than one file. " + "Ignoring it.\n"); + } else { + for (int n = 0; n < f->num_tracks; n++) { + struct cue_track *t = &f->tracks[n]; + int idx = demuxer_add_chapter(demuxer, "", t->start, -1); + mp_tags_merge(demuxer->chapters[idx].metadata, t->tags); + } } } talloc_free(f); @@ -1108,8 +1167,8 @@ struct demuxer *demux_open_url(const char *url, static void flush_locked(demuxer_t *demuxer) { - for (int n = 0; n < demuxer->num_streams; n++) - ds_flush(demuxer->streams[n]->ds); + for (int n = 0; n < demuxer->in->num_streams; n++) + ds_flush(demuxer->in->streams[n]->ds); demuxer->in->warned_queue_overflow = false; demuxer->in->eof = false; demuxer->in->last_eof = false; @@ -1187,10 +1246,11 @@ void demux_set_enable_refresh_seeks(struct demuxer *demuxer, bool enabled) struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d, enum stream_type t, int id) { - for (int n = 0; n < d->num_streams; n++) { - struct sh_stream *s = d->streams[n]; + int num = demux_get_num_stream(d); + for (int n = 0; n < num; n++) { + struct sh_stream *s = demux_get_stream(d, n); if (s->type == t && s->demuxer_id == id) - return d->streams[n]; + return s; } return NULL; } @@ -1200,8 +1260,9 @@ void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type, { assert(!stream || stream->type == type); - for (int n = 0; n < demuxer->num_streams; n++) { - struct sh_stream *cur = demuxer->streams[n]; + int num = demux_get_num_stream(demuxer); + for (int n = 0; n < num; n++) { + struct sh_stream *cur = demux_get_stream(demuxer, n); if (cur->type == type) demuxer_select_track(demuxer, cur, cur == stream); } @@ -1403,8 +1464,8 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg) double *rates = arg; for (int n = 0; n < STREAM_TYPE_COUNT; n++) rates[n] = -1; - for (int n = 0; n < in->d_user->num_streams; n++) { - struct demux_stream *ds = in->d_user->streams[n]->ds; + for (int n = 0; n < in->num_streams; n++) { + struct demux_stream *ds = in->streams[n]->ds; if (ds->selected && ds->bitrate >= 0) rates[ds->type] = MPMAX(0, rates[ds->type]) + ds->bitrate; } @@ -1418,8 +1479,8 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg) .ts_duration = -1, }; int num_packets = 0; - for (int n = 0; n < in->d_user->num_streams; n++) { - struct demux_stream *ds = in->d_user->streams[n]->ds; + for (int n = 0; n < in->num_streams; n++) { + struct demux_stream *ds = in->streams[n]->ds; if (ds->active) { r->underrun |= !ds->head && !ds->eof; r->ts_range[0] = MP_PTS_MAX(r->ts_range[0], ds->base_ts); diff --git a/demux/demux.h b/demux/demux.h index 96717d5eeb..d274be5ae7 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -86,8 +86,6 @@ enum demux_event { DEMUX_EVENT_ALL = 0xFFFF, }; -#define MAX_SH_STREAMS 256 - struct demuxer; struct timeline; @@ -199,9 +197,6 @@ typedef struct demuxer { // Bitmask of DEMUX_EVENT_* int events; - struct sh_stream **streams; - int num_streams; - struct demux_edition *editions; int num_editions; int edition; @@ -247,11 +242,14 @@ void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp); struct demux_packet *demux_read_packet(struct sh_stream *sh); int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt); bool demux_stream_is_selected(struct sh_stream *stream); -double demux_get_next_pts(struct sh_stream *sh); bool demux_has_packet(struct sh_stream *sh); struct demux_packet *demux_read_any_packet(struct demuxer *demuxer); -struct sh_stream *new_sh_stream(struct demuxer *demuxer, enum stream_type type); +struct sh_stream *demux_get_stream(struct demuxer *demuxer, int index); +int demux_get_num_stream(struct demuxer *demuxer); + +struct sh_stream *demux_alloc_sh_stream(enum stream_type type); +void demux_add_sh_stream(struct demuxer *demuxer, struct sh_stream *sh); struct demuxer *demux_open(struct stream *stream, struct demuxer_params *params, struct mpv_global *global); diff --git a/demux/demux_cue.c b/demux/demux_cue.c index 43420573ec..bef1516057 100644 --- a/demux/demux_cue.c +++ b/demux/demux_cue.c @@ -23,7 +23,7 @@ #include <dirent.h> #include <inttypes.h> -#include "talloc.h" +#include "mpv_talloc.h" #include "misc/bstr.h" #include "common/msg.h" @@ -150,8 +150,18 @@ static void build_timeline(struct timeline *tl) add_source(tl, tl->demuxer); - struct cue_track *tracks = p->f->tracks; - size_t track_count = p->f->num_tracks; + struct cue_track *tracks = NULL; + size_t track_count = 0; + + for (size_t n = 0; n < p->f->num_tracks; n++) { + struct cue_track *track = &p->f->tracks[n]; + if (track->filename) { + MP_TARRAY_APPEND(ctx, tracks, track_count, *track); + } else { + MP_WARN(tl->demuxer, "No file specified for track entry %zd. " + "It will be removed\n", n + 1); + } + } if (track_count == 0) { MP_ERR(tl, "CUE: no tracks found!\n"); diff --git a/demux/demux_disc.c b/demux/demux_disc.c index b994b3cf11..dcc3e7c79f 100644 --- a/demux/demux_disc.c +++ b/demux/demux_disc.c @@ -23,6 +23,7 @@ #include "common/msg.h" #include "stream/stream.h" +#include "video/mp_image.h" #include "demux.h" #include "stheader.h" @@ -53,9 +54,10 @@ struct priv { static void reselect_streams(demuxer_t *demuxer) { struct priv *p = demuxer->priv; - for (int n = 0; n < MPMIN(p->slave->num_streams, p->num_streams); n++) { + int num_slave = demux_get_num_stream(p->slave); + for (int n = 0; n < MPMIN(num_slave, p->num_streams); n++) { if (p->streams[n]) { - demuxer_select_track(p->slave, p->slave->streams[n], + demuxer_select_track(p->slave, demux_get_stream(p->slave, n), demux_stream_is_selected(p->streams[n])); } } @@ -80,11 +82,9 @@ static void add_dvd_streams(demuxer_t *demuxer) struct stream_dvd_info_req info; if (stream_control(stream, STREAM_CTRL_GET_DVD_INFO, &info) > 0) { for (int n = 0; n < MPMIN(32, info.num_subs); n++) { - struct sh_stream *sh = new_sh_stream(demuxer, STREAM_SUB); - if (!sh) - break; + struct sh_stream *sh = demux_alloc_sh_stream(STREAM_SUB); sh->demuxer_id = n + 0x20; - sh->codec = "dvd_subtitle"; + sh->codec->codec = "dvd_subtitle"; get_disc_lang(stream, sh); // p->streams _must_ match with p->slave->streams, so we can't add // it yet - it has to be done when the real stream appears, which @@ -111,8 +111,10 @@ static void add_dvd_streams(demuxer_t *demuxer) } s = talloc_asprintf_append(s, "\n"); - sh->extradata = s; - sh->extradata_size = strlen(s); + sh->codec->extradata = s; + sh->codec->extradata_size = strlen(s); + + demux_add_sh_stream(demuxer, sh); } } } @@ -121,9 +123,9 @@ static void add_streams(demuxer_t *demuxer) { struct priv *p = demuxer->priv; - for (int n = p->num_streams; n < p->slave->num_streams; n++) { - struct sh_stream *src = p->slave->streams[n]; - if (src->sub) { + for (int n = p->num_streams; n < demux_get_num_stream(p->slave); n++) { + struct sh_stream *src = demux_get_stream(p->slave, n); + if (src->type == STREAM_SUB) { struct sh_stream *sub = NULL; if (src->demuxer_id >= 0x20 && src->demuxer_id <= 0x3F) sub = p->dvd_subs[src->demuxer_id - 0x20]; @@ -133,25 +135,26 @@ static void add_streams(demuxer_t *demuxer) continue; } } - struct sh_stream *sh = new_sh_stream(demuxer, src->type); - if (!sh) - break; + struct sh_stream *sh = demux_alloc_sh_stream(src->type); assert(p->num_streams == n); // directly mapped MP_TARRAY_APPEND(p, p->streams, p->num_streams, sh); // Copy all stream fields that might be relevant - sh->codec = talloc_strdup(sh, src->codec); - sh->codec_tag = src->codec_tag; - sh->lav_headers = src->lav_headers; + *sh->codec = *src->codec; sh->demuxer_id = src->demuxer_id; - if (src->video) { + if (src->type == STREAM_VIDEO) { double ar; if (stream_control(demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar) == STREAM_OK) - sh->video->aspect = ar; + { + struct mp_image_params f = {.w = src->codec->disp_w, + .h = src->codec->disp_h}; + mp_image_params_set_dsize(&f, 1728 * ar, 1728); + sh->codec->par_w = f.p_w; + sh->codec->par_h = f.p_h; + } } - if (src->audio) - sh->audio = src->audio; get_disc_lang(demuxer->stream, sh); + demux_add_sh_stream(demuxer, sh); } reselect_streams(demuxer); } diff --git a/demux/demux_edl.c b/demux/demux_edl.c index 9ba0307487..74ce7aef66 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -23,7 +23,7 @@ #include <inttypes.h> #include <math.h> -#include "talloc.h" +#include "mpv_talloc.h" #include "demux.h" #include "timeline.h" diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 2d12f5cfa2..1b3105170d 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -40,6 +40,7 @@ #include "common/tags.h" #include "common/av_common.h" #include "misc/bstr.h" +#include "misc/charset_conv.h" #include "stream/stream.h" #include "demux.h" @@ -108,6 +109,7 @@ struct format_hack { bool no_stream : 1; // do not wrap struct stream as AVIOContext bool use_stream_ids : 1; // export the native stream IDs bool fully_read : 1; // set demuxer.fully_read flag + bool detect_charset : 1; // format is a small text file, possibly not UTF8 bool image_format : 1; // expected to contain exactly 1 frame // Do not confuse player's position estimation (position is into external // segment, with e.g. HLS, player knows about the playlist main file only). @@ -115,8 +117,8 @@ struct format_hack { }; #define BLACKLIST(fmt) {fmt, .ignore = true} -#define TEXTSUB(fmt) {fmt, .fully_read = true} -#define IMAGEFMT(fmt) {fmt, .image_format = true} +#define TEXTSUB(fmt) {fmt, .fully_read = true, .detect_charset = true} +#define TEXTSUB_UTF8(fmt) {fmt, .fully_read = true} static const struct format_hack format_hacks[] = { // for webradios @@ -135,10 +137,12 @@ static const struct format_hack format_hacks[] = { {"h264", .if_flags = AVFMT_NOTIMESTAMPS }, {"hevc", .if_flags = A |