diff options
Diffstat (limited to 'demux')
-rw-r--r-- | demux/aviheader.c | 3 | ||||
-rw-r--r-- | demux/codec_tags.c | 1 | ||||
-rw-r--r-- | demux/demux.c | 290 | ||||
-rw-r--r-- | demux/demux.h | 30 | ||||
-rw-r--r-- | demux/demux_asf.c | 9 | ||||
-rw-r--r-- | demux/demux_avi.c | 1 | ||||
-rw-r--r-- | demux/demux_cue.c | 8 | ||||
-rw-r--r-- | demux/demux_edl.c | 8 | ||||
-rw-r--r-- | demux/demux_lavf.c | 170 | ||||
-rw-r--r-- | demux/demux_libass.c | 121 | ||||
-rw-r--r-- | demux/demux_mf.c | 2 | ||||
-rw-r--r-- | demux/demux_mkv.c | 255 | ||||
-rw-r--r-- | demux/demux_mpg.c | 2 | ||||
-rw-r--r-- | demux/demux_packet.h | 1 | ||||
-rw-r--r-- | demux/demux_rawaudio.c | 13 | ||||
-rw-r--r-- | demux/demux_subreader.c | 1402 | ||||
-rw-r--r-- | demux/demux_ts.c | 10 | ||||
-rw-r--r-- | demux/ebml.c | 5 | ||||
-rw-r--r-- | demux/matroska.h | 1 | ||||
-rw-r--r-- | demux/stheader.h | 13 |
20 files changed, 2122 insertions, 223 deletions
diff --git a/demux/aviheader.c b/demux/aviheader.c index 2226be25d4..c1b9c59692 100644 --- a/demux/aviheader.c +++ b/demux/aviheader.c @@ -479,7 +479,6 @@ if (priv->isodml && (index_mode==-1 || index_mode==0 || index_mode==1)) { // read the standard indices for (cx = &priv->suidx[0], i=0; i<priv->suidx_size; cx++, i++) { - stream_reset(demuxer->stream); for (j=0; j<cx->nEntriesInUse; j++) { int ret1, ret2; memset(&cx->stdidx[j], 0, 32); @@ -543,7 +542,6 @@ if (priv->isodml && (index_mode==-1 || index_mode==0 || index_mode==1)) { { uint32_t id; uint32_t db = 0; - stream_reset (demuxer->stream); // find out the video stream id. I have seen files with 01db. for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){ @@ -590,7 +588,6 @@ freeout: if(index_mode>=2 || (priv->idx_size==0 && index_mode==1)){ int idx_pos = 0; // build index for file: - stream_reset(demuxer->stream); stream_seek(demuxer->stream,demuxer->movi_start); priv->idx_size=0; diff --git a/demux/codec_tags.c b/demux/codec_tags.c index 2af450ad07..cf7e0356be 100644 --- a/demux/codec_tags.c +++ b/demux/codec_tags.c @@ -102,6 +102,7 @@ static const struct mp_codec_tag mp_audio_codec_tags[] = { {0x1 , "pcm"}, // lavf: pcm_s16le {0x3 , "pcm"}, // lavf: pcm_f32le {0xfffe , "pcm"}, + {MKTAG('t', 'w', 'o', 's'), "pcm"}, // ------- internal mplayer FourCCs ------ {MKTAG('O', 'p', 'u', 's'), "opus"}, // demux_mkv.c {MKTAG('a', 'L', 'a', 'C'), "alac"}, // demux_mkv.c diff --git a/demux/demux.c b/demux/demux.c index e1bb960e78..c783b0cbc2 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -40,7 +40,8 @@ #include "audio/format.h" -#include "libavcodec/avcodec.h" +#include <libavcodec/avcodec.h> + #if MP_INPUT_BUFFER_PADDING_SIZE < FF_INPUT_BUFFER_PADDING_SIZE #error MP_INPUT_BUFFER_PADDING_SIZE is too small! #endif @@ -66,6 +67,8 @@ extern const demuxer_desc_t demuxer_desc_mpeg_es; extern const demuxer_desc_t demuxer_desc_mpeg4_es; extern const demuxer_desc_t demuxer_desc_h264_es; extern const demuxer_desc_t demuxer_desc_mpeg_ts; +extern const demuxer_desc_t demuxer_desc_libass; +extern const demuxer_desc_t demuxer_desc_subreader; /* Please do not add any new demuxers here. If you want to implement a new * demuxer, add it to libavformat, except for wrappers around external @@ -79,8 +82,12 @@ const demuxer_desc_t *const demuxer_list[] = { #ifdef CONFIG_TV &demuxer_desc_tv, #endif +#ifdef CONFIG_LIBASS + &demuxer_desc_libass, +#endif &demuxer_desc_matroska, &demuxer_desc_lavf, + &demuxer_desc_subreader, &demuxer_desc_avi, &demuxer_desc_asf, #ifdef CONFIG_MNG @@ -101,6 +108,16 @@ const demuxer_desc_t *const demuxer_list[] = { NULL }; +static void add_stream_chapters(struct demuxer *demuxer); + +static int packet_destroy(void *ptr) +{ + struct demux_packet *dp = ptr; + talloc_free(dp->avpacket); + free(dp->allocation); + return 0; +} + static struct demux_packet *create_packet(size_t len) { if (len > 1000000000) { @@ -108,16 +125,14 @@ static struct demux_packet *create_packet(size_t len) "over 1 GB!\n"); abort(); } - struct demux_packet *dp = malloc(sizeof(struct demux_packet)); - dp->len = len; - dp->next = NULL; - dp->pts = MP_NOPTS_VALUE; - dp->duration = -1; - dp->stream_pts = MP_NOPTS_VALUE; - dp->pos = 0; - dp->keyframe = false; - dp->buffer = NULL; - dp->avpacket = NULL; + struct demux_packet *dp = talloc(NULL, struct demux_packet); + talloc_set_destructor(dp, packet_destroy); + *dp = (struct demux_packet) { + .len = len, + .pts = MP_NOPTS_VALUE, + .duration = -1, + .stream_pts = MP_NOPTS_VALUE, + }; return dp; } @@ -130,6 +145,7 @@ struct demux_packet *new_demux_packet(size_t len) abort(); } memset(dp->buffer + len, 0, MP_INPUT_BUFFER_PADDING_SIZE); + dp->allocation = dp->buffer; return dp; } @@ -155,6 +171,7 @@ void resize_demux_packet(struct demux_packet *dp, size_t len) "over 1 GB!\n"); abort(); } + assert(dp->allocation); dp->buffer = realloc(dp->buffer, len + MP_INPUT_BUFFER_PADDING_SIZE); if (!dp->buffer) { mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Memory allocation failure!\n"); @@ -162,15 +179,47 @@ void resize_demux_packet(struct demux_packet *dp, size_t len) } memset(dp->buffer + len, 0, MP_INPUT_BUFFER_PADDING_SIZE); dp->len = len; + dp->allocation = dp->buffer; } void free_demux_packet(struct demux_packet *dp) { - if (dp->avpacket) - talloc_free(dp->avpacket); - else - free(dp->buffer); - free(dp); + talloc_free(dp); +} + +static int destroy_avpacket(void *pkt) +{ + av_free_packet(pkt); + return 0; +} + +struct demux_packet *demux_copy_packet(struct demux_packet *dp) +{ + struct demux_packet *new = NULL; + // No av_copy_packet() in Libav +#if LIBAVCODEC_VERSION_MICRO >= 100 + if (dp->avpacket) { + assert(dp->buffer == dp->avpacket->data); + assert(dp->len == dp->avpacket->size); + AVPacket *newavp = talloc_zero(NULL, AVPacket); + talloc_set_destructor(newavp, destroy_avpacket); + av_init_packet(newavp); + if (av_copy_packet(newavp, dp->avpacket) < 0) + abort(); + new = new_demux_packet_fromdata(newavp->data, newavp->size); + new->avpacket = newavp; + } +#endif + if (!new) { + new = new_demux_packet(dp->len); + memcpy(new->buffer, dp->buffer, new->len); + } + new->pts = dp->pts; + new->duration = dp->duration; + new->stream_pts = dp->stream_pts; + new->pos = dp->pos; + new->keyframe = dp->keyframe; + return new; } static void free_demuxer_stream(struct demux_stream *ds) @@ -210,8 +259,8 @@ static const demuxer_desc_t *get_demuxer_desc_from_type(int file_format) } -demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, - int a_id, int v_id, int s_id, char *filename) +static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, + int a_id, int v_id, int s_id, char *filename) { struct demuxer *d = talloc_zero(NULL, struct demuxer); d->stream = stream; @@ -222,8 +271,8 @@ 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, STREAM_VIDEO, a_id); - d->video = new_demuxer_stream(d, STREAM_AUDIO, v_id); + d->audio = new_demuxer_stream(d, STREAM_AUDIO, a_id); + d->video = new_demuxer_stream(d, STREAM_VIDEO, v_id); d->sub = new_demuxer_stream(d, STREAM_SUB, s_id); d->ds[STREAM_VIDEO] = d->video; d->ds[STREAM_AUDIO] = d->audio; @@ -308,10 +357,6 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) static void free_sh_stream(struct sh_stream *sh) { - if (sh->lav_headers) { - avcodec_close(sh->lav_headers); - av_free(sh->lav_headers); - } } sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid) @@ -428,13 +473,16 @@ void free_demuxer(demuxer_t *demuxer) talloc_free(demuxer); } -void demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream, - demux_packet_t *dp) +// Returns the same value as demuxer->fill_buffer: 1 ok, 0 EOF/not selected. +int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream, + demux_packet_t *dp) { - if (!demuxer_stream_is_selected(demuxer, stream)) { + if (!dp || !demuxer_stream_is_selected(demuxer, stream)) { free_demux_packet(dp); + return 0; } else { ds_add_packet(demuxer->ds[stream->type], dp); + return 1; } } @@ -581,7 +629,7 @@ static bool demux_check_queue_full(demuxer_t *demux) int demux_fill_buffer(demuxer_t *demux, demux_stream_t *ds) { // Note: parameter 'ds' can be NULL! - return demux->desc->fill_buffer(demux, ds); + return demux->desc->fill_buffer ? demux->desc->fill_buffer(demux, ds) : 0; } // return value: @@ -739,8 +787,7 @@ void ds_free_packs(demux_stream_t *ds) } if (ds->asf_packet) { // free unfinished .asf fragments: - free(ds->asf_packet->buffer); - free(ds->asf_packet); + free_demux_packet(ds->asf_packet); ds->asf_packet = NULL; } ds->first = ds->last = NULL; @@ -784,28 +831,34 @@ int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts) return len; } -int ds_get_packet_sub(demux_stream_t *ds, unsigned char **start) +struct demux_packet *ds_get_packet_sub(demux_stream_t *ds) { - int len; if (ds->buffer_pos >= ds->buffer_size) { - *start = NULL; if (!ds->packs) - return -1; // no sub + return NULL; // no sub if (!ds_fill_buffer(ds)) - return -1; // EOF + return NULL; // EOF } - len = ds->buffer_size - ds->buffer_pos; - *start = &ds->buffer[ds->buffer_pos]; - ds->buffer_pos += len; - return len; + if (ds->buffer_pos < ds->buffer_size) { + ds->current->buffer += ds->buffer_pos; + ds->buffer_size -= ds->buffer_pos; + } + ds->buffer_pos = ds->buffer_size; + return ds->current; } struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last) { - // This shouldn't get used together with partial reads - assert(ds->buffer_pos == 0 || ds->buffer_pos >= ds->buffer_size); if (!repeat_last) ds_fill_buffer(ds); + // This shouldn't get used together with partial reads + // However, some old demuxers return parsed packets with an offset in + // -correct-pts mode (at least mpegts). + // Not all old demuxers will actually work. + if (ds->buffer_pos < ds->buffer_size) { + ds->current->buffer += ds->buffer_pos; + ds->buffer_size -= ds->buffer_pos; + } ds->buffer_pos = ds->buffer_size; return ds->current; } @@ -917,12 +970,15 @@ static struct demuxer *open_given_type(struct MPOpts *opts, demuxer = demux2; } demuxer->file_format = fformat; - opts->correct_pts = opts->user_correct_pts; - if (opts->correct_pts < 0) - opts->correct_pts = - demux_control(demuxer, DEMUXER_CTRL_CORRECT_PTS, - NULL) == DEMUXER_CTRL_OK; + if (stream_manages_timeline(demuxer->stream)) { + // Incorrect, but fixes some behavior with DVD/BD + demuxer->ts_resets_possible = false; + // Doesn't work, because stream_pts is a "guess". + demuxer->accurate_seek = false; + } + add_stream_chapters(demuxer); demuxer_sort_chapters(demuxer); + demux_info_update(demuxer); return demuxer; } else { // demux_mov can return playlist instead of mov @@ -1071,7 +1127,7 @@ int demux_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, * (nothing actually implements DEMUXER_CTRL_RESYNC now). */ struct stream *stream = demuxer->stream; - if (stream->type == STREAMTYPE_DVD) { + if (stream_manages_timeline(stream)) { double pts; if (flags & SEEK_ABSOLUTE) @@ -1174,6 +1230,18 @@ char *demux_info_get(demuxer_t *demuxer, const char *opt) return NULL; } +void demux_info_update(struct demuxer *demuxer) +{ + demux_control(demuxer, DEMUXER_CTRL_UPDATE_INFO, NULL); + // Take care of stream metadata as well + char **meta; + if (stream_control(demuxer->stream, STREAM_CTRL_GET_METADATA, &meta) > 0) { + for (int n = 0; meta[n + 0]; n += 2) + demux_info_add(demuxer, meta[n + 0], meta[n + 1]); + talloc_free(meta); + } +} + int demux_control(demuxer_t *demuxer, int cmd, void *arg) { @@ -1199,6 +1267,10 @@ void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type, { assert(!stream || stream->type == type); + // don't flush buffers if stream is already selected + if (stream && demuxer_stream_is_selected(demuxer, stream)) + return; + int old_id = demuxer->ds[type]->id; // legacy @@ -1283,13 +1355,26 @@ int demuxer_add_chapter(demuxer_t *demuxer, struct bstr name, .original_index = demuxer->num_chapters, .start = start, .end = end, - .name = name.len ? bstrdup0(demuxer, name) - : talloc_strdup(demuxer, mp_gtext("unknown")), + .name = name.len ? bstrdup0(demuxer, name) : NULL, }; MP_TARRAY_APPEND(demuxer, demuxer->chapters, demuxer->num_chapters, new); return 0; } +static void add_stream_chapters(struct demuxer *demuxer) +{ + if (demuxer->num_chapters) + return; + int num_chapters = demuxer_chapter_count(demuxer); + for (int n = 0; n < num_chapters; n++) { + double p = n; + if (stream_control(demuxer->stream, STREAM_CTRL_GET_CHAPTER_TIME, &p) + != STREAM_OK) + return; + demuxer_add_chapter(demuxer, bstr0(""), p * 1e9, 0); + } +} + /** * \brief demuxer_seek_chapter() seeks to a chapter in two possible ways: * either using the demuxer->chapters structure set by the demuxer @@ -1301,22 +1386,22 @@ int demuxer_add_chapter(demuxer_t *demuxer, struct bstr name, int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, double *seek_pts) { - int ris; - - if (!demuxer->num_chapters || !demuxer->chapters) { - demux_flush(demuxer); + int ris = STREAM_UNSUPPORTED; + if (demuxer->num_chapters == 0) ris = stream_control(demuxer->stream, STREAM_CTRL_SEEK_TO_CHAPTER, &chapter); - if (ris != STREAM_UNSUPPORTED) - demux_control(demuxer, DEMUXER_CTRL_RESYNC, NULL); + + if (ris != STREAM_UNSUPPORTED) { + demux_flush(demuxer); + demux_control(demuxer, DEMUXER_CTRL_RESYNC, NULL); // exit status may be ok, but main() doesn't have to seek itself // (because e.g. dvds depend on sectors, not on pts) *seek_pts = -1.0; - return ris != STREAM_UNSUPPORTED ? chapter : -1; - } else { // chapters structure is set in the demuxer + return chapter; + } else { if (chapter >= demuxer->num_chapters) return -1; if (chapter < 0) @@ -1355,12 +1440,10 @@ char *demuxer_chapter_name(demuxer_t *demuxer, int chapter) return NULL; } -float demuxer_chapter_time(demuxer_t *demuxer, int chapter, float *end) +double demuxer_chapter_time(demuxer_t *demuxer, int chapter) { if (demuxer->num_chapters && demuxer->chapters && chapter >= 0 && chapter < demuxer->num_chapters) { - if (end) - *end = demuxer->chapters[chapter].end / 1e9; return demuxer->chapters[chapter].start / 1e9; } return -1.0; @@ -1378,6 +1461,27 @@ int demuxer_chapter_count(demuxer_t *demuxer) return demuxer->num_chapters; } +double demuxer_get_time_length(struct demuxer *demuxer) +{ + double len; + if (stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, &len) > 0) + return len; + // <= 0 means DEMUXER_CTRL_NOTIMPL or DEMUXER_CTRL_DONTKNOW + if (demux_control(demuxer, DEMUXER_CTRL_GET_TIME_LENGTH, &len) > 0) + return len; + return -1; +} + +double demuxer_get_start_time(struct demuxer *demuxer) +{ + double time; + if (stream_control(demuxer->stream, STREAM_CTRL_GET_START_TIME, &time) > 0) + return time; + if (demux_control(demuxer, DEMUXER_CTRL_GET_START_TIME, &time) > 0) + return time; + return 0; +} + int demuxer_angles_count(demuxer_t *demuxer) { int ris, angles = -1; @@ -1416,3 +1520,69 @@ int demuxer_set_angle(demuxer_t *demuxer, int angle) return angle; } + +static int packet_sort_compare(const void *p1, const void *p2) +{ + struct demux_packet *c1 = *(struct demux_packet **)p1; + struct demux_packet *c2 = *(struct demux_packet **)p2; + + if (c1->pts > c2->pts) + return 1; + else if (c1->pts < c2->pts) + return -1; + return 0; +} + +void demux_packet_list_sort(struct demux_packet **pkts, int num_pkts) +{ + qsort(pkts, num_pkts, sizeof(struct demux_packet *), packet_sort_compare); +} + +void demux_packet_list_seek(struct demux_packet **pkts, int num_pkts, + int *current, float rel_seek_secs, int flags) +{ + double ref_time = 0; + if (*current >= 0 && *current < num_pkts) { + ref_time = pkts[*current]->pts; + } else if (*current == num_pkts && num_pkts > 0) { + ref_time = pkts[num_pkts - 1]->pts + pkts[num_pkts - 1]->duration; + } + + if (flags & SEEK_ABSOLUTE) + ref_time = 0; + + if (flags & SEEK_FACTOR) { + ref_time += demux_packet_list_duration(pkts, num_pkts) * rel_seek_secs; + } else { + ref_time += rel_seek_secs; + } + + // Could do binary search, but it's probably not worth the complexity. + int last_index = 0; + for (int n = 0; n < num_pkts; n++) { + if (pkts[n]->pts > ref_time) + break; + last_index = n; + } + *current = last_index; +} + +double demux_packet_list_duration(struct demux_packet **pkts, int num_pkts) +{ + if (num_pkts > 0) + return pkts[num_pkts - 1]->pts + pkts[num_pkts - 1]->duration; + return 0; +} + +struct demux_packet *demux_packet_list_fill(struct demux_packet **pkts, + int num_pkts, int *current) +{ + if (*current < 0) + *current = 0; + if (*current >= num_pkts) + return NULL; + struct demux_packet *new = talloc(NULL, struct demux_packet); + *new = *pkts[*current]; + *current += 1; + return new; +} diff --git a/demux/demux.h b/demux/demux.h index 3d66139d69..20e6ba7a66 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -71,6 +71,8 @@ enum demuxer_type { DEMUXER_TYPE_MNG, DEMUXER_TYPE_EDL, DEMUXER_TYPE_CUE, + DEMUXER_TYPE_SUBREADER, + DEMUXER_TYPE_LIBASS, /* Values after this are for internal use and can not be selected * as demuxer type by the user (-demuxer option). */ @@ -91,6 +93,7 @@ enum timestamp_type { #define DEMUXER_CTRL_OK 1 #define DEMUXER_CTRL_GUESS 2 +#define DEMUXER_CTRL_UPDATE_INFO 8 #define DEMUXER_CTRL_SWITCHED_TRACKS 9 #define DEMUXER_CTRL_GET_TIME_LENGTH 10 #define DEMUXER_CTRL_GET_START_TIME 11 @@ -215,6 +218,7 @@ struct demuxer_params { unsigned char (*matroska_wanted_uids)[16]; int matroska_wanted_segment; bool *matroska_was_valid; + struct ass_library *ass_library; }; typedef struct demuxer { @@ -290,6 +294,7 @@ struct demux_packet *new_demux_packet_fromdata(void *data, size_t len); struct demux_packet *new_demux_packet_from(void *data, size_t len); void resize_demux_packet(struct demux_packet *dp, size_t len); void free_demux_packet(struct demux_packet *dp); +struct demux_packet *demux_copy_packet(struct demux_packet *dp); #ifndef SIZE_MAX #define SIZE_MAX ((size_t)-1) @@ -304,13 +309,10 @@ static inline void *realloc_struct(void *ptr, size_t nmemb, size_t size) return realloc(ptr, nmemb * size); } -struct demuxer *new_demuxer(struct MPOpts *opts, struct stream *stream, - int type, int a_id, int v_id, int s_id, - char *filename); void free_demuxer(struct demuxer *demuxer); -void demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream, - demux_packet_t *dp); +int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream, + demux_packet_t *dp); 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, int64_t pos, bool keyframe); @@ -343,7 +345,7 @@ void ds_free_packs(struct demux_stream *ds); int ds_get_packet(struct demux_stream *ds, unsigned char **start); int ds_get_packet_pts(struct demux_stream *ds, unsigned char **start, double *pts); -int ds_get_packet_sub(struct demux_stream *ds, unsigned char **start); +struct demux_packet *ds_get_packet_sub(demux_stream_t *ds); struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last); double ds_get_next_pts(struct demux_stream *ds); int ds_parse(struct demux_stream *sh, uint8_t **buffer, int *len, double pts, @@ -384,6 +386,8 @@ int demux_info_add_bstr(struct demuxer *demuxer, struct bstr opt, struct bstr param); char *demux_info_get(struct demuxer *demuxer, const char *opt); int demux_info_print(struct demuxer *demuxer); +void demux_info_update(struct demuxer *demuxer); + int demux_control(struct demuxer *demuxer, int cmd, void *arg); void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type, @@ -401,12 +405,15 @@ int demuxer_seek_chapter(struct demuxer *demuxer, int chapter, double *seek_pts); void demuxer_sort_chapters(demuxer_t *demuxer); +double demuxer_get_time_length(struct demuxer *demuxer); +double demuxer_get_start_time(struct demuxer *demuxer); + /// Get current chapter index if available. int demuxer_get_current_chapter(struct demuxer *demuxer, double time_now); /// Get chapter name by index if available. char *demuxer_chapter_name(struct demuxer *demuxer, int chapter); -/// Get chapter start time and end time by index if available. -float demuxer_chapter_time(struct demuxer *demuxer, int chapter, float *end); +/// Get chapter start time by index if available. +double demuxer_chapter_time(struct demuxer *demuxer, int chapter); /// Get total chapter number. int demuxer_chapter_count(struct demuxer *demuxer); /// Get current angle index. @@ -421,4 +428,11 @@ struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d, bool demuxer_stream_is_selected(struct demuxer *d, struct sh_stream *stream); +void demux_packet_list_sort(struct demux_packet **pkts, int num_pkts); +void demux_packet_list_seek(struct demux_packet **pkts, int num_pkts, + int *current, float rel_seek_secs, int flags); +double demux_packet_list_duration(struct demux_packet **pkts, int num_pkts); +struct demux_packet *demux_packet_list_fill(struct demux_packet **pkts, + int num_pkts, int *current); + #endif /* MPLAYER_DEMUXER_H */ diff --git a/demux/demux_asf.c b/demux/demux_asf.c index 1d181eac67..f800e09dc3 100644 --- a/demux/demux_asf.c +++ b/demux/demux_asf.c @@ -100,11 +100,9 @@ static void init_priv (struct asf_priv* asf){ static void demux_asf_append_to_packet(demux_packet_t* dp,unsigned char *data,int len,int offs) { if(dp->len!=offs && offs!=-1) mp_msg(MSGT_DEMUX,MSGL_V,"warning! fragment.len=%d BUT next fragment offset=%d \n",dp->len,offs); - dp->buffer=realloc(dp->buffer,dp->len+len+MP_INPUT_BUFFER_PADDING_SIZE); - memcpy(dp->buffer+dp->len,data,len); - memset(dp->buffer+dp->len+len, 0, MP_INPUT_BUFFER_PADDING_SIZE); - mp_dbg(MSGT_DEMUX,MSGL_DBG4,"data appended! %d+%d\n",dp->len,len); - dp->len+=len; + size_t old_len = dp->len; + resize_demux_packet(dp, dp->len + len); + memcpy(dp->buffer + old_len, data, len); } static int demux_asf_read_packet(demuxer_t *demux,unsigned char *data,int len,int id,int seq,uint64_t time,unsigned short dur,int offs,int keyframe){ @@ -630,7 +628,6 @@ static demuxer_t* demux_open_asf(demuxer_t* demuxer) init_priv(asf); if (!read_asf_header(demuxer,asf)) return NULL; - stream_reset(demuxer->stream); stream_seek(demuxer->stream,demuxer->movi_start); // demuxer->idx_pos=0; // demuxer->endpos=avi_header.movi_end; diff --git a/demux/demux_avi.c b/demux/demux_avi.c index daf542bfac..a07f022cde 100644 --- a/demux/demux_avi.c +++ b/demux/demux_avi.c @@ -456,7 +456,6 @@ static demuxer_t* demux_open_avi(demuxer_t* demuxer){ demuxer->video->id=-1; // autodetect } - stream_reset(demuxer->stream); stream_seek(demuxer->stream,demuxer->movi_start); if(priv->idx_size>1){ // decide index format: diff --git a/demux/demux_cue.c b/demux/demux_cue.c index 31a3e00e40..073fa9d336 100644 --- a/demux/demux_cue.c +++ b/demux/demux_cue.c @@ -39,7 +39,7 @@ static int try_open_file(struct demuxer *demuxer) if (!mp_probe_cue((struct bstr) { buf, len })) return 0; stream_seek(s, 0); - demuxer->file_contents = stream_read_complete(s, demuxer, 1000000, 0); + demuxer->file_contents = stream_read_complete(s, demuxer, 1000000); if (demuxer->file_contents.start == NULL) return 0; if (!mp_probe_cue((struct bstr) { buf, len })) @@ -47,11 +47,6 @@ static int try_open_file(struct demuxer *demuxer) return DEMUXER_TYPE_CUE; } -static int dummy_fill_buffer(struct demuxer *demuxer, struct demux_stream *ds) -{ - return 0; -} - const struct demuxer_desc demuxer_desc_cue = { .info = "CUE file demuxer", .name = "cue", @@ -61,5 +56,4 @@ const struct demuxer_desc demuxer_desc_cue = { .type = DEMUXER_TYPE_CUE, .safe_check = true, .check_file = try_open_file, // no separate .open - .fill_buffer = dummy_fill_buffer, }; diff --git a/demux/demux_edl.c b/demux/demux_edl.c index 1e1db5be93..c35137ffb2 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -34,17 +34,12 @@ static int try_open_file(struct demuxer *demuxer) if (strncmp(buf, header, len)) return 0; stream_seek(s, 0); - demuxer->file_contents = stream_read_complete(s, demuxer, 1000000, 0); + demuxer->file_contents = stream_read_complete(s, demuxer, 1000000); if (demuxer->file_contents.start == NULL) return 0; return DEMUXER_TYPE_EDL; } -static int dummy_fill_buffer(struct demuxer *demuxer, struct demux_stream *ds) -{ - return 0; -} - const struct demuxer_desc demuxer_desc_edl = { .info = "EDL file demuxer", .name = "edl", @@ -54,5 +49,4 @@ const struct demuxer_desc demuxer_desc_edl = { .type = DEMUXER_TYPE_EDL, .safe_check = true, .check_file = try_open_file, // no separate .open - .fill_buffer = dummy_fill_buffer, }; diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 8a8b003680..39e1cb28c5 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -47,24 +47,28 @@ #include "core/m_option.h" #define INITIAL_PROBE_SIZE STREAM_BUFFER_SIZE -#define PROBE_BUF_SIZE (2 * 1024 * 1024) +#define PROBE_BUF_SIZE FFMIN(STREAM_MAX_BUFFER_SIZE, 2 * 1024 * 1024) #define OPT_BASE_STRUCT struct MPOpts const m_option_t lavfdopts_conf[] = { OPT_INTRANGE("probesize", lavfdopts.probesize, 0, 32, INT_MAX), OPT_STRING("format", lavfdopts.format, 0), - OPT_INTRANGE("analyzeduration", lavfdopts.analyzeduration, 0, 0, INT_MAX), + OPT_FLOATRANGE("analyzeduration", lavfdopts.analyzeduration, 0, 0, 3600), + OPT_FLAG("allow-mimetype", lavfdopts.allow_mimetype, 0), OPT_INTRANGE("probescore", lavfdopts.probescore, 0, 0, 100), OPT_STRING("cryptokey", lavfdopts.cryptokey, 0), OPT_STRING("o", lavfdopts.avopt, 0), {NULL, NULL, 0, 0, 0, 0, NULL} }; +// Should correspond to IO_BUFFER_SIZE in libavformat/aviobuf.c (not public) +// libavformat (almost) always reads data in blocks of this size. #define BIO_BUFFER_SIZE 32768 typedef struct lavf_priv { char *filename; + const struct format_hack *format_hack; AVInputFormat *avif; AVFormatContext *avfc; AVIOContext *pb; @@ -80,16 +84,25 @@ typedef struct lavf_priv { char *mime_type; } lavf_priv_t; -static const char *map_demuxer_mime_type[][2] = { - {"audio/aacp", "aac"}, +struct format_hack { + const char *ff_name; + const char *mime_type; + int probescore; + float analyzeduration; +}; + +static const struct format_hack format_hacks[] = { + {"aac", "audio/aacp", 25, 0.5}, + {"aac", "audio/aac", 25, 0.5}, + {"mp3", "audio/mpeg", 25, 0.5}, {0} }; -static const char *find_demuxer_from_mime_type(char *mime_type) +static const struct format_hack *find_format_from_mime_type(char *mime_type) { - for (int n = 0; map_demuxer_mime_type[n][0]; n++) { - if (strcasecmp(map_demuxer_mime_type[n][0], mime_type) == 0) - return map_demuxer_mime_type[n][1]; + for (int n = 0; format_hacks[n].ff_name; n++) { + if (strcasecmp(format_hacks[n].mime_type, mime_type) == 0) + return &format_hacks[n]; } return NULL; } @@ -131,7 +144,6 @@ static int64_t mp_seek(void *opaque, int64_t pos, int whence) return -1; current_pos = stream_tell(stream); if (stream_seek(stream, pos) == 0) { - stream_reset(stream); stream_seek(stream, current_pos); return -1; } @@ -178,18 +190,15 @@ static int lavf_check_file(demuxer_t *demuxer) { struct MPOpts *opts = demuxer->opts; struct lavfdopts *lavfdopts = &opts->lavfdopts; - AVProbeData avpd; + struct stream *s = demuxer->stream; lavf_priv_t *priv; - int probe_data_size = 0; - int read_size = INITIAL_PROBE_SIZE; - int score; assert(!demuxer->priv); demuxer->priv = talloc_zero(NULL, lavf_priv_t); priv = demuxer->priv; priv->autoselect_sub = -1; - priv->filename = demuxer->stream->url; + priv->filename = s->url; if (!priv->filename) { priv->filename = "mp:unknown"; mp_msg(MSGT_DEMUX, MSGL_WARN, "Stream |