diff options
Diffstat (limited to 'demux/demux.c')
-rw-r--r-- | demux/demux.c | 389 |
1 files changed, 42 insertions, 347 deletions
diff --git a/demux/demux.c b/demux/demux.c index c783b0cbc2..c21e249dca 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -46,8 +46,6 @@ #error MP_INPUT_BUFFER_PADDING_SIZE is too small! #endif -static void clear_parser(sh_audio_t *sh); - // Demuxer list extern const struct demuxer_desc demuxer_desc_edl; extern const struct demuxer_desc demuxer_desc_cue; @@ -55,18 +53,9 @@ extern const demuxer_desc_t demuxer_desc_rawaudio; extern const demuxer_desc_t demuxer_desc_rawvideo; extern const demuxer_desc_t demuxer_desc_tv; extern const demuxer_desc_t demuxer_desc_mf; -extern const demuxer_desc_t demuxer_desc_avi; -extern const demuxer_desc_t demuxer_desc_asf; extern const demuxer_desc_t demuxer_desc_matroska; extern const demuxer_desc_t demuxer_desc_lavf; extern const demuxer_desc_t demuxer_desc_mng; -extern const demuxer_desc_t demuxer_desc_mpeg_ps; -extern const demuxer_desc_t demuxer_desc_mpeg_pes; -extern const demuxer_desc_t demuxer_desc_mpeg_gxf; -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; @@ -88,18 +77,9 @@ const demuxer_desc_t *const demuxer_list[] = { &demuxer_desc_matroska, &demuxer_desc_lavf, &demuxer_desc_subreader, - &demuxer_desc_avi, - &demuxer_desc_asf, #ifdef CONFIG_MNG &demuxer_desc_mng, #endif - &demuxer_desc_mpeg_ps, - &demuxer_desc_mpeg_pes, - &demuxer_desc_mpeg_gxf, - &demuxer_desc_mpeg_es, - &demuxer_desc_mpeg4_es, - &demuxer_desc_h264_es, - &demuxer_desc_mpeg_ts, // auto-probe last, because it checks file-extensions only &demuxer_desc_mf, /* Please do not add any new demuxers here. If you want to implement a new @@ -229,14 +209,12 @@ static void free_demuxer_stream(struct demux_stream *ds) } static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer, - enum stream_type type, int id) + enum stream_type type) { demux_stream_t *ds = malloc(sizeof(demux_stream_t)); *ds = (demux_stream_t) { .stream_type = type, - .id = id, .demuxer = demuxer, - .asf_seq = -1, }; return ds; } @@ -260,7 +238,7 @@ static const demuxer_desc_t *get_demuxer_desc_from_type(int file_format) static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, - int a_id, int v_id, int s_id, char *filename) + char *filename) { struct demuxer *d = talloc_zero(NULL, struct demuxer); d->stream = stream; @@ -271,9 +249,9 @@ static 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_AUDIO, a_id); - d->video = new_demuxer_stream(d, STREAM_VIDEO, v_id); - d->sub = new_demuxer_stream(d, STREAM_SUB, s_id); + d->audio = new_demuxer_stream(d, STREAM_AUDIO); + d->video = new_demuxer_stream(d, STREAM_VIDEO); + d->sub = new_demuxer_stream(d, STREAM_SUB); d->ds[STREAM_VIDEO] = d->video; d->ds[STREAM_AUDIO] = d->audio; d->ds[STREAM_SUB] = d->sub; @@ -290,22 +268,24 @@ static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, return d; } -static struct sh_stream *new_sh_stream_id(demuxer_t *demuxer, - enum stream_type type, - int stream_index, - int demuxer_id) +struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) { - if (demuxer->num_streams > MAX_SH_STREAMS || stream_index > MAX_SH_STREAMS) { + if (demuxer->num_streams > MAX_SH_STREAMS) { mp_msg(MSGT_DEMUXER, MSGL_WARN, "Too many streams."); 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_struct(demuxer, struct sh_stream, { .type = type, .demuxer = demuxer, .index = demuxer->num_streams, .demuxer_id = demuxer_id, // may be overwritten by demuxer - .stream_index = stream_index, .opts = demuxer->opts, }); MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh); @@ -316,7 +296,6 @@ static struct sh_stream *new_sh_stream_id(demuxer_t *demuxer, sht->opts = sh->opts; sht->ds = demuxer->video; sh->video = sht; - demuxer->v_streams[sh->stream_index] = sht; break; } case STREAM_AUDIO: { @@ -327,7 +306,6 @@ static struct sh_stream *new_sh_stream_id(demuxer_t *demuxer, sht->samplesize = 2; sht->sample_format = AF_FORMAT_S16_NE; sh->audio = sht; - demuxer->a_streams[sh->stream_index] = sht; break; } case STREAM_SUB: { @@ -336,7 +314,6 @@ static struct sh_stream *new_sh_stream_id(demuxer_t *demuxer, sht->opts = sh->opts; sht->ds = demuxer->sub; sh->sub = sht; - demuxer->s_streams[sh->stream_index] = sht; break; } default: assert(false); @@ -344,127 +321,41 @@ static struct sh_stream *new_sh_stream_id(demuxer_t *demuxer, return sh; } -// This is what "modern" demuxers are supposed to use. -struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) -{ - int num = 0; - for (int n = 0; n < demuxer->num_streams; n++) { - if (demuxer->streams[n]->type == type) - num++; - } - return new_sh_stream_id(demuxer, type, demuxer->num_streams, num); -} - -static void free_sh_stream(struct sh_stream *sh) -{ -} - -sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid) -{ - if (id > MAX_S_STREAMS - 1 || id < 0) { - mp_msg(MSGT_DEMUXER, MSGL_WARN, - "Requested sub stream id overflow (%d > %d)\n", id, - MAX_S_STREAMS); - return NULL; - } - if (demuxer->s_streams[id]) - mp_msg(MSGT_DEMUXER, MSGL_WARN, "Sub stream %i redefined\n", id); - else { - new_sh_stream_id(demuxer, STREAM_SUB, id, sid); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid); - } - return demuxer->s_streams[id]; -} - -struct sh_sub *new_sh_sub_sid_lang(struct demuxer *demuxer, int id, int sid, - const char *lang) -{ - struct sh_sub *sh = new_sh_sub_sid(demuxer, id, sid); - if (lang && lang[0] && strcmp(lang, "und")) { - sh->gsh->lang = talloc_strdup(sh, lang); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", sid, lang); - } - return sh; -} - static void free_sh_sub(sh_sub_t *sh) { - mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_sub at %p\n", sh); free(sh->extradata); - free_sh_stream(sh->gsh); -} - -sh_audio_t *new_sh_audio_aid(demuxer_t *demuxer, int id, int aid) -{ - if (id > MAX_A_STREAMS - 1 || id < 0) { - mp_msg(MSGT_DEMUXER, MSGL_WARN, - "Requested audio stream id overflow (%d > %d)\n", id, - MAX_A_STREAMS); - return NULL; - } - if (demuxer->a_streams[id]) { - mp_tmsg(MSGT_DEMUXER, MSGL_WARN, "WARNING: Audio stream header %d redefined.\n", id); - } else { - mp_tmsg(MSGT_DEMUXER, MSGL_V, "==> Found audio stream: %d\n", id); - new_sh_stream_id(demuxer, STREAM_AUDIO, id, aid); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_ID=%d\n", aid); - } - return demuxer->a_streams[id]; } -static void free_sh_audio(demuxer_t *demuxer, int id) +static void free_sh_audio(sh_audio_t *sh) { - sh_audio_t *sh = demuxer->a_streams[id]; - demuxer->a_streams[id] = NULL; - mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_audio at %p\n", sh); free(sh->wf); free(sh->codecdata); - clear_parser(sh); - free_sh_stream(sh->gsh); } -sh_video_t *new_sh_video_vid(demuxer_t *demuxer, int id, int vid) +static void free_sh_video(sh_video_t *sh) { - if (id > MAX_V_STREAMS - 1 || id < 0) { - mp_msg(MSGT_DEMUXER, MSGL_WARN, - "Requested video stream id overflow (%d > %d)\n", id, - MAX_V_STREAMS); - return NULL; - } - if (demuxer->v_streams[id]) - mp_tmsg(MSGT_DEMUXER, MSGL_WARN, "WARNING: Video stream header %d redefined.\n", id); - else { - mp_tmsg(MSGT_DEMUXER, MSGL_V, "==> Found video stream: %d\n", id); - new_sh_stream_id(demuxer, STREAM_VIDEO, id, vid); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ID=%d\n", vid); - } - return demuxer->v_streams[id]; + free(sh->bih); } -static void free_sh_video(sh_video_t *sh) +static void free_sh_stream(struct sh_stream *sh) { - mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_video at %p\n", sh); - free(sh->bih); - free_sh_stream(sh->gsh); + switch (sh->type) { + case STREAM_AUDIO: free_sh_audio(sh->audio); break; + case STREAM_VIDEO: free_sh_video(sh->video); break; + case STREAM_SUB: free_sh_sub(sh->sub); break; + default: abort(); + } } void free_demuxer(demuxer_t *demuxer) { - int i; mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing %s demuxer at %p\n", demuxer->desc->shortdesc, demuxer); if (demuxer->desc->close) demuxer->desc->close(demuxer); // free streams: - for (i = 0; i < MAX_A_STREAMS; i++) - if (demuxer->a_streams[i]) - free_sh_audio(demuxer, i); - for (i = 0; i < MAX_V_STREAMS; i++) - if (demuxer->v_streams[i]) - free_sh_video(demuxer->v_streams[i]); - for (i = 0; i < MAX_S_STREAMS; i++) - if (demuxer->s_streams[i]) - free_sh_sub(demuxer->s_streams[i]); + for (int n = 0; n < demuxer->num_streams; n++) + free_sh_stream(demuxer->streams[n]); // free demuxers: free_demuxer_stream(demuxer->audio); free_demuxer_stream(demuxer->video); @@ -516,73 +407,6 @@ void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp) ds->demuxer->video->packs); } -static void allocate_parser(AVCodecContext **avctx, AVCodecParserContext **parser, const char *format) -{ - enum AVCodecID codec_id = mp_codec_to_av_codec_id(format); - - switch (codec_id) { - case AV_CODEC_ID_AAC_LATM: - case AV_CODEC_ID_AC3: - case AV_CODEC_ID_EAC3: - case AV_CODEC_ID_DTS: - case AV_CODEC_ID_FLAC: - case AV_CODEC_ID_MLP: - case AV_CODEC_ID_MP3: - case AV_CODEC_ID_MP2: - case AV_CODEC_ID_TRUEHD: - *avctx = avcodec_alloc_context3(NULL); - if (!*avctx) - return; - *parser = av_parser_init(codec_id); - if (!*parser) - av_freep(avctx); - break; - default: ; - } -} - -static void get_parser(sh_audio_t *sh, AVCodecContext **avctx, AVCodecParserContext **parser) -{ - *avctx = NULL; - *parser = NULL; - - if (!sh || !sh->needs_parsing) - return; - - *avctx = sh->avctx; - *parser = sh->parser; - if (*parser) - return; - - allocate_parser(avctx, parser, sh->gsh->codec); - sh->avctx = *avctx; - sh->parser = *parser; -} - -int ds_parse(demux_stream_t *ds, uint8_t **buffer, int *len, double pts, int64_t pos) -{ - AVCodecContext *avctx; - AVCodecParserContext *parser; - get_parser(ds->sh, &avctx, &parser); - if (!parser) - return *len; - return av_parser_parse2(parser, avctx, buffer, len, *buffer, *len, pts, pts, pos); -} - -static void clear_parser(sh_audio_t *sh) -{ - av_parser_close(sh->parser); - sh->parser = NULL; - av_freep(&sh->avctx); -} - -void ds_clear_parser(demux_stream_t *ds) -{ - if (!ds->sh) - return; - clear_parser(ds->sh); -} - void ds_read_packet(demux_stream_t *ds, stream_t *stream, int len, double pts, int64_t pos, bool keyframe) { @@ -612,9 +436,7 @@ static bool demux_check_queue_full(demuxer_t *demux) "packet queue (video: %d packets in %d bytes, audio: %d " "packets in %d bytes).\n", vpacks, vbytes, apacks, abytes); mp_tmsg(MSGT_DEMUXER, MSGL_HINT, "Maybe you are playing a non-" - "interleaved stream/file or the codec failed?\nFor AVI files, " - "try to force non-interleaved mode with the " - "--demuxer=avi --avi-ni options.\n"); + "interleaved stream/file or the codec failed?\n"); } demux->warned_queue_overflow = true; @@ -700,9 +522,7 @@ int ds_fill_buffer(demux_stream_t *ds) break; // EOF } - struct sh_video *sh_video = demux->video->sh; - - if (sh_video && sh_video->gsh->attached_picture) { + if (demux->video->gsh && demux->video->gsh->attached_picture) { if (demux->audio) ds->fill_count += demux->audio->packs - apacks; if (demux->video && demux->video->packs > vpacks) @@ -718,65 +538,6 @@ int ds_fill_buffer(demux_stream_t *ds) return 0; } -int demux_read_data(demux_stream_t *ds, unsigned char *mem, int len) -{ - int x; - int bytes = 0; - while (len > 0) { - x = ds->buffer_size - ds->buffer_pos; - if (x == 0) { - if (!ds_fill_buffer(ds)) - return bytes; - } else { - if (x > len) - x = len; - if (mem) - memcpy(mem + bytes, &ds->buffer[ds->buffer_pos], x); - bytes += x; - len -= x; - ds->buffer_pos += x; - } - } - return bytes; -} - -/** - * \brief read data until the given 3-byte pattern is encountered, up to maxlen - * \param mem memory to read data into, may be NULL to discard data - * \param maxlen maximum number of bytes to read - * \param read number of bytes actually read - * \param pattern pattern to search for (lowest 8 bits are ignored) - * \return whether pattern was found - */ -int demux_pattern_3(demux_stream_t *ds, unsigned char *mem, int maxlen, - int *read, uint32_t pattern) -{ - register uint32_t head = 0xffffff00; - register uint32_t pat = pattern & 0xffffff00; - int total_len = 0; - do { - register unsigned char *ds_buf = &ds->buffer[ds->buffer_size]; - int len = ds->buffer_size - ds->buffer_pos; - register long pos = -len; - if (unlikely(pos >= 0)) { // buffer is empty - ds_fill_buffer(ds); - continue; - } - do { - head |= ds_buf[pos]; - head <<= 8; - } while (++pos && head != pat); - len += pos; - if (total_len + len > maxlen) - len = maxlen - total_len; - len = demux_read_data(ds, mem ? &mem[total_len] : NULL, len); - total_len += len; - } while ((head != pat || total_len < 3) && total_len < maxlen && !ds->eof); - if (read) - *read = total_len; - return total_len >= 3 && head == pat; -} - void ds_free_packs(demux_stream_t *ds) { demux_packet_t *dp = ds->first; @@ -785,11 +546,6 @@ void ds_free_packs(demux_stream_t *ds) free_demux_packet(dp); dp = dn; } - if (ds->asf_packet) { - // free unfinished .asf fragments: - free_demux_packet(ds->asf_packet); - ds->asf_packet = NULL; - } ds->first = ds->last = NULL; ds->packs = 0; // !!!!! ds->bytes = 0; @@ -933,15 +689,13 @@ static int get_demuxer_type_from_name(char *demuxer_name, int *force) static struct demuxer *open_given_type(struct MPOpts *opts, const struct demuxer_desc *desc, struct stream *stream, bool force, - int audio_id, int video_id, int sub_id, char *filename, struct demuxer_params *params) { struct demuxer *demuxer; int fformat; mp_msg(MSGT_DEMUXER, MSGL_V, "Trying demuxer: %s\n", desc->name); - demuxer = new_demuxer(opts, stream, desc->type, audio_id, - video_id, sub_id, filename); + demuxer = new_demuxer(opts, stream, desc->type, filename); demuxer->params = params; if (desc->check_file) fformat = desc->check_file(demuxer); @@ -994,8 +748,7 @@ static struct demuxer *open_given_type(struct MPOpts *opts, "BUG: recursion to nonexistent file format\n"); return NULL; } - return open_given_type(opts, desc, stream, false, audio_id, - video_id, sub_id, filename, params); + return open_given_type(opts, desc, stream, false, filename, params); } fail: free_demuxer(demuxer); @@ -1004,8 +757,7 @@ static struct demuxer *open_given_type(struct MPOpts *opts, struct demuxer *demux_open_withparams(struct MPOpts *opts, struct stream *stream, int file_format, - char *force_format, int audio_id, - int video_id, int sub_id, char *filename, + char *force_format, char *filename, struct demuxer_params *params) { struct demuxer *demuxer = NULL; @@ -1021,37 +773,19 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, if (demuxer_type) file_format = demuxer_type; - // Some code (e.g. dvd stuff, network code, or extension.c) explicitly - // request certain file formats. The list of formats are always handled by - // libavformat. - // Maybe attempts should be made to convert the mplayer format to the libav - // format, instead of reyling on libav to auto-detect the stream's format - // correctly. - switch (file_format) { - //case DEMUXER_TYPE_MPEG_PS: - //case DEMUXER_TYPE_MPEG_TS: - case DEMUXER_TYPE_Y4M: - case DEMUXER_TYPE_NSV: - case DEMUXER_TYPE_AAC: - case DEMUXER_TYPE_MPC: - file_format = DEMUXER_TYPE_LAVF; - } - // If somebody requested a demuxer check it if (file_format) { desc = get_demuxer_desc_from_type(file_format); if (!desc) // should only happen with obsolete -demuxer 99 numeric format return NULL; - return open_given_type(opts, desc, stream, force, audio_id, - video_id, sub_id, filename, params); + return open_given_type(opts, desc, stream, force, filename, params); } // Test demuxers with safe file checks for (int i = 0; (desc = demuxer_list[i]); i++) { if (desc->safe_check) { - demuxer = open_given_type(opts, desc, stream, false, audio_id, - video_id, sub_id, filename, params); + demuxer = open_given_type(opts, desc, stream, false, filename, params); if (demuxer) return demuxer; } @@ -1063,8 +797,7 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, if (filename && opts->extension_parsing == 1) { desc = get_demuxer_desc_from_type(demuxer_type_by_filename(filename)); if (desc) - demuxer = open_given_type(opts, desc, stream, false, audio_id, - video_id, sub_id, filename, params); + demuxer = open_given_type(opts, desc, stream, false, filename, params); if (demuxer) return demuxer; } @@ -1072,8 +805,7 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, // Finally try detection for demuxers with unsafe checks for (int i = 0; (desc = demuxer_list[i]); i++) { if (!desc->safe_check && desc->check_file) { - demuxer = open_given_type(opts, desc, stream, false, audio_id, - video_id, sub_id, filename, params); + demuxer = open_given_type(opts, desc, stream, false, filename, params); if (demuxer) return demuxer; } @@ -1083,11 +815,10 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, } struct demuxer *demux_open(struct MPOpts *opts, stream_t *vs, int file_format, - int audio_id, int video_id, int sub_id, char *filename) { return demux_open_withparams(opts, vs, file_format, opts->demuxer_name, - audio_id, video_id, sub_id, filename, NULL); + filename, NULL); } void demux_flush(demuxer_t *demuxer) @@ -1101,14 +832,7 @@ int demux_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) { if (!demuxer->seekable) { - if (demuxer->file_format == DEMUXER_TYPE_AVI) - mp_tmsg(MSGT_SEEK, MSGL_WARN, "Cannot seek in raw AVI streams. (Index required, try with the -idx switch.)\n"); -#ifdef CONFIG_TV - else if (demuxer->file_format == DEMUXER_TYPE_TV) - mp_tmsg(MSGT_SEEK, MSGL_WARN, "TV input is not seekable! (Seeking will probably be for changing channels ;)\n"); -#endif - else - mp_tmsg(MSGT_SEEK, MSGL_WARN, "Cannot seek in this file.\n"); + mp_tmsg(MSGT_SEEK, MSGL_WARN, "Cannot seek in this file.\n"); return 0; } @@ -1267,48 +991,19 @@ 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)) + // don't flush buffers if stream is already selected / none are selected + if (demuxer->ds[type]->gsh == stream) return; - int old_id = demuxer->ds[type]->id; - - // legacy - int index = stream ? stream->stream_index : -2; - if (type == STREAM_AUDIO) { - if (demux_control(demuxer, DEMUXER_CTRL_SWITCH_AUDIO, &index) - == DEMUXER_CTRL_NOTIMPL) - demuxer->audio->id = index; - } else if (type == STREAM_VIDEO) { - if (demux_control(demuxer, DEMUXER_CTRL_SWITCH_VIDEO, &index) - == DEMUXER_CTRL_NOTIMPL) - demuxer->video->id = index; - } else if (type == STREAM_SUB) { - demuxer->ds[type]->id = index; - } else { - abort(); - } + demuxer->ds[type]->gsh = stream; - 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; - - if (old_id != new_id) { - ds_free_packs(demuxer->ds[type]); - demux_control(demuxer, DEMUXER_CTRL_SWITCHED_TRACKS, NULL); - } + ds_free_packs(demuxer->ds[type]); + demux_control(demuxer, DEMUXER_CTRL_SWITCHED_TRACKS, NULL); } bool demuxer_stream_is_selected(struct demuxer *d, struct sh_stream *stream) { - return stream && d->ds[stream->type]->id == stream->stream_index; + return stream && d->ds[stream->type]->gsh == stream; } int demuxer_add_attachment(demuxer_t *demuxer, struct bstr name, |